Workshop o mikrokontrolérech na SKSP 2024.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.5 KiB

3 months ago
/*
* UCW Library -- Fast Allocator for Fixed-Size Elements
*
* (c) 2007 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
*/
/*
* This allocator is optimized for intensive allocation and freeing of small
* blocks of identical sizes. System memory is allocated by multiples of the
* page size and it is returned back only when the whole eltpool is deleted.
*
* In the future, we can add returning of memory to the system and also cache
* coloring like in the SLAB allocator used in the Linux kernel.
*/
#undef LOCAL_DEBUG
#include <ucw/lib.h>
#include <ucw/eltpool.h>
struct eltpool *
ep_new(uint elt_size, uint elts_per_chunk)
{
struct eltpool *pool = xmalloc_zero(sizeof(*pool));
pool->elt_size = ALIGN_TO(MAX(elt_size, sizeof(struct eltpool_free)), CPU_STRUCT_ALIGN);
pool->chunk_size = CPU_PAGE_SIZE;
while (pool->elt_size * elts_per_chunk + sizeof(struct eltpool_chunk) > pool->chunk_size)
pool->chunk_size *= 2;
pool->elts_per_chunk = (pool->chunk_size - sizeof(struct eltpool_chunk)) / pool->elt_size;
DBG("ep_new(): got elt_size=%d, epc=%d; used chunk_size=%d, epc=%d", elt_size, elts_per_chunk, pool->chunk_size, pool->elts_per_chunk);
return pool;
}
void
ep_delete(struct eltpool *pool)
{
struct eltpool_chunk *ch;
while (ch = pool->first_chunk)
{
pool->first_chunk = ch->next;
page_free(ch, pool->chunk_size);
}
xfree(pool);
}
void *
ep_alloc_slow(struct eltpool *pool)
{
struct eltpool_chunk *ch = page_alloc(pool->chunk_size);
void *p = (void *)(ch+1);
for (uint i=1; i<pool->elts_per_chunk; i++)
{
struct eltpool_free *f = p;
f->next = pool->first_free;
pool->first_free = f;
p += pool->elt_size;
}
ch->next = pool->first_chunk;
pool->first_chunk = ch;
pool->num_chunks++;
return p;
}
u64
ep_total_size(struct eltpool *pool)
{
return (u64)pool->num_chunks * pool->chunk_size + sizeof(*pool);
}
#ifdef TEST
#include <stdio.h>
#include <ucw/clists.h>
struct argh {
cnode n;
byte x[1];
} PACKED;
int main(void)
{
struct eltpool *ep = ep_new(sizeof(struct argh), 64);
clist l;
clist_init(&l);
for (uint i=0; i<65536; i++)
{
struct argh *a = ep_alloc(ep);
if (i % 3)
clist_add_tail(&l, &a->n);
else
clist_add_head(&l, &a->n);
if (!(i % 5))
{
a = clist_head(&l);
clist_remove(&a->n);
ep_free(ep, a);
}
}
ep_delete(ep);
puts("OK");
return 0;
}
#endif