mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-01-01 06:23:35 +01:00
175 lines
6 KiB
C
175 lines
6 KiB
C
//---
|
|
// gint:kmalloc - gint's memory allocator
|
|
//---
|
|
|
|
#ifndef GINT_KMALLOC
|
|
#define GINT_KMALLOC
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <gint/config.h>
|
|
#include <gint/defs/types.h>
|
|
|
|
//---
|
|
// Standard memory allocation API
|
|
//---
|
|
|
|
/* kmalloc(): Allocate memory in one of the available arenas
|
|
This function acts like malloc(). The second parameter specifies which arena
|
|
to allocate from; when NULL, all default arenas are considered.
|
|
|
|
@size Size of requested block
|
|
@arena_name Name of arena to allocate in (can be NULL)
|
|
Returns address of allocated block, NULL on error. */
|
|
void *kmalloc(size_t size, char const *arena_name);
|
|
|
|
/* krealloc(): Reallocate memory
|
|
This function acts like realloc(). It only tries to reallocate the block in
|
|
the arena where it was previously allocated. Note that if NULL is returned,
|
|
the user needs to have a copy of the original address or the memory will
|
|
become unreachable.
|
|
|
|
@ptr Existing allocated block
|
|
@size New requested size for the block
|
|
Returns address of reallocated block, NULL on error. */
|
|
void *krealloc(void *ptr, size_t size);
|
|
|
|
/* kfree(): Free memory allocated with kalloc() */
|
|
void kfree(void *ptr);
|
|
|
|
//---
|
|
// Extension API for new areas and statistics
|
|
//---
|
|
|
|
typedef struct {
|
|
/* Functions managing the arena. The last argument is the [data]
|
|
attribute in this structure. */
|
|
|
|
/* kmalloc() handles size == 0 */
|
|
void * (*malloc)(size_t size, void *data);
|
|
/* krealloc() handles ptr == NULL, as well as newsize == 0 */
|
|
void * (*realloc)(void *ptr, size_t newsize, void *data);
|
|
/* kfree() handles ptr == NULL*/
|
|
void (*free)(void *ptr, void *data);
|
|
|
|
/* Name, should be unique; gint reserves names starting with "_" */
|
|
char const *name;
|
|
/* Start and end of arena. This is used to find the proper arena to
|
|
free from in kfree(). This cannot be NULL except for the OS heap as
|
|
the exact addresses are unknown. */
|
|
void *start, *end;
|
|
/* Pointer to arena-provided data, passed to malloc() and free() */
|
|
void *data;
|
|
/* Whether to consider this arena when performing default allocations
|
|
(kmalloc() with arena_name == NULL) */
|
|
int is_default;
|
|
|
|
/* Statistics maintained by kmalloc() */
|
|
struct kmalloc_stats {
|
|
int live_blocks;
|
|
int peak_live_blocks;
|
|
int total_volume;
|
|
int total_blocks;
|
|
int total_failures;
|
|
} stats;
|
|
|
|
} kmalloc_arena_t;
|
|
|
|
/* kmalloc_init_arena(): Initialize an arena with gint's allocator
|
|
|
|
This function initializes an arena on the region located between (a->start)
|
|
and (a->end) and initializes the data structures for gint's allocator. It
|
|
only sets the malloc(), realloc(), free() and (data) attributes of the
|
|
structure, everything else should be initialized manually. The arena must
|
|
have at least 256 bytes. */
|
|
void kmalloc_init_arena(kmalloc_arena_t *a, bool enable_statistics);
|
|
|
|
/* kmalloc_add_arena(): Add a new arena to the heap source
|
|
Adds a fully-initialized arena to the heap source. The priority of the new
|
|
arena compared to other default arenas is not specified. Returns true on
|
|
success, false if the maximum number of arenas has been reached. */
|
|
bool kmalloc_add_arena(kmalloc_arena_t *arena);
|
|
|
|
//---
|
|
// Internal functions
|
|
//---
|
|
|
|
/* kmalloc_init(): Initialize the dynamic allocator */
|
|
void kmalloc_init(void);
|
|
|
|
/* kmalloc_get_arena(): Find an arena by name */
|
|
kmalloc_arena_t *kmalloc_get_arena(char const *name);
|
|
|
|
//---
|
|
// Introspection functions for arenas managed by gint's allocator
|
|
//---
|
|
|
|
/* kmalloc_gint_stats_t: Optional statistics for gint's allocator
|
|
|
|
These statistics are tracked by gint's allocator if requested when the arena
|
|
is created. They can't be added or removed after creation.
|
|
|
|
The free memory and used memory are counted in data bytes. Because the
|
|
allocator uses some data, the initial value of (free_memory) is less than
|
|
the size of the region. Additionally, because each used or free block has a
|
|
4-byte header, (free_memory + used_memory) is not a constant value, so don't
|
|
expect to get exactly what these values indicate (also fragmentation). */
|
|
typedef struct {
|
|
/* Free space, used space, peak used space over time */
|
|
uint32_t free_memory;
|
|
uint32_t used_memory;
|
|
uint32_t peak_used_memory;
|
|
/* Number of mallocs that failed because of not enough free space */
|
|
int exhaustion_failures;
|
|
/* Number of mallocs that failed because of fragmentation */
|
|
int fragmentation_failures;
|
|
/* Number of reallocs that successfully re-used the same location */
|
|
int expanding_reallocs;
|
|
/* Number of reallocs that moved the data around */
|
|
int relocating_reallocs;
|
|
} kmalloc_gint_stats_t;
|
|
|
|
/* kmalloc_get_gint_stats(): Get gint statistics for an arena
|
|
|
|
Returns a pointer to the arena's statistics; returns NULL if the arena is
|
|
not managed by gint's allocator or statistics were not enabled. */
|
|
kmalloc_gint_stats_t *kmalloc_get_gint_stats(kmalloc_arena_t *arena);
|
|
|
|
#ifdef GINT_KMALLOC_DEBUG
|
|
|
|
/* Check that the sequence covers exactly the arena's region. */
|
|
bool kmallocdbg_sequence_covers(kmalloc_arena_t *a);
|
|
|
|
/* Check that the marker for the last block is correctly set and unique. */
|
|
bool kmallocdbg_sequence_terminator(kmalloc_arena_t *a);
|
|
|
|
/* Check that the values of (used) and (previous_used) are coherent. */
|
|
bool kmallocdbg_sequence_coherent_used(kmalloc_arena_t *a);
|
|
|
|
/* Check that the size in the footer is correct for all free blocks. */
|
|
bool kmallocdbg_sequence_footer_size(kmalloc_arena_t *a);
|
|
|
|
/* Check that all free blocks are surrounded by used blocks. */
|
|
bool kmallocdbg_sequence_merged_free(kmalloc_arena_t *a);
|
|
|
|
/* Check that the doubly-linked list is well-formed. */
|
|
bool kmallocdbg_list_structure(kmalloc_arena_t *a);
|
|
|
|
/* Check that used blocks and list cover exactly the arena's region. */
|
|
bool kmallocdbg_index_covers(kmalloc_arena_t *a);
|
|
|
|
/* Check that all blocs referenced in free lists are of the correct class. */
|
|
bool kmallocdbg_index_class_separation(kmalloc_arena_t *a);
|
|
|
|
/* Number of blocks in the sequence. */
|
|
int kmallocdbg_sequence_length(kmalloc_arena_t *a);
|
|
|
|
#endif /* GINT_KMALLOC_DEBUG */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* GINT_KMALLOC */
|