| version 1.112, 2006/02/24 11:46:20 |
version 1.112.4.1, 2006/04/19 05:14:00 |
| Line 183 static void pool_prime_page(struct pool |
|
| Line 183 static void pool_prime_page(struct pool |
|
| struct pool_item_header *); |
struct pool_item_header *); |
| static void pool_update_curpage(struct pool *); |
static void pool_update_curpage(struct pool *); |
| |
|
| |
static int pool_grow(struct pool *, int); |
| void *pool_allocator_alloc(struct pool *, int); |
void *pool_allocator_alloc(struct pool *, int); |
| void pool_allocator_free(struct pool *, void *); |
void pool_allocator_free(struct pool *, void *); |
| |
|
|
|
| pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, |
pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, |
| const char *wchan, struct pool_allocator *palloc) |
const char *wchan, struct pool_allocator *palloc) |
| { |
{ |
| int off, slack; |
#ifdef DEBUG |
| |
struct pool *pp1; |
| |
#endif |
| size_t trysize, phsize; |
size_t trysize, phsize; |
| int s; |
int off, slack, s; |
| |
|
| KASSERT((1UL << (CHAR_BIT * sizeof(pool_item_freelist_t))) - 2 >= |
KASSERT((1UL << (CHAR_BIT * sizeof(pool_item_freelist_t))) - 2 >= |
| PHPOOL_FREELIST_NELEM(PHPOOL_MAX - 1)); |
PHPOOL_FREELIST_NELEM(PHPOOL_MAX - 1)); |
| |
|
| |
#ifdef DEBUG |
| |
/* |
| |
* Check that the pool hasn't already been initialised and |
| |
* added to the list of all pools. |
| |
*/ |
| |
LIST_FOREACH(pp1, &pool_head, pr_poollist) { |
| |
if (pp == pp1) |
| |
panic("pool_init: pool %s already initialised", |
| |
wchan); |
| |
} |
| |
#endif |
| |
|
| #ifdef POOL_DIAGNOSTIC |
#ifdef POOL_DIAGNOSTIC |
| /* |
/* |
| * Always log if POOL_DIAGNOSTIC is defined. |
* Always log if POOL_DIAGNOSTIC is defined. |
| Line 867 pool_get(struct pool *pp, int flags) |
|
| Line 882 pool_get(struct pool *pp, int flags) |
|
| * has no items in its bucket. |
* has no items in its bucket. |
| */ |
*/ |
| if ((ph = pp->pr_curpage) == NULL) { |
if ((ph = pp->pr_curpage) == NULL) { |
| |
int error; |
| |
|
| #ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
| if (pp->pr_nitems != 0) { |
if (pp->pr_nitems != 0) { |
| simple_unlock(&pp->pr_slock); |
simple_unlock(&pp->pr_slock); |
| Line 882 pool_get(struct pool *pp, int flags) |
|
| Line 899 pool_get(struct pool *pp, int flags) |
|
| * may block. |
* may block. |
| */ |
*/ |
| pr_leave(pp); |
pr_leave(pp); |
| simple_unlock(&pp->pr_slock); |
error = pool_grow(pp, flags); |
| v = pool_allocator_alloc(pp, flags); |
pr_enter(pp, file, line); |
| if (__predict_true(v != NULL)) |
if (error != 0) { |
| ph = pool_alloc_item_header(pp, v, flags); |
|
| |
|
| if (__predict_false(v == NULL || ph == NULL)) { |
|
| if (v != NULL) |
|
| pool_allocator_free(pp, v); |
|
| |
|
| simple_lock(&pp->pr_slock); |
|
| pr_enter(pp, file, line); |
|
| |
|
| /* |
/* |
| * We were unable to allocate a page or item |
* We were unable to allocate a page or item |
| * header, but we released the lock during |
* header, but we released the lock during |
| Line 921 pool_get(struct pool *pp, int flags) |
|
| Line 929 pool_get(struct pool *pp, int flags) |
|
| pr_leave(pp); |
pr_leave(pp); |
| ltsleep(pp, PSWP, pp->pr_wchan, hz, &pp->pr_slock); |
ltsleep(pp, PSWP, pp->pr_wchan, hz, &pp->pr_slock); |
| pr_enter(pp, file, line); |
pr_enter(pp, file, line); |
| goto startover; |
|
| } |
} |
| |
|
| /* We have more memory; add it to the pool */ |
|
| simple_lock(&pp->pr_slock); |
|
| pr_enter(pp, file, line); |
|
| pool_prime_page(pp, v, ph); |
|
| pp->pr_npagealloc++; |
|
| |
|
| /* Start the allocation process over. */ |
/* Start the allocation process over. */ |
| goto startover; |
goto startover; |
| } |
} |
| Line 1204 pool_put(struct pool *pp, void *v) |
|
| Line 1205 pool_put(struct pool *pp, void *v) |
|
| #endif |
#endif |
| |
|
| /* |
/* |
| |
* pool_grow: grow a pool by a page. |
| |
* |
| |
* => called with pool locked. |
| |
* => unlock and relock the pool. |
| |
* => return with pool locked. |
| |
*/ |
| |
|
| |
static int |
| |
pool_grow(struct pool *pp, int flags) |
| |
{ |
| |
struct pool_item_header *ph = NULL; |
| |
char *cp; |
| |
|
| |
simple_unlock(&pp->pr_slock); |
| |
cp = pool_allocator_alloc(pp, flags); |
| |
if (__predict_true(cp != NULL)) { |
| |
ph = pool_alloc_item_header(pp, cp, flags); |
| |
} |
| |
if (__predict_false(cp == NULL || ph == NULL)) { |
| |
if (cp != NULL) { |
| |
pool_allocator_free(pp, cp); |
| |
} |
| |
simple_lock(&pp->pr_slock); |
| |
return ENOMEM; |
| |
} |
| |
|
| |
simple_lock(&pp->pr_slock); |
| |
pool_prime_page(pp, cp, ph); |
| |
pp->pr_npagealloc++; |
| |
return 0; |
| |
} |
| |
|
| |
/* |
| * Add N items to the pool. |
* Add N items to the pool. |
| */ |
*/ |
| int |
int |
| pool_prime(struct pool *pp, int n) |
pool_prime(struct pool *pp, int n) |
| { |
{ |
| struct pool_item_header *ph = NULL; |
|
| caddr_t cp; |
|
| int newpages; |
int newpages; |
| |
int error = 0; |
| |
|
| simple_lock(&pp->pr_slock); |
simple_lock(&pp->pr_slock); |
| |
|
| newpages = roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage; |
newpages = roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage; |
| |
|
| while (newpages-- > 0) { |
while (newpages-- > 0) { |
| simple_unlock(&pp->pr_slock); |
error = pool_grow(pp, PR_NOWAIT); |
| cp = pool_allocator_alloc(pp, PR_NOWAIT); |
if (error) { |
| if (__predict_true(cp != NULL)) |
|
| ph = pool_alloc_item_header(pp, cp, PR_NOWAIT); |
|
| |
|
| if (__predict_false(cp == NULL || ph == NULL)) { |
|
| if (cp != NULL) |
|
| pool_allocator_free(pp, cp); |
|
| simple_lock(&pp->pr_slock); |
|
| break; |
break; |
| } |
} |
| |
|
| simple_lock(&pp->pr_slock); |
|
| pool_prime_page(pp, cp, ph); |
|
| pp->pr_npagealloc++; |
|
| pp->pr_minpages++; |
pp->pr_minpages++; |
| } |
} |
| |
|
| Line 1240 pool_prime(struct pool *pp, int n) |
|
| Line 1262 pool_prime(struct pool *pp, int n) |
|
| pp->pr_maxpages = pp->pr_minpages + 1; /* XXX */ |
pp->pr_maxpages = pp->pr_minpages + 1; /* XXX */ |
| |
|
| simple_unlock(&pp->pr_slock); |
simple_unlock(&pp->pr_slock); |
| return (0); |
return error; |
| } |
} |
| |
|
| /* |
/* |
| Line 1345 pool_prime_page(struct pool *pp, caddr_t |
|
| Line 1367 pool_prime_page(struct pool *pp, caddr_t |
|
| static int |
static int |
| pool_catchup(struct pool *pp) |
pool_catchup(struct pool *pp) |
| { |
{ |
| struct pool_item_header *ph = NULL; |
|
| caddr_t cp; |
|
| int error = 0; |
int error = 0; |
| |
|
| while (POOL_NEEDS_CATCHUP(pp)) { |
while (POOL_NEEDS_CATCHUP(pp)) { |
| /* |
error = pool_grow(pp, PR_NOWAIT); |
| * Call the page back-end allocator for more memory. |
if (error) { |
| * |
|
| * XXX: We never wait, so should we bother unlocking |
|
| * the pool descriptor? |
|
| */ |
|
| simple_unlock(&pp->pr_slock); |
|
| cp = pool_allocator_alloc(pp, PR_NOWAIT); |
|
| if (__predict_true(cp != NULL)) |
|
| ph = pool_alloc_item_header(pp, cp, PR_NOWAIT); |
|
| if (__predict_false(cp == NULL || ph == NULL)) { |
|
| if (cp != NULL) |
|
| pool_allocator_free(pp, cp); |
|
| error = ENOMEM; |
|
| simple_lock(&pp->pr_slock); |
|
| break; |
break; |
| } |
} |
| simple_lock(&pp->pr_slock); |
|
| pool_prime_page(pp, cp, ph); |
|
| pp->pr_npagealloc++; |
|
| } |
} |
| |
return error; |
| return (error); |
|
| } |
} |
| |
|
| static void |
static void |
| Line 1540 pool_drain(void *arg) |
|
| Line 1543 pool_drain(void *arg) |
|
| drainpp = LIST_NEXT(pp, pr_poollist); |
drainpp = LIST_NEXT(pp, pr_poollist); |
| } |
} |
| simple_unlock(&pool_head_slock); |
simple_unlock(&pool_head_slock); |
| pool_reclaim(pp); |
if (pp) |
| |
pool_reclaim(pp); |
| splx(s); |
splx(s); |
| } |
} |
| |
|