Compare commits

..

6 Commits

9 changed files with 183 additions and 22 deletions

View File

@@ -13,6 +13,8 @@ extern "C" {
Design goal: easy to use in tools, easy to test, portable across Linux/macOS. Design goal: easy to use in tools, easy to test, portable across Linux/macOS.
*/ */
//#define ENABLE_NICKEL_ALLOC_SHIM
typedef struct ni_alloc_stats { typedef struct ni_alloc_stats {
/* current usage */ /* current usage */
size_t bytes_in_use; /* user-visible allocated bytes (approx if desired) */ size_t bytes_in_use; /* user-visible allocated bytes (approx if desired) */
@@ -115,6 +117,17 @@ size_t ni_align_up(size_t x, size_t align);
*/ */
bool ni_alloc_validate(void); bool ni_alloc_validate(void);
#ifdef ENABLE_NICKEL_ALLOC_SHIM
/* Allocation functions using the global allocator.
define symbols pointing at our versions
*/
void* malloc(size_t size) { ni_malloc(size); }
void free(void* ptr) { ni_free(ptr); }
void* realloc(void* ptr, size_t new_size) { ni_realloc(ptr, new_size); }
void* calloc(size_t count, size_t elem_size) { ni_calloc(count, elem_size); }
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

29
include/nickel.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef __NICKEL_H_
#define __NICKEL_H_
/* common includes across the project */
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
/* includes from internal to the project */
// ...
#ifdef __cplusplus
extern "C" {
#endif
// any thing we need in the top level here
#ifdef __cplusplus
}
#endif
#endif /* __NICKEL_H_ */

View File

@@ -1,10 +1,7 @@
#ifndef __NICKEL_LINKEDLIST_H_ #ifndef __NICKEL_LINKEDLIST_H_
#define __NICKEL_LINKEDLIST_H_ #define __NICKEL_LINKEDLIST_H_
#include <stdlib.h> #include "nickel.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -1,19 +1,13 @@
#ifndef __NICKEL_XALLOC_H_ #ifndef __NICKEL_XALLOC_H_
#define __NICKEL_XALLOC_H_ #define __NICKEL_XALLOC_H_
#include <sys/types.h> #include "nickel.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void* ni_xmalloc(size_t size); void* ni_xmalloc(size_t size);
void ni_free(void* ptr);
void* ni_xcalloc(size_t nmemb,size_t size); void* ni_xcalloc(size_t nmemb,size_t size);
void* ni_xrealloc(void* ptr, size_t size); void* ni_xrealloc(void* ptr, size_t size);

View File

@@ -1,9 +1,13 @@
ALLOC_LIB := $(BUILD_DIR)/lib/libnia.a
LIB := $(BUILD_DIR)/lib/libnickel.a LIB := $(BUILD_DIR)/lib/libnickel.a
BIN_DIR := $(BUILD_DIR)/bin BIN_DIR := $(BUILD_DIR)/bin
OBJ_DIR := $(BUILD_DIR)/obj OBJ_DIR := $(BUILD_DIR)/obj
NI_ALLOC_SRCS := $(wildcard src/nickel/ni_alloc/*.c)
NI_ALLOC_OBJS := $(patsubst src/ni_alloc/%.c,$(OBJ_DIR)/ni_alloc/%.o,$(NI_ALLOC_SRCS))
NICKEL_SRCS := $(wildcard src/nickel/*.c) NICKEL_SRCS := $(wildcard src/nickel/*.c)
NICKEL_OBJS := $(patsubst src/%.c,$(OBJ_DIR)/%.o,$(NICKEL_SRCS)) NICKEL_OBJS := $(patsubst src/nickel/%.c,$(OBJ_DIR)/nickel/%.o,$(NICKEL_SRCS))
TEST_SRCS := $(wildcard tests/*.c) TEST_SRCS := $(wildcard tests/*.c)
TEST_BIN := $(BIN_DIR)/tests TEST_BIN := $(BIN_DIR)/tests
@@ -14,7 +18,12 @@ TOOL_BINS := \
.PHONY: all clean test tools examples .PHONY: all clean test tools examples
all: $(LIB) tools $(TEST_BIN) all: $(ALLOC_LIB) $(LIB) tools $(TEST_BIN)
$(ALLOC_LIB): $(NI_ALLOC_OBJS)
@mkdir -p $(dir $@)
$(AR) rcs $@ $^
$(RANLIB) $@
$(LIB): $(NICKEL_OBJS) $(LIB): $(NICKEL_OBJS)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@@ -26,9 +35,9 @@ $(OBJ_DIR)/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
# Tests link against libnickel.a # Tests link against libnickel.a
$(TEST_BIN): $(TEST_SRCS) $(LIB) $(TEST_BIN): $(TEST_SRCS) $(ALLOC_LIB) $(LIB)
@mkdir -p $(BIN_DIR) @mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TEST_SRCS) $(LIB) $(LDLIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TEST_SRCS) $(ALLOC_LIB) $(LIB) $(LDLIBS)
# Tools (one main.c each; expand as needed) # Tools (one main.c each; expand as needed)
#$(BIN_DIR)/logscan: tools/logscan/main.c $(LIB) #$(BIN_DIR)/logscan: tools/logscan/main.c $(LIB)
@@ -39,10 +48,10 @@ $(TEST_BIN): $(TEST_SRCS) $(LIB)
# @mkdir -p $(BIN_DIR) # @mkdir -p $(BIN_DIR)
# $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIB) $(LDLIBS) # $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIB) $(LDLIBS)
tools: $(TOOL_BINS)
test: $(TEST_BIN) test: $(TEST_BIN)
$(TEST_BIN) $(TEST_BIN)
tools: $(TOOL_BINS)
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)

View File

@@ -0,0 +1,58 @@
#include "ni_alloc/alloc.h"
/* -------- 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);

View File

@@ -0,0 +1,29 @@
#include "ni_alloc/vm.h"
/* 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);

View File

@@ -1,5 +1,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@@ -8,25 +9,56 @@
#include "nickel/xalloc.h" #include "nickel/xalloc.h"
void* ni_xmalloc(size_t size) { void* ni_xmalloc(size_t size) {
void* retptr = malloc(size);
} if (retptr != NULL) {
return retptr;
void ni_free(void* ptr) { } else {
perror("xmalloc failed");
exit(EXIT_FAILURE);
}
} }
void* ni_xcalloc(size_t nmemb,size_t size) { void* ni_xcalloc(size_t nmemb,size_t size) {
void* retptr = calloc(nmemb, size);
if (retptr != NULL) {
return retptr;
} else {
perror("xcalloc failed");
exit(EXIT_FAILURE);
}
} }
void* ni_xrealloc(void* ptr, size_t size) { void* ni_xrealloc(void* ptr, size_t size) {
void* retptr = realloc(ptr, size);
if (retptr != NULL) {
return retptr;
} else {
perror("xrealloc failed");
exit(EXIT_FAILURE);
}
} }
char* ni_xstrdup(const char *s) { char* ni_xstrdup(const char *s) {
void* dupstr = strdup(s);
if (dupstr != NULL) {
return dupstr;
} else {
perror("xdupstr failed");
exit(EXIT_FAILURE);
}
} }
char* ni_xstrndup(const char s[], size_t n) { char* ni_xstrndup(const char s[], size_t n) {
void* dupstr = strndup(s, n);
if (dupstr != NULL) {
return dupstr;
} else {
perror("xdupstr failed");
exit(EXIT_FAILURE);
}
} }