| version 1.162, 2008/07/04 13:28:08 |
version 1.163, 2008/07/04 16:38:59 |
| Line 2085 pool_cache_bootstrap(pool_cache_t pc, si |
|
| Line 2085 pool_cache_bootstrap(pool_cache_t pc, si |
|
| |
|
| if ((flags & PR_LARGECACHE) != 0) { |
if ((flags & PR_LARGECACHE) != 0) { |
| pc->pc_pcgsize = PCG_NOBJECTS_LARGE; |
pc->pc_pcgsize = PCG_NOBJECTS_LARGE; |
| |
pc->pc_pcgpool = &pcg_large_pool; |
| } else { |
} else { |
| pc->pc_pcgsize = PCG_NOBJECTS_NORMAL; |
pc->pc_pcgsize = PCG_NOBJECTS_NORMAL; |
| |
pc->pc_pcgpool = &pcg_normal_pool; |
| } |
} |
| |
|
| /* Allocate per-CPU caches. */ |
/* Allocate per-CPU caches. */ |
| Line 2480 pool_cache_get_paddr(pool_cache_t pc, in |
|
| Line 2482 pool_cache_get_paddr(pool_cache_t pc, in |
|
| *pap = pcg->pcg_objects[pcg->pcg_avail].pcgo_pa; |
*pap = pcg->pcg_objects[pcg->pcg_avail].pcgo_pa; |
| #if defined(DIAGNOSTIC) |
#if defined(DIAGNOSTIC) |
| pcg->pcg_objects[pcg->pcg_avail].pcgo_va = NULL; |
pcg->pcg_objects[pcg->pcg_avail].pcgo_va = NULL; |
| #endif /* defined(DIAGNOSTIC) */ |
KASSERT(pcg->pcg_avail < pcg->pcg_size); |
| KASSERT(pcg->pcg_avail <= pcg->pcg_size); |
|
| KASSERT(object != NULL); |
KASSERT(object != NULL); |
| |
#endif |
| cc->cc_hits++; |
cc->cc_hits++; |
| splx(s); |
splx(s); |
| FREECHECK_OUT(&pc->pc_freecheck, object); |
FREECHECK_OUT(&pc->pc_freecheck, object); |
| Line 2514 pool_cache_get_paddr(pool_cache_t pc, in |
|
| Line 2516 pool_cache_get_paddr(pool_cache_t pc, in |
|
| static bool __noinline |
static bool __noinline |
| pool_cache_put_slow(pool_cache_cpu_t *cc, int s, void *object) |
pool_cache_put_slow(pool_cache_cpu_t *cc, int s, void *object) |
| { |
{ |
| pcg_t *pcg, *cur, *empty; |
pcg_t *pcg, *cur; |
| uint64_t ncsw; |
uint64_t ncsw; |
| pool_cache_t pc; |
pool_cache_t pc; |
| |
|
| pc = cc->cc_cache; |
pc = cc->cc_cache; |
| cc->cc_misses++; |
cc->cc_misses++; |
| |
|
| /* |
|
| * If there appear to be no empty groups in the cache then |
|
| * allocate one in advance. |
|
| */ |
|
| empty = NULL; |
|
| if (__predict_false(pc->pc_emptygroups == NULL)) { |
|
| if (__predict_false(pool_cache_disable)) { |
|
| empty = NULL; |
|
| } else if (pc->pc_pcgsize == PCG_NOBJECTS_LARGE) { |
|
| empty = pool_get(&pcg_large_pool, PR_NOWAIT); |
|
| } else { |
|
| empty = pool_get(&pcg_normal_pool, PR_NOWAIT); |
|
| } |
|
| } |
|
| |
|
| /* Lock the cache. */ |
/* Lock the cache. */ |
| ncsw = curlwp->l_ncsw; |
ncsw = curlwp->l_ncsw; |
| if (__predict_false(!mutex_tryenter(&pc->pc_lock))) { |
if (__predict_false(!mutex_tryenter(&pc->pc_lock))) { |
| mutex_enter(&pc->pc_lock); |
mutex_enter(&pc->pc_lock); |
| pc->pc_contended++; |
pc->pc_contended++; |
| } |
|
| |
|
| /* |
/* |
| * If we speculatively allocated an empty group, link it into |
* If we context switched while locking, then our view of |
| * the cache's list. |
* the per-CPU data is invalid: retry. |
| */ |
*/ |
| if (empty != NULL) { |
if (__predict_false(curlwp->l_ncsw != ncsw)) { |
| empty->pcg_avail = 0; |
mutex_exit(&pc->pc_lock); |
| empty->pcg_size = pc->pc_pcgsize; |
return true; |
| empty->pcg_next = pc->pc_emptygroups; |
} |
| pc->pc_emptygroups = empty; |
|
| pc->pc_nempty++; |
|
| pc->pc_misses++; |
|
| } |
} |
| |
|
| /* |
/* If there are no empty groups in the cache then allocate one. */ |
| * If we context switched while locking, then our view of the |
if (__predict_false((pcg = pc->pc_emptygroups) == NULL)) { |
| * per-CPU data is invalid: retry. |
if (__predict_true(!pool_cache_disable)) { |
| */ |
pcg = pool_get(pc->pc_pcgpool, PR_NOWAIT); |
| if (__predict_false(curlwp->l_ncsw != ncsw)) { |
} |
| mutex_exit(&pc->pc_lock); |
if (__predict_true(pcg != NULL)) { |
| return true; |
pcg->pcg_avail = 0; |
| |
pcg->pcg_size = pc->pc_pcgsize; |
| |
} |
| |
} else { |
| |
pc->pc_emptygroups = pcg->pcg_next; |
| |
pc->pc_nempty--; |
| } |
} |
| |
|
| /* |
/* |
| Line 2570 pool_cache_put_slow(pool_cache_cpu_t *cc |
|
| Line 2558 pool_cache_put_slow(pool_cache_cpu_t *cc |
|
| * to the cache. Install the empty group to the local CPU |
* to the cache. Install the empty group to the local CPU |
| * and return. |
* and return. |
| */ |
*/ |
| if (__predict_true((pcg = pc->pc_emptygroups) != NULL)) { |
if (pcg != NULL) { |
| KASSERT(pcg->pcg_avail == 0); |
KASSERT(pcg->pcg_avail == 0); |
| pc->pc_emptygroups = pcg->pcg_next; |
|
| if (__predict_false(cc->cc_previous == &pcg_dummy)) { |
if (__predict_false(cc->cc_previous == &pcg_dummy)) { |
| cc->cc_previous = pcg; |
cc->cc_previous = pcg; |
| } else { |
} else { |
| cur = cc->cc_current; |
cur = cc->cc_current; |
| if (__predict_true(cur != &pcg_dummy)) { |
if (__predict_true(cur != &pcg_dummy)) { |
| KASSERT(cur->pcg_avail == pcg->pcg_size); |
KASSERT(cur->pcg_avail == cur->pcg_size); |
| cur->pcg_next = pc->pc_fullgroups; |
cur->pcg_next = pc->pc_fullgroups; |
| pc->pc_fullgroups = cur; |
pc->pc_fullgroups = cur; |
| pc->pc_nfull++; |
pc->pc_nfull++; |
| } |
} |
| cc->cc_current = pcg; |
cc->cc_current = pcg; |
| } |
} |
| pc->pc_hits += (empty == NULL); |
pc->pc_hits++; |
| pc->pc_nempty--; |
|
| mutex_exit(&pc->pc_lock); |
mutex_exit(&pc->pc_lock); |
| return true; |
return true; |
| } |
} |