#ifndef CADO_UTILS_ELECTRIC_ALLOC_H_ #define CADO_UTILS_ELECTRIC_ALLOC_H_ /* This file is a debugging aid. It carries good chances of working on * POSIX system, but I wouldn't bet much on it, since mmap is kind of * strongly tied to the OS. * * To use, simply include this .h file, and use electric_alloc and * electric_free for for allocation/free routines. * * The vanilla electric_free needs the size of the allocated area. If * this is an inconvenient, try the _nosize versions below. Never tested. */ /* By default we protect overruns. Undefine this macro to protect * underruns instead */ #define PROTECT_OVERRUN #include #include #ifndef MAP_ANONYMOUS #error "Please define _GNU_SOURCE or _BSD_SOURCE on top of the translation unit" #endif static inline void * electric_alloc(size_t s) { /* Use the method of the good old days from electric fence. */ char *p; size_t r = 8192; /* Any multiple of the page size will do. */ unsigned int multip = (s+r-1)/r; p = (char *) mmap(0, (multip + 1) * r, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); // could please valgrind ? // memset(p, 0, (multip + 1) * r); #ifdef PROTECT_OVERRUN p += (multip + 1) * r; mprotect((void*) (p-r), r, PROT_NONE); p -= r+s; #else /* protect underrun */ mprotect(p, r, PROT_NONE); p += r; #endif return (void *) p; } static inline void electric_free(void * p0, size_t s) { char * p = (char *) p0; size_t r = 8192; unsigned int multip = (s+r-1)/r; #ifdef PROTECT_OVERRUN p += s; mprotect((void*) p, r, PROT_READ | PROT_WRITE); p -= multip * r; #else p -= r; mprotect(p, r, PROT_READ | PROT_WRITE); #endif munmap(p, (multip + 1) * r); } static inline void * electric_alloc_nosize(size_t s) { void * ptr = electric_alloc(s + sizeof(s)); *(size_t *)ptr = s; return (void *) (((size_t *) ptr) + 1); } static inline void electric_free_nosize(void * p0) { p0 = (void*) (((size_t *)p0)-1); size_t s = * (size_t *) p0; electric_free(p0, s + sizeof(s)); } #ifdef __cplusplus template inline T * electric_new(size_t s) { return (T*) electric_alloc(sizeof(T)*s); } template inline void electric_delete(T * p, size_t s) { electric_free(p, sizeof(T)*s); } #endif #endif /* CADO_UTILS_ELECTRIC_ALLOC_H_ */