Output hex with local_hex_string for Modula-2 support.
[deliverable/binutils-gdb.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 (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
21/*doc*
22@section File Caching
23The file caching mechanism is embedded within BFD and allows the application to open as many
24BFDs as it wants without regard to the underlying operating system's
25file descriptor limit (often as low as 20 open files).
26
27The module in @code{cache.c} maintains a least recently used list of
28@code{BFD_CACHE_MAX_OPEN} files, and exports the name
29@code{bfd_cache_lookup} which runs around and makes sure that the
30required BFD is open. If not, then it chooses a file to close, closes
31it and opens the one wanted, returning its file handle.
32
33*/
34
35
4a81b561
DHW
36
37/* $Id$ */
6724ff46 38#include <sysdep.h>
4a81b561
DHW
39#include "bfd.h"
40#include "libbfd.h"
41
6724ff46
RP
42
43/*proto-internal* BFD_CACHE_MAX_OPEN
44The maxiumum number of files which the cache will keep open at one
45time.
46*+
4a81b561 47#define BFD_CACHE_MAX_OPEN 10
6724ff46
RP
48*-
49
50*/
51
4a81b561 52
4a81b561
DHW
53static int open_files;
54
6724ff46 55static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
4a81b561 56 opened */
4a81b561 57
6724ff46
RP
58/*proto-internal* bfd_last_cache
59Zero, or a pointer to the topmost BFD on the chain. This is used by
60the @code{bfd_cache_lookup} macro in @file{libbfd.h} to determine when
61it can avoid a function call.
62*+
63extern bfd *bfd_last_cache;
64*-
65
66*/
67
68bfd *bfd_last_cache;
69
70/*proto-internal* bfd_cache_lookup
71Checks to see if the required BFD is the same as the last one looked
72up. If so then it can use the iostream in the BFD with impunity, since
73it can't have changed since the last lookup, otherwise it has to
74perform the complicated lookup function
75*+
76#define bfd_cache_lookup(x) \
77 ((x)==bfd_last_cache? \
78 (FILE*)(bfd_last_cache->iostream): \
79 bfd_cache_lookup_worker(x))
80
81*-
82
83*/
fc723380
JG
84
85static void bfd_cache_delete();
6724ff46 86
4a81b561
DHW
87
88static void
9872a49c 89DEFUN_VOID(close_one)
4a81b561
DHW
90{
91 bfd *kill = cache_sentinel;
92 if (kill == 0) /* Nothing in the cache */
93 return ;
94
95 /* We can only close files that want to play this game. */
96 while (!kill->cacheable) {
97 kill = kill->lru_prev;
98 if (kill == cache_sentinel) /* Nobody wants to play */
99 return ;
100 }
101
102 kill->where = ftell((FILE *)(kill->iostream));
103 bfd_cache_delete(kill);
4a81b561 104}
fc723380 105
6724ff46 106/* Cuts the BFD abfd out of the chain in the cache */
4a81b561 107static void
9872a49c
SC
108DEFUN(snip,(abfd),
109 bfd *abfd)
4a81b561
DHW
110{
111 abfd->lru_prev->lru_next = abfd->lru_next;
112 abfd->lru_next->lru_prev = abfd->lru_prev;
113 if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
114}
115
116static void
9872a49c
SC
117DEFUN(bfd_cache_delete,(abfd),
118 bfd *abfd)
4a81b561
DHW
119{
120 fclose ((FILE *)(abfd->iostream));
121 snip (abfd);
122 abfd->iostream = NULL;
123 open_files--;
9872a49c 124 bfd_last_cache = 0;
4a81b561
DHW
125}
126
127static bfd *
9872a49c
SC
128DEFUN(insert,(x,y),
129 bfd *x AND
130 bfd *y)
4a81b561
DHW
131{
132 if (y) {
133 x->lru_next = y;
134 x->lru_prev = y->lru_prev;
135 y->lru_prev->lru_next = x;
136 y->lru_prev = x;
137
138 }
139 else {
140 x->lru_prev = x;
141 x->lru_next = x;
142 }
143 return x;
144}
145\f
146
6724ff46
RP
147/*proto-internal*
148*i bfd_cache_init
149Initialize a BFD by putting it on the cache LRU.
150*; PROTO(void, bfd_cache_init, (bfd *));
151*-*/
152
4a81b561 153void
9872a49c
SC
154DEFUN(bfd_cache_init,(abfd),
155 bfd *abfd)
4a81b561
DHW
156{
157 cache_sentinel = insert(abfd, cache_sentinel);
158}
159
6724ff46
RP
160
161/*proto-internal*
162*i bfd_cache_close
163Remove the BFD from the cache. If the attatched file is open, then close it too.
164*; PROTO(void, bfd_cache_close, (bfd *));
165*-*/
4a81b561 166void
9872a49c
SC
167DEFUN(bfd_cache_close,(abfd),
168 bfd *abfd)
4a81b561
DHW
169{
170 /* If this file is open then remove from the chain */
171 if (abfd->iostream)
172 {
173 bfd_cache_delete(abfd);
174 }
175}
4a81b561 176
6724ff46
RP
177/*proto-internal*
178*i bfd_open_file
179Call the OS to open a file for this BFD. Returns the FILE *
180(possibly null) that results from this operation. Sets up the
181BFD so that future accesses know the file is open. If the FILE *
182returned is null, then there is won't have been put in the cache, so
183it won't have to be removed from it.
184*; PROTO(FILE *, bfd_open_file, (bfd *));
185*-*/
4a81b561 186FILE *
9872a49c
SC
187DEFUN(bfd_open_file, (abfd),
188 bfd *abfd)
4a81b561 189{
6724ff46
RP
190 abfd->cacheable = true; /* Allow it to be closed later. */
191 if(open_files >= BFD_CACHE_MAX_OPEN) {
192 close_one();
193 }
194 switch (abfd->direction) {
195 case read_direction:
196 case no_direction:
197 abfd->iostream = (char *) fopen(abfd->filename, "r");
198 break;
199 case both_direction:
200 case write_direction:
201 if (abfd->opened_once == true) {
202 abfd->iostream = (char *) fopen(abfd->filename, "r+");
203 if (!abfd->iostream) {
204 abfd->iostream = (char *) fopen(abfd->filename, "w+");
205 }
206 } else {
207 /*open for creat */
208 abfd->iostream = (char *) fopen(abfd->filename, "w");
209 abfd->opened_once = true;
4a81b561 210 }
6724ff46
RP
211 break;
212 }
213 if (abfd->iostream) {
214 open_files++;
215 bfd_cache_init (abfd);
216 }
4a81b561 217
6724ff46 218 return (FILE *)(abfd->iostream);
4a81b561
DHW
219}
220
6724ff46
RP
221/*proto-internal*
222*i bfd_cache_lookup_worker
223Called when the macro @code{bfd_cache_lookup} fails to find a quick
224answer. Finds a file descriptor for this BFD. If necessary, it open it.
225If there are already more than BFD_CACHE_MAX_OPEN files open, it trys to close
226one first, to avoid running out of file descriptors.
227*; PROTO(FILE *, bfd_cache_lookup_worker, (bfd *));
228
229*-*/
4a81b561
DHW
230
231FILE *
9872a49c
SC
232DEFUN(bfd_cache_lookup_worker,(abfd),
233 bfd *abfd)
4a81b561
DHW
234{
235 if (abfd->my_archive)
9872a49c
SC
236 {
237 abfd = abfd->my_archive;
238 }
4a81b561
DHW
239 /* Is this file already open .. if so then quick exit */
240 if (abfd->iostream)
9872a49c
SC
241 {
242 if (abfd != cache_sentinel) {
243 /* Place onto head of lru chain */
244 snip (abfd);
245 cache_sentinel = insert(abfd, cache_sentinel);
246 }
4a81b561 247 }
6724ff46 248 /* This is a BFD without a stream -
4a81b561
DHW
249 so it must have been closed or never opened.
250 find an empty cache entry and use it. */
251 else
9872a49c 252 {
4a81b561 253
9872a49c
SC
254 if (open_files >= BFD_CACHE_MAX_OPEN)
255 {
256 close_one();
257 }
4a81b561 258
9872a49c
SC
259 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
260 fseek((FILE *)(abfd->iostream), abfd->where, false);
261 }
262 bfd_last_cache = abfd;
4a81b561
DHW
263 return (FILE *)(abfd->iostream);
264}
This page took 0.041381 seconds and 4 git commands to generate.