//--- // gint:kmalloc:kmalloc - Main allocator routines //--- #include #include #include /* Maximum number of arenas */ #define KMALLOC_ARENA_MAX 8 /* List of arenas in order of consideration */ static kmalloc_arena_t *arenas[KMALLOC_ARENA_MAX] = { 0 }; /* kmalloc_init(): Initialize the dynamic allocator */ void kmalloc_init(void) { /* Provide the OS heap */ extern kmalloc_arena_t kmalloc_arena_osheap; arenas[0 /* KMALLOC_ARENA_MAX - 1 */] = &kmalloc_arena_osheap; } //--- // Allocation functions //--- /* Find the arena that contains a given block */ static kmalloc_arena_t *arena_owning(void *ptr) { for(int i = 0; i < KMALLOC_ARENA_MAX; i++) { kmalloc_arena_t *a = arenas[i]; if(!a) continue; if((a->start <= ptr && ptr < a->end) || (a->start == NULL && a->end == NULL)) return a; } return NULL; } /* kmalloc(): Allocate memory in one of the available arenas */ void *kmalloc(size_t size, char const *name) { if(size == 0) return NULL; for(int i = 0; i < KMALLOC_ARENA_MAX; i++) if(arenas[i]) { kmalloc_arena_t *a = arenas[i]; if(name && strcmp(a->name, name)) continue; if(!name && !a->is_default) continue; /* Try to allocate in this arena */ void *rc = a->malloc(size, a->data); /* 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; } /* krealloc(): Reallocate memory */ void *krealloc(void *ptr, size_t size) { if(!ptr) { return kmalloc(size, NULL); } if(!size) { kfree(ptr); return NULL; } kmalloc_arena_t *a = arena_owning(ptr); if(!a) return NULL; return a->realloc(ptr, size, a->data); } /* kfree(): Free memory allocated with kalloc() */ void kfree(void *ptr) { if(!ptr) return; /* If this condition fails, then the pointer is invalid */ kmalloc_arena_t *a = arena_owning(ptr); if(!a) return; a->free(ptr, a->data); /* Maintain statistics */ a->stats.live_blocks--; } /* kmalloc_add_arena(): Add a new arena to the heap source */ bool kmalloc_add_arena(kmalloc_arena_t *arena) { for(int i = 0; i < KMALLOC_ARENA_MAX; i++) { if(!arenas[i]) { arenas[i] = arena; return true; } } return false; }