/* * Copyright (c) 2008-2024 OARC, Inc. * Copyright (c) 2007-2008, Internet Systems Consortium, Inc. * Copyright (c) 2003-2007, The Measurement Factory, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "xmalloc.h" #include "syslog_debug.h" #include "compat.h" #include #include #include #include /********** xmalloc **********/ void* xmalloc(size_t size) { char errbuf[512]; void* p = malloc(size); if (NULL == p) dsyslogf(LOG_CRIT, "malloc: %s", dsc_strerror(errno, errbuf, sizeof(errbuf))); return p; } void* xcalloc(size_t number, size_t size) { char errbuf[512]; void* p = calloc(number, size); if (NULL == p) dsyslogf(LOG_CRIT, "calloc: %s", dsc_strerror(errno, errbuf, sizeof(errbuf))); return p; } void* xrealloc(void* p, size_t size) { char errbuf[512]; p = realloc(p, size); if (NULL == p) dsyslogf(LOG_CRIT, "realloc: %s", dsc_strerror(errno, errbuf, sizeof(errbuf))); return p; } char* xstrdup(const char* s) { char errbuf[512]; void* p = strdup(s); if (NULL == p) dsyslogf(LOG_CRIT, "strdup: %s", dsc_strerror(errno, errbuf, sizeof(errbuf))); return p; } void xfree(void* p) { free(p); } /********** amalloc **********/ typedef struct arena { struct arena* prevArena; char* end; char* nextAlloc; } Arena; Arena* currentArena = NULL; #define align(size, a) (((size_t)(size) + ((a)-1)) & ~((a)-1)) #define ALIGNMENT 4 #define HEADERSIZE align(sizeof(Arena), ALIGNMENT) #define CHUNK_SIZE (1 * 1024 * 1024 + 1024) static Arena* newArena(size_t size) { char errbuf[512]; Arena* arena; size = align(size, ALIGNMENT); arena = malloc(HEADERSIZE + size); if (NULL == arena) { dsyslogf(LOG_CRIT, "amalloc %d: %s", (int)size, dsc_strerror(errno, errbuf, sizeof(errbuf))); return NULL; } arena->prevArena = NULL; arena->nextAlloc = (char*)arena + HEADERSIZE; arena->end = arena->nextAlloc + size; return arena; } void useArena() { currentArena = newArena(CHUNK_SIZE); } void freeArena() { while (currentArena) { Arena* prev = currentArena->prevArena; free(currentArena); currentArena = prev; } } void* amalloc(size_t size) { void* p; size = align(size, ALIGNMENT); if (currentArena->end - currentArena->nextAlloc <= size) { if (size >= (CHUNK_SIZE >> 2)) { /* Create a new dedicated chunk for this large allocation, and * continue to use the current chunk for future smaller * allocations. */ Arena* new = newArena(size); new->prevArena = currentArena->prevArena; currentArena->prevArena = new; return new->nextAlloc; } /* Move on to a new chunk. */ Arena* new = newArena(CHUNK_SIZE); if (NULL == new) return NULL; new->prevArena = currentArena; currentArena = new; } p = currentArena->nextAlloc; currentArena->nextAlloc += size; return p; } void* acalloc(size_t number, size_t size) { void* p = amalloc(size * number); if (p) memset(p, 0, size * number); return p; } void* arealloc(void* p, size_t size) { void* r = amalloc(size); if (p) memcpy(r, p, size); return r; } char* astrdup(const char* s) { size_t size = strlen(s) + 1; char* p = amalloc(size); if (p) memcpy(p, s, size); return p; } void afree(void* p) { return; }