| version 1.134, 2007/11/07 00:23:23 |
version 1.135, 2007/11/10 07:29:28 |
| Line 46 __KERNEL_RCSID(0, "$NetBSD$"); |
|
| Line 46 __KERNEL_RCSID(0, "$NetBSD$"); |
|
| |
|
| #include <sys/param.h> |
#include <sys/param.h> |
| #include <sys/systm.h> |
#include <sys/systm.h> |
| |
#include <sys/bitops.h> |
| #include <sys/proc.h> |
#include <sys/proc.h> |
| #include <sys/errno.h> |
#include <sys/errno.h> |
| #include <sys/kernel.h> |
#include <sys/kernel.h> |
| Line 83 LIST_HEAD(,pool_cache) pool_cache_head = |
|
| Line 84 LIST_HEAD(,pool_cache) pool_cache_head = |
|
| /* Private pool for page header structures */ |
/* Private pool for page header structures */ |
| #define PHPOOL_MAX 8 |
#define PHPOOL_MAX 8 |
| static struct pool phpool[PHPOOL_MAX]; |
static struct pool phpool[PHPOOL_MAX]; |
| #define PHPOOL_FREELIST_NELEM(idx) (((idx) == 0) ? 0 : (1 << (idx))) |
#define PHPOOL_FREELIST_NELEM(idx) \ |
| |
(((idx) == 0) ? 0 : BITMAP_SIZE * (1 << (idx))) |
| |
|
| #ifdef POOL_SUBPAGE |
#ifdef POOL_SUBPAGE |
| /* Pool of subpages for use by normal pools. */ |
/* Pool of subpages for use by normal pools. */ |
| Line 112 static struct pool *drainpp; |
|
| Line 114 static struct pool *drainpp; |
|
| static kmutex_t pool_head_lock; |
static kmutex_t pool_head_lock; |
| static kcondvar_t pool_busy; |
static kcondvar_t pool_busy; |
| |
|
| typedef uint8_t pool_item_freelist_t; |
typedef uint32_t pool_item_bitmap_t; |
| |
#define BITMAP_SIZE (CHAR_BIT * sizeof(pool_item_bitmap_t)) |
| |
#define BITMAP_MASK (BITMAP_SIZE - 1) |
| |
|
| struct pool_item_header { |
struct pool_item_header { |
| /* Page headers */ |
/* Page headers */ |
| Line 122 struct pool_item_header { |
|
| Line 126 struct pool_item_header { |
|
| ph_node; /* Off-page page headers */ |
ph_node; /* Off-page page headers */ |
| void * ph_page; /* this page's address */ |
void * ph_page; /* this page's address */ |
| struct timeval ph_time; /* last referenced */ |
struct timeval ph_time; /* last referenced */ |
| |
uint16_t ph_nmissing; /* # of chunks in use */ |
| union { |
union { |
| /* !PR_NOTOUCH */ |
/* !PR_NOTOUCH */ |
| struct { |
struct { |
| Line 130 struct pool_item_header { |
|
| Line 135 struct pool_item_header { |
|
| } phu_normal; |
} phu_normal; |
| /* PR_NOTOUCH */ |
/* PR_NOTOUCH */ |
| struct { |
struct { |
| uint16_t |
uint16_t phu_off; /* start offset in page */ |
| phu_off; /* start offset in page */ |
pool_item_bitmap_t phu_bitmap[]; |
| pool_item_freelist_t |
|
| phu_firstfree; /* first free item */ |
|
| /* |
|
| * XXX it might be better to use |
|
| * a simple bitmap and ffs(3) |
|
| */ |
|
| } phu_notouch; |
} phu_notouch; |
| } ph_u; |
} ph_u; |
| uint16_t ph_nmissing; /* # of chunks in use */ |
|
| }; |
}; |
| #define ph_itemlist ph_u.phu_normal.phu_itemlist |
#define ph_itemlist ph_u.phu_normal.phu_itemlist |
| #define ph_off ph_u.phu_notouch.phu_off |
#define ph_off ph_u.phu_notouch.phu_off |
| #define ph_firstfree ph_u.phu_notouch.phu_firstfree |
#define ph_bitmap ph_u.phu_notouch.phu_bitmap |
| |
|
| struct pool_item { |
struct pool_item { |
| #ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
| Line 330 pr_enter_check(struct pool *pp, void (*p |
|
| Line 328 pr_enter_check(struct pool *pp, void (*p |
|
| #define pr_enter_check(pp, pr) |
#define pr_enter_check(pp, pr) |
| #endif /* POOL_DIAGNOSTIC */ |
#endif /* POOL_DIAGNOSTIC */ |
| |
|
| static inline int |
static inline unsigned int |
| pr_item_notouch_index(const struct pool *pp, const struct pool_item_header *ph, |
pr_item_notouch_index(const struct pool *pp, const struct pool_item_header *ph, |
| const void *v) |
const void *v) |
| { |
{ |
| const char *cp = v; |
const char *cp = v; |
| int idx; |
unsigned int idx; |
| |
|
| KASSERT(pp->pr_roflags & PR_NOTOUCH); |
KASSERT(pp->pr_roflags & PR_NOTOUCH); |
| idx = (cp - (char *)ph->ph_page - ph->ph_off) / pp->pr_size; |
idx = (cp - (char *)ph->ph_page - ph->ph_off) / pp->pr_size; |
| Line 343 pr_item_notouch_index(const struct pool |
|
| Line 341 pr_item_notouch_index(const struct pool |
|
| return idx; |
return idx; |
| } |
} |
| |
|
| #define PR_FREELIST_ALIGN(p) \ |
|
| roundup((uintptr_t)(p), sizeof(pool_item_freelist_t)) |
|
| #define PR_FREELIST(ph) ((pool_item_freelist_t *)PR_FREELIST_ALIGN((ph) + 1)) |
|
| #define PR_INDEX_USED ((pool_item_freelist_t)-1) |
|
| #define PR_INDEX_EOL ((pool_item_freelist_t)-2) |
|
| |
|
| static inline void |
static inline void |
| pr_item_notouch_put(const struct pool *pp, struct pool_item_header *ph, |
pr_item_notouch_put(const struct pool *pp, struct pool_item_header *ph, |
| void *obj) |
void *obj) |
| { |
{ |
| int idx = pr_item_notouch_index(pp, ph, obj); |
unsigned int idx = pr_item_notouch_index(pp, ph, obj); |
| pool_item_freelist_t *freelist = PR_FREELIST(ph); |
pool_item_bitmap_t *bitmap = ph->ph_bitmap + (idx / BITMAP_SIZE); |
| |
pool_item_bitmap_t mask = 1 << (idx & BITMAP_MASK); |
| |
|
| KASSERT(freelist[idx] == PR_INDEX_USED); |
KASSERT((*bitmap & mask) == 0); |
| freelist[idx] = ph->ph_firstfree; |
*bitmap |= mask; |
| ph->ph_firstfree = idx; |
|
| } |
} |
| |
|
| static inline void * |
static inline void * |
| pr_item_notouch_get(const struct pool *pp, struct pool_item_header *ph) |
pr_item_notouch_get(const struct pool *pp, struct pool_item_header *ph) |
| { |
{ |
| int idx = ph->ph_firstfree; |
pool_item_bitmap_t *bitmap = ph->ph_bitmap; |
| pool_item_freelist_t *freelist = PR_FREELIST(ph); |
unsigned int idx; |
| |
int i; |
| |
|
| KASSERT(freelist[idx] != PR_INDEX_USED); |
for (i = 0; ; i++) { |
| ph->ph_firstfree = freelist[idx]; |
int bit; |
| freelist[idx] = PR_INDEX_USED; |
|
| |
|
| |
KASSERT((i * BITMAP_SIZE) < pp->pr_itemsperpage); |
| |
bit = ffs32(bitmap[i]); |
| |
if (bit) { |
| |
pool_item_bitmap_t mask; |
| |
|
| |
bit--; |
| |
idx = (i * BITMAP_SIZE) + bit; |
| |
mask = 1 << bit; |
| |
KASSERT((bitmap[i] & mask) != 0); |
| |
bitmap[i] &= ~mask; |
| |
break; |
| |
} |
| |
} |
| |
KASSERT(idx < pp->pr_itemsperpage); |
| return (char *)ph->ph_page + ph->ph_off + idx * pp->pr_size; |
return (char *)ph->ph_page + ph->ph_off + idx * pp->pr_size; |
| } |
} |
| |
|
| |
static inline void |
| |
pr_item_notouch_init(const struct pool *pp, struct pool_item_header *ph) |
| |
{ |
| |
pool_item_bitmap_t *bitmap = ph->ph_bitmap; |
| |
const int n = howmany(pp->pr_itemsperpage, BITMAP_SIZE); |
| |
int i; |
| |
|
| |
for (i = 0; i < n; i++) { |
| |
bitmap[i] = (pool_item_bitmap_t)-1; |
| |
} |
| |
} |
| |
|
| static inline int |
static inline int |
| phtree_compare(struct pool_item_header *a, struct pool_item_header *b) |
phtree_compare(struct pool_item_header *a, struct pool_item_header *b) |
| { |
{ |
| Line 603 pool_init(struct pool *pp, size_t size, |
|
| Line 621 pool_init(struct pool *pp, size_t size, |
|
| size_t trysize, phsize; |
size_t trysize, phsize; |
| int off, slack; |
int off, slack; |
| |
|
| KASSERT((1UL << (CHAR_BIT * sizeof(pool_item_freelist_t))) - 2 >= |
|
| PHPOOL_FREELIST_NELEM(PHPOOL_MAX - 1)); |
|
| |
|
| #ifdef DEBUG |
#ifdef DEBUG |
| /* |
/* |
| * Check that the pool hasn't already been initialised and |
* Check that the pool hasn't already been initialised and |
| Line 808 pool_init(struct pool *pp, size_t size, |
|
| Line 823 pool_init(struct pool *pp, size_t size, |
|
| "phpool-%d", nelem); |
"phpool-%d", nelem); |
| sz = sizeof(struct pool_item_header); |
sz = sizeof(struct pool_item_header); |
| if (nelem) { |
if (nelem) { |
| sz = PR_FREELIST_ALIGN(sz) |
sz = offsetof(struct pool_item_header, |
| + nelem * sizeof(pool_item_freelist_t); |
ph_bitmap[howmany(nelem, BITMAP_SIZE)]); |
| } |
} |
| pool_init(&phpool[idx], sz, 0, 0, 0, |
pool_init(&phpool[idx], sz, 0, 0, 0, |
| phpool_names[idx], &pool_allocator_meta, IPL_VM); |
phpool_names[idx], &pool_allocator_meta, IPL_VM); |
| Line 1433 pool_prime_page(struct pool *pp, void *s |
|
| Line 1448 pool_prime_page(struct pool *pp, void *s |
|
| pp->pr_nitems += n; |
pp->pr_nitems += n; |
| |
|
| if (pp->pr_roflags & PR_NOTOUCH) { |
if (pp->pr_roflags & PR_NOTOUCH) { |
| pool_item_freelist_t *freelist = PR_FREELIST(ph); |
pr_item_notouch_init(pp, ph); |
| int i; |
|
| |
|
| ph->ph_off = (char *)cp - (char *)storage; |
|
| ph->ph_firstfree = 0; |
|
| for (i = 0; i < n - 1; i++) |
|
| freelist[i] = i + 1; |
|
| freelist[n - 1] = PR_INDEX_EOL; |
|
| } else { |
} else { |
| while (n--) { |
while (n--) { |
| pi = (struct pool_item *)cp; |
pi = (struct pool_item *)cp; |