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