]> Git Repo - binutils.git/blame - bfd/cache.c
New file: rs6000-core.c.
[binutils.git] / bfd / cache.c
CommitLineData
6724ff46
RP
1/* BFD library -- caching of file descriptors.
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Hacked by Steve Chamberlain of Cygnus Support ([email protected]).
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/* $Id$ */
b645b632 39
4a81b561 40#include "bfd.h"
b645b632 41#include "sysdep.h"
4a81b561
DHW
42#include "libbfd.h"
43
b645b632
SC
44/*
45INTERNAL_FUNCTION
46 BFD_CACHE_MAX_OPEN macro
6724ff46 47
b645b632
SC
48DESCRIPTION
49 The maxiumum number of files which the cache will keep open at
50 one time.
51
52.#define BFD_CACHE_MAX_OPEN 10
6724ff46
RP
53
54*/
55
4a81b561 56
4a81b561
DHW
57static int open_files;
58
6724ff46 59static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
4a81b561 60 opened */
4a81b561 61
b645b632
SC
62/*
63INTERNAL_FUNCTION
64 bfd_last_cache
65
66SYNOPSIS
67 extern bfd *bfd_last_cache;
6724ff46 68
b645b632
SC
69DESCRIPTION
70 Zero, or a pointer to the topmost BFD on the chain. This is
71 used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
72 determine when it can avoid a function call.
6724ff46
RP
73*/
74
75bfd *bfd_last_cache;
76
b645b632
SC
77/*
78 * INTERNAL_FUNCTION
79 * bfd_cache_lookup
80 *
81 * DESCRIPTION
82 * Checks to see if the required BFD is the same as the last one
83 * looked up. If so then it can use the iostream in the BFD with
84 * impunity, since it can't have changed since the last lookup,
85 * otherwise it has to perform the complicated lookup function
86 *
87 * .#define bfd_cache_lookup(x) \
88 * . ((x)==bfd_last_cache? \
89 * . (FILE*)(bfd_last_cache->iostream): \
90 * . bfd_cache_lookup_worker(x))
91 *
92 *
93 */
fc723380
JG
94
95static void bfd_cache_delete();
6724ff46 96
4a81b561
DHW
97
98static void
9872a49c 99DEFUN_VOID(close_one)
4a81b561
DHW
100{
101 bfd *kill = cache_sentinel;
102 if (kill == 0) /* Nothing in the cache */
103 return ;
104
105 /* We can only close files that want to play this game. */
106 while (!kill->cacheable) {
107 kill = kill->lru_prev;
108 if (kill == cache_sentinel) /* Nobody wants to play */
109 return ;
110 }
111
112 kill->where = ftell((FILE *)(kill->iostream));
113 bfd_cache_delete(kill);
4a81b561 114}
fc723380 115
6724ff46 116/* Cuts the BFD abfd out of the chain in the cache */
4a81b561 117static void
9872a49c
SC
118DEFUN(snip,(abfd),
119 bfd *abfd)
4a81b561
DHW
120{
121 abfd->lru_prev->lru_next = abfd->lru_next;
122 abfd->lru_next->lru_prev = abfd->lru_prev;
123 if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
124}
125
126static void
9872a49c
SC
127DEFUN(bfd_cache_delete,(abfd),
128 bfd *abfd)
4a81b561
DHW
129{
130 fclose ((FILE *)(abfd->iostream));
131 snip (abfd);
132 abfd->iostream = NULL;
133 open_files--;
9872a49c 134 bfd_last_cache = 0;
4a81b561
DHW
135}
136
137static bfd *
9872a49c
SC
138DEFUN(insert,(x,y),
139 bfd *x AND
140 bfd *y)
4a81b561
DHW
141{
142 if (y) {
143 x->lru_next = y;
144 x->lru_prev = y->lru_prev;
145 y->lru_prev->lru_next = x;
146 y->lru_prev = x;
147
148 }
149 else {
150 x->lru_prev = x;
151 x->lru_next = x;
152 }
153 return x;
154}
155\f
156
b645b632
SC
157/*
158INTERNAL_FUNCTION
159 bfd_cache_init
160
161SYNOPSIS
162 void bfd_cache_init (bfd *);
163
164DESCRIPTION
165 Initialize a BFD by putting it on the cache LRU.
166*/
6724ff46 167
4a81b561 168void
9872a49c
SC
169DEFUN(bfd_cache_init,(abfd),
170 bfd *abfd)
4a81b561
DHW
171{
172 cache_sentinel = insert(abfd, cache_sentinel);
173}
174
6724ff46 175
b645b632
SC
176/*
177INTERNAL_FUNCTION
178 bfd_cache_close
179
180DESCRIPTION
181 Remove the BFD from the cache. If the attached file is open,
182 then close it too.
183
184SYNOPSIS
185 void bfd_cache_close (bfd *);
186*/
4a81b561 187void
9872a49c
SC
188DEFUN(bfd_cache_close,(abfd),
189 bfd *abfd)
4a81b561
DHW
190{
191 /* If this file is open then remove from the chain */
192 if (abfd->iostream)
193 {
194 bfd_cache_delete(abfd);
195 }
196}
4a81b561 197
b645b632
SC
198/*
199INTERNAL_FUNCTION
200 bfd_open_file
201
202DESCRIPTION
203 Call the OS to open a file for this BFD. Returns the FILE *
204 (possibly null) that results from this operation. Sets up the
205 BFD so that future accesses know the file is open. If the FILE
206 * returned is null, then there is won't have been put in the
207 cache, so it won't have to be removed from it.
208
209SYNOPSIS
210 FILE* bfd_open_file(bfd *);
211*/
212
4a81b561 213FILE *
9872a49c
SC
214DEFUN(bfd_open_file, (abfd),
215 bfd *abfd)
4a81b561 216{
6724ff46
RP
217 abfd->cacheable = true; /* Allow it to be closed later. */
218 if(open_files >= BFD_CACHE_MAX_OPEN) {
219 close_one();
220 }
221 switch (abfd->direction) {
222 case read_direction:
223 case no_direction:
b645b632 224 abfd->iostream = (char *) fopen(abfd->filename, "rb");
6724ff46
RP
225 break;
226 case both_direction:
227 case write_direction:
228 if (abfd->opened_once == true) {
b645b632 229 abfd->iostream = (char *) fopen(abfd->filename, "r+b");
6724ff46 230 if (!abfd->iostream) {
b645b632 231 abfd->iostream = (char *) fopen(abfd->filename, "w+b");
6724ff46
RP
232 }
233 } else {
234 /*open for creat */
b645b632 235 abfd->iostream = (char *) fopen(abfd->filename, "wb");
6724ff46 236 abfd->opened_once = true;
4a81b561 237 }
6724ff46
RP
238 break;
239 }
240 if (abfd->iostream) {
241 open_files++;
242 bfd_cache_init (abfd);
243 }
4a81b561 244
6724ff46 245 return (FILE *)(abfd->iostream);
4a81b561
DHW
246}
247
b645b632
SC
248/*
249INTERNAL_FUNCTION
250 bfd_cache_lookup_worker
251
252DESCRIPTION
253 Called when the macro <<bfd_cache_lookup>> fails to find a
254 quick answer. Finds a file descriptor for this BFD. If
255 necessary, it open it. If there are already more than
256 BFD_CACHE_MAX_OPEN files open, it trys to close one first, to
257 avoid running out of file descriptors.
6724ff46 258
b645b632
SC
259SYNOPSIS
260 FILE *bfd_cache_lookup_worker(bfd *);
261
262*/
4a81b561
DHW
263
264FILE *
9872a49c
SC
265DEFUN(bfd_cache_lookup_worker,(abfd),
266 bfd *abfd)
4a81b561
DHW
267{
268 if (abfd->my_archive)
9872a49c
SC
269 {
270 abfd = abfd->my_archive;
271 }
4a81b561
DHW
272 /* Is this file already open .. if so then quick exit */
273 if (abfd->iostream)
9872a49c
SC
274 {
275 if (abfd != cache_sentinel) {
276 /* Place onto head of lru chain */
277 snip (abfd);
278 cache_sentinel = insert(abfd, cache_sentinel);
279 }
4a81b561 280 }
6724ff46 281 /* This is a BFD without a stream -
4a81b561
DHW
282 so it must have been closed or never opened.
283 find an empty cache entry and use it. */
284 else
9872a49c 285 {
4a81b561 286
9872a49c
SC
287 if (open_files >= BFD_CACHE_MAX_OPEN)
288 {
289 close_one();
290 }
4a81b561 291
9872a49c
SC
292 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
293 fseek((FILE *)(abfd->iostream), abfd->where, false);
294 }
295 bfd_last_cache = abfd;
4a81b561
DHW
296 return (FILE *)(abfd->iostream);
297}
This page took 0.145583 seconds and 4 git commands to generate.