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