Compare commits

..

3 Commits

Author SHA1 Message Date
b0db2effc7 library is now C++ compatible :^) 2026-01-15 10:22:01 -05:00
11f1a7e7c3 add header guards 2026-01-15 10:14:32 -05:00
d078546eab prototypes for malloc impl 2026-01-15 10:14:05 -05:00
24 changed files with 441 additions and 0 deletions

122
include/ni_alloc/alloc.h Normal file
View File

@@ -0,0 +1,122 @@
#ifndef __NICKEL_ALLOC_H
#define __NICKEL_ALLOC_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Nickel Allocator API (explicit; does NOT replace libc malloc unless you opt-in).
Design goal: easy to use in tools, easy to test, portable across Linux/macOS.
*/
typedef struct ni_alloc_stats {
/* current usage */
size_t bytes_in_use; /* user-visible allocated bytes (approx if desired) */
size_t bytes_reserved; /* backing store reserved from VM */
size_t bytes_peak; /* peak in-use */
size_t bytes_reserved_peak;
/* counters */
uint64_t alloc_calls;
uint64_t free_calls;
uint64_t realloc_calls;
uint64_t calloc_calls;
uint64_t memalign_calls;
/* failures */
uint64_t oom_count;
} ni_alloc_stats;
/* Allocator configuration knobs (keep minimal at first; extend later). */
typedef struct ni_alloc_config {
/* If true, ni_free(NULL) is allowed and a no-op (recommended true). */
bool free_null_is_noop;
/* If true, ni_realloc(p,0) behaves like free(p) and returns NULL. */
bool realloc_zero_frees;
/* If true, scribble freed blocks with a pattern (debug build feature). */
bool scribble_free;
/* If true, scribble newly allocated blocks with a pattern (debug). */
bool scribble_alloc;
/* Optional alignment for default allocations (usually alignof(max_align_t)). */
size_t default_alignment;
/* Optional: maximum small-bin size, arena chunk size, etc. */
size_t arena_chunk_bytes;
} ni_alloc_config;
/* Opaque allocator instance.
You can use the global allocator, or create a private allocator instance
(handy for tests / subsystems).
*/
typedef struct ni_allocator ni_allocator;
/* -------- Global allocator API -------- */
/* Initialize/shutdown global allocator (optional; can be lazy).
Returns false if initialization fails.
*/
bool ni_alloc_global_init(const ni_alloc_config* cfg);
void ni_alloc_global_shutdown(void);
/* Allocation functions using the global allocator. */
void* ni_malloc(size_t size);
void ni_free(void* ptr);
void* ni_realloc(void* ptr, size_t new_size);
void* ni_calloc(size_t count, size_t elem_size);
/* Alignment:
- alignment must be power of two and >= sizeof(void*)
- returns NULL on failure
*/
void* ni_memalign(size_t alignment, size_t size);
/* Equivalent of C11 aligned_alloc semantics:
- alignment must be power of two
- size must be a multiple of alignment
*/
void* ni_aligned_alloc(size_t alignment, size_t size);
/* Query/reset stats for global allocator. */
void ni_alloc_get_stats(ni_alloc_stats* out_stats);
void ni_alloc_reset_stats(void);
/* -------- Instance allocator API -------- */
ni_allocator* ni_allocator_create(const ni_alloc_config* cfg);
void ni_allocator_destroy(ni_allocator* a);
void* ni_allocator_malloc(ni_allocator* a, size_t size);
void ni_allocator_free(ni_allocator* a, void* ptr);
void* ni_allocator_realloc(ni_allocator* a, void* ptr, size_t new_size);
void* ni_allocator_calloc(ni_allocator* a, size_t count, size_t elem_size);
void* ni_allocator_memalign(ni_allocator* a, size_t alignment, size_t size);
void ni_allocator_get_stats(ni_allocator* a, ni_alloc_stats* out_stats);
void ni_allocator_reset_stats(ni_allocator* a);
/* -------- Utilities / validation -------- */
/* Returns true if n is a power of two (and nonzero). */
bool ni_is_pow2_size(size_t n);
/* Round up x to next multiple of align (align must be power of two). */
size_t ni_align_up(size_t x, size_t align);
/* Optional: verify internal invariants in debug builds.
- returns false if corruption detected
*/
bool ni_alloc_validate(void);
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_ALLOC_H */

59
include/ni_alloc/vm.h Normal file
View File

@@ -0,0 +1,59 @@
#ifndef __NICKEL_VM_H
#define __NICKEL_VM_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* VM layer: portable-ish page allocation based on mmap/munmap (Linux + macOS). */
typedef struct ni_vm_stats {
size_t page_size;
/* cumulative counters */
uint64_t reserves; /* number of reserve calls */
uint64_t releases; /* number of release calls */
uint64_t commits; /* if supported by impl (optional), else 0 */
uint64_t decommits; /* if supported by impl (optional), else 0 */
size_t bytes_reserved; /* current bytes reserved */
size_t bytes_peak; /* peak reserved */
} ni_vm_stats;
/* Returns OS page size (usually sysconf(_SC_PAGESIZE)). Never returns 0. */
size_t ni_vm_page_size(void);
/* Reserve anonymous virtual memory.
- bytes will be rounded up to a page multiple.
- returns NULL on failure.
*/
void* ni_vm_reserve(size_t bytes);
/* Release a region previously returned by ni_vm_reserve (page-multiple size). */
bool ni_vm_release(void* addr, size_t bytes);
/* Optional: “commit/decommit” for platforms where its meaningful.
On many Unix systems, reserve implies commit; implementations may no-op.
*/
bool ni_vm_commit(void* addr, size_t bytes);
bool ni_vm_decommit(void* addr, size_t bytes);
/* Optional: set guard pages (mprotect) for debug.
Returns false if unsupported or fails.
*/
bool ni_vm_protect_none(void* addr, size_t bytes);
bool ni_vm_protect_rw(void* addr, size_t bytes);
/* Stats are optional but very useful for tests/tools. */
void ni_vm_get_stats(ni_vm_stats* out_stats);
void ni_vm_reset_stats(void);
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_VM_H */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_ARENA_H_
#define __NICKEL_ARENA_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_ARENA_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_ARGPARSE_H_
#define __NICKEL_ARGPARSE_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_ARGPARSE_H_ */

14
include/nickel/bitman.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_BITMAN_H_
#define __NICKEL_BITMAN_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_BITMAN_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_BUF_H_
#define __NICKEL_BUF_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_BUF_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_CTASSERT_H_
#define __NICKEL_CTASSERT_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_CTASSERT_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_DEFER_H_
#define __NICKEL_DEFER_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_DEFER_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_HASHMAP_H_
#define __NICKEL_HASHMAP_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_HASHMAP_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_INI_H_
#define __NICKEL_INI_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_INI_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_IO_H_
#define __NICKEL_IO_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_IO_H_ */

View File

@@ -6,6 +6,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ni_list_node { typedef struct ni_list_node {
struct ni_list_node* next; struct ni_list_node* next;
struct ni_list_node* prev; struct ni_list_node* prev;
@@ -65,4 +69,8 @@ static inline ni_list_node* ni_list__get_back(ni_list* l) {
#define NI_LIST_CONTAINER_OF(ptr, type, member) \ #define NI_LIST_CONTAINER_OF(ptr, type, member) \
((type*)((uint8_t*)(ptr) - offsetof(type, member))) ((type*)((uint8_t*)(ptr) - offsetof(type, member)))
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_LINKEDLIST_H_ */ #endif /* __NICKEL_LINKEDLIST_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_LOG_H_
#define __NICKEL_LOG_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_LOG_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_REFCNT_H_
#define __NICKEL_REFCNT_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_REFCNT_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_RESULT_H_
#define __NICKEL_RESULT_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_RESULT_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_RINGSPSC_H_
#define __NICKEL_RINGSPSC_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_RINGSPSC_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_SPAN_H_
#define __NICKEL_SPAN_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_SPAN_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_THREADPOOL_H_
#define __NICKEL_THREADPOOL_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_THREADPOOL_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_TIMEUTIL_H_
#define __NICKEL_TIMEUTIL_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_TIMEUTIL_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_VERSION_H_
#define __NICKEL_VERSION_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_VERSION_H_ */

View File

@@ -0,0 +1,14 @@
#ifndef __NICKEL_XALLOC_H_
#define __NICKEL_XALLOC_H_
#ifdef __cplusplus
extern "C" {
#endif
/* header contents */
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_XALLOC_H_ */

0
src/ni_alloc/vm_legacy.c Normal file
View File

0
src/ni_alloc/vm_posix.c Normal file
View File