Initial commit
This commit is contained in:
		
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) [year] [fullname] | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | SOFTWARE. | ||||||
							
								
								
									
										76
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | # Compiler Flags | ||||||
|  | CC := gcc | ||||||
|  | CFLAGS := -g -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined -fno-omit-frame-pointer | ||||||
|  | export ASAN_OPTIONS = allocator_may_return_null=1 | ||||||
|  | # Directory variables  | ||||||
|  | LIBDIR := lib | ||||||
|  | OBJ := obj | ||||||
|  | INC := include | ||||||
|  | SRC := src | ||||||
|  | TEST := tests | ||||||
|  |  | ||||||
|  | # Filepath Pattern Matching | ||||||
|  | LIB := $(LIBDIR)/lib.a | ||||||
|  | SRCS := $(wildcard $(SRC)/*.c) | ||||||
|  | OBJS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SRCS)) | ||||||
|  | TESTS := $(wildcard $(TEST)/*.c) | ||||||
|  | TESTBINS := $(patsubst $(TEST)/%.c, $(TEST)/bin/%, $(TESTS)) | ||||||
|  |  | ||||||
|  | # Commands must be labeled PHONY | ||||||
|  | .PHONY: all release clean test | ||||||
|  |  | ||||||
|  | # Compiler Release Flags  | ||||||
|  | release: CFLAGS := -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined -fno-omit-frame-pointer -O2 -DNDEBUG | ||||||
|  | release: clean $(LIB) | ||||||
|  |  | ||||||
|  | # Target for compilation. | ||||||
|  | all: $(LIB) | ||||||
|  |  | ||||||
|  | # Target / Dependencies | ||||||
|  | $(LIB): $(OBJS) | $(LIBDIR) | ||||||
|  | 	$(RM) $(LIB) | ||||||
|  | 	ar -cvrs $@ $^ | ||||||
|  |  | ||||||
|  | $(OBJ)/%.o: $(SRC)/%.c $(SRC)/%.h | $(OBJ) | ||||||
|  | 	$(CC) $(CFLAGS) -c $< -o $@ | ||||||
|  |  | ||||||
|  | $(OBJ)/%.o: $(SRC)/%.c | $(OBJ) | ||||||
|  | 	$(CC) $(CFLAGS) -c $< -o $@ | ||||||
|  |  | ||||||
|  | $(TEST)/bin/%: $(TEST)/%.c $(LIB) | $(TEST)/bin | ||||||
|  | 	$(CC) $(CFLAGS) $< $(LIB) -o $@ | ||||||
|  |  | ||||||
|  | # Make directories if none.  | ||||||
|  | $(LIBDIR): | ||||||
|  | 	mkdir $@ | ||||||
|  |  | ||||||
|  | $(INC): | ||||||
|  | 	mkdir $@ | ||||||
|  |  | ||||||
|  | $(OBJ): | ||||||
|  | 	mkdir $@ | ||||||
|  |  | ||||||
|  | $(TEST)/bin: | ||||||
|  | 	mkdir $@ | ||||||
|  |  | ||||||
|  | # Run the tests in the bin folder and track results | ||||||
|  | test: $(LIB) $(TEST)/bin $(TESTBINS) | ||||||
|  | 	@SUCCESS_COUNT=0; FAILURE_COUNT=0; \ | ||||||
|  | 	for test in $(TESTBINS); do \ | ||||||
|  | 		./$$test; \ | ||||||
|  | 		EXIT_CODE=$$?; \ | ||||||
|  | 		TEST_NAME=$(notdir $$test); \ | ||||||
|  | 		if [ $$EXIT_CODE -eq 0 ]; then \ | ||||||
|  | 			echo "\033[0;32m$$TEST_NAME: EXIT CODE: $$EXIT_CODE (SUCCESS)\033[0m"; \ | ||||||
|  | 			SUCCESS_COUNT=$$((SUCCESS_COUNT + 1)); \ | ||||||
|  | 		else \ | ||||||
|  | 			echo "\033[0;31m$$TEST_NAME: EXIT CODE: $$EXIT_CODE (FAILURE)\033[0m"; \ | ||||||
|  | 			FAILURE_COUNT=$$((FAILURE_COUNT + 1)); \ | ||||||
|  | 		fi; \ | ||||||
|  | 	done; \ | ||||||
|  | 	echo "\n\nTests completed"; \ | ||||||
|  | 	echo "SUCCESS: $$SUCCESS_COUNT"; \ | ||||||
|  | 	echo "FAILURE: $$FAILURE_COUNT"; | ||||||
|  |  | ||||||
|  | clean: | ||||||
|  | 	$(RM) -r $(LIBDIR) $(OBJ) $(TEST)/bin/ | ||||||
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # arena  | ||||||
|  |  | ||||||
|  | ## Description | ||||||
|  | Arena based memory allocation. | ||||||
|  |  | ||||||
|  | ## Table of Contents | ||||||
|  |  | ||||||
|  | - [Description](#description) | ||||||
|  | - [Features](#features)  | ||||||
|  | - [Usage](#usage) | ||||||
|  | - [Credits / Resources](#credits--resources) | ||||||
|  | - [License](#license) | ||||||
|  |  | ||||||
|  | ## Features / TODOS | ||||||
|  |  | ||||||
|  | ## Usage | ||||||
|  |  | ||||||
|  | ## Credits / Resources | ||||||
|  | [C Interfaces and Implementations - David Hanson](https://github.com/drh/cii)<br> | ||||||
|  | [Arena Allocator Tips and Tricks - Chris Wellons](https://nullprogram.com/blog/2023/09/27/)<br> | ||||||
|  | [Memory Allocation Strategies - Ginger Bill](https://www.gingerbill.org/series/memory-allocation-strategies/)<br> | ||||||
|  | ## License | ||||||
|  | This project is licensed under MIT - see the [LICENSE](LICENSE) file for details. | ||||||
							
								
								
									
										20
									
								
								include/arena.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/arena.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | #ifndef ARENA_INCLUDED | ||||||
|  | #define ARENA_INCLUDED | ||||||
|  |  | ||||||
|  | struct Arena { | ||||||
|  |     unsigned char *beg; | ||||||
|  |     unsigned char *end; | ||||||
|  | }; | ||||||
|  | typedef struct Arena Arena; | ||||||
|  |  | ||||||
|  | extern void *arena_alloc(int flags, struct Arena *a, size_t nbytes,  | ||||||
|  |         size_t align, size_t count, const char *file, int line); | ||||||
|  |  | ||||||
|  | extern struct Arena arena_new(int flags, size_t cap, const char *file, int line); | ||||||
|  | extern void arena_back(struct Arena *a, void *buf, size_t len); | ||||||
|  |  | ||||||
|  | #define ARENA(flags, cap) arena_new((flags), (cap), __FILE__, __LINE__) | ||||||
|  | #define ARENA_BACK(a, buf, len) arena_back((a), (buf), (len)) | ||||||
|  | #define ARENA_ALLOC(flags, a, nbytes, align, count) \ | ||||||
|  |     arena_alloc((flags), (a), (nbytes), (align), (count), __FILE__, __LINE__) | ||||||
|  | #endif | ||||||
							
								
								
									
										81
									
								
								include/except.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								include/except.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | #ifndef EXCEPT_INCLUDED | ||||||
|  | #define EXCEPT_INCLUDED | ||||||
|  |  | ||||||
|  | #include <setjmp.h> | ||||||
|  | #define UNUSED(x) (void)(x) | ||||||
|  |  | ||||||
|  | struct Exception { | ||||||
|  | 	const char *reason; | ||||||
|  | }; | ||||||
|  | typedef struct Exception Exception; | ||||||
|  |  | ||||||
|  | struct ExceptFrame { | ||||||
|  | 	struct ExceptFrame *prev;   // Exception Stack | ||||||
|  | 	jmp_buf env;                // Enviroment Buffer | ||||||
|  |     	const char *file;           // Exception File | ||||||
|  | 	int line;                   // Exception Line | ||||||
|  | 	const Exception *exception; // Exception Reason | ||||||
|  | }; | ||||||
|  | typedef struct ExceptFrame ExceptFrame; | ||||||
|  |  | ||||||
|  | // Exception States  | ||||||
|  | enum { EXCEPT_ENTERED=0, EXCEPT_RAISED, EXCEPT_HANDLED, EXCEPT_FINALIZED}; | ||||||
|  |  | ||||||
|  | void except_raise(const Exception *e, const char *file,int line); // Raise exceptions | ||||||
|  |  | ||||||
|  | // External declarations  | ||||||
|  | extern ExceptFrame *except_stack; // Global exception stack | ||||||
|  | extern const Exception assert_failed; // Forward declaration for assert.  | ||||||
|  | extern void asserted(int e); | ||||||
|  |  | ||||||
|  | #ifdef NDEBUG | ||||||
|  | #define ASSERTED(e) ((void)0) | ||||||
|  | #else | ||||||
|  | #define ASSERTED(e) ((void)((e)||(RAISE(assert_failed),0))) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // Raise an Exception. | ||||||
|  | #define RAISE(e) except_raise(&(e), __FILE__, __LINE__) | ||||||
|  |  | ||||||
|  | // Reraise the currect exception. | ||||||
|  | #define RERAISE except_raise(except_frame.exception, \ | ||||||
|  | 	except_frame.file, except_frame.line) | ||||||
|  |  | ||||||
|  | // Switch to the previous exception frame and return. | ||||||
|  | #define RETURN switch (except_stack = except_stack->prev,0) default: return | ||||||
|  |  | ||||||
|  | // Start a try block. | ||||||
|  | #define TRY do { \ | ||||||
|  | 	volatile int except_flag; \ | ||||||
|  | 	ExceptFrame except_frame; \ | ||||||
|  | 	except_frame.prev = except_stack; \ | ||||||
|  | 	except_stack = &except_frame;  \ | ||||||
|  | 	except_flag = setjmp(except_frame.env); \ | ||||||
|  | 	if (except_flag == EXCEPT_ENTERED) { | ||||||
|  |  | ||||||
|  | // Handle specific example. | ||||||
|  | #define EXCEPT(e) \ | ||||||
|  | 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||||
|  | 	} else if (except_frame.exception == &(e)) { \ | ||||||
|  | 		except_flag = EXCEPT_HANDLED; | ||||||
|  |  | ||||||
|  | // Catch all other exceptions.         | ||||||
|  | #define ELSE \ | ||||||
|  | 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||||
|  | 	} else { \ | ||||||
|  | 		except_flag = EXCEPT_HANDLED; | ||||||
|  |  | ||||||
|  | // Execute finalization code.         | ||||||
|  | #define FINALLY \ | ||||||
|  | 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||||
|  | 	} { \ | ||||||
|  | 		if (except_flag == EXCEPT_ENTERED) \ | ||||||
|  | 			except_flag = EXCEPT_FINALIZED; | ||||||
|  |  | ||||||
|  | // End Try block.          | ||||||
|  | #define END_TRY \ | ||||||
|  | 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||||
|  | 		} if (except_flag == EXCEPT_RAISED) RERAISE; \ | ||||||
|  | } while (0) | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										35
									
								
								include/mem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/mem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | #ifndef MEM_INCLUDED | ||||||
|  | #define MEM_INCLUDED | ||||||
|  |  | ||||||
|  | #include "except.h" // Exceptions | ||||||
|  | #include <stddef.h> // size_t | ||||||
|  |  | ||||||
|  | /* General Macros*/ | ||||||
|  | #define MEM_KB(x) ((size_t)(x) * 1024ULL) | ||||||
|  | #define MEM_MB(x) ((size_t)(x) * 1024ULL * 1024ULL) | ||||||
|  | #define MEM_GB(x) ((size_t)(x) * 1024ULL * 1024ULL * 1024ULL) | ||||||
|  | #define MEM_SIZE(x)    (ptrdiff_t)sizeof(x) | ||||||
|  | #define MEM_COUNT(a)   (MEM_SIZE(a) / MEM_SIZE(*(a))) | ||||||
|  | #define MEM_LEN(s)     (MEM_COUNT(s) - 1) | ||||||
|  |  | ||||||
|  | /* Default behavior is to throw exceptions and zero out memory*/ | ||||||
|  | enum MemFlags { | ||||||
|  |     NOZERO       = 1 << 0,  /* 0001 */ | ||||||
|  |     SOFT_FAIL    = 1 << 1,  /* 0010 */ | ||||||
|  |     HARD_FAIL    = 1 << 2,  /* 0100 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | extern const Exception OOM; // Out of memory | ||||||
|  |  | ||||||
|  | extern void *mem_alloc (int flags, size_t nbytes, const char *file, int line); | ||||||
|  | extern void mem_free(void *ptr, const char *file, int line); | ||||||
|  | extern void *mem_resize(int flags, void *ptr, size_t nbytes, const char *file, int line); | ||||||
|  | extern int mem_is_zero(const void *ptr, size_t nbytes); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define ALLOC(flags, nbytes)  mem_alloc((flags), (nbytes), __FILE__, __LINE__) | ||||||
|  | #define FREE(ptr) ((void)(mem_free((ptr), __FILE__, __LINE__), (ptr) = 0)) | ||||||
|  | #define RESIZE(flags, ptr, nbytes) 	((ptr) = mem_resize((flags), (ptr), \ | ||||||
|  | 	(nbytes), __FILE__, __LINE__)) | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										38
									
								
								src/arena.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/arena.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | #include "../include/mem.h"   // Flags | ||||||
|  | #include "../include/arena.h" // Arena | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | struct Arena arena_new(int flags, size_t cap, const char *file, int line){ | ||||||
|  |     struct Arena a = {0}; | ||||||
|  |     a.beg = mem_alloc(flags, cap, file, line); | ||||||
|  |     a.end = a.beg ? a.beg+cap : 0; | ||||||
|  |     return a; | ||||||
|  | } | ||||||
|  | void arena_back(struct Arena *a, void *buf, size_t len){ | ||||||
|  |     ASSERTED(a != NULL); | ||||||
|  |     ASSERTED(buf != NULL); | ||||||
|  |     ASSERTED(len > 0); | ||||||
|  |     a->beg = (unsigned char *)buf; | ||||||
|  |     a->end = a->beg+len; | ||||||
|  | } | ||||||
|  | void *arena_alloc(int flags, struct Arena *a, size_t nbytes, size_t align,  | ||||||
|  |         size_t count, const char *file, int line){ | ||||||
|  |     ptrdiff_t padding = -(uintptr_t)a->beg & (align - 1); | ||||||
|  |     ptrdiff_t available = a->end - a->beg - padding; | ||||||
|  |     if (available < 0 || count > available/nbytes) { | ||||||
|  |         if(flags & SOFT_FAIL) return NULL; | ||||||
|  |         if(flags & HARD_FAIL) exit(12); // ENOMEM | ||||||
|  |         // Raise Exception  | ||||||
|  |         if (file == NULL) // Wasn't called by macro | ||||||
|  |             RAISE(OOM); // Out of Memory Exception | ||||||
|  |         else // Called by macro | ||||||
|  |             except_raise(&OOM, file, line); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void *p = a->beg + padding; | ||||||
|  |     a->beg += padding + count*nbytes; | ||||||
|  |     // Check flags to see if it gets zeroed out | ||||||
|  |     return flags&NOZERO ? p : memset(p, 0, count*nbytes); | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/except.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/except.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | #include "../include/except.h" | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | ExceptFrame *except_stack = NULL; // Global exception stack. | ||||||
|  | const Exception assert_failed = { "Assertion Failure!" }; // If ASSERT fails. | ||||||
|  |  | ||||||
|  | void except_raise(const Exception *e, const char *file,int line) { | ||||||
|  |     // An exception was raised, grab the exception stack. | ||||||
|  | 	ExceptFrame *p = except_stack; | ||||||
|  |     asserted(e != NULL);  // Ensure exception pointer is not NULL | ||||||
|  | 	if (p == NULL) { // Uncaught Exception | ||||||
|  |         const char *msg = e->reason ? e->reason : "Uncaught Exception!";  | ||||||
|  | 		fprintf(stderr,"\033[31m%s | Address: 0x%p | Raised at %s@%d \033[0m" ,msg,(void *)e,file,line); | ||||||
|  |         fflush(stderr); | ||||||
|  |         abort(); | ||||||
|  |     } | ||||||
|  |    // Set the exception details to the current frame.  | ||||||
|  | 	p->exception = e; // Exception reason | ||||||
|  | 	p->file = file; | ||||||
|  | 	p->line = line; | ||||||
|  |     // Move to the previous frame in the stack. | ||||||
|  | 	except_stack = except_stack->prev; | ||||||
|  |     // Jump to the saved context environment. | ||||||
|  | 	longjmp(p->env, EXCEPT_RAISED); | ||||||
|  | } | ||||||
|  | void asserted(int e) { | ||||||
|  | 	ASSERTED(e); | ||||||
|  |     UNUSED(e); | ||||||
|  | } | ||||||
							
								
								
									
										65
									
								
								src/mem.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/mem.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include "../include/except.h" | ||||||
|  | #include "../include/mem.h" | ||||||
|  |  | ||||||
|  | const Exception OOM = { "Out of Memory" };/* Out of memory Exception */ | ||||||
|  | #define MEM_ENOMEM 12 /* Out of memory errno */ | ||||||
|  |  | ||||||
|  | void *mem_alloc(int flags, size_t nbytes, const char *file, int line){ | ||||||
|  |     void *ptr; | ||||||
|  |     ASSERTED(nbytes > 0); | ||||||
|  |     ptr = malloc(nbytes); | ||||||
|  |     if (ptr == NULL){ | ||||||
|  |         if (flags & SOFT_FAIL) return 0; | ||||||
|  |         if (flags & HARD_FAIL) exit(MEM_ENOMEM); | ||||||
|  |  | ||||||
|  |         if (file == NULL) // Wasn't called by macro | ||||||
|  |             RAISE(OOM); // Out of Memory Exception | ||||||
|  |         else // Called by macro | ||||||
|  |             except_raise(&OOM, file, line); | ||||||
|  |     } | ||||||
|  |     return flags&NOZERO ? ptr : memset(ptr, 0, nbytes); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mem_free(void *ptr, const char *file, int line) { | ||||||
|  |     UNUSED(file); | ||||||
|  |     UNUSED(line); | ||||||
|  |     if (ptr){ | ||||||
|  |         free(ptr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *mem_resize(int flags, void *ptr, size_t nbytes,const char *file, int line) { | ||||||
|  |     ASSERTED(ptr); | ||||||
|  |     ASSERTED(nbytes > 0); | ||||||
|  |     ptr = realloc(ptr, nbytes); | ||||||
|  |     if (ptr == NULL){ | ||||||
|  |         if(flags & SOFT_FAIL) return 0; | ||||||
|  |         if(flags & HARD_FAIL) exit(MEM_ENOMEM); | ||||||
|  |          | ||||||
|  |         if (file == NULL) | ||||||
|  |             RAISE(OOM); // Out of memory exception | ||||||
|  |         else // Called by macro | ||||||
|  |             except_raise(&OOM, file, line); | ||||||
|  |     } | ||||||
|  |     return ptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int mem_is_zero(const void *ptr, size_t nbytes) { | ||||||
|  |     ASSERTED(ptr); | ||||||
|  |     ASSERTED(nbytes > 0); | ||||||
|  |     static const unsigned char zero_block[1024] = {0}; /* reused */ | ||||||
|  |     while (nbytes >= sizeof(zero_block)) { | ||||||
|  |         if (memcmp(ptr, zero_block, sizeof(zero_block)) != 0) | ||||||
|  |             return 0; | ||||||
|  |         ptr = (const unsigned char *)ptr + sizeof(zero_block); | ||||||
|  |         nbytes -= sizeof(zero_block); | ||||||
|  |     } | ||||||
|  |     if (nbytes > 0 && memcmp(ptr, zero_block, nbytes) != 0) | ||||||
|  |         return 0; | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								tests/01_arena_new.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/01_arena_new.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | #define DEBUG | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include "../include/arena.h" | ||||||
|  | #include "../include/mem.h" | ||||||
|  |  | ||||||
|  | int main(void){ | ||||||
|  |     size_t nbytes = 20; | ||||||
|  |     Arena a = ARENA(0,nbytes); | ||||||
|  |     assert(a.beg != NULL); | ||||||
|  |     assert( mem_is_zero(a.beg, nbytes)); | ||||||
|  |     free(a.beg); | ||||||
|  |     return EXIT_SUCCESS; | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								tests/02_arena_nozero.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/02_arena_nozero.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | #define DEBUG | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include "../include/arena.h" | ||||||
|  | #include "../include/mem.h" | ||||||
|  |  | ||||||
|  | int main(void){ | ||||||
|  |     size_t nbytes = 20; | ||||||
|  |     Arena a = ARENA(NOZERO,nbytes); | ||||||
|  |     assert(a.beg != NULL); | ||||||
|  |     assert( !mem_is_zero(a.beg, nbytes)); | ||||||
|  |     free(a.beg); | ||||||
|  |     return EXIT_SUCCESS; | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								tests/03_arena_softfail.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/03_arena_softfail.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | #define DEBUG | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include "../include/arena.h" | ||||||
|  | #include "../include/mem.h" | ||||||
|  | int main(void){ | ||||||
|  |     size_t nbytes = MEM_GB(1024); | ||||||
|  |     Arena a = ARENA(SOFT_FAIL, nbytes); | ||||||
|  |     assert(a.beg == NULL); | ||||||
|  |     return EXIT_SUCCESS; | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								tests/04_arena_exception.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/04_arena_exception.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | #define DEBUG | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include "../include/arena.h" | ||||||
|  |  | ||||||
|  | #include "../include/mem.h" | ||||||
|  | int main(void){ | ||||||
|  |     size_t nbytes = MEM_GB(1024); | ||||||
|  |     Arena a; | ||||||
|  |     TRY { | ||||||
|  |         a = ARENA(0,nbytes); /* try 1GB */ | ||||||
|  |         if (!a.beg) | ||||||
|  |             RAISE(OOM); | ||||||
|  |         free(a.beg); | ||||||
|  |     } | ||||||
|  |     EXCEPT(OOM) { | ||||||
|  |         /* handle memory failure gracefully */ | ||||||
|  |         fprintf(stderr, "Caught: %s\n", OOM.reason); | ||||||
|  |         return EXIT_SUCCESS; /* requested behavior */ | ||||||
|  |     } | ||||||
|  |     FINALLY { | ||||||
|  |         /* cleanup if needed, runs always */ | ||||||
|  |         if (a.beg) free(a.beg); | ||||||
|  |     } | ||||||
|  |     END_TRY; | ||||||
|  |  | ||||||
|  |     return EXIT_FAILURE; /* shouldn't reach here for this example */ | ||||||
|  |   } | ||||||
		Reference in New Issue
	
	Block a user