Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/subr_pool.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/subr_pool.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.12 retrieving revision 1.16 diff -u -p -r1.12 -r1.16 --- src/sys/kern/subr_pool.c 1998/08/28 21:18:37 1.12 +++ src/sys/kern/subr_pool.c 1998/12/16 04:28:23 1.16 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_pool.c,v 1.12 1998/08/28 21:18:37 thorpej Exp $ */ +/* $NetBSD: subr_pool.c,v 1.16 1998/12/16 04:28:23 briggs Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -17,8 +17,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -109,7 +109,6 @@ static void pr_rmpage __P((struct pool * static int pool_prime_page __P((struct pool *, caddr_t)); static void *pool_page_alloc __P((unsigned long, int, int)); static void pool_page_free __P((void *, unsigned long, int)); -int pool_chk __P((struct pool *, char *)); #ifdef POOL_DIAGNOSTIC @@ -324,7 +323,7 @@ pool_init(pp, size, align, ioff, flags, void (*release) __P((void *, unsigned long, int)); int mtype; { - int off, slack; + int off, slack, i; /* * Check arguments and construct default values. @@ -347,6 +346,9 @@ pool_init(pp, size, align, ioff, flags, if (align == 0) align = ALIGN(1); + if (size < sizeof(struct pool_item)) + size = sizeof(struct pool_item); + /* * Initialize the pool structure. */ @@ -384,7 +386,9 @@ pool_init(pp, size, align, ioff, flags, /* The page header will be taken from our page header pool */ pp->pr_phoffset = 0; off = pagesz; - memset(pp->pr_hashtab, 0, sizeof(pp->pr_hashtab)); + for (i = 0; i < PR_HASHTABSIZE; i++) { + LIST_INIT(&pp->pr_hashtab[i]); + } } /* @@ -425,6 +429,7 @@ pool_init(pp, size, align, ioff, flags, #endif simple_lock_init(&pp->pr_lock); + lockinit(&pp->pr_resourcelock, PSWP, wchan, 0, 0); /* * Initialize private page header pool if we haven't done so yet. @@ -511,28 +516,52 @@ pool_get(pp, flags) * never points at a page header which has PR_PHINPAGE set and * has no items in its bucket. */ -again: - if ((ph = pp->pr_curpage) == NULL) { - void *v = (*pp->pr_alloc)(pp->pr_pagesz, flags, pp->pr_mtype); + while ((ph = pp->pr_curpage) == NULL) { + void *v; + int lkflags = LK_EXCLUSIVE | LK_INTERLOCK | + ((flags & PR_WAITOK) == 0 ? LK_NOWAIT : 0); + + /* Get long-term lock on pool */ + if (lockmgr(&pp->pr_resourcelock, lkflags, &pp->pr_lock) != 0) + return (NULL); + + /* Check if pool became non-empty while we slept */ + if ((ph = pp->pr_curpage) != NULL) + goto again; + + /* Call the page back-end allocator for more memory */ + v = (*pp->pr_alloc)(pp->pr_pagesz, flags, pp->pr_mtype); if (v == NULL) { if (flags & PR_URGENT) panic("pool_get: urgent"); if ((flags & PR_WAITOK) == 0) { pp->pr_nfail++; - simple_unlock(&pp->pr_lock); + lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); return (NULL); } + /* + * Wait for items to be returned to this pool. + * XXX: we actually want to wait just until + * the page allocator has memory again. Depending + * on this pool's usage, we might get stuck here + * for a long time. + */ pp->pr_flags |= PR_WANTED; - simple_unlock(&pp->pr_lock); + lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); tsleep((caddr_t)pp, PSWP, pp->pr_wchan, 0); simple_lock(&pp->pr_lock); - } else { - pp->pr_npagealloc++; - pool_prime_page(pp, v); + continue; } - goto again; + /* We have more memory; add it to the pool */ + pp->pr_npagealloc++; + pool_prime_page(pp, v); + +again: + /* Re-acquire pool interlock */ + simple_lock(&pp->pr_lock); + lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); } if ((v = pi = TAILQ_FIRST(&ph->ph_itemlist)) == NULL) @@ -632,6 +661,8 @@ pool_put(pp, v) if (pp->pr_flags & PR_WANTED) { pp->pr_flags &= ~PR_WANTED; + if (ph->ph_nmissing == 0) + pp->pr_nidle++; wakeup((caddr_t)pp); simple_unlock(&pp->pr_lock); return; @@ -685,12 +716,12 @@ pool_prime(pp, n, storage) /* !storage && static caught below */ #endif + (void)lockmgr(&pp->pr_resourcelock, LK_EXCLUSIVE, NULL); newnitems = pp->pr_minitems + n; newpages = roundup(pp->pr_itemsperpage,newnitems) / pp->pr_itemsperpage - pp->pr_minpages; - simple_lock(&pp->pr_lock); while (newpages-- > 0) { if (pp->pr_flags & PR_STATIC) { @@ -701,7 +732,7 @@ pool_prime(pp, n, storage) } if (cp == NULL) { - simple_unlock(&pp->pr_lock); + (void)lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); return (ENOMEM); } @@ -714,7 +745,7 @@ pool_prime(pp, n, storage) if (pp->pr_minpages >= pp->pr_maxpages) pp->pr_maxpages = pp->pr_minpages + 1; /* XXX */ - simple_unlock(&pp->pr_lock); + (void)lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); return (0); } @@ -733,6 +764,8 @@ pool_prime_page(pp, storage) unsigned int ioff = pp->pr_itemoffset; int n; + simple_lock(&pp->pr_lock); + if ((pp->pr_flags & PR_PHINPAGE) != 0) { ph = (struct pool_item_header *)(cp + pp->pr_phoffset); } else { @@ -790,6 +823,7 @@ pool_prime_page(pp, storage) if (++pp->pr_npages > pp->pr_hiwat) pp->pr_hiwat = pp->pr_npages; + simple_unlock(&pp->pr_lock); return (0); } @@ -798,13 +832,13 @@ pool_setlowat(pp, n) pool_handle_t pp; int n; { + + (void)lockmgr(&pp->pr_resourcelock, LK_EXCLUSIVE, NULL); pp->pr_minitems = n; - if (n == 0) { - pp->pr_minpages = 0; - return; - } - pp->pr_minpages = - roundup(pp->pr_itemsperpage,n) / pp->pr_itemsperpage; + pp->pr_minpages = (n == 0) + ? 0 + : roundup(pp->pr_itemsperpage,n) / pp->pr_itemsperpage; + (void)lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); } void @@ -812,12 +846,12 @@ pool_sethiwat(pp, n) pool_handle_t pp; int n; { - if (n == 0) { - pp->pr_maxpages = 0; - return; - } - pp->pr_maxpages = - roundup(pp->pr_itemsperpage,n) / pp->pr_itemsperpage; + + (void)lockmgr(&pp->pr_resourcelock, LK_EXCLUSIVE, NULL); + pp->pr_maxpages = (n == 0) + ? 0 + : roundup(pp->pr_itemsperpage,n) / pp->pr_itemsperpage; + (void)lockmgr(&pp->pr_resourcelock, LK_RELEASE, NULL); } @@ -1001,11 +1035,11 @@ pool_chk(pp, label) caddr_t page; page = (caddr_t)((u_long)ph & pp->pr_pagemask); - if (page != ph->ph_page) { + if (page != ph->ph_page && (pp->pr_flags & PR_PHINPAGE) != 0) { if (label != NULL) printf("%s: ", label); - printf("pool(%s): page inconsistency: page %p;" - " at page head addr %p (p %p)\n", + printf("pool(%p:%s): page inconsistency: page %p;" + " at page head addr %p (p %p)\n", pp, pp->pr_wchan, ph->ph_page, ph, page); r++; @@ -1034,8 +1068,8 @@ pool_chk(pp, label) if (label != NULL) printf("%s: ", label); - printf("pool(%s): page inconsistency: page %p;" - " item ordinal %d; addr %p (p %p)\n", + printf("pool(%p:%s): page inconsistency: page %p;" + " item ordinal %d; addr %p (p %p)\n", pp, pp->pr_wchan, ph->ph_page, n, pi, page); r++;