diff options
author | dyson <dyson@FreeBSD.org> | 1996-03-03 21:11:08 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1996-03-03 21:11:08 +0000 |
commit | 1b4bcc8dfdb83ce62d2fe7487294e3e0063b9bf5 (patch) | |
tree | b22ebb5b3acd848b2cf53168a691ce53a95f41a1 /sys/kern/subr_rlist.c | |
parent | cda4a6ceba724cde233d6ee3ab68f77e1e22ad10 (diff) | |
download | FreeBSD-src-1b4bcc8dfdb83ce62d2fe7487294e3e0063b9bf5.zip FreeBSD-src-1b4bcc8dfdb83ce62d2fe7487294e3e0063b9bf5.tar.gz |
In order to fix some concurrency problems with the swap pager early
on in the FreeBSD development, I had made a global lock around the
rlist code. This was bogus, and now the lock is maintained on a
per resource list basis. This now allows the rlist code to be used for
almost any non-interrupt level application.
Diffstat (limited to 'sys/kern/subr_rlist.c')
-rw-r--r-- | sys/kern/subr_rlist.c | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/sys/kern/subr_rlist.c b/sys/kern/subr_rlist.c index 19f0b8d..df4fc7d 100644 --- a/sys/kern/subr_rlist.c +++ b/sys/kern/subr_rlist.c @@ -54,7 +54,7 @@ * functioning of this software, nor does the author assume any responsibility * for damages incurred with its use. * - * $Id: subr_rlist.c,v 1.15 1995/12/14 08:31:45 phk Exp $ + * $Id: subr_rlist.c,v 1.16 1996/03/02 22:57:45 dyson Exp $ */ #include <sys/param.h> @@ -72,9 +72,8 @@ */ #define RLIST_MIN 128 -static int rlist_count=0, rlist_desired=0; +static int rlist_count=0; static struct rlist *rlfree; -static int rlist_active; static struct rlist *rlist_malloc __P((void)); @@ -115,19 +114,20 @@ rlist_mfree( struct rlist *rl) } void -rlist_free(rlp, start, end) - struct rlist **rlp; +rlist_free(rlh, start, end) + struct rlisthdr *rlh; u_int start, end; { + struct rlist **rlp = &rlh->rlh_list; struct rlist *prev_rlp = NULL, *cur_rlp = *rlp, *next_rlp = NULL; int s; s = splhigh(); - while (rlist_active) { - rlist_desired = 1; - tsleep((caddr_t)&rlist_active, PSWP, "rlistf", 0); + while (rlh->rlh_lock & RLH_LOCKED) { + rlh->rlh_lock |= RLH_DESIRED; + tsleep(rlh, PSWP, "rlistf", 0); } - rlist_active = 1; + rlh->rlh_lock |= RLH_LOCKED; splx(s); /* @@ -217,10 +217,10 @@ rlist_free(rlp, start, end) } done: - rlist_active = 0; - if (rlist_desired) { - wakeup((caddr_t)&rlist_active); - rlist_desired = 0; + rlh->rlh_lock &= ~RLH_LOCKED; + if (rlh->rlh_lock & RLH_DESIRED) { + wakeup(rlh); + rlh->rlh_lock &= ~RLH_DESIRED; } return; } @@ -232,20 +232,21 @@ done: * "*loc". (Note: loc can be zero if we don't wish the value) */ int -rlist_alloc (rlp, size, loc) - struct rlist **rlp; +rlist_alloc (rlh, size, loc) + struct rlisthdr *rlh; unsigned size, *loc; { + struct rlist **rlp = &rlh->rlh_list; register struct rlist *lp; int s; register struct rlist *olp = 0; s = splhigh(); - while( rlist_active) { - rlist_desired = 1; - tsleep((caddr_t)&rlist_active, PSWP, "rlista", 0); + while (rlh->rlh_lock & RLH_LOCKED) { + rlh->rlh_lock |= RLH_DESIRED; + tsleep(rlh, PSWP, "rlistf", 0); } - rlist_active = 1; + rlh->rlh_lock |= RLH_LOCKED; splx(s); /* walk list, allocating first thing that's big enough (first fit) */ @@ -271,20 +272,20 @@ rlist_alloc (rlp, size, loc) } } - rlist_active = 0; - if( rlist_desired) { - rlist_desired = 0; - wakeup((caddr_t)&rlist_active); + rlh->rlh_lock &= ~RLH_LOCKED; + if (rlh->rlh_lock & RLH_DESIRED) { + wakeup(rlh); + rlh->rlh_lock &= ~RLH_DESIRED; } return (1); } else { olp = *rlp; } - rlist_active = 0; - if( rlist_desired) { - rlist_desired = 0; - wakeup((caddr_t)&rlist_active); + rlh->rlh_lock &= ~RLH_LOCKED; + if (rlh->rlh_lock & RLH_DESIRED) { + wakeup(rlh); + rlh->rlh_lock &= ~RLH_DESIRED; } /* nothing in list that's big enough */ return (0); @@ -295,9 +296,10 @@ rlist_alloc (rlp, size, loc) * mark it as being empty. */ void -rlist_destroy (rlp) - struct rlist **rlp; +rlist_destroy (rlh) + struct rlisthdr *rlh; { + struct rlist **rlp = &rlh->rlh_list; struct rlist *lp, *nlp; lp = *rlp; |