OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [cache.c] - Blame information for rev 1770

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* BFD library -- caching of file descriptors.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001
3
   Free Software Foundation, Inc.
4
   Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
5
 
6
This file is part of BFD, the Binary File Descriptor library.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
 
22
/*
23
SECTION
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.
36
 
37
*/
38
 
39
#include "bfd.h"
40
#include "sysdep.h"
41
#include "libbfd.h"
42
 
43
static void insert PARAMS ((bfd *));
44
static void snip PARAMS ((bfd *));
45
static boolean close_one PARAMS ((void));
46
static boolean bfd_cache_delete PARAMS ((bfd *));
47
 
48
/*
49
INTERNAL_FUNCTION
50
        BFD_CACHE_MAX_OPEN macro
51
 
52
DESCRIPTION
53
        The maximum number of files which the cache will keep open at
54
        one time.
55
 
56
.#define BFD_CACHE_MAX_OPEN 10
57
 
58
*/
59
 
60
/* The number of BFD files we have open.  */
61
 
62
static int open_files;
63
 
64
/*
65
INTERNAL_FUNCTION
66
        bfd_last_cache
67
 
68
SYNOPSIS
69
        extern bfd *bfd_last_cache;
70
 
71
DESCRIPTION
72
        Zero, or a pointer to the topmost BFD on the chain.  This is
73
        used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
74
        determine when it can avoid a function call.
75
*/
76
 
77
bfd *bfd_last_cache;
78
 
79
/*
80
  INTERNAL_FUNCTION
81
        bfd_cache_lookup
82
 
83
  DESCRIPTION
84
        Check to see if the required BFD is the same as the last one
85
        looked up. If so, then it can use the stream in the BFD with
86
        impunity, since it can't have changed since the last lookup;
87
        otherwise, it has to perform the complicated lookup function.
88
 
89
  .#define bfd_cache_lookup(x) \
90
  .    ((x)==bfd_last_cache? \
91
  .      (FILE*) (bfd_last_cache->iostream): \
92
  .       bfd_cache_lookup_worker(x))
93
 
94
 */
95
 
96
/* Insert a BFD into the cache.  */
97
 
98
static INLINE void
99
insert (abfd)
100
     bfd *abfd;
101
{
102
  if (bfd_last_cache == NULL)
103
    {
104
      abfd->lru_next = abfd;
105
      abfd->lru_prev = abfd;
106
    }
107
  else
108
    {
109
      abfd->lru_next = bfd_last_cache;
110
      abfd->lru_prev = bfd_last_cache->lru_prev;
111
      abfd->lru_prev->lru_next = abfd;
112
      abfd->lru_next->lru_prev = abfd;
113
    }
114
  bfd_last_cache = abfd;
115
}
116
 
117
/* Remove a BFD from the cache.  */
118
 
119
static INLINE void
120
snip (abfd)
121
     bfd *abfd;
122
{
123
  abfd->lru_prev->lru_next = abfd->lru_next;
124
  abfd->lru_next->lru_prev = abfd->lru_prev;
125
  if (abfd == bfd_last_cache)
126
    {
127
      bfd_last_cache = abfd->lru_next;
128
      if (abfd == bfd_last_cache)
129
        bfd_last_cache = NULL;
130
    }
131
}
132
 
133
/* We need to open a new file, and the cache is full.  Find the least
134
   recently used cacheable BFD and close it.  */
135
 
136
static boolean
137
close_one ()
138
{
139
  register bfd *kill;
140
 
141
  if (bfd_last_cache == NULL)
142
    kill = NULL;
143
  else
144
    {
145
      for (kill = bfd_last_cache->lru_prev;
146
           ! kill->cacheable;
147
           kill = kill->lru_prev)
148
        {
149
          if (kill == bfd_last_cache)
150
            {
151
              kill = NULL;
152
              break;
153
            }
154
        }
155
    }
156
 
157
  if (kill == NULL)
158
    {
159
      /* There are no open cacheable BFD's.  */
160
      return true;
161
    }
162
 
163
  kill->where = ftell ((FILE *) kill->iostream);
164
 
165
  return bfd_cache_delete (kill);
166
}
167
 
168
/* Close a BFD and remove it from the cache.  */
169
 
170
static boolean
171
bfd_cache_delete (abfd)
172
     bfd *abfd;
173
{
174
  boolean ret;
175
 
176
  if (fclose ((FILE *) abfd->iostream) == 0)
177
    ret = true;
178
  else
179
    {
180
      ret = false;
181
      bfd_set_error (bfd_error_system_call);
182
    }
183
 
184
  snip (abfd);
185
 
186
  abfd->iostream = NULL;
187
  --open_files;
188
 
189
  return ret;
190
}
191
 
192
/*
193
INTERNAL_FUNCTION
194
        bfd_cache_init
195
 
196
SYNOPSIS
197
        boolean bfd_cache_init (bfd *abfd);
198
 
199
DESCRIPTION
200
        Add a newly opened BFD to the cache.
201
*/
202
 
203
boolean
204
bfd_cache_init (abfd)
205
     bfd *abfd;
206
{
207
  BFD_ASSERT (abfd->iostream != NULL);
208
  if (open_files >= BFD_CACHE_MAX_OPEN)
209
    {
210
      if (! close_one ())
211
        return false;
212
    }
213
  insert (abfd);
214
  ++open_files;
215
  return true;
216
}
217
 
218
/*
219
INTERNAL_FUNCTION
220
        bfd_cache_close
221
 
222
SYNOPSIS
223
        boolean bfd_cache_close (bfd *abfd);
224
 
225
DESCRIPTION
226
        Remove the BFD @var{abfd} from the cache. If the attached file is open,
227
        then close it too.
228
 
229
RETURNS
230
        <<false>> is returned if closing the file fails, <<true>> is
231
        returned if all is well.
232
*/
233
 
234
boolean
235
bfd_cache_close (abfd)
236
     bfd *abfd;
237
{
238
  if (abfd->iostream == NULL
239
      || (abfd->flags & BFD_IN_MEMORY) != 0)
240
    return true;
241
 
242
  return bfd_cache_delete (abfd);
243
}
244
 
245
/*
246
INTERNAL_FUNCTION
247
        bfd_open_file
248
 
249
SYNOPSIS
250
        FILE* bfd_open_file(bfd *abfd);
251
 
252
DESCRIPTION
253
        Call the OS to open a file for @var{abfd}.  Return the <<FILE *>>
254
        (possibly <<NULL>>) that results from this operation.  Set up the
255
        BFD so that future accesses know the file is open. If the <<FILE *>>
256
        returned is <<NULL>>, then it won't have been put in the
257
        cache, so it won't have to be removed from it.
258
*/
259
 
260
FILE *
261
bfd_open_file (abfd)
262
     bfd *abfd;
263
{
264
  abfd->cacheable = true;       /* Allow it to be closed later.  */
265
 
266
  if (open_files >= BFD_CACHE_MAX_OPEN)
267
    {
268
      if (! close_one ())
269
        return NULL;
270
    }
271
 
272
  switch (abfd->direction)
273
    {
274
    case read_direction:
275
    case no_direction:
276
      abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
277
      break;
278
    case both_direction:
279
    case write_direction:
280
      if (abfd->opened_once == true)
281
        {
282
          abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
283
          if (abfd->iostream == NULL)
284
            abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
285
        }
286
      else
287
        {
288
          /* Create the file.
289
 
290
             Some operating systems won't let us overwrite a running
291
             binary.  For them, we want to unlink the file first.
292
 
293
             However, gcc 2.95 will create temporary files using
294
             O_EXCL and tight permissions to prevent other users from
295
             substituting other .o files during the compilation.  gcc
296
             will then tell the assembler to use the newly created
297
             file as an output file.  If we unlink the file here, we
298
             open a brief window when another user could still
299
             substitute a file.
300
 
301
             So we unlink the output file if and only if it has
302
             non-zero size.  */
303
#ifndef __MSDOS__
304
          /* Don't do this for MSDOS: it doesn't care about overwriting
305
             a running binary, but if this file is already open by
306
             another BFD, we will be in deep trouble if we delete an
307
             open file.  In fact, objdump does just that if invoked with
308
             the --info option.  */
309
          struct stat s;
310
 
311
          if (stat (abfd->filename, &s) == 0 && s.st_size != 0)
312
            unlink (abfd->filename);
313
#endif
314
          abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
315
          abfd->opened_once = true;
316
        }
317
      break;
318
    }
319
 
320
  if (abfd->iostream != NULL)
321
    {
322
      if (! bfd_cache_init (abfd))
323
        return NULL;
324
    }
325
 
326
  return (FILE *) abfd->iostream;
327
}
328
 
329
/*
330
INTERNAL_FUNCTION
331
        bfd_cache_lookup_worker
332
 
333
SYNOPSIS
334
        FILE *bfd_cache_lookup_worker(bfd *abfd);
335
 
336
DESCRIPTION
337
        Called when the macro <<bfd_cache_lookup>> fails to find a
338
        quick answer.  Find a file descriptor for @var{abfd}.  If
339
        necessary, it open it.  If there are already more than
340
        <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
341
        avoid running out of file descriptors.
342
*/
343
 
344
FILE *
345
bfd_cache_lookup_worker (abfd)
346
     bfd *abfd;
347
{
348
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
349
    abort ();
350
 
351
  if (abfd->my_archive)
352
    abfd = abfd->my_archive;
353
 
354
  if (abfd->iostream != NULL)
355
    {
356
      /* Move the file to the start of the cache.  */
357
      if (abfd != bfd_last_cache)
358
        {
359
          snip (abfd);
360
          insert (abfd);
361
        }
362
    }
363
  else
364
    {
365
      if (bfd_open_file (abfd) == NULL)
366
        return NULL;
367
      if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0)
368
        return NULL;
369
    }
370
 
371
  return (FILE *) abfd->iostream;
372
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.