doc cleanup
[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
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
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
c188b0be
DM
55static boolean
56bfd_cache_delete PARAMS ((bfd *));
57
58/* Number of bfds on the chain. All such bfds have their file open;
59 if it closed, they get snipd()d from the chain. */
60
4a81b561
DHW
61static int open_files;
62
6724ff46 63static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
4a81b561 64 opened */
4a81b561 65
b645b632
SC
66/*
67INTERNAL_FUNCTION
68 bfd_last_cache
69
70SYNOPSIS
71 extern bfd *bfd_last_cache;
6724ff46 72
b645b632
SC
73DESCRIPTION
74 Zero, or a pointer to the topmost BFD on the chain. This is
75 used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
76 determine when it can avoid a function call.
6724ff46
RP
77*/
78
79bfd *bfd_last_cache;
80
b645b632 81/*
c188b0be
DM
82 INTERNAL_FUNCTION
83 bfd_cache_lookup
84
85 DESCRIPTION
86 Check to see if the required BFD is the same as the last one
87 looked up. If so, then it can use the stream in the BFD with
88 impunity, since it can't have changed since the last lookup;
89 otherwise, it has to perform the complicated lookup function.
90
91 .#define bfd_cache_lookup(x) \
92 . ((x)==bfd_last_cache? \
93 . (FILE*)(bfd_last_cache->iostream): \
94 . bfd_cache_lookup_worker(x))
95
96
b645b632 97 */
fc723380 98
4a81b561 99static void
9872a49c 100DEFUN_VOID(close_one)
4a81b561
DHW
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));
700b2ee3 114 (void) bfd_cache_delete(kill);
4a81b561 115}
fc723380 116
6724ff46 117/* Cuts the BFD abfd out of the chain in the cache */
4a81b561 118static void
9872a49c
SC
119DEFUN(snip,(abfd),
120 bfd *abfd)
4a81b561
DHW
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
700b2ee3 127static boolean
9872a49c
SC
128DEFUN(bfd_cache_delete,(abfd),
129 bfd *abfd)
4a81b561 130{
700b2ee3
ILT
131 boolean ret;
132
09141f8d 133 if (fclose ((FILE *)(abfd->iostream)) == 0)
700b2ee3 134 ret = true;
09141f8d
ILT
135 else
136 {
137 ret = false;
138 bfd_error = system_call_error;
139 }
4a81b561
DHW
140 snip (abfd);
141 abfd->iostream = NULL;
142 open_files--;
9872a49c 143 bfd_last_cache = 0;
700b2ee3 144 return ret;
4a81b561
DHW
145}
146
147static bfd *
9872a49c
SC
148DEFUN(insert,(x,y),
149 bfd *x AND
150 bfd *y)
4a81b561
DHW
151{
152 if (y) {
153 x->lru_next = y;
154 x->lru_prev = y->lru_prev;
155 y->lru_prev->lru_next = x;
156 y->lru_prev = x;
157
158 }
159 else {
160 x->lru_prev = x;
161 x->lru_next = x;
162 }
163 return x;
164}
165\f
166
c188b0be 167/* Initialize a BFD by putting it on the cache LRU. */
6724ff46 168
4a81b561 169void
9872a49c
SC
170DEFUN(bfd_cache_init,(abfd),
171 bfd *abfd)
4a81b561 172{
c188b0be
DM
173 if (open_files >= BFD_CACHE_MAX_OPEN)
174 close_one ();
4a81b561 175 cache_sentinel = insert(abfd, cache_sentinel);
c188b0be 176 ++open_files;
4a81b561
DHW
177}
178
6724ff46 179
b645b632
SC
180/*
181INTERNAL_FUNCTION
182 bfd_cache_close
183
c188b0be
DM
184SYNOPSIS
185 boolean bfd_cache_close (bfd *abfd);
186
b645b632 187DESCRIPTION
c188b0be 188 Remove the BFD @var{abfd} from the cache. If the attached file is open,
b645b632
SC
189 then close it too.
190
700b2ee3
ILT
191RETURNS
192 <<false>> is returned if closing the file fails, <<true>> is
193 returned if all is well.
b645b632 194*/
700b2ee3 195boolean
9872a49c
SC
196DEFUN(bfd_cache_close,(abfd),
197 bfd *abfd)
4a81b561
DHW
198{
199 /* If this file is open then remove from the chain */
200 if (abfd->iostream)
201 {
700b2ee3
ILT
202 return bfd_cache_delete(abfd);
203 }
204 else
205 {
206 return true;
4a81b561
DHW
207 }
208}
4a81b561 209
b645b632
SC
210/*
211INTERNAL_FUNCTION
212 bfd_open_file
213
c188b0be
DM
214SYNOPSIS
215 FILE* bfd_open_file(bfd *abfd);
216
b645b632 217DESCRIPTION
c188b0be
DM
218 Call the OS to open a file for @var{abfd}. Return the <<FILE *>>
219 (possibly NULL) that results from this operation. Set up the
220 BFD so that future accesses know the file is open. If the <<FILE *>>
221 returned is NULL, then it won't have been put in the
b645b632 222 cache, so it won't have to be removed from it.
b645b632
SC
223*/
224
4a81b561 225FILE *
9872a49c
SC
226DEFUN(bfd_open_file, (abfd),
227 bfd *abfd)
4a81b561 228{
6724ff46 229 abfd->cacheable = true; /* Allow it to be closed later. */
8b046402 230
6724ff46
RP
231 if(open_files >= BFD_CACHE_MAX_OPEN) {
232 close_one();
233 }
8b046402 234
6724ff46
RP
235 switch (abfd->direction) {
236 case read_direction:
237 case no_direction:
8b046402 238 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
6724ff46
RP
239 break;
240 case both_direction:
241 case write_direction:
242 if (abfd->opened_once == true) {
8b046402 243 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
6724ff46 244 if (!abfd->iostream) {
8b046402 245 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
6724ff46
RP
246 }
247 } else {
248 /*open for creat */
8b046402 249 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
6724ff46 250 abfd->opened_once = true;
4a81b561 251 }
6724ff46
RP
252 break;
253 }
8b046402 254
6724ff46 255 if (abfd->iostream) {
6724ff46
RP
256 bfd_cache_init (abfd);
257 }
4a81b561 258
6724ff46 259 return (FILE *)(abfd->iostream);
4a81b561
DHW
260}
261
b645b632
SC
262/*
263INTERNAL_FUNCTION
264 bfd_cache_lookup_worker
265
c188b0be
DM
266SYNOPSIS
267 FILE *bfd_cache_lookup_worker(bfd *abfd);
268
b645b632
SC
269DESCRIPTION
270 Called when the macro <<bfd_cache_lookup>> fails to find a
c188b0be
DM
271 quick answer. Find a file descriptor for @var{abfd}. If
272 necessary, it open it. If there are already more than
273 <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
b645b632 274 avoid running out of file descriptors.
6724ff46 275
b645b632 276*/
4a81b561
DHW
277
278FILE *
9872a49c
SC
279DEFUN(bfd_cache_lookup_worker,(abfd),
280 bfd *abfd)
4a81b561
DHW
281{
282 if (abfd->my_archive)
9872a49c
SC
283 {
284 abfd = abfd->my_archive;
285 }
4a81b561
DHW
286 /* Is this file already open .. if so then quick exit */
287 if (abfd->iostream)
9872a49c
SC
288 {
289 if (abfd != cache_sentinel) {
290 /* Place onto head of lru chain */
291 snip (abfd);
292 cache_sentinel = insert(abfd, cache_sentinel);
293 }
4a81b561 294 }
6724ff46 295 /* This is a BFD without a stream -
4a81b561
DHW
296 so it must have been closed or never opened.
297 find an empty cache entry and use it. */
298 else
9872a49c 299 {
4a81b561 300
9872a49c
SC
301 if (open_files >= BFD_CACHE_MAX_OPEN)
302 {
303 close_one();
304 }
4a81b561 305
9872a49c
SC
306 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
307 fseek((FILE *)(abfd->iostream), abfd->where, false);
308 }
309 bfd_last_cache = abfd;
4a81b561
DHW
310 return (FILE *)(abfd->iostream);
311}
This page took 0.100641 seconds and 4 git commands to generate.