aboutsummaryrefslogtreecommitdiff
path: root/bfd/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/cache.c')
-rw-r--r--bfd/cache.c180
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