X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Fmempool.c;h=44713cebd417ffa09caa532a352e9a83ad7d5e19;hb=da418321735b159f0ff39366d68203c772f152d4;hp=fdfd019ea47dda15010fb414e71addd5056e3406;hpb=005c9e87ad3d682be29837ed3da6ed1de3214c40;p=libucw.git diff --git a/ucw/mempool.c b/ucw/mempool.c index fdfd019e..44713ceb 100644 --- a/ucw/mempool.c +++ b/ucw/mempool.c @@ -17,18 +17,18 @@ #include #define MP_CHUNK_TAIL ALIGN_TO(sizeof(struct mempool_chunk), CPU_STRUCT_ALIGN) -#define MP_SIZE_MAX (~0U - MP_CHUNK_TAIL - CPU_PAGE_SIZE) +#define MP_SIZE_MAX (SIZE_MAX - MP_CHUNK_TAIL - CPU_PAGE_SIZE) struct mempool_chunk { #ifdef CONFIG_DEBUG struct mempool *pool; // Can be useful when analysing coredump for memory leaks #endif struct mempool_chunk *next; - uns size; + size_t size; }; -static uns -mp_align_size(uns size) +static size_t +mp_align_size(size_t size) { #ifdef CONFIG_UCW_POOL_IS_MMAP return ALIGN_TO(size + MP_CHUNK_TAIL, CPU_PAGE_SIZE) - MP_CHUNK_TAIL; @@ -64,7 +64,7 @@ static void mp_allocator_free(struct ucw_allocator *a UNUSED, void *ptr UNUSED) } void -mp_init(struct mempool *pool, uns chunk_size) +mp_init(struct mempool *pool, size_t chunk_size) { chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size)); *pool = (struct mempool) { @@ -80,48 +80,54 @@ mp_init(struct mempool *pool, uns chunk_size) } static void * -mp_new_big_chunk(uns size) +mp_new_big_chunk(struct mempool *pool, size_t size) { struct mempool_chunk *chunk; chunk = xmalloc(size + MP_CHUNK_TAIL) + size; chunk->size = size; + if (pool) + pool->total_size += size + MP_CHUNK_TAIL; return chunk; } static void -mp_free_big_chunk(struct mempool_chunk *chunk) +mp_free_big_chunk(struct mempool *pool, struct mempool_chunk *chunk) { + pool->total_size -= chunk->size + MP_CHUNK_TAIL; xfree((void *)chunk - chunk->size); } static void * -mp_new_chunk(uns size) +mp_new_chunk(struct mempool *pool, size_t size) { #ifdef CONFIG_UCW_POOL_IS_MMAP struct mempool_chunk *chunk; chunk = page_alloc(size + MP_CHUNK_TAIL) + size; chunk->size = size; + if (pool) + pool->total_size += size + MP_CHUNK_TAIL; return chunk; #else - return mp_new_big_chunk(size); + return mp_new_big_chunk(pool, size); #endif } static void -mp_free_chunk(struct mempool_chunk *chunk) +mp_free_chunk(struct mempool *pool, struct mempool_chunk *chunk) { #ifdef CONFIG_UCW_POOL_IS_MMAP + pool->total_size -= chunk->size + MP_CHUNK_TAIL; page_free((void *)chunk - chunk->size, chunk->size + MP_CHUNK_TAIL); #else - mp_free_big_chunk(chunk); + mp_free_big_chunk(pool, chunk); #endif } struct mempool * -mp_new(uns chunk_size) +mp_new(size_t chunk_size) { chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size)); - struct mempool_chunk *chunk = mp_new_chunk(chunk_size); + struct mempool_chunk *chunk = mp_new_chunk(NULL, chunk_size); struct mempool *pool = (void *)chunk - chunk_size; DBG("Creating mempool %p with %u bytes long chunks", pool, chunk_size); chunk->next = NULL; @@ -137,28 +143,30 @@ mp_new(uns chunk_size) .state = { .free = { chunk_size - sizeof(*pool) }, .last = { chunk } }, .chunk_size = chunk_size, .threshold = chunk_size >> 1, - .last_big = &pool->last_big }; + .last_big = &pool->last_big, + .total_size = chunk->size + MP_CHUNK_TAIL, + }; return pool; } static void -mp_free_chain(struct mempool_chunk *chunk) +mp_free_chain(struct mempool *pool, struct mempool_chunk *chunk) { while (chunk) { struct mempool_chunk *next = chunk->next; - mp_free_chunk(chunk); + mp_free_chunk(pool, chunk); chunk = next; } } static void -mp_free_big_chain(struct mempool_chunk *chunk) +mp_free_big_chain(struct mempool *pool, struct mempool_chunk *chunk) { while (chunk) { struct mempool_chunk *next = chunk->next; - mp_free_big_chunk(chunk); + mp_free_big_chunk(pool, chunk); chunk = next; } } @@ -167,15 +175,15 @@ void mp_delete(struct mempool *pool) { DBG("Deleting mempool %p", pool); - mp_free_big_chain(pool->state.last[1]); - mp_free_chain(pool->unused); - mp_free_chain(pool->state.last[0]); // can contain the mempool structure + mp_free_big_chain(pool, pool->state.last[1]); + mp_free_chain(pool, pool->unused); + mp_free_chain(pool, pool->state.last[0]); // can contain the mempool structure } void mp_flush(struct mempool *pool) { - mp_free_big_chain(pool->state.last[1]); + mp_free_big_chain(pool, pool->state.last[1]); struct mempool_chunk *chunk, *next; for (chunk = pool->state.last[0]; chunk && (void *)chunk - chunk->size != pool; chunk = next) { @@ -192,12 +200,18 @@ mp_flush(struct mempool *pool) } static void -mp_stats_chain(struct mempool_chunk *chunk, struct mempool_stats *stats, uns idx) +mp_stats_chain(struct mempool *pool, struct mempool_chunk *chunk, struct mempool_stats *stats, uns idx) { while (chunk) { - stats->chain_size[idx] += chunk->size + sizeof(*chunk); + stats->chain_size[idx] += chunk->size + MP_CHUNK_TAIL; stats->chain_count[idx]++; + if (idx < 2) + { + stats->used_size += chunk->size; + if ((byte *)pool == (byte *)chunk - chunk->size) + stats->used_size -= sizeof(*pool); + } chunk = chunk->next; } stats->total_size += stats->chain_size[idx]; @@ -207,21 +221,35 @@ void mp_stats(struct mempool *pool, struct mempool_stats *stats) { bzero(stats, sizeof(*stats)); - mp_stats_chain(pool->state.last[0], stats, 0); - mp_stats_chain(pool->state.last[1], stats, 1); - mp_stats_chain(pool->unused, stats, 2); + mp_stats_chain(pool, pool->state.last[0], stats, 0); + mp_stats_chain(pool, pool->state.last[1], stats, 1); + mp_stats_chain(pool, pool->unused, stats, 2); + stats->used_size -= pool->state.free[0] + pool->state.free[1]; + ASSERT(stats->total_size == pool->total_size); + ASSERT(stats->used_size <= stats->total_size); } u64 mp_total_size(struct mempool *pool) { - struct mempool_stats stats; - mp_stats(pool, &stats); - return stats.total_size; + return pool->total_size; +} + +void +mp_shrink(struct mempool *pool, u64 min_total_size) +{ + while (1) + { + struct mempool_chunk *chunk = pool->unused; + if (!chunk || pool->total_size - (chunk->size + MP_CHUNK_TAIL) < min_total_size) + break; + pool->unused = chunk->next; + mp_free_chunk(pool, chunk); + } } void * -mp_alloc_internal(struct mempool *pool, uns size) +mp_alloc_internal(struct mempool *pool, size_t size) { struct mempool_chunk *chunk; if (size <= pool->threshold) @@ -234,7 +262,7 @@ mp_alloc_internal(struct mempool *pool, uns size) } else { - chunk = mp_new_chunk(pool->chunk_size); + chunk = mp_new_chunk(pool, pool->chunk_size); #ifdef CONFIG_DEBUG chunk->pool = pool; #endif @@ -247,8 +275,8 @@ mp_alloc_internal(struct mempool *pool, uns size) else if (likely(size <= MP_SIZE_MAX)) { pool->idx = 1; - uns aligned = ALIGN_TO(size, CPU_STRUCT_ALIGN); - chunk = mp_new_big_chunk(aligned); + size_t aligned = ALIGN_TO(size, CPU_STRUCT_ALIGN); + chunk = mp_new_big_chunk(pool, aligned); chunk->next = pool->state.last[1]; #ifdef CONFIG_DEBUG chunk->pool = pool; @@ -258,23 +286,23 @@ mp_alloc_internal(struct mempool *pool, uns size) return pool->last_big = (void *)chunk - aligned; } else - die("Cannot allocate %u bytes from a mempool", size); + die("Cannot allocate %zu bytes from a mempool", size); } void * -mp_alloc(struct mempool *pool, uns size) +mp_alloc(struct mempool *pool, size_t size) { return mp_alloc_fast(pool, size); } void * -mp_alloc_noalign(struct mempool *pool, uns size) +mp_alloc_noalign(struct mempool *pool, size_t size) { return mp_alloc_fast_noalign(pool, size); } void * -mp_alloc_zero(struct mempool *pool, uns size) +mp_alloc_zero(struct mempool *pool, size_t size) { void *ptr = mp_alloc_fast(pool, size); bzero(ptr, size); @@ -282,7 +310,7 @@ mp_alloc_zero(struct mempool *pool, uns size) } void * -mp_start_internal(struct mempool *pool, uns size) +mp_start_internal(struct mempool *pool, size_t size) { void *ptr = mp_alloc_internal(pool, size); pool->state.free[pool->idx] += size; @@ -290,30 +318,31 @@ mp_start_internal(struct mempool *pool, uns size) } void * -mp_start(struct mempool *pool, uns size) +mp_start(struct mempool *pool, size_t size) { return mp_start_fast(pool, size); } void * -mp_start_noalign(struct mempool *pool, uns size) +mp_start_noalign(struct mempool *pool, size_t size) { return mp_start_fast_noalign(pool, size); } void * -mp_grow_internal(struct mempool *pool, uns size) +mp_grow_internal(struct mempool *pool, size_t size) { if (unlikely(size > MP_SIZE_MAX)) - die("Cannot allocate %u bytes of memory", size); - uns avail = mp_avail(pool); + die("Cannot allocate %zu bytes of memory", size); + size_t avail = mp_avail(pool); void *ptr = mp_ptr(pool); if (pool->idx) { - uns amortized = likely(avail <= MP_SIZE_MAX / 2) ? avail * 2 : MP_SIZE_MAX; + size_t amortized = likely(avail <= MP_SIZE_MAX / 2) ? avail * 2 : MP_SIZE_MAX; amortized = MAX(amortized, size); amortized = ALIGN_TO(amortized, CPU_STRUCT_ALIGN); struct mempool_chunk *chunk = pool->state.last[1], *next = chunk->next; + pool->total_size = pool->total_size - chunk->size + amortized; ptr = xrealloc(ptr, amortized + MP_CHUNK_TAIL); chunk = ptr + amortized; chunk->next = next; @@ -331,22 +360,22 @@ mp_grow_internal(struct mempool *pool, uns size) } } -uns +size_t mp_open(struct mempool *pool, void *ptr) { return mp_open_fast(pool, ptr); } void * -mp_realloc(struct mempool *pool, void *ptr, uns size) +mp_realloc(struct mempool *pool, void *ptr, size_t size) { return mp_realloc_fast(pool, ptr, size); } void * -mp_realloc_zero(struct mempool *pool, void *ptr, uns size) +mp_realloc_zero(struct mempool *pool, void *ptr, size_t size) { - uns old_size = mp_open_fast(pool, ptr); + size_t old_size = mp_open_fast(pool, ptr); ptr = mp_grow(pool, size); if (size > old_size) bzero(ptr + old_size, size - old_size); @@ -355,7 +384,7 @@ mp_realloc_zero(struct mempool *pool, void *ptr, uns size) } void * -mp_spread_internal(struct mempool *pool, void *p, uns size) +mp_spread_internal(struct mempool *pool, void *p, size_t size) { void *old = mp_ptr(pool); void *new = mp_grow_internal(pool, p-old+size); @@ -376,7 +405,7 @@ mp_restore(struct mempool *pool, struct mempool_state *state) for (chunk = pool->state.last[1]; chunk != s.last[1]; chunk = next) { next = chunk->next; - mp_free_big_chunk(chunk); + mp_free_big_chunk(pool, chunk); } pool->state = s; pool->last_big = &pool->last_big; @@ -541,6 +570,11 @@ grow: } else if (can_realloc && n && (r -= 5) < 0) ASSERT(mp_size(mp, ptr[n - 1]) == len[n - 1]); + else + { + struct mempool_stats stats; + mp_stats(mp, &stats); + } } mp_delete(mp);