mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-01-01 06:23:35 +01:00
kmalloc: add kmalloc_max() function
This commit is contained in:
parent
252bd4eb41
commit
7b662987f8
3 changed files with 95 additions and 0 deletions
|
@ -39,6 +39,20 @@ void *krealloc(void *ptr, size_t size);
|
||||||
/* kfree(): Free memory allocated with kalloc() */
|
/* kfree(): Free memory allocated with kalloc() */
|
||||||
void kfree(void *ptr);
|
void kfree(void *ptr);
|
||||||
|
|
||||||
|
/* kmalloc_max(): Allocate the largest block available in an arena
|
||||||
|
|
||||||
|
This function is like kmalloc(), but it find the largest block in the arena
|
||||||
|
and returns it whole after setting its size in *size. This is useful if you
|
||||||
|
need memory to manage with another allocator, or you don't yet know the size
|
||||||
|
of the data to be generated. The block can later be shrunk with realloc().
|
||||||
|
|
||||||
|
Currently only gint-managed arenas support this operation.
|
||||||
|
|
||||||
|
@size Will be set to size of returned block (if there is one)
|
||||||
|
@arean_name Name of arena to allocate in (*cannot* be NULL)
|
||||||
|
Returns the address of the largest block available, NULL on error. */
|
||||||
|
void *kmalloc_max(size_t *size, char const *arena_name);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Extension API for new areas and statistics
|
// Extension API for new areas and statistics
|
||||||
//---
|
//---
|
||||||
|
@ -53,6 +67,8 @@ typedef struct {
|
||||||
void * (*realloc)(void *ptr, size_t newsize, void *data);
|
void * (*realloc)(void *ptr, size_t newsize, void *data);
|
||||||
/* kfree() handles ptr == NULL*/
|
/* kfree() handles ptr == NULL*/
|
||||||
void (*free)(void *ptr, void *data);
|
void (*free)(void *ptr, void *data);
|
||||||
|
/* kmalloc_max() backend */
|
||||||
|
void * (*malloc_max)(size_t *size, void *data);
|
||||||
|
|
||||||
/* Name, should be unique; gint reserves names starting with "_" */
|
/* Name, should be unique; gint reserves names starting with "_" */
|
||||||
char const *name;
|
char const *name;
|
||||||
|
|
|
@ -178,6 +178,25 @@ static block_t *best_fit(block_t *list, size_t size)
|
||||||
return best_match;
|
return best_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find a worst fit in the list */
|
||||||
|
static block_t *worst_fit(block_t *list)
|
||||||
|
{
|
||||||
|
block_t *best_match = NULL;
|
||||||
|
size_t best_size = 0;
|
||||||
|
|
||||||
|
while(list)
|
||||||
|
{
|
||||||
|
if(list->size >= best_size)
|
||||||
|
{
|
||||||
|
best_match = list;
|
||||||
|
best_size = list->size;
|
||||||
|
}
|
||||||
|
list = next_link(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return best_match;
|
||||||
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Index-level operations
|
// Index-level operations
|
||||||
//---
|
//---
|
||||||
|
@ -366,6 +385,35 @@ static void *gint_realloc(void *ptr, size_t size, void *data)
|
||||||
return new_ptr;
|
return new_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *gint_malloc_max(size_t *size, void *data)
|
||||||
|
{
|
||||||
|
index_t *index = data;
|
||||||
|
stats_t *s = index->stats;
|
||||||
|
|
||||||
|
/* Find the largest available block in the largest possible class */
|
||||||
|
block_t *alloc;
|
||||||
|
for(int c = 15; c >= 0; c--)
|
||||||
|
{
|
||||||
|
block_t *list = index->classes[c];
|
||||||
|
alloc = (c < 14) ? list : worst_fit(list);
|
||||||
|
if(alloc) break;
|
||||||
|
}
|
||||||
|
if(!alloc) return NULL;
|
||||||
|
|
||||||
|
remove_link(alloc, index);
|
||||||
|
|
||||||
|
/* Mark the block as allocated and return it */
|
||||||
|
block_t *next = next_block(alloc);
|
||||||
|
alloc->used = true;
|
||||||
|
if(next) next->previous_used = true;
|
||||||
|
|
||||||
|
if(s) s->used_memory += alloc->size;
|
||||||
|
if(s) s->peak_used_memory = max(s->peak_used_memory, s->used_memory);
|
||||||
|
|
||||||
|
*size = alloc->size;
|
||||||
|
return (void *)alloc + sizeof(block_t);
|
||||||
|
}
|
||||||
|
|
||||||
/* kmalloc_init_arena(): Initialize an arena with gint's allocator */
|
/* kmalloc_init_arena(): Initialize an arena with gint's allocator */
|
||||||
void kmalloc_init_arena(kmalloc_arena_t *a, bool enable_statistics)
|
void kmalloc_init_arena(kmalloc_arena_t *a, bool enable_statistics)
|
||||||
{
|
{
|
||||||
|
@ -375,6 +423,7 @@ void kmalloc_init_arena(kmalloc_arena_t *a, bool enable_statistics)
|
||||||
a->malloc = gint_malloc;
|
a->malloc = gint_malloc;
|
||||||
a->free = gint_free;
|
a->free = gint_free;
|
||||||
a->realloc = gint_realloc;
|
a->realloc = gint_realloc;
|
||||||
|
a->malloc_max = gint_malloc_max;
|
||||||
|
|
||||||
/* The index is located at the very start of the arena */
|
/* The index is located at the very start of the arena */
|
||||||
index_t *index = a->start;
|
index_t *index = a->start;
|
||||||
|
|
|
@ -131,6 +131,36 @@ void kfree(void *ptr)
|
||||||
a->stats.live_blocks--;
|
a->stats.live_blocks--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* kmalloc_max(): Allocate the largest block available in an arena */
|
||||||
|
void *kmalloc_max(size_t *size, char const *name)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < KMALLOC_ARENA_MAX; i++) if(arenas[i])
|
||||||
|
{
|
||||||
|
kmalloc_arena_t *a = arenas[i];
|
||||||
|
if(strcmp(a->name, name)) continue;
|
||||||
|
|
||||||
|
void *rc = a->malloc_max ? a->malloc_max(size, a->data) : NULL;
|
||||||
|
|
||||||
|
/* Maintain statistics */
|
||||||
|
struct kmalloc_stats *s = &a->stats;
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
s->live_blocks++;
|
||||||
|
s->peak_live_blocks = max(s->live_blocks,
|
||||||
|
s->peak_live_blocks);
|
||||||
|
s->total_volume += *size;
|
||||||
|
s->total_blocks++;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s->total_failures++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* kmalloc_add_arena(): Add a new arena to the heap source */
|
/* kmalloc_add_arena(): Add a new arena to the heap source */
|
||||||
bool kmalloc_add_arena(kmalloc_arena_t *arena)
|
bool kmalloc_add_arena(kmalloc_arena_t *arena)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue