diff options
Diffstat (limited to 'bfd/cache.c')
-rw-r--r-- | bfd/cache.c | 180 |
1 files changed, 123 insertions, 57 deletions
diff --git a/bfd/cache.c b/bfd/cache.c index c3418ea..be85f2b 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -1,45 +1,89 @@ -/*** cache.c -- Allows you to have more bfds open than your system has fds. */ +/* BFD library -- caching of file descriptors. + Copyright (C) 1990-1991 Free Software Foundation, Inc. + Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com). -/* Copyright (C) 1990, 1991 Free Software Foundation, Inc. +This file is part of BFD, the Binary File Descriptor library. -This file is part of BFD, the Binary File Diddler. - -BFD is free software; you can redistribute it and/or modify +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. -BFD is distributed in the hope that it will be useful, +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with BFD; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/*doc* +@section File Caching +The file caching mechanism is embedded within BFD and allows the application to open as many +BFDs as it wants without regard to the underlying operating system's +file descriptor limit (often as low as 20 open files). + +The module in @code{cache.c} maintains a least recently used list of +@code{BFD_CACHE_MAX_OPEN} files, and exports the name +@code{bfd_cache_lookup} which runs around and makes sure that the +required BFD is open. If not, then it chooses a file to close, closes +it and opens the one wanted, returning its file handle. + +*/ + + /* $Id$ */ -#include "sysdep.h" +#include <sysdep.h> #include "bfd.h" #include "libbfd.h" -/* The maximum number of FDs opened by bfd */ + +/*proto-internal* BFD_CACHE_MAX_OPEN +The maxiumum number of files which the cache will keep open at one +time. +*+ #define BFD_CACHE_MAX_OPEN 10 +*- + +*/ + -/* when this exceeds BFD_CACHE_MAX_OPEN, we get to work */ static int open_files; -static bfd *cache_sentinel; /* Chain of bfds with active fds we've +static bfd *cache_sentinel; /* Chain of BFDs with active fds we've opened */ -bfd *bfd_last_cache; /* Zero, or a pointer to the topmost - bfd on the chain. This is used by the - bfd_cache_lookup() macro in libbfd.h - to determine when it can avoid a function - call. */ +/*proto-internal* bfd_last_cache +Zero, or a pointer to the topmost BFD on the chain. This is used by +the @code{bfd_cache_lookup} macro in @file{libbfd.h} to determine when +it can avoid a function call. +*+ +extern bfd *bfd_last_cache; +*- + +*/ + +bfd *bfd_last_cache; + +/*proto-internal* bfd_cache_lookup +Checks to see if the required BFD is the same as the last one looked +up. If so then it can use the iostream in the BFD with impunity, since +it can't have changed since the last lookup, otherwise it has to +perform the complicated lookup function +*+ +#define bfd_cache_lookup(x) \ + ((x)==bfd_last_cache? \ + (FILE*)(bfd_last_cache->iostream): \ + bfd_cache_lookup_worker(x)) + +*- + +*/ static void bfd_cache_delete(); - + static void DEFUN_VOID(close_one) @@ -59,7 +103,7 @@ DEFUN_VOID(close_one) bfd_cache_delete(kill); } -/* Cuts the bfd abfd out of the chain in the cache */ +/* Cuts the BFD abfd out of the chain in the cache */ static void DEFUN(snip,(abfd), bfd *abfd) @@ -100,7 +144,12 @@ DEFUN(insert,(x,y), } -/* Initialize a BFD by putting it on the cache LRU. */ +/*proto-internal* +*i bfd_cache_init +Initialize a BFD by putting it on the cache LRU. +*; PROTO(void, bfd_cache_init, (bfd *)); +*-*/ + void DEFUN(bfd_cache_init,(abfd), bfd *abfd) @@ -108,6 +157,12 @@ DEFUN(bfd_cache_init,(abfd), cache_sentinel = insert(abfd, cache_sentinel); } + +/*proto-internal* +*i bfd_cache_close +Remove the BFD from the cache. If the attatched file is open, then close it too. +*; PROTO(void, bfd_cache_close, (bfd *)); +*-*/ void DEFUN(bfd_cache_close,(abfd), bfd *abfd) @@ -118,49 +173,60 @@ DEFUN(bfd_cache_close,(abfd), bfd_cache_delete(abfd); } } - -/* Call the OS to open a file for this BFD. Returns the FILE * - (possibly null) that results from this operation. Sets up the - BFD so that future accesses know the file is open. */ +/*proto-internal* +*i bfd_open_file +Call the OS to open a file for this BFD. Returns the FILE * +(possibly null) that results from this operation. Sets up the +BFD so that future accesses know the file is open. If the FILE * +returned is null, then there is won't have been put in the cache, so +it won't have to be removed from it. +*; PROTO(FILE *, bfd_open_file, (bfd *)); +*-*/ FILE * DEFUN(bfd_open_file, (abfd), bfd *abfd) { - abfd->cacheable = true; /* Allow it to be closed later. */ - if(open_files >= BFD_CACHE_MAX_OPEN) { - close_one(); - } - switch (abfd->direction) { - case read_direction: - case no_direction: - abfd->iostream = (char *) fopen(abfd->filename, "r"); - break; - case both_direction: - case write_direction: - if (abfd->opened_once == true) { - abfd->iostream = (char *) fopen(abfd->filename, "r+"); - if (!abfd->iostream) { - abfd->iostream = (char *) fopen(abfd->filename, "w+"); - } - } else { - /*open for creat */ - abfd->iostream = (char *) fopen(abfd->filename, "w"); - abfd->opened_once = true; - } - break; - } - if (abfd->iostream) { - open_files++; - bfd_cache_init (abfd); + abfd->cacheable = true; /* Allow it to be closed later. */ + if(open_files >= BFD_CACHE_MAX_OPEN) { + close_one(); + } + switch (abfd->direction) { + case read_direction: + case no_direction: + abfd->iostream = (char *) fopen(abfd->filename, "r"); + break; + case both_direction: + case write_direction: + if (abfd->opened_once == true) { + abfd->iostream = (char *) fopen(abfd->filename, "r+"); + if (!abfd->iostream) { + abfd->iostream = (char *) fopen(abfd->filename, "w+"); + } + } else { + /*open for creat */ + abfd->iostream = (char *) fopen(abfd->filename, "w"); + abfd->opened_once = true; } + break; + } + if (abfd->iostream) { + open_files++; + bfd_cache_init (abfd); + } - return (FILE *)(abfd->iostream); + return (FILE *)(abfd->iostream); } -/* Find a file descriptor for this BFD. If necessary, open it. - If there are already more than BFD_CACHE_MAX_OPEN files open, try to close - one first, to avoid running out of file descriptors. */ +/*proto-internal* +*i bfd_cache_lookup_worker +Called when the macro @code{bfd_cache_lookup} fails to find a quick +answer. Finds a file descriptor for this BFD. If necessary, it open it. +If there are already more than BFD_CACHE_MAX_OPEN files open, it trys to close +one first, to avoid running out of file descriptors. +*; PROTO(FILE *, bfd_cache_lookup_worker, (bfd *)); + +*-*/ FILE * DEFUN(bfd_cache_lookup_worker,(abfd), @@ -179,7 +245,7 @@ DEFUN(bfd_cache_lookup_worker,(abfd), cache_sentinel = insert(abfd, cache_sentinel); } } - /* This is a bfd without a stream - + /* This is a BFD without a stream - so it must have been closed or never opened. find an empty cache entry and use it. */ else |