This is a test to see if the file is still locked.
[deliverable/binutils-gdb.git] / bfd / cache.c
1
2 /* BFD library -- caching of file descriptors.
3 Copyright (C) 1990-1991 Free Software Foundation, Inc.
4 Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 /*
23 SECTION
24 File Caching
25
26 The file caching mechanism is embedded within BFD and allows
27 the application to open as many BFDs as it wants without
28 regard to the underlying operating system's file descriptor
29 limit (often as low as 20 open files). The module in
30 <<cache.c>> maintains a least recently used list of
31 <<BFD_CACHE_MAX_OPEN>> files, and exports the name
32 <<bfd_cache_lookup>> which runs around and makes sure that
33 the required BFD is open. If not, then it chooses a file to
34 close, closes it and opens the one wanted, returning its file
35 handle.
36
37 */
38
39 /* $Id$ */
40
41 #include "bfd.h"
42 #include "sysdep.h"
43 #include "libbfd.h"
44
45 /*
46 INTERNAL_FUNCTION
47 BFD_CACHE_MAX_OPEN macro
48
49 DESCRIPTION
50 The maxiumum number of files which the cache will keep open at
51 one time.
52
53 .#define BFD_CACHE_MAX_OPEN 10
54
55 */
56
57
58 static int open_files;
59
60 static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
61 opened */
62
63 /*
64 INTERNAL_FUNCTION
65 bfd_last_cache
66
67 SYNOPSIS
68 extern bfd *bfd_last_cache;
69
70 DESCRIPTION
71 Zero, or a pointer to the topmost BFD on the chain. This is
72 used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
73 determine when it can avoid a function call.
74 */
75
76 bfd *bfd_last_cache;
77
78 /*
79 * INTERNAL_FUNCTION
80 * bfd_cache_lookup
81 *
82 * DESCRIPTION
83 * Checks to see if the required BFD is the same as the last one
84 * looked up. If so then it can use the iostream in the BFD with
85 * impunity, since it can't have changed since the last lookup,
86 * otherwise it has to perform the complicated lookup function
87 *
88 * .#define bfd_cache_lookup(x) \
89 * . ((x)==bfd_last_cache? \
90 * . (FILE*)(bfd_last_cache->iostream): \
91 * . bfd_cache_lookup_worker(x))
92 *
93 *
94 */
95
96 static void bfd_cache_delete();
97
98
99 static void
100 DEFUN_VOID(close_one)
101 {
102 bfd *kill = cache_sentinel;
103 if (kill == 0) /* Nothing in the cache */
104 return ;
105
106 /* We can only close files that want to play this game. */
107 while (!kill->cacheable) {
108 kill = kill->lru_prev;
109 if (kill == cache_sentinel) /* Nobody wants to play */
110 return ;
111 }
112
113 kill->where = ftell((FILE *)(kill->iostream));
114 bfd_cache_delete(kill);
115 }
116
117 /* Cuts the BFD abfd out of the chain in the cache */
118 static void
119 DEFUN(snip,(abfd),
120 bfd *abfd)
121 {
122 abfd->lru_prev->lru_next = abfd->lru_next;
123 abfd->lru_next->lru_prev = abfd->lru_prev;
124 if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
125 }
126
127 static void
128 DEFUN(bfd_cache_delete,(abfd),
129 bfd *abfd)
130 {
131 fclose ((FILE *)(abfd->iostream));
132 snip (abfd);
133 abfd->iostream = NULL;
134 open_files--;
135 bfd_last_cache = 0;
136 }
137
138 static bfd *
139 DEFUN(insert,(x,y),
140 bfd *x AND
141 bfd *y)
142 {
143 if (y) {
144 x->lru_next = y;
145 x->lru_prev = y->lru_prev;
146 y->lru_prev->lru_next = x;
147 y->lru_prev = x;
148
149 }
150 else {
151 x->lru_prev = x;
152 x->lru_next = x;
153 }
154 return x;
155 }
156 \f
157
158 /*
159 INTERNAL_FUNCTION
160 bfd_cache_init
161
162 SYNOPSIS
163 void bfd_cache_init (bfd *);
164
165 DESCRIPTION
166 Initialize a BFD by putting it on the cache LRU.
167 */
168
169 void
170 DEFUN(bfd_cache_init,(abfd),
171 bfd *abfd)
172 {
173 cache_sentinel = insert(abfd, cache_sentinel);
174 }
175
176
177 /*
178 INTERNAL_FUNCTION
179 bfd_cache_close
180
181 DESCRIPTION
182 Remove the BFD from the cache. If the attached file is open,
183 then close it too.
184
185 SYNOPSIS
186 void bfd_cache_close (bfd *);
187 */
188 void
189 DEFUN(bfd_cache_close,(abfd),
190 bfd *abfd)
191 {
192 /* If this file is open then remove from the chain */
193 if (abfd->iostream)
194 {
195 bfd_cache_delete(abfd);
196 }
197 }
198
199 /*
200 INTERNAL_FUNCTION
201 bfd_open_file
202
203 DESCRIPTION
204 Call the OS to open a file for this BFD. Returns the FILE *
205 (possibly null) that results from this operation. Sets up the
206 BFD so that future accesses know the file is open. If the FILE
207 * returned is null, then there is won't have been put in the
208 cache, so it won't have to be removed from it.
209
210 SYNOPSIS
211 FILE* bfd_open_file(bfd *);
212 */
213
214 FILE *
215 DEFUN(bfd_open_file, (abfd),
216 bfd *abfd)
217 {
218 abfd->cacheable = true; /* Allow it to be closed later. */
219
220 if(open_files >= BFD_CACHE_MAX_OPEN) {
221 close_one();
222 }
223
224 switch (abfd->direction) {
225 case read_direction:
226 case no_direction:
227 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
228 break;
229 case both_direction:
230 case write_direction:
231 if (abfd->opened_once == true) {
232 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
233 if (!abfd->iostream) {
234 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
235 }
236 } else {
237 /*open for creat */
238 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
239 abfd->opened_once = true;
240 }
241 break;
242 }
243
244 if (abfd->iostream) {
245 open_files++;
246 bfd_cache_init (abfd);
247 }
248
249 return (FILE *)(abfd->iostream);
250 }
251
252 /*
253 INTERNAL_FUNCTION
254 bfd_cache_lookup_worker
255
256 DESCRIPTION
257 Called when the macro <<bfd_cache_lookup>> fails to find a
258 quick answer. Finds a file descriptor for this BFD. If
259 necessary, it open it. If there are already more than
260 BFD_CACHE_MAX_OPEN files open, it trys to close one first, to
261 avoid running out of file descriptors.
262
263 SYNOPSIS
264 FILE *bfd_cache_lookup_worker(bfd *);
265
266 */
267
268 FILE *
269 DEFUN(bfd_cache_lookup_worker,(abfd),
270 bfd *abfd)
271 {
272 if (abfd->my_archive)
273 {
274 abfd = abfd->my_archive;
275 }
276 /* Is this file already open .. if so then quick exit */
277 if (abfd->iostream)
278 {
279 if (abfd != cache_sentinel) {
280 /* Place onto head of lru chain */
281 snip (abfd);
282 cache_sentinel = insert(abfd, cache_sentinel);
283 }
284 }
285 /* This is a BFD without a stream -
286 so it must have been closed or never opened.
287 find an empty cache entry and use it. */
288 else
289 {
290
291 if (open_files >= BFD_CACHE_MAX_OPEN)
292 {
293 close_one();
294 }
295
296 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
297 fseek((FILE *)(abfd->iostream), abfd->where, false);
298 }
299 bfd_last_cache = abfd;
300 return (FILE *)(abfd->iostream);
301 }
This page took 0.036587 seconds and 5 git commands to generate.