* Makefile.am (PROGS,bin_PROGRAMS): Add @BUILD_MISC@
[deliverable/binutils-gdb.git] / bfd / cache.c
CommitLineData
6724ff46 1/* BFD library -- caching of file descriptors.
64d5f5d0 2 Copyright 1990, 1991, 1992, 1994 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 18along with this program; if not, write to the Free Software
64d5f5d0 19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
6724ff46 20
b645b632
SC
21/*
22SECTION
c188b0be 23 File caching
b645b632
SC
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
c188b0be 31 <<bfd_cache_lookup>>, which runs around and makes sure that
b645b632
SC
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
64d5f5d0
ILT
42static void insert PARAMS ((bfd *));
43static void snip PARAMS ((bfd *));
44static boolean close_one PARAMS ((void));
45static boolean bfd_cache_delete PARAMS ((bfd *));
46
b645b632
SC
47/*
48INTERNAL_FUNCTION
49 BFD_CACHE_MAX_OPEN macro
6724ff46 50
b645b632 51DESCRIPTION
700b2ee3 52 The maximum number of files which the cache will keep open at
b645b632
SC
53 one time.
54
55.#define BFD_CACHE_MAX_OPEN 10
6724ff46
RP
56
57*/
58
64d5f5d0 59/* The number of BFD files we have open. */
c188b0be 60
4a81b561
DHW
61static int open_files;
62
b645b632
SC
63/*
64INTERNAL_FUNCTION
65 bfd_last_cache
66
67SYNOPSIS
68 extern bfd *bfd_last_cache;
6724ff46 69
b645b632
SC
70DESCRIPTION
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.
6724ff46
RP
74*/
75
76bfd *bfd_last_cache;
77
b645b632 78/*
c188b0be
DM
79 INTERNAL_FUNCTION
80 bfd_cache_lookup
81
82 DESCRIPTION
83 Check to see if the required BFD is the same as the last one
84 looked up. If so, then it can use the stream 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
b645b632 94 */
fc723380 95
64d5f5d0
ILT
96/* Insert a BFD into the cache. */
97
98static INLINE void
99insert (abfd)
100 bfd *abfd;
4a81b561 101{
64d5f5d0
ILT
102 if (bfd_last_cache == NULL)
103 {
104 abfd->lru_next = abfd;
105 abfd->lru_prev = abfd;
4a81b561 106 }
64d5f5d0
ILT
107 else
108 {
109 abfd->lru_next = bfd_last_cache;
110 abfd->lru_prev = bfd_last_cache->lru_prev;
111 abfd->lru_prev->lru_next = abfd;
112 abfd->lru_next->lru_prev = abfd;
113 }
114 bfd_last_cache = abfd;
4a81b561 115}
fc723380 116
64d5f5d0
ILT
117/* Remove a BFD from the cache. */
118
119static INLINE void
120snip (abfd)
121 bfd *abfd;
4a81b561
DHW
122{
123 abfd->lru_prev->lru_next = abfd->lru_next;
64d5f5d0
ILT
124 abfd->lru_next->lru_prev = abfd->lru_prev;
125 if (abfd == bfd_last_cache)
126 {
127 bfd_last_cache = abfd->lru_next;
128 if (abfd == bfd_last_cache)
129 bfd_last_cache = NULL;
130 }
4a81b561
DHW
131}
132
64d5f5d0
ILT
133/* We need to open a new file, and the cache is full. Find the least
134 recently used cacheable BFD and close it. */
135
700b2ee3 136static boolean
64d5f5d0
ILT
137close_one ()
138{
139 register bfd *kill;
140
141 if (bfd_last_cache == NULL)
142 kill = NULL;
143 else
144 {
145 for (kill = bfd_last_cache->lru_prev;
146 ! kill->cacheable;
147 kill = kill->lru_prev)
148 {
149 if (kill == bfd_last_cache)
150 {
151 kill = NULL;
152 break;
153 }
154 }
155 }
156
157 if (kill == NULL)
158 {
159 /* There are no open cacheable BFD's. */
160 return true;
161 }
162
163 kill->where = ftell ((FILE *) kill->iostream);
164
165 return bfd_cache_delete (kill);
166}
167
168/* Close a BFD and remove it from the cache. */
169
170static boolean
171bfd_cache_delete (abfd)
172 bfd *abfd;
4a81b561 173{
700b2ee3
ILT
174 boolean ret;
175
64d5f5d0 176 if (fclose ((FILE *) abfd->iostream) == 0)
700b2ee3 177 ret = true;
09141f8d
ILT
178 else
179 {
180 ret = false;
2f88343d 181 bfd_set_error (bfd_error_system_call);
09141f8d 182 }
64d5f5d0 183
4a81b561 184 snip (abfd);
64d5f5d0 185
4a81b561 186 abfd->iostream = NULL;
64d5f5d0
ILT
187 --open_files;
188
700b2ee3 189 return ret;
4a81b561 190}
4a81b561 191
64d5f5d0
ILT
192/*
193INTERNAL_FUNCTION
194 bfd_cache_init
195
196SYNOPSIS
197 boolean bfd_cache_init (bfd *abfd);
198
199DESCRIPTION
200 Add a newly opened BFD to the cache.
201*/
6724ff46 202
64d5f5d0
ILT
203boolean
204bfd_cache_init (abfd)
205 bfd *abfd;
4a81b561 206{
64d5f5d0 207 BFD_ASSERT (abfd->iostream != NULL);
c188b0be 208 if (open_files >= BFD_CACHE_MAX_OPEN)
64d5f5d0
ILT
209 {
210 if (! close_one ())
211 return false;
212 }
213 insert (abfd);
c188b0be 214 ++open_files;
64d5f5d0 215 return true;
4a81b561
DHW
216}
217
b645b632
SC
218/*
219INTERNAL_FUNCTION
220 bfd_cache_close
221
c188b0be
DM
222SYNOPSIS
223 boolean bfd_cache_close (bfd *abfd);
224
b645b632 225DESCRIPTION
c188b0be 226 Remove the BFD @var{abfd} from the cache. If the attached file is open,
b645b632
SC
227 then close it too.
228
700b2ee3
ILT
229RETURNS
230 <<false>> is returned if closing the file fails, <<true>> is
231 returned if all is well.
b645b632 232*/
64d5f5d0 233
700b2ee3 234boolean
64d5f5d0
ILT
235bfd_cache_close (abfd)
236 bfd *abfd;
4a81b561 237{
64d5f5d0
ILT
238 if (abfd->iostream == NULL
239 || (abfd->flags & BFD_IN_MEMORY) != 0)
240 return true;
241
242 return bfd_cache_delete (abfd);
4a81b561 243}
4a81b561 244
b645b632
SC
245/*
246INTERNAL_FUNCTION
247 bfd_open_file
248
c188b0be
DM
249SYNOPSIS
250 FILE* bfd_open_file(bfd *abfd);
251
b645b632 252DESCRIPTION
c188b0be 253 Call the OS to open a file for @var{abfd}. Return the <<FILE *>>
2f88343d 254 (possibly <<NULL>>) that results from this operation. Set up the
c188b0be 255 BFD so that future accesses know the file is open. If the <<FILE *>>
2f88343d 256 returned is <<NULL>>, then it won't have been put in the
b645b632 257 cache, so it won't have to be removed from it.
b645b632
SC
258*/
259
4a81b561 260FILE *
64d5f5d0
ILT
261bfd_open_file (abfd)
262 bfd *abfd;
4a81b561 263{
6724ff46 264 abfd->cacheable = true; /* Allow it to be closed later. */
8b046402 265
64d5f5d0
ILT
266 if (open_files >= BFD_CACHE_MAX_OPEN)
267 {
268 if (! close_one ())
269 return NULL;
270 }
271
272 switch (abfd->direction)
273 {
274 case read_direction:
275 case no_direction:
276 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
277 break;
278 case both_direction:
279 case write_direction:
280 if (abfd->opened_once == true)
281 {
282 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
283 if (abfd->iostream == NULL)
284 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
285 }
286 else
287 {
288 /*open for creat */
289 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WB);
290 abfd->opened_once = true;
291 }
292 break;
4a81b561 293 }
8b046402 294
64d5f5d0
ILT
295 if (abfd->iostream != NULL)
296 {
297 if (! bfd_cache_init (abfd))
298 return NULL;
299 }
4a81b561 300
64d5f5d0 301 return (FILE *) abfd->iostream;
4a81b561
DHW
302}
303
b645b632
SC
304/*
305INTERNAL_FUNCTION
306 bfd_cache_lookup_worker
307
c188b0be
DM
308SYNOPSIS
309 FILE *bfd_cache_lookup_worker(bfd *abfd);
310
b645b632
SC
311DESCRIPTION
312 Called when the macro <<bfd_cache_lookup>> fails to find a
c188b0be
DM
313 quick answer. Find a file descriptor for @var{abfd}. If
314 necessary, it open it. If there are already more than
315 <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
b645b632 316 avoid running out of file descriptors.
b645b632 317*/
4a81b561
DHW
318
319FILE *
64d5f5d0
ILT
320bfd_cache_lookup_worker (abfd)
321 bfd *abfd;
4a81b561 322{
64d5f5d0
ILT
323 if ((abfd->flags & BFD_IN_MEMORY) != 0)
324 abort ();
325
4a81b561 326 if (abfd->my_archive)
64d5f5d0
ILT
327 abfd = abfd->my_archive;
328
329 if (abfd->iostream != NULL)
330 {
331 /* Move the file to the start of the cache. */
332 if (abfd != bfd_last_cache)
333 {
9872a49c 334 snip (abfd);
64d5f5d0 335 insert (abfd);
9872a49c 336 }
64d5f5d0
ILT
337 }
338 else
339 {
340 if (bfd_open_file (abfd) == NULL)
341 return NULL;
342 if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0)
343 return NULL;
344 }
4a81b561 345
64d5f5d0 346 return (FILE *) abfd->iostream;
4a81b561 347}
This page took 0.261594 seconds and 4 git commands to generate.