* libbfd.h, libbfd-in.h (bfd_seek): Make prototype match definition.
[deliverable/binutils-gdb.git] / bfd / cache.c
CommitLineData
8b046402 1
6724ff46
RP
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).
4a81b561 5
6724ff46 6This file is part of BFD, the Binary File Descriptor library.
4a81b561 7
6724ff46 8This program is free software; you can redistribute it and/or modify
4a81b561 9it under the terms of the GNU General Public License as published by
6724ff46
RP
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
4a81b561 12
6724ff46 13This program is distributed in the hope that it will be useful,
4a81b561
DHW
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
6724ff46
RP
19along with this program; if not, write to the Free Software
20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
b645b632
SC
22/*
23SECTION
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.
6724ff46
RP
36
37*/
38
4a81b561 39/* $Id$ */
b645b632 40
4a81b561 41#include "bfd.h"
b645b632 42#include "sysdep.h"
4a81b561
DHW
43#include "libbfd.h"
44
b645b632
SC
45/*
46INTERNAL_FUNCTION
47 BFD_CACHE_MAX_OPEN macro
6724ff46 48
b645b632
SC
49DESCRIPTION
50 The maxiumum number of files which the cache will keep open at
51 one time.
52
53.#define BFD_CACHE_MAX_OPEN 10
6724ff46
RP
54
55*/
56
4a81b561 57
4a81b561
DHW
58static int open_files;
59
6724ff46 60static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
4a81b561 61 opened */
4a81b561 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
SC
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 */
fc723380
JG
95
96static void bfd_cache_delete();
6724ff46 97
4a81b561
DHW
98
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));
114 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
127static void
9872a49c
SC
128DEFUN(bfd_cache_delete,(abfd),
129 bfd *abfd)
4a81b561
DHW
130{
131 fclose ((FILE *)(abfd->iostream));
132 snip (abfd);
133 abfd->iostream = NULL;
134 open_files--;
9872a49c 135 bfd_last_cache = 0;
4a81b561
DHW
136}
137
138static bfd *
9872a49c
SC
139DEFUN(insert,(x,y),
140 bfd *x AND
141 bfd *y)
4a81b561
DHW
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
b645b632
SC
158/*
159INTERNAL_FUNCTION
160 bfd_cache_init
161
162SYNOPSIS
163 void bfd_cache_init (bfd *);
164
165DESCRIPTION
166 Initialize a BFD by putting it on the cache LRU.
167*/
6724ff46 168
4a81b561 169void
9872a49c
SC
170DEFUN(bfd_cache_init,(abfd),
171 bfd *abfd)
4a81b561
DHW
172{
173 cache_sentinel = insert(abfd, cache_sentinel);
174}
175
6724ff46 176
b645b632
SC
177/*
178INTERNAL_FUNCTION
179 bfd_cache_close
180
181DESCRIPTION
182 Remove the BFD from the cache. If the attached file is open,
183 then close it too.
184
185SYNOPSIS
186 void bfd_cache_close (bfd *);
187*/
4a81b561 188void
9872a49c
SC
189DEFUN(bfd_cache_close,(abfd),
190 bfd *abfd)
4a81b561
DHW
191{
192 /* If this file is open then remove from the chain */
193 if (abfd->iostream)
194 {
195 bfd_cache_delete(abfd);
196 }
197}
4a81b561 198
b645b632
SC
199/*
200INTERNAL_FUNCTION
201 bfd_open_file
202
203DESCRIPTION
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
210SYNOPSIS
211 FILE* bfd_open_file(bfd *);
212*/
213
4a81b561 214FILE *
9872a49c
SC
215DEFUN(bfd_open_file, (abfd),
216 bfd *abfd)
4a81b561 217{
6724ff46 218 abfd->cacheable = true; /* Allow it to be closed later. */
8b046402 219
6724ff46
RP
220 if(open_files >= BFD_CACHE_MAX_OPEN) {
221 close_one();
222 }
8b046402 223
6724ff46
RP
224 switch (abfd->direction) {
225 case read_direction:
226 case no_direction:
8b046402 227 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
6724ff46
RP
228 break;
229 case both_direction:
230 case write_direction:
231 if (abfd->opened_once == true) {
8b046402 232 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
6724ff46 233 if (!abfd->iostream) {
8b046402 234 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
6724ff46
RP
235 }
236 } else {
237 /*open for creat */
8b046402 238 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
6724ff46 239 abfd->opened_once = true;
4a81b561 240 }
6724ff46
RP
241 break;
242 }
8b046402 243
6724ff46
RP
244 if (abfd->iostream) {
245 open_files++;
246 bfd_cache_init (abfd);
247 }
4a81b561 248
6724ff46 249 return (FILE *)(abfd->iostream);
4a81b561
DHW
250}
251
b645b632
SC
252/*
253INTERNAL_FUNCTION
254 bfd_cache_lookup_worker
255
256DESCRIPTION
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.
6724ff46 262
b645b632
SC
263SYNOPSIS
264 FILE *bfd_cache_lookup_worker(bfd *);
265
266*/
4a81b561
DHW
267
268FILE *
9872a49c
SC
269DEFUN(bfd_cache_lookup_worker,(abfd),
270 bfd *abfd)
4a81b561
DHW
271{
272 if (abfd->my_archive)
9872a49c
SC
273 {
274 abfd = abfd->my_archive;
275 }
4a81b561
DHW
276 /* Is this file already open .. if so then quick exit */
277 if (abfd->iostream)
9872a49c
SC
278 {
279 if (abfd != cache_sentinel) {
280 /* Place onto head of lru chain */
281 snip (abfd);
282 cache_sentinel = insert(abfd, cache_sentinel);
283 }
4a81b561 284 }
6724ff46 285 /* This is a BFD without a stream -
4a81b561
DHW
286 so it must have been closed or never opened.
287 find an empty cache entry and use it. */
288 else
9872a49c 289 {
4a81b561 290
9872a49c
SC
291 if (open_files >= BFD_CACHE_MAX_OPEN)
292 {
293 close_one();
294 }
4a81b561 295
9872a49c
SC
296 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
297 fseek((FILE *)(abfd->iostream), abfd->where, false);
298 }
299 bfd_last_cache = abfd;
4a81b561
DHW
300 return (FILE *)(abfd->iostream);
301}
This page took 0.086243 seconds and 4 git commands to generate.