X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fecoli_malloc.h;h=e80c3d9116194244bf773152ff58d26e4f8c5770;hb=51028779e0a8772091aec5ab96bcf2519cf2f1ad;hp=ddf1828e8bc1a1c8da0c42c5c20d44a2cd9c4d0d;hpb=370740deec2b521df48065f890a794f7eaf2f1b6;p=protos%2Flibecoli.git diff --git a/lib/ecoli_malloc.h b/lib/ecoli_malloc.h index ddf1828..e80c3d9 100644 --- a/lib/ecoli_malloc.h +++ b/lib/ecoli_malloc.h @@ -1,38 +1,93 @@ -/* - * Copyright (c) 2016, Olivier MATZ - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2016, Olivier MATZ + */ + +/** + * Interface to configure the allocator used by libecoli. + * By default, the standard allocation functions from libc are used. */ #ifndef ECOLI_MALLOC_ #define ECOLI_MALLOC_ #include +#include +#include + +/** + * Function type of malloc, passed to ec_malloc_register(). + * + * The API is the same than malloc(), excepted the file and line + * arguments. + * + * @param size + * The size of the memory area to allocate. + * @param file + * The path to the file that invoked the malloc. + * @param line + * The line in the file that invoked the malloc. + * @return + * A pointer to the allocated memory area, or NULL on error (errno + * is set). + */ +typedef void *(*ec_malloc_t)(size_t size, const char *file, unsigned int line); + +/** + * Function type of free, passed to ec_malloc_register(). + * + * The API is the same than free(), excepted the file and line + * arguments. + * + * @param ptr + * The pointer to the memory area to be freed. + * @param file + * The path to the file that invoked the malloc. + * @param line + * The line in the file that invoked the malloc. + */ +typedef void (*ec_free_t)(void *ptr, const char *file, unsigned int line); + +/** + * Function type of realloc, passed to ec_malloc_register(). + * + * The API is the same than realloc(), excepted the file and line + * arguments. + * + * @param ptr + * The pointer to the memory area to be reallocated. + * @param file + * The path to the file that invoked the malloc. + * @param line + * The line in the file that invoked the malloc. + * @return + * A pointer to the allocated memory area, or NULL on error (errno + * is set). + */ +typedef void *(*ec_realloc_t)(void *ptr, size_t size, const char *file, + unsigned int line); -typedef void *(*ec_malloc_t)(size_t size); -typedef void (*ec_free_t)(void *ptr); -typedef void *(*ec_realloc_t)(void *ptr, size_t size); +/** + * Register allocation functions. + * + * This function can be use to register another allocator + * to be used by libecoli. By default, ec_malloc(), ec_free() and + * ec_realloc() use the standard libc allocator. Another handler + * can be used for debug purposes or when running in a specific + * environment. + * + * This function must be called before ec_init(). + * + * @param usr_malloc + * A user-defined malloc function. + * @param usr_free + * A user-defined free function. + * @param usr_realloc + * A user-defined realloc function. + * @return + * 0 on success, or -1 on error (errno is set). + */ +int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free, + ec_realloc_t usr_realloc); struct ec_malloc_handler { ec_malloc_t malloc; @@ -42,71 +97,151 @@ struct ec_malloc_handler { extern struct ec_malloc_handler ec_malloc_handler; -int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free, - ec_realloc_t usr_realloc); - -/* internal */ -void *__ec_malloc(size_t size); -void __ec_free(void *ptr); -void *__ec_calloc(size_t nmemb, size_t size); -void *__ec_realloc(void *ptr, size_t size); -char *__ec_strdup(const char *s); -char *__ec_strndup(const char *s, size_t n); - -/* we use macros here to ensure the file/line stay correct when - * debugging the standard malloc with valgrind */ - -#define ec_malloc(sz) ({ \ - void *ret_; \ - if (ec_malloc_handler.malloc == NULL) \ - ret_ = malloc(sz); \ - else \ - ret_ = __ec_malloc(sz); \ - ret_; \ +/** + * Allocate a memory area. + * + * Like malloc(), ec_malloc() allocates size bytes and returns a pointer + * to the allocated memory. The memory is not initialized. The memory is + * freed with ec_free(). + * + * @param size + * The size of the area to allocate in bytes. + * @return + * The pointer to the allocated memory, or NULL on error (errno is set). + */ +#define ec_malloc(size) ({ \ + void *ret_; \ + if (ec_malloc_handler.malloc == NULL) \ + ret_ = malloc(size); \ + else \ + ret_ = __ec_malloc(size, __FILE__, __LINE__); \ + ret_; \ }) -#define ec_free(ptr) ({ \ - if (ec_malloc_handler.free == NULL) \ - free(ptr); \ - else \ - __ec_free(ptr); \ +/** + * Ecoli malloc function. + * + * Use this function when the macro ec_malloc() cannot be used, + * for instance when it is passed as a callback pointer. + */ +void *ec_malloc_func(size_t size); + +/** + * Free a memory area. + * + * Like free(), ec_free() frees the area pointed by ptr, which must have + * been returned by a previous call to ec_malloc() or any other + * allocation function of this file. + * + * @param ptr + * The pointer to the memory area. + */ +#define ec_free(ptr) ({ \ + if (ec_malloc_handler.free == NULL) \ + free(ptr); \ + else \ + __ec_free(ptr, __FILE__, __LINE__); \ }) -#define ec_realloc(ptr, sz) ({ \ - void *ret_; \ - if (ec_malloc_handler.realloc == NULL) \ - ret_ = realloc(ptr, sz); \ - else \ - ret_ = __ec_realloc(ptr, sz); \ - ret_; \ +/** + * Ecoli free function. + * + * Use this function when the macro ec_free() cannot be used, + * for instance when it is passed as a callback pointer. + */ +void ec_free_func(void *ptr); + +/** + * Resize an allocated memory area. + * + * @param ptr + * The pointer to the previously allocated memory area, or NULL. + * @param size + * The new size of the memory area. + * @return + * A pointer to the newly allocated memory, or NULL if the request + * fails. In that case, the original area is left untouched. + */ +#define ec_realloc(ptr, size) ({ \ + void *ret_; \ + if (ec_malloc_handler.realloc == NULL) \ + ret_ = realloc(ptr, size); \ + else \ + ret_ = __ec_realloc(ptr, size, __FILE__, __LINE__); \ + ret_; \ }) -#define ec_calloc(n, sz) ({ \ - void *ret_; \ - if (ec_malloc_handler.malloc == NULL) \ - ret_ = calloc(n, sz); \ - else \ - ret_ = __ec_calloc(n, sz); \ - ret_; \ +/** + * Allocate and initialize an array of elements. + * + * @param n + * The number of elements. + * @param size + * The size of each element. + * @return + * The pointer to the allocated memory, or NULL on error (errno is set). + */ +#define ec_calloc(n, size) ({ \ + void *ret_; \ + if (ec_malloc_handler.malloc == NULL) \ + ret_ = calloc(n, size); \ + else \ + ret_ = __ec_calloc(n, size, __FILE__, __LINE__); \ + ret_; \ }) -#define ec_strdup(s) ({ \ - void *ret_; \ - if (ec_malloc_handler.malloc == NULL) \ - ret_ = strdup(s); \ - else \ - ret_ = __ec_strdup(s); \ - ret_; \ +/** + * Duplicate a string. + * + * Memory for the new string is obtained with ec_malloc(), and can be + * freed with ec_free(). + * + * @param s + * The string to be duplicated. + * @return + * The pointer to the duplicated string, or NULL on error (errno is set). + */ +#define ec_strdup(s) ({ \ + void *ret_; \ + if (ec_malloc_handler.malloc == NULL) \ + ret_ = strdup(s); \ + else \ + ret_ = __ec_strdup(s, __FILE__, __LINE__); \ + ret_; \ }) -#define ec_strndup(s, n) ({ \ - void *ret_; \ - if (ec_malloc_handler.malloc == NULL) \ - ret_ = strndup(s, n); \ - else \ - ret_ = __ec_strndup(s, n); \ - ret_; \ +/** + * Duplicate at most n bytes of a string. + * + * This function is similar to ec_strdup(), except that it copies at + * most n bytes. If s is longer than n, only n bytes are copied, and a + * terminating null byte ('\0') is added. + * + * @param s + * The string to be duplicated. + * @param n + * The maximum length of the new string. + * @return + * The pointer to the duplicated string, or NULL on error (errno is set). + */ +#define ec_strndup(s, n) ({ \ + void *ret_; \ + if (ec_malloc_handler.malloc == NULL) \ + ret_ = strndup(s, n); \ + else \ + ret_ = __ec_strndup(s, n, __FILE__, __LINE__); \ + ret_; \ }) +/* internal */ +void *__ec_malloc(size_t size, const char *file, unsigned int line); +void __ec_free(void *ptr, const char *file, unsigned int line); +void *__ec_calloc(size_t nmemb, size_t size, const char *file, + unsigned int line); +void *__ec_realloc(void *ptr, size_t size, const char *file, unsigned int line); +char *__ec_strdup(const char *s, const char *file, unsigned int line); +char *__ec_strndup(const char *s, size_t n, const char *file, + unsigned int line); + #endif