Kouhei Sutou
null+****@clear*****
Tue Apr 12 18:09:26 JST 2016
Kouhei Sutou 2016-04-12 18:09:26 +0900 (Tue, 12 Apr 2016) New Revision: cfb93fdbffb6c6e345e80c77c7a4c51687ece466 https://github.com/groonga/groonga/commit/cfb93fdbffb6c6e345e80c77c7a4c51687ece466 Message: Extract allocation related codes to separated file Added files: lib/alloc.c lib/grn_alloc.h Modified files: lib/ctx.c lib/grn_ctx.h lib/proc.c lib/sources.am Added: lib/alloc.c (+957 -0) 100644 =================================================================== --- /dev/null +++ lib/alloc.c 2016-04-12 18:09:26 +0900 (bc5264e) @@ -0,0 +1,957 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "grn.h" +#include "grn_alloc.h" +#include "grn_ctx_impl.h" + +static int alloc_count = 0; + +#ifdef USE_FAIL_MALLOC +static int grn_fmalloc_prob = 0; +static char *grn_fmalloc_func = NULL; +static char *grn_fmalloc_file = NULL; +static int grn_fmalloc_line = 0; +#endif /* USE_FAIL_MALLOC */ + +#ifdef USE_EXACT_ALLOC_COUNT +# define GRN_ADD_ALLOC_COUNT(count) do { \ + uint32_t alloced; \ + GRN_ATOMIC_ADD_EX(&alloc_count, count, alloced); \ +} while (0) +#else /* USE_EXACT_ALLOC_COUNT */ +# define GRN_ADD_ALLOC_COUNT(count) do { \ + alloc_count += count; \ +} while (0) +#endif + +void +grn_alloc_init_from_env(void) +{ +#ifdef USE_FAIL_MALLOC + { + char grn_fmalloc_prob_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_PROB", + grn_fmalloc_prob_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_prob_env[0]) { + char grn_fmalloc_seed_env[GRN_ENV_BUFFER_SIZE]; + grn_fmalloc_prob = strtod(grn_fmalloc_prob_env, 0) * RAND_MAX; + grn_getenv("GRN_FMALLOC_SEED", + grn_fmalloc_seed_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_seed_env[0]) { + srand((unsigned int)atoi(grn_fmalloc_seed_env)); + } else { + srand((unsigned int)time(NULL)); + } + } + } + { + static char grn_fmalloc_func_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_FUNC", + grn_fmalloc_func_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_func_env[0]) { + grn_fmalloc_func = grn_fmalloc_func_env; + } + } + { + static char grn_fmalloc_file_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_FILE", + grn_fmalloc_file_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_file_env[0]) { + grn_fmalloc_file = grn_fmalloc_file_env; + } + } + { + char grn_fmalloc_line_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_LINE", + grn_fmalloc_line_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_line_env[0]) { + grn_fmalloc_line = atoi(grn_fmalloc_line_env); + } + } +#endif /* USE_FAIL_MALLOC */ +} + +#ifdef USE_MEMORY_DEBUG +static grn_critical_section grn_alloc_info_lock; + +void +grn_alloc_info_init(void) +{ + CRITICAL_SECTION_INIT(grn_alloc_info_lock); +} + +void +grn_alloc_info_fin(void) +{ + CRITICAL_SECTION_FIN(grn_alloc_info_lock); +} + +inline static void +grn_alloc_info_set_backtrace(char *buffer, size_t size) +{ +# ifdef HAVE_BACKTRACE +# define N_TRACE_LEVEL 100 + static void *trace[N_TRACE_LEVEL]; + char **symbols; + int i, n, rest; + + rest = size; + n = backtrace(trace, N_TRACE_LEVEL); + symbols = backtrace_symbols(trace, n); + if (symbols) { + for (i = 0; i < n; i++) { + int symbol_length; + + symbol_length = strlen(symbols[i]); + if (symbol_length + 2 > rest) { + break; + } + grn_memcpy(buffer, symbols[i], symbol_length); + buffer += symbol_length; + rest -= symbol_length; + buffer[0] = '\n'; + buffer++; + rest--; + buffer[0] = '\0'; + rest--; + } + free(symbols); + } else { + buffer[0] = '\0'; + } +# undef N_TRACE_LEVEL +# else /* HAVE_BACKTRACE */ + buffer[0] = '\0'; +# endif /* HAVE_BACKTRACE */ +} + +inline static void +grn_alloc_info_add(void *address, size_t size, + const char *file, int line, const char *func) +{ + grn_ctx *ctx; + grn_alloc_info *new_alloc_info; + + ctx = &grn_gctx; + if (!ctx->impl) { return; } + + CRITICAL_SECTION_ENTER(grn_alloc_info_lock); + new_alloc_info = malloc(sizeof(grn_alloc_info)); + if (new_alloc_info) { + new_alloc_info->address = address; + new_alloc_info->size = size; + new_alloc_info->freed = GRN_FALSE; + grn_alloc_info_set_backtrace(new_alloc_info->alloc_backtrace, + sizeof(new_alloc_info->alloc_backtrace)); + if (file) { + new_alloc_info->file = strdup(file); + } else { + new_alloc_info->file = NULL; + } + new_alloc_info->line = line; + if (func) { + new_alloc_info->func = strdup(func); + } else { + new_alloc_info->func = NULL; + } + new_alloc_info->next = ctx->impl->alloc_info; + ctx->impl->alloc_info = new_alloc_info; + } + CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); +} + +inline static void +grn_alloc_info_change(void *old_address, void *new_address, size_t size) +{ + grn_ctx *ctx; + grn_alloc_info *alloc_info; + + ctx = &grn_gctx; + if (!ctx->impl) { return; } + + CRITICAL_SECTION_ENTER(grn_alloc_info_lock); + alloc_info = ctx->impl->alloc_info; + for (; alloc_info; alloc_info = alloc_info->next) { + if (alloc_info->address == old_address) { + alloc_info->address = new_address; + alloc_info->size = size; + grn_alloc_info_set_backtrace(alloc_info->alloc_backtrace, + sizeof(alloc_info->alloc_backtrace)); + } + } + CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); +} + +void +grn_alloc_info_dump(grn_ctx *ctx) +{ + int i = 0; + grn_alloc_info *alloc_info; + + if (!ctx) { return; } + if (!ctx->impl) { return; } + + alloc_info = ctx->impl->alloc_info; + for (; alloc_info; alloc_info = alloc_info->next) { + if (alloc_info->freed) { + printf("address[%d][freed]: %p(%" GRN_FMT_SIZE ")\n", + i, alloc_info->address, alloc_info->size); + } else { + printf("address[%d][not-freed]: %p(%" GRN_FMT_SIZE "): %s:%d: %s()\n%s", + i, + alloc_info->address, + alloc_info->size, + alloc_info->file ? alloc_info->file : "(unknown)", + alloc_info->line, + alloc_info->func ? alloc_info->func : "(unknown)", + alloc_info->alloc_backtrace); + } + i++; + } +} + +inline static void +grn_alloc_info_check(grn_ctx *ctx, void *address) +{ + grn_alloc_info *alloc_info; + + if (!grn_gctx.impl) { return; } + /* grn_alloc_info_dump(ctx); */ + + CRITICAL_SECTION_ENTER(grn_alloc_info_lock); + alloc_info = grn_gctx.impl->alloc_info; + for (; alloc_info; alloc_info = alloc_info->next) { + if (alloc_info->address == address) { + if (alloc_info->freed) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "double free: %p(%" GRN_FMT_SIZE "):\n" + "alloc backtrace:\n" + "%sfree backtrace:\n" + "%s", + alloc_info->address, + alloc_info->size, + alloc_info->alloc_backtrace, + alloc_info->free_backtrace); + } else { + alloc_info->freed = GRN_TRUE; + grn_alloc_info_set_backtrace(alloc_info->free_backtrace, + sizeof(alloc_info->free_backtrace)); + } + break; + } + } + CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); +} + +void +grn_alloc_info_free(grn_ctx *ctx) +{ + grn_alloc_info *alloc_info; + + if (!ctx) { return; } + if (!ctx->impl) { return; } + + alloc_info = ctx->impl->alloc_info; + while (alloc_info) { + grn_alloc_info *current_alloc_info = alloc_info; + alloc_info = alloc_info->next; + current_alloc_info->next = NULL; + free(current_alloc_info->file); + free(current_alloc_info->func); + free(current_alloc_info); + } + ctx->impl->alloc_info = NULL; +} + +#else /* USE_MEMORY_DEBUG */ +void +grn_alloc_info_init(void) +{ +} + +void +grn_alloc_info_fin(void) +{ +} + +# define grn_alloc_info_add(address, size, file, line, func) +# define grn_alloc_info_change(old_address, new_address, size) +# define grn_alloc_info_check(ctx, address) + +void +grn_alloc_info_dump(grn_ctx *ctx) +{ +} + +void +grn_alloc_info_free(grn_ctx *ctx) +{ +} +#endif /* USE_MEMORY_DEBUG */ + +#define GRN_CTX_SEGMENT_SIZE (1<<22) +#define GRN_CTX_SEGMENT_MASK (GRN_CTX_SEGMENT_SIZE - 1) + +#define GRN_CTX_SEGMENT_WORD (1<<31) +#define GRN_CTX_SEGMENT_VLEN (1<<30) +#define GRN_CTX_SEGMENT_LIFO (1<<29) +#define GRN_CTX_SEGMENT_DIRTY (1<<28) + +void +grn_alloc_init_ctx_impl(grn_ctx *ctx) +{ +#ifdef USE_DYNAMIC_MALLOC_CHANGE +# ifdef USE_FAIL_MALLOC + ctx->impl->malloc_func = grn_malloc_fail; + ctx->impl->calloc_func = grn_calloc_fail; + ctx->impl->realloc_func = grn_realloc_fail; + ctx->impl->strdup_func = grn_strdup_fail; +# else + ctx->impl->malloc_func = grn_malloc_default; + ctx->impl->calloc_func = grn_calloc_default; + ctx->impl->realloc_func = grn_realloc_default; + ctx->impl->strdup_func = grn_strdup_default; +# endif +#endif + +#ifdef USE_MEMORY_DEBUG + ctx->impl->alloc_info = NULL; +#endif +} + +void +grn_alloc_fin_ctx_impl(grn_ctx *ctx) +{ + int i; + grn_io_mapinfo *mi; + for (i = 0, mi = ctx->impl->segs; i < GRN_CTX_N_SEGMENTS; i++, mi++) { + if (mi->map) { + //GRN_LOG(ctx, GRN_LOG_NOTICE, "unmap in ctx_fin(%d,%d,%d)", i, (mi->count & GRN_CTX_SEGMENT_MASK), mi->nref); + if (mi->count & GRN_CTX_SEGMENT_VLEN) { + grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); + } else { + grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); + } + } + } +} + +#define ALIGN_SIZE (1<<3) +#define ALIGN_MASK (ALIGN_SIZE-1) +#define GRN_CTX_ALLOC_CLEAR 1 + +static void * +grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags, + const char* file, int line, const char *func) +{ + void *res = NULL; + if (!ctx) { return res; } + if (!ctx->impl) { + if (ERRP(ctx, GRN_ERROR)) { return res; } + } + CRITICAL_SECTION_ENTER(ctx->impl->lock); + { + int32_t i; + int32_t *header; + grn_io_mapinfo *mi; + size = ((size + ALIGN_MASK) & ~ALIGN_MASK) + ALIGN_SIZE; + if (size > GRN_CTX_SEGMENT_SIZE) { + uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; + if (npages >= (1LL<<32)) { + MERR("too long request size=%" GRN_FMT_SIZE, size); + goto exit; + } + for (i = 0, mi = ctx->impl->segs;; i++, mi++) { + if (i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + goto exit; + } + if (!mi->map) { break; } + } + if (!grn_io_anon_map(ctx, mi, npages * grn_pagesize)) { goto exit; } + /* GRN_LOG(ctx, GRN_LOG_NOTICE, "map i=%d (%d)", i, npages * grn_pagesize); */ + mi->nref = (uint32_t) npages; + mi->count = GRN_CTX_SEGMENT_VLEN; + ctx->impl->currseg = -1; + header = mi->map; + header[0] = i; + header[1] = (int32_t) size; + } else { + i = ctx->impl->currseg; + mi = &ctx->impl->segs[i]; + if (i < 0 || size + mi->nref > GRN_CTX_SEGMENT_SIZE) { + for (i = 0, mi = ctx->impl->segs;; i++, mi++) { + if (i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + goto exit; + } + if (!mi->map) { break; } + } + if (!grn_io_anon_map(ctx, mi, GRN_CTX_SEGMENT_SIZE)) { goto exit; } + /* GRN_LOG(ctx, GRN_LOG_NOTICE, "map i=%d", i); */ + mi->nref = 0; + mi->count = GRN_CTX_SEGMENT_WORD; + ctx->impl->currseg = i; + } + header = (int32_t *)((byte *)mi->map + mi->nref); + mi->nref += size; + mi->count++; + header[0] = i; + header[1] = (int32_t) size; + if ((flags & GRN_CTX_ALLOC_CLEAR) && + (mi->count & GRN_CTX_SEGMENT_DIRTY) && (size > ALIGN_SIZE)) { + memset(&header[2], 0, size - ALIGN_SIZE); + } + } + /* + { + char g = (ctx == &grn_gctx) ? 'g' : ' '; + GRN_LOG(ctx, GRN_LOG_NOTICE, "+%c(%p) %s:%d(%s) (%d:%d)%p mi(%d:%d)", g, ctx, file, line, func, header[0], header[1], &header[2], mi->nref, (mi->count & GRN_CTX_SEGMENT_MASK)); + } + */ + res = &header[2]; + } +exit : + CRITICAL_SECTION_LEAVE(ctx->impl->lock); + return res; +} + +void * +grn_ctx_malloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + return grn_ctx_alloc(ctx, size, 0, file, line, func); +} + +void * +grn_ctx_calloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + return grn_ctx_alloc(ctx, size, GRN_CTX_ALLOC_CLEAR, file, line, func); +} + +void * +grn_ctx_realloc(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + void *res = NULL; + if (size) { + /* todo : expand if possible */ + res = grn_ctx_alloc(ctx, size, 0, file, line, func); + if (res && ptr) { + int32_t *header = &((int32_t *)ptr)[-2]; + size_t size_ = header[1]; + grn_memcpy(res, ptr, size_ > size ? size : size_); + grn_ctx_free(ctx, ptr, file, line, func); + } + } else { + grn_ctx_free(ctx, ptr, file, line, func); + } + return res; +} + +char * +grn_ctx_strdup(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func) +{ + void *res = NULL; + if (s) { + size_t size = strlen(s) + 1; + if ((res = grn_ctx_alloc(ctx, size, 0, file, line, func))) { + grn_memcpy(res, s, size); + } + } + return res; +} + +void +grn_ctx_free(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (!ctx) { return; } + if (!ctx->impl) { + ERR(GRN_INVALID_ARGUMENT,"ctx without impl passed."); + return; + } + CRITICAL_SECTION_ENTER(ctx->impl->lock); + if (ptr) { + int32_t *header = &((int32_t *)ptr)[-2]; + + if (header[0] >= GRN_CTX_N_SEGMENTS) { + ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed. ptr=%p seg=%d", ptr, *header); + goto exit; + } + /* + { + int32_t i = header[0]; + char c = 'X', g = (ctx == &grn_gctx) ? 'g' : ' '; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (!(mi->count & GRN_CTX_SEGMENT_VLEN) && + mi->map <= (void *)header && (char *)header < ((char *)mi->map + GRN_CTX_SEGMENT_SIZE)) { c = '-'; } + GRN_LOG(ctx, GRN_LOG_NOTICE, "%c%c(%p) %s:%d(%s) (%d:%d)%p mi(%d:%d)", c, g, ctx, file, line, func, header[0], header[1], &header[2], mi->nref, (mi->count & GRN_CTX_SEGMENT_MASK)); + } + */ + { + int32_t i = header[0]; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (mi->count & GRN_CTX_SEGMENT_VLEN) { + if (mi->map != header) { + ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed.. ptr=%p seg=%d", ptr, i); + goto exit; + } + //GRN_LOG(ctx, GRN_LOG_NOTICE, "umap i=%d (%d)", i, mi->nref * grn_pagesize); + grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); + mi->map = NULL; + } else { + if (!mi->map) { + ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed... ptr=%p seg=%d", ptr, i); + goto exit; + } + mi->count--; + if (!(mi->count & GRN_CTX_SEGMENT_MASK)) { + //GRN_LOG(ctx, GRN_LOG_NOTICE, "umap i=%d", i); + if (i == ctx->impl->currseg) { + mi->count |= GRN_CTX_SEGMENT_DIRTY; + mi->nref = 0; + } else { + grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); + mi->map = NULL; + } + } + } + } + } +exit : + CRITICAL_SECTION_LEAVE(ctx->impl->lock); +} + +void * +grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + if (!ctx->impl) { + if (ERRP(ctx, GRN_ERROR)) { return NULL; } + } + { + int32_t i = ctx->impl->lifoseg; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (size > GRN_CTX_SEGMENT_SIZE) { + uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; + if (npages >= (1LL<<32)) { + MERR("too long request size=%" GRN_FMT_SIZE, size); + return NULL; + } + for (;;) { + if (++i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + return NULL; + } + mi++; + if (!mi->map) { break; } + } + if (!grn_io_anon_map(ctx, mi, npages * grn_pagesize)) { return NULL; } + mi->nref = (uint32_t) npages; + mi->count = GRN_CTX_SEGMENT_VLEN|GRN_CTX_SEGMENT_LIFO; + ctx->impl->lifoseg = i; + return mi->map; + } else { + size = (size + ALIGN_MASK) & ~ALIGN_MASK; + if (i < 0 || (mi->count & GRN_CTX_SEGMENT_VLEN) || size + mi->nref > GRN_CTX_SEGMENT_SIZE) { + for (;;) { + if (++i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + return NULL; + } + if (!(++mi)->map) { break; } + } + if (!grn_io_anon_map(ctx, mi, GRN_CTX_SEGMENT_SIZE)) { return NULL; } + mi->nref = 0; + mi->count = GRN_CTX_SEGMENT_WORD|GRN_CTX_SEGMENT_LIFO; + ctx->impl->lifoseg = i; + } + { + uint32_t u = mi->nref; + mi->nref += size; + return (byte *)mi->map + u; + } + } + } +} + +void +grn_ctx_free_lifo(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (!ctx) { return; } + if (!ctx->impl) { + ERR(GRN_INVALID_ARGUMENT,"ctx without impl passed."); + return; + } + { + int32_t i = ctx->impl->lifoseg, done = 0; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (i < 0) { + ERR(GRN_INVALID_ARGUMENT, "lifo buffer is void"); + return; + } + for (; i >= 0; i--, mi--) { + if (!(mi->count & GRN_CTX_SEGMENT_LIFO)) { continue; } + if (done) { break; } + if (mi->count & GRN_CTX_SEGMENT_VLEN) { + if (mi->map == ptr) { done = 1; } + grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); + mi->map = NULL; + } else { + if (mi->map == ptr) { + done = 1; + } else { + if (mi->map < ptr && ptr < (void *)((byte*)mi->map + mi->nref)) { + mi->nref = (uint32_t) ((uintptr_t)ptr - (uintptr_t)mi->map); + break; + } + } + grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); + mi->map = NULL; + } + } + ctx->impl->lifoseg = i; + } +} + +#if USE_DYNAMIC_MALLOC_CHANGE +grn_malloc_func +grn_ctx_get_malloc(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->malloc_func; +} + +void +grn_ctx_set_malloc(grn_ctx *ctx, grn_malloc_func malloc_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->malloc_func = malloc_func; +} + +grn_calloc_func +grn_ctx_get_calloc(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->calloc_func; +} + +void +grn_ctx_set_calloc(grn_ctx *ctx, grn_calloc_func calloc_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->calloc_func = calloc_func; +} + +grn_realloc_func +grn_ctx_get_realloc(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->realloc_func; +} + +void +grn_ctx_set_realloc(grn_ctx *ctx, grn_realloc_func realloc_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->realloc_func = realloc_func; +} + +grn_strdup_func +grn_ctx_get_strdup(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->strdup_func; +} + +void +grn_ctx_set_strdup(grn_ctx *ctx, grn_strdup_func strdup_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->strdup_func = strdup_func; +} + +grn_free_func +grn_ctx_get_free(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->free_func; +} + +void +grn_ctx_set_free(grn_ctx *ctx, grn_free_func free_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->free_func = free_func; +} + +void * +grn_malloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->malloc_func) { + return ctx->impl->malloc_func(ctx, size, file, line, func); + } else { + return grn_malloc_default(ctx, size, file, line, func); + } +} + +void * +grn_calloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->calloc_func) { + return ctx->impl->calloc_func(ctx, size, file, line, func); + } else { + return grn_calloc_default(ctx, size, file, line, func); + } +} + +void * +grn_realloc(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->realloc_func) { + return ctx->impl->realloc_func(ctx, ptr, size, file, line, func); + } else { + return grn_realloc_default(ctx, ptr, size, file, line, func); + } +} + +char * +grn_strdup(grn_ctx *ctx, const char *string, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->strdup_func) { + return ctx->impl->strdup_func(ctx, string, file, line, func); + } else { + return grn_strdup_default(ctx, string, file, line, func); + } +} + +void +grn_free(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->free_func) { + return ctx->impl->free_func(ctx, ptr, file, line, func); + } else { + return grn_free_default(ctx, ptr, file, line, func); + } +} +#endif + +void * +grn_malloc_default(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + { + void *res = malloc(size); + if (res) { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } else { + if (!(res = malloc(size))) { + MERR("malloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + size, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } + } + return res; + } +} + +void * +grn_calloc_default(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + { + void *res = calloc(size, 1); + if (res) { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } else { + if (!(res = calloc(size, 1))) { + MERR("calloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + size, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } + } + return res; + } +} + +void +grn_free_default(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (!ctx) { return; } + grn_alloc_info_check(ctx, ptr); + { + free(ptr); + if (ptr) { + GRN_ADD_ALLOC_COUNT(-1); + } else { + GRN_LOG(ctx, GRN_LOG_ALERT, "free fail (%p) (%s:%d) <%d>", + ptr, file, line, alloc_count); + } + } +} + +void * +grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + void *res; + if (!ctx) { return NULL; } + if (size) { + if (!(res = realloc(ptr, size))) { + if (!(res = realloc(ptr, size))) { + MERR("realloc fail (%p,%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + ptr, size, res, file, line, alloc_count); + return NULL; + } + } + if (ptr) { + grn_alloc_info_change(ptr, res, size); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } + } else { + if (!ptr) { return NULL; } + grn_alloc_info_check(ctx, ptr); + GRN_ADD_ALLOC_COUNT(-1); + free(ptr); + res = NULL; + } + return res; +} + +int +grn_alloc_count(void) +{ + return alloc_count; +} + +char * +grn_strdup_default(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + { + char *res = grn_strdup_raw(s); + if (res) { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, strlen(res) + 1, file, line, func); + } else { + if (!(res = grn_strdup_raw(s))) { + MERR("strdup(%p)=%p (%s:%d) <%d>", s, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, strlen(res) + 1, file, line, func); + } + } + return res; + } +} + +#ifdef USE_FAIL_MALLOC +int +grn_fail_malloc_check(size_t size, + const char *file, int line, const char *func) +{ + if ((grn_fmalloc_file && strcmp(file, grn_fmalloc_file)) || + (grn_fmalloc_line && line != grn_fmalloc_line) || + (grn_fmalloc_func && strcmp(func, grn_fmalloc_func))) { + return 1; + } + if (grn_fmalloc_prob && grn_fmalloc_prob >= rand()) { + return 0; + } + return 1; +} + +void * +grn_malloc_fail(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(size, file, line, func)) { + return grn_malloc_default(ctx, size, file, line, func); + } else { + MERR("fail_malloc (%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + size, file, line, func, alloc_count); + return NULL; + } +} + +void * +grn_calloc_fail(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(size, file, line, func)) { + return grn_calloc_default(ctx, size, file, line, func); + } else { + MERR("fail_calloc (%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + size, file, line, func, alloc_count); + return NULL; + } +} + +void * +grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(size, file, line, func)) { + return grn_realloc_default(ctx, ptr, size, file, line, func); + } else { + MERR("fail_realloc (%p,%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + ptr, size, file, line, func, alloc_count); + return NULL; + } +} + +char * +grn_strdup_fail(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(strlen(s), file, line, func)) { + return grn_strdup_default(ctx, s, file, line, func); + } else { + MERR("fail_strdup(%p) (%s:%d@%s) <%d>", s, file, line, func, alloc_count); + return NULL; + } +} +#endif /* USE_FAIL_MALLOC */ Modified: lib/ctx.c (+4 -906) =================================================================== --- lib/ctx.c 2016-04-11 23:40:30 +0900 (8af8b1a) +++ lib/ctx.c 2016-04-12 18:09:26 +0900 (7cd6431) @@ -66,17 +66,6 @@ #define GRN_CTX_CLOSED(ctx) ((ctx)->stat == GRN_CTX_FIN) -#ifdef USE_EXACT_ALLOC_COUNT -#define GRN_ADD_ALLOC_COUNT(count) do { \ - uint32_t alloced; \ - GRN_ATOMIC_ADD_EX(&alloc_count, count, alloced); \ -} while (0) -#else /* USE_EXACT_ALLOC_COUNT */ -#define GRN_ADD_ALLOC_COUNT(count) do { \ - alloc_count += count; \ -} while (0) -#endif - grn_ctx grn_gctx = GRN_CTX_INITIALIZER(GRN_ENC_DEFAULT); int grn_pagesize; grn_critical_section grn_glock; @@ -102,6 +91,7 @@ grn_init_from_env(void) } } + grn_alloc_init_from_env(); grn_mrb_init_from_env(); grn_ctx_impl_mrb_init_from_env(); grn_io_init_from_env(); @@ -303,245 +293,6 @@ grn_get_global_error_message(void) return grn_gctx.errbuf; } -#ifdef USE_MEMORY_DEBUG -static grn_critical_section grn_alloc_info_lock; - -static void grn_alloc_info_init(void) -{ - CRITICAL_SECTION_INIT(grn_alloc_info_lock); -} - -static void grn_alloc_info_fin(void) -{ - CRITICAL_SECTION_FIN(grn_alloc_info_lock); -} - -inline static void -grn_alloc_info_set_backtrace(char *buffer, size_t size) -{ -# ifdef HAVE_BACKTRACE -# define N_TRACE_LEVEL 100 - static void *trace[N_TRACE_LEVEL]; - char **symbols; - int i, n, rest; - - rest = size; - n = backtrace(trace, N_TRACE_LEVEL); - symbols = backtrace_symbols(trace, n); - if (symbols) { - for (i = 0; i < n; i++) { - int symbol_length; - - symbol_length = strlen(symbols[i]); - if (symbol_length + 2 > rest) { - break; - } - grn_memcpy(buffer, symbols[i], symbol_length); - buffer += symbol_length; - rest -= symbol_length; - buffer[0] = '\n'; - buffer++; - rest--; - buffer[0] = '\0'; - rest--; - } - free(symbols); - } else { - buffer[0] = '\0'; - } -# undef N_TRACE_LEVEL -# else /* HAVE_BACKTRACE */ - buffer[0] = '\0'; -# endif /* HAVE_BACKTRACE */ -} - -inline static void -grn_alloc_info_add(void *address, size_t size, - const char *file, int line, const char *func) -{ - grn_ctx *ctx; - grn_alloc_info *new_alloc_info; - - ctx = &grn_gctx; - if (!ctx->impl) { return; } - - CRITICAL_SECTION_ENTER(grn_alloc_info_lock); - new_alloc_info = malloc(sizeof(grn_alloc_info)); - if (new_alloc_info) { - new_alloc_info->address = address; - new_alloc_info->size = size; - new_alloc_info->freed = GRN_FALSE; - grn_alloc_info_set_backtrace(new_alloc_info->alloc_backtrace, - sizeof(new_alloc_info->alloc_backtrace)); - if (file) { - new_alloc_info->file = strdup(file); - } else { - new_alloc_info->file = NULL; - } - new_alloc_info->line = line; - if (func) { - new_alloc_info->func = strdup(func); - } else { - new_alloc_info->func = NULL; - } - new_alloc_info->next = ctx->impl->alloc_info; - ctx->impl->alloc_info = new_alloc_info; - } - CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); -} - -inline static void -grn_alloc_info_change(void *old_address, void *new_address, size_t size) -{ - grn_ctx *ctx; - grn_alloc_info *alloc_info; - - ctx = &grn_gctx; - if (!ctx->impl) { return; } - - CRITICAL_SECTION_ENTER(grn_alloc_info_lock); - alloc_info = ctx->impl->alloc_info; - for (; alloc_info; alloc_info = alloc_info->next) { - if (alloc_info->address == old_address) { - alloc_info->address = new_address; - alloc_info->size = size; - grn_alloc_info_set_backtrace(alloc_info->alloc_backtrace, - sizeof(alloc_info->alloc_backtrace)); - } - } - CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); -} - -inline static void -grn_alloc_info_dump(grn_ctx *ctx) -{ - int i = 0; - grn_alloc_info *alloc_info; - - if (!ctx) { return; } - if (!ctx->impl) { return; } - - alloc_info = ctx->impl->alloc_info; - for (; alloc_info; alloc_info = alloc_info->next) { - if (alloc_info->freed) { - printf("address[%d][freed]: %p(%" GRN_FMT_SIZE ")\n", - i, alloc_info->address, alloc_info->size); - } else { - printf("address[%d][not-freed]: %p(%" GRN_FMT_SIZE "): %s:%d: %s()\n%s", - i, - alloc_info->address, - alloc_info->size, - alloc_info->file ? alloc_info->file : "(unknown)", - alloc_info->line, - alloc_info->func ? alloc_info->func : "(unknown)", - alloc_info->alloc_backtrace); - } - i++; - } -} - -inline static void -grn_alloc_info_check(grn_ctx *ctx, void *address) -{ - grn_alloc_info *alloc_info; - - if (!grn_gctx.impl) { return; } - /* grn_alloc_info_dump(ctx); */ - - CRITICAL_SECTION_ENTER(grn_alloc_info_lock); - alloc_info = grn_gctx.impl->alloc_info; - for (; alloc_info; alloc_info = alloc_info->next) { - if (alloc_info->address == address) { - if (alloc_info->freed) { - GRN_LOG(ctx, GRN_LOG_WARNING, - "double free: %p(%" GRN_FMT_SIZE "):\n" - "alloc backtrace:\n" - "%sfree backtrace:\n" - "%s", - alloc_info->address, - alloc_info->size, - alloc_info->alloc_backtrace, - alloc_info->free_backtrace); - } else { - alloc_info->freed = GRN_TRUE; - grn_alloc_info_set_backtrace(alloc_info->free_backtrace, - sizeof(alloc_info->free_backtrace)); - } - break; - } - } - CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); -} - -inline static void -grn_alloc_info_free(grn_ctx *ctx) -{ - grn_alloc_info *alloc_info; - - if (!ctx) { return; } - if (!ctx->impl) { return; } - - alloc_info = ctx->impl->alloc_info; - while (alloc_info) { - grn_alloc_info *current_alloc_info = alloc_info; - alloc_info = alloc_info->next; - current_alloc_info->next = NULL; - free(current_alloc_info->file); - free(current_alloc_info->func); - free(current_alloc_info); - } - ctx->impl->alloc_info = NULL; -} - -#else /* USE_MEMORY_DEBUG */ -# define grn_alloc_info_init() -# define grn_alloc_info_fin() -# define grn_alloc_info_add(address, size, file, line, func) -# define grn_alloc_info_change(old_address, new_address, size) -# define grn_alloc_info_check(ctx, address) -# define grn_alloc_info_dump(ctx) -# define grn_alloc_info_free(ctx) -#endif /* USE_MEMORY_DEBUG */ - -void -grn_debug_dump_alloc_info(grn_ctx *ctx) -{ - grn_alloc_info_dump(ctx); -} - -#ifdef USE_FAIL_MALLOC -int grn_fmalloc_prob = 0; -char *grn_fmalloc_func = NULL; -char *grn_fmalloc_file = NULL; -int grn_fmalloc_line = 0; -#endif /* USE_FAIL_MALLOC */ - -#define GRN_CTX_SEGMENT_SIZE (1<<22) -#define GRN_CTX_SEGMENT_MASK (GRN_CTX_SEGMENT_SIZE - 1) - -#define GRN_CTX_SEGMENT_WORD (1<<31) -#define GRN_CTX_SEGMENT_VLEN (1<<30) -#define GRN_CTX_SEGMENT_LIFO (1<<29) -#define GRN_CTX_SEGMENT_DIRTY (1<<28) - -#ifdef USE_DYNAMIC_MALLOC_CHANGE -static void -grn_ctx_impl_init_malloc(grn_ctx *ctx) -{ -# ifdef USE_FAIL_MALLOC - ctx->impl->malloc_func = grn_malloc_fail; - ctx->impl->calloc_func = grn_calloc_fail; - ctx->impl->realloc_func = grn_realloc_fail; - ctx->impl->strdup_func = grn_strdup_fail; -# else - ctx->impl->malloc_func = grn_malloc_default; - ctx->impl->calloc_func = grn_calloc_default; - ctx->impl->realloc_func = grn_realloc_default; - ctx->impl->strdup_func = grn_strdup_default; -# endif -} -#endif - static void grn_loader_init(grn_loader *loader) { @@ -598,12 +349,7 @@ grn_ctx_impl_init(grn_ctx *ctx) if (!(ctx->impl = grn_io_anon_map(ctx, &mi, IMPL_SIZE))) { return ctx->rc; } -#ifdef USE_DYNAMIC_MALLOC_CHANGE - grn_ctx_impl_init_malloc(ctx); -#endif -#ifdef USE_MEMORY_DEBUG - ctx->impl->alloc_info = NULL; -#endif + grn_alloc_init_ctx_impl(ctx); ctx->impl->encoding = ctx->encoding; ctx->impl->lifoseg = -1; ctx->impl->currseg = -1; @@ -877,20 +623,7 @@ grn_ctx_fin(grn_ctx *ctx) ctx->impl->db = NULL; grn_obj_close(ctx, db); } - { - int i; - grn_io_mapinfo *mi; - for (i = 0, mi = ctx->impl->segs; i < GRN_CTX_N_SEGMENTS; i++, mi++) { - if (mi->map) { - //GRN_LOG(ctx, GRN_LOG_NOTICE, "unmap in ctx_fin(%d,%d,%d)", i, (mi->count & GRN_CTX_SEGMENT_MASK), mi->nref); - if (mi->count & GRN_CTX_SEGMENT_VLEN) { - grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); - } else { - grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); - } - } - } - } + grn_alloc_fin_ctx_impl(ctx); grn_alloc_info_dump(ctx); grn_alloc_info_free(ctx); CRITICAL_SECTION_FIN(ctx->impl->lock); @@ -985,53 +718,6 @@ grn_init(void) GRN_LOG(ctx, GRN_LOG_CRIT, "pagesize=%x", grn_pagesize); } // expand_stack(); -#ifdef USE_FAIL_MALLOC - { - char grn_fmalloc_prob_env[GRN_ENV_BUFFER_SIZE]; - grn_getenv("GRN_FMALLOC_PROB", - grn_fmalloc_prob_env, - GRN_ENV_BUFFER_SIZE); - if (grn_fmalloc_prob_env[0]) { - char grn_fmalloc_seed_env[GRN_ENV_BUFFER_SIZE]; - grn_fmalloc_prob = strtod(grn_fmalloc_prob_env, 0) * RAND_MAX; - grn_getenv("GRN_FMALLOC_SEED", - grn_fmalloc_seed_env, - GRN_ENV_BUFFER_SIZE); - if (grn_fmalloc_seed_env[0]) { - srand((unsigned int)atoi(grn_fmalloc_seed_env)); - } else { - srand((unsigned int)time(NULL)); - } - } - } - { - static char grn_fmalloc_func_env[GRN_ENV_BUFFER_SIZE]; - grn_getenv("GRN_FMALLOC_FUNC", - grn_fmalloc_func_env, - GRN_ENV_BUFFER_SIZE); - if (grn_fmalloc_func_env[0]) { - grn_fmalloc_func = grn_fmalloc_func_env; - } - } - { - static char grn_fmalloc_file_env[GRN_ENV_BUFFER_SIZE]; - grn_getenv("GRN_FMALLOC_FILE", - grn_fmalloc_file_env, - GRN_ENV_BUFFER_SIZE); - if (grn_fmalloc_file_env[0]) { - grn_fmalloc_file = grn_fmalloc_file_env; - } - } - { - char grn_fmalloc_line_env[GRN_ENV_BUFFER_SIZE]; - grn_getenv("GRN_FMALLOC_LINE", - grn_fmalloc_line_env, - GRN_ENV_BUFFER_SIZE); - if (grn_fmalloc_line_env[0]) { - grn_fmalloc_line = atoi(grn_fmalloc_line_env); - } - } -#endif /* USE_FAIL_MALLOC */ if ((rc = grn_com_init())) { GRN_LOG(ctx, GRN_LOG_ALERT, "grn_com_init failed (%d)", rc); goto fail_com; @@ -1157,8 +843,6 @@ grn_set_lock_timeout(int timeout) return GRN_SUCCESS; } -static int alloc_count = 0; - grn_rc grn_fin(void) { @@ -1182,7 +866,7 @@ grn_fin(void) grn_plugins_fin(); grn_ctx_fin(ctx); grn_com_fin(); - GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_fin (%d)", alloc_count); + GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_fin (%d)", grn_alloc_count()); grn_logger_fin(ctx); CRITICAL_SECTION_FIN(grn_glock); grn_alloc_info_fin(); @@ -1932,197 +1616,6 @@ grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info) return GRN_SUCCESS; } - -/**** memory allocation ****/ - -#define ALIGN_SIZE (1<<3) -#define ALIGN_MASK (ALIGN_SIZE-1) -#define GRN_CTX_ALLOC_CLEAR 1 - -void * -grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags, - const char* file, int line, const char *func) -{ - void *res = NULL; - if (!ctx) { return res; } - if (!ctx->impl) { - if (ERRP(ctx, GRN_ERROR)) { return res; } - } - CRITICAL_SECTION_ENTER(ctx->impl->lock); - { - int32_t i; - int32_t *header; - grn_io_mapinfo *mi; - size = ((size + ALIGN_MASK) & ~ALIGN_MASK) + ALIGN_SIZE; - if (size > GRN_CTX_SEGMENT_SIZE) { - uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; - if (npages >= (1LL<<32)) { - MERR("too long request size=%" GRN_FMT_SIZE, size); - goto exit; - } - for (i = 0, mi = ctx->impl->segs;; i++, mi++) { - if (i >= GRN_CTX_N_SEGMENTS) { - MERR("all segments are full"); - goto exit; - } - if (!mi->map) { break; } - } - if (!grn_io_anon_map(ctx, mi, npages * grn_pagesize)) { goto exit; } - //GRN_LOG(ctx, GRN_LOG_NOTICE, "map i=%d (%d)", i, npages * grn_pagesize); - mi->nref = (uint32_t) npages; - mi->count = GRN_CTX_SEGMENT_VLEN; - ctx->impl->currseg = -1; - header = mi->map; - header[0] = i; - header[1] = (int32_t) size; - } else { - i = ctx->impl->currseg; - mi = &ctx->impl->segs[i]; - if (i < 0 || size + mi->nref > GRN_CTX_SEGMENT_SIZE) { - for (i = 0, mi = ctx->impl->segs;; i++, mi++) { - if (i >= GRN_CTX_N_SEGMENTS) { - MERR("all segments are full"); - goto exit; - } - if (!mi->map) { break; } - } - if (!grn_io_anon_map(ctx, mi, GRN_CTX_SEGMENT_SIZE)) { goto exit; } - //GRN_LOG(ctx, GRN_LOG_NOTICE, "map i=%d", i); - mi->nref = 0; - mi->count = GRN_CTX_SEGMENT_WORD; - ctx->impl->currseg = i; - } - header = (int32_t *)((byte *)mi->map + mi->nref); - mi->nref += size; - mi->count++; - header[0] = i; - header[1] = (int32_t) size; - if ((flags & GRN_CTX_ALLOC_CLEAR) && - (mi->count & GRN_CTX_SEGMENT_DIRTY) && (size > ALIGN_SIZE)) { - memset(&header[2], 0, size - ALIGN_SIZE); - } - } - /* - { - char g = (ctx == &grn_gctx) ? 'g' : ' '; - GRN_LOG(ctx, GRN_LOG_NOTICE, "+%c(%p) %s:%d(%s) (%d:%d)%p mi(%d:%d)", g, ctx, file, line, func, header[0], header[1], &header[2], mi->nref, (mi->count & GRN_CTX_SEGMENT_MASK)); - } - */ - res = &header[2]; - } -exit : - CRITICAL_SECTION_LEAVE(ctx->impl->lock); - return res; -} - -void * -grn_ctx_malloc(grn_ctx *ctx, size_t size, - const char* file, int line, const char *func) -{ - return grn_ctx_alloc(ctx, size, 0, file, line, func); -} - -void * -grn_ctx_calloc(grn_ctx *ctx, size_t size, - const char* file, int line, const char *func) -{ - return grn_ctx_alloc(ctx, size, GRN_CTX_ALLOC_CLEAR, file, line, func); -} - -void * -grn_ctx_realloc(grn_ctx *ctx, void *ptr, size_t size, - const char* file, int line, const char *func) -{ - void *res = NULL; - if (size) { - /* todo : expand if possible */ - res = grn_ctx_alloc(ctx, size, 0, file, line, func); - if (res && ptr) { - int32_t *header = &((int32_t *)ptr)[-2]; - size_t size_ = header[1]; - grn_memcpy(res, ptr, size_ > size ? size : size_); - grn_ctx_free(ctx, ptr, file, line, func); - } - } else { - grn_ctx_free(ctx, ptr, file, line, func); - } - return res; -} - -char * -grn_ctx_strdup(grn_ctx *ctx, const char *s, const char* file, int line, const char *func) -{ - void *res = NULL; - if (s) { - size_t size = strlen(s) + 1; - if ((res = grn_ctx_alloc(ctx, size, 0, file, line, func))) { - grn_memcpy(res, s, size); - } - } - return res; -} - -void -grn_ctx_free(grn_ctx *ctx, void *ptr, - const char* file, int line, const char *func) -{ - if (!ctx) { return; } - if (!ctx->impl) { - ERR(GRN_INVALID_ARGUMENT,"ctx without impl passed."); - return; - } - CRITICAL_SECTION_ENTER(ctx->impl->lock); - if (ptr) { - int32_t *header = &((int32_t *)ptr)[-2]; - - if (header[0] >= GRN_CTX_N_SEGMENTS) { - ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed. ptr=%p seg=%d", ptr, *header); - goto exit; - } - /* - { - int32_t i = header[0]; - char c = 'X', g = (ctx == &grn_gctx) ? 'g' : ' '; - grn_io_mapinfo *mi = &ctx->impl->segs[i]; - if (!(mi->count & GRN_CTX_SEGMENT_VLEN) && - mi->map <= (void *)header && (char *)header < ((char *)mi->map + GRN_CTX_SEGMENT_SIZE)) { c = '-'; } - GRN_LOG(ctx, GRN_LOG_NOTICE, "%c%c(%p) %s:%d(%s) (%d:%d)%p mi(%d:%d)", c, g, ctx, file, line, func, header[0], header[1], &header[2], mi->nref, (mi->count & GRN_CTX_SEGMENT_MASK)); - } - */ - { - int32_t i = header[0]; - grn_io_mapinfo *mi = &ctx->impl->segs[i]; - if (mi->count & GRN_CTX_SEGMENT_VLEN) { - if (mi->map != header) { - ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed.. ptr=%p seg=%d", ptr, i); - goto exit; - } - //GRN_LOG(ctx, GRN_LOG_NOTICE, "umap i=%d (%d)", i, mi->nref * grn_pagesize); - grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); - mi->map = NULL; - } else { - if (!mi->map) { - ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed... ptr=%p seg=%d", ptr, i); - goto exit; - } - mi->count--; - if (!(mi->count & GRN_CTX_SEGMENT_MASK)) { - //GRN_LOG(ctx, GRN_LOG_NOTICE, "umap i=%d", i); - if (i == ctx->impl->currseg) { - mi->count |= GRN_CTX_SEGMENT_DIRTY; - mi->nref = 0; - } else { - grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); - mi->map = NULL; - } - } - } - } - } -exit : - CRITICAL_SECTION_LEAVE(ctx->impl->lock); -} - #define DB_P(s) ((s) && (s)->header.type == GRN_DB) grn_rc @@ -2146,401 +1639,6 @@ grn_ctx_use(grn_ctx *ctx, grn_obj *db) GRN_API_RETURN(ctx->rc); } -void * -grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, - const char* file, int line, const char *func) -{ - if (!ctx) { return NULL; } - if (!ctx->impl) { - if (ERRP(ctx, GRN_ERROR)) { return NULL; } - } - { - int32_t i = ctx->impl->lifoseg; - grn_io_mapinfo *mi = &ctx->impl->segs[i]; - if (size > GRN_CTX_SEGMENT_SIZE) { - uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; - if (npages >= (1LL<<32)) { - MERR("too long request size=%" GRN_FMT_SIZE, size); - return NULL; - } - for (;;) { - if (++i >= GRN_CTX_N_SEGMENTS) { - MERR("all segments are full"); - return NULL; - } - mi++; - if (!mi->map) { break; } - } - if (!grn_io_anon_map(ctx, mi, npages * grn_pagesize)) { return NULL; } - mi->nref = (uint32_t) npages; - mi->count = GRN_CTX_SEGMENT_VLEN|GRN_CTX_SEGMENT_LIFO; - ctx->impl->lifoseg = i; - return mi->map; - } else { - size = (size + ALIGN_MASK) & ~ALIGN_MASK; - if (i < 0 || (mi->count & GRN_CTX_SEGMENT_VLEN) || size + mi->nref > GRN_CTX_SEGMENT_SIZE) { - for (;;) { - if (++i >= GRN_CTX_N_SEGMENTS) { - MERR("all segments are full"); - return NULL; - } - if (!(++mi)->map) { break; } - } - if (!grn_io_anon_map(ctx, mi, GRN_CTX_SEGMENT_SIZE)) { return NULL; } - mi->nref = 0; - mi->count = GRN_CTX_SEGMENT_WORD|GRN_CTX_SEGMENT_LIFO; - ctx->impl->lifoseg = i; - } - { - uint32_t u = mi->nref; - mi->nref += size; - return (byte *)mi->map + u; - } - } - } -} - -void -grn_ctx_free_lifo(grn_ctx *ctx, void *ptr, - const char* file, int line, const char *func) -{ - if (!ctx) { return; } - if (!ctx->impl) { - ERR(GRN_INVALID_ARGUMENT,"ctx without impl passed."); - return; - } - { - int32_t i = ctx->impl->lifoseg, done = 0; - grn_io_mapinfo *mi = &ctx->impl->segs[i]; - if (i < 0) { - ERR(GRN_INVALID_ARGUMENT, "lifo buffer is void"); - return; - } - for (; i >= 0; i--, mi--) { - if (!(mi->count & GRN_CTX_SEGMENT_LIFO)) { continue; } - if (done) { break; } - if (mi->count & GRN_CTX_SEGMENT_VLEN) { - if (mi->map == ptr) { done = 1; } - grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); - mi->map = NULL; - } else { - if (mi->map == ptr) { - done = 1; - } else { - if (mi->map < ptr && ptr < (void *)((byte*)mi->map + mi->nref)) { - mi->nref = (uint32_t) ((uintptr_t)ptr - (uintptr_t)mi->map); - break; - } - } - grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); - mi->map = NULL; - } - } - ctx->impl->lifoseg = i; - } -} - -#if USE_DYNAMIC_MALLOC_CHANGE -grn_malloc_func -grn_ctx_get_malloc(grn_ctx *ctx) -{ - if (!ctx || !ctx->impl) { return NULL; } - return ctx->impl->malloc_func; -} - -void -grn_ctx_set_malloc(grn_ctx *ctx, grn_malloc_func malloc_func) -{ - if (!ctx || !ctx->impl) { return; } - ctx->impl->malloc_func = malloc_func; -} - -grn_calloc_func -grn_ctx_get_calloc(grn_ctx *ctx) -{ - if (!ctx || !ctx->impl) { return NULL; } - return ctx->impl->calloc_func; -} - -void -grn_ctx_set_calloc(grn_ctx *ctx, grn_calloc_func calloc_func) -{ - if (!ctx || !ctx->impl) { return; } - ctx->impl->calloc_func = calloc_func; -} - -grn_realloc_func -grn_ctx_get_realloc(grn_ctx *ctx) -{ - if (!ctx || !ctx->impl) { return NULL; } - return ctx->impl->realloc_func; -} - -void -grn_ctx_set_realloc(grn_ctx *ctx, grn_realloc_func realloc_func) -{ - if (!ctx || !ctx->impl) { return; } - ctx->impl->realloc_func = realloc_func; -} - -grn_strdup_func -grn_ctx_get_strdup(grn_ctx *ctx) -{ - if (!ctx || !ctx->impl) { return NULL; } - return ctx->impl->strdup_func; -} - -void -grn_ctx_set_strdup(grn_ctx *ctx, grn_strdup_func strdup_func) -{ - if (!ctx || !ctx->impl) { return; } - ctx->impl->strdup_func = strdup_func; -} - -grn_free_func -grn_ctx_get_free(grn_ctx *ctx) -{ - if (!ctx || !ctx->impl) { return NULL; } - return ctx->impl->free_func; -} - -void -grn_ctx_set_free(grn_ctx *ctx, grn_free_func free_func) -{ - if (!ctx || !ctx->impl) { return; } - ctx->impl->free_func = free_func; -} - -void * -grn_malloc(grn_ctx *ctx, size_t size, const char* file, int line, const char *func) -{ - if (ctx && ctx->impl && ctx->impl->malloc_func) { - return ctx->impl->malloc_func(ctx, size, file, line, func); - } else { - return grn_malloc_default(ctx, size, file, line, func); - } -} - -void * -grn_calloc(grn_ctx *ctx, size_t size, const char* file, int line, const char *func) -{ - if (ctx && ctx->impl && ctx->impl->calloc_func) { - return ctx->impl->calloc_func(ctx, size, file, line, func); - } else { - return grn_calloc_default(ctx, size, file, line, func); - } -} - -void * -grn_realloc(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func) -{ - if (ctx && ctx->impl && ctx->impl->realloc_func) { - return ctx->impl->realloc_func(ctx, ptr, size, file, line, func); - } else { - return grn_realloc_default(ctx, ptr, size, file, line, func); - } -} - -char * -grn_strdup(grn_ctx *ctx, const char *string, const char* file, int line, const char *func) -{ - if (ctx && ctx->impl && ctx->impl->strdup_func) { - return ctx->impl->strdup_func(ctx, string, file, line, func); - } else { - return grn_strdup_default(ctx, string, file, line, func); - } -} - -void -grn_free(grn_ctx *ctx, void *ptr, const char* file, int line, const char *func) -{ - if (ctx && ctx->impl && ctx->impl->free_func) { - return ctx->impl->free_func(ctx, ptr, file, line, func); - } else { - return grn_free_default(ctx, ptr, file, line, func); - } -} -#endif - -void * -grn_malloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const char *func) -{ - if (!ctx) { return NULL; } - { - void *res = malloc(size); - if (res) { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, size, file, line, func); - } else { - if (!(res = malloc(size))) { - MERR("malloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", - size, res, file, line, alloc_count); - } else { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, size, file, line, func); - } - } - return res; - } -} - -void * -grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const char *func) -{ - if (!ctx) { return NULL; } - { - void *res = calloc(size, 1); - if (res) { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, size, file, line, func); - } else { - if (!(res = calloc(size, 1))) { - MERR("calloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", - size, res, file, line, alloc_count); - } else { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, size, file, line, func); - } - } - return res; - } -} - -void -grn_free_default(grn_ctx *ctx, void *ptr, const char* file, int line, const char *func) -{ - if (!ctx) { return; } - grn_alloc_info_check(ctx, ptr); - { - free(ptr); - if (ptr) { - GRN_ADD_ALLOC_COUNT(-1); - } else { - GRN_LOG(ctx, GRN_LOG_ALERT, "free fail (%p) (%s:%d) <%d>", ptr, file, line, alloc_count); - } - } -} - -void * -grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func) -{ - void *res; - if (!ctx) { return NULL; } - if (size) { - if (!(res = realloc(ptr, size))) { - if (!(res = realloc(ptr, size))) { - MERR("realloc fail (%p,%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", - ptr, size, res, file, line, alloc_count); - return NULL; - } - } - if (ptr) { - grn_alloc_info_change(ptr, res, size); - } else { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, size, file, line, func); - } - } else { - if (!ptr) { return NULL; } - grn_alloc_info_check(ctx, ptr); - GRN_ADD_ALLOC_COUNT(-1); - free(ptr); - res = NULL; - } - return res; -} - -int -grn_alloc_count(void) -{ - return alloc_count; -} - -char * -grn_strdup_default(grn_ctx *ctx, const char *s, const char* file, int line, const char *func) -{ - if (!ctx) { return NULL; } - { - char *res = grn_strdup_raw(s); - if (res) { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, strlen(res) + 1, file, line, func); - } else { - if (!(res = grn_strdup_raw(s))) { - MERR("strdup(%p)=%p (%s:%d) <%d>", s, res, file, line, alloc_count); - } else { - GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res, strlen(res) + 1, file, line, func); - } - } - return res; - } -} - -#ifdef USE_FAIL_MALLOC -int -grn_fail_malloc_check(size_t size, const char *file, int line, const char *func) -{ - if ((grn_fmalloc_file && strcmp(file, grn_fmalloc_file)) || - (grn_fmalloc_line && line != grn_fmalloc_line) || - (grn_fmalloc_func && strcmp(func, grn_fmalloc_func))) { - return 1; - } - if (grn_fmalloc_prob && grn_fmalloc_prob >= rand()) { - return 0; - } - return 1; -} - -void * -grn_malloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func) -{ - if (grn_fail_malloc_check(size, file, line, func)) { - return grn_malloc_default(ctx, size, file, line, func); - } else { - MERR("fail_malloc (%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", - size, file, line, func, alloc_count); - return NULL; - } -} - -void * -grn_calloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func) -{ - if (grn_fail_malloc_check(size, file, line, func)) { - return grn_calloc_default(ctx, size, file, line, func); - } else { - MERR("fail_calloc (%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", - size, file, line, func, alloc_count); - return NULL; - } -} - -void * -grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, - const char *func) -{ - if (grn_fail_malloc_check(size, file, line, func)) { - return grn_realloc_default(ctx, ptr, size, file, line, func); - } else { - MERR("fail_realloc (%p,%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", - ptr, size, file, line, func, alloc_count); - return NULL; - } -} - -char * -grn_strdup_fail(grn_ctx *ctx, const char *s, const char* file, int line, const char *func) -{ - if (grn_fail_malloc_check(strlen(s), file, line, func)) { - return grn_strdup_default(ctx, s, file, line, func); - } else { - MERR("fail_strdup(%p) (%s:%d@%s) <%d>", s, file, line, func, alloc_count); - return NULL; - } -} -#endif /* USE_FAIL_MALLOC */ - /* don't handle error inside logger functions */ void Added: lib/grn_alloc.h (+124 -0) 100644 =================================================================== --- /dev/null +++ lib/grn_alloc.h 2016-04-12 18:09:26 +0900 (2026c67) @@ -0,0 +1,124 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_alloc_init_from_env(void); + +void grn_alloc_init_ctx_impl(grn_ctx *ctx); +void grn_alloc_fin_ctx_impl(grn_ctx *ctx); + +void grn_alloc_info_init(void); +void grn_alloc_info_fin(void); + +void grn_alloc_info_dump(grn_ctx *ctx); +void grn_alloc_info_free(grn_ctx *ctx); + +#define GRN_MALLOC(s) grn_malloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CALLOC(s) grn_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_REALLOC(p,s) grn_realloc(ctx,p,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_STRDUP(s) grn_strdup(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GMALLOC(s) grn_malloc(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GCALLOC(s) grn_calloc(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GREALLOC(p,s) grn_realloc(&grn_gctx,p,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GSTRDUP(s) grn_strdup(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_FREE(p) grn_free(ctx,p,__FILE__,__LINE__,__FUNCTION__) +#define GRN_MALLOCN(t,n) ((t *)(GRN_MALLOC(sizeof(t) * (n)))) +#define GRN_GFREE(p) grn_free(&grn_gctx,p,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GMALLOCN(t,n) ((t *)(GRN_GMALLOC(sizeof(t) * (n)))) + +#define GRN_CTX_ALLOC(ctx,s) grn_ctx_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CTX_FREE(ctx,p) grn_ctx_free(ctx,p,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CTX_ALLOC_L(ctx,s) grn_ctx_alloc_lifo(ctx,s,f,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CTX_FREE_L(ctx,p) grn_ctx_free_lifo(ctx,p,__FILE__,__LINE__,__FUNCTION__) + +void *grn_ctx_malloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func); +void *grn_ctx_calloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func); +void *grn_ctx_realloc(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func); +char *grn_ctx_strdup(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func); +void grn_ctx_free(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func); +void *grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func); +void grn_ctx_free_lifo(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func); + +#ifdef USE_DYNAMIC_MALLOC_CHANGE +typedef void *(*grn_malloc_func) (grn_ctx *ctx, size_t size, + const char *file, int line, const char *func); +typedef void *(*grn_calloc_func) (grn_ctx *ctx, size_t size, + const char *file, int line, const char *func); +typedef void *(*grn_realloc_func) (grn_ctx *ctx, void *ptr, size_t size, + const char *file, int line, const char *func); +typedef char *(*grn_strdup_func) (grn_ctx *ctx, const char *string, + const char *file, int line, const char *func); +typedef void (*grn_free_func) (grn_ctx *ctx, void *ptr, + const char *file, int line, const char *func); +grn_malloc_func grn_ctx_get_malloc(grn_ctx *ctx); +void grn_ctx_set_malloc(grn_ctx *ctx, grn_malloc_func malloc_func); +grn_calloc_func grn_ctx_get_calloc(grn_ctx *ctx); +void grn_ctx_set_calloc(grn_ctx *ctx, grn_calloc_func calloc_func); +grn_realloc_func grn_ctx_get_realloc(grn_ctx *ctx); +void grn_ctx_set_realloc(grn_ctx *ctx, grn_realloc_func realloc_func); +grn_strdup_func grn_ctx_get_strdup(grn_ctx *ctx); +void grn_ctx_set_strdup(grn_ctx *ctx, grn_strdup_func strdup_func); +grn_free_func grn_ctx_get_free(grn_ctx *ctx); +void grn_ctx_set_free(grn_ctx *ctx, grn_free_func free_func); + +void *grn_malloc(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_calloc(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_realloc(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); +char *grn_strdup(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); +void grn_free(grn_ctx *ctx, void *ptr, const char *file, int line, const char *func); +#else +# define grn_malloc grn_malloc_default +# define grn_calloc grn_calloc_default +# define grn_realloc grn_realloc_default +# define grn_strdup grn_strdup_default +# define grn_free grn_free_default +#endif + +GRN_API void *grn_malloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); +GRN_API char *grn_strdup_default(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); +GRN_API void grn_free_default(grn_ctx *ctx, void *ptr, const char* file, int line, const char *func); + +#ifdef USE_FAIL_MALLOC +int grn_fail_malloc_check(size_t size, const char *file, int line, const char *func); +void *grn_malloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_calloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); +char *grn_strdup_fail(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); +#endif + +int grn_alloc_count(void); + +#ifdef __cplusplus +} +#endif Modified: lib/grn_ctx.h (+1 -88) =================================================================== --- lib/grn_ctx.h 2016-04-11 23:40:30 +0900 (47d83bf) +++ lib/grn_ctx.h 2016-04-12 18:09:26 +0900 (48b023f) @@ -33,6 +33,7 @@ #endif /* HAVE_EXECINFO_H */ #include "grn_io.h" +#include "grn_alloc.h" #ifdef __cplusplus extern "C" { @@ -404,96 +405,12 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx); #define GERR(rc,...) ERRSET(&grn_gctx, GRN_ERROR, (rc), __VA_ARGS__) #define GMERR(...) ERRSET(&grn_gctx, GRN_ALERT, GRN_NO_MEMORY_AVAILABLE, __VA_ARGS__) -#define GRN_MALLOC(s) grn_malloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_CALLOC(s) grn_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_REALLOC(p,s) grn_realloc(ctx,p,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_STRDUP(s) grn_strdup(ctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_GMALLOC(s) grn_malloc(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_GCALLOC(s) grn_calloc(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_GREALLOC(p,s) grn_realloc(&grn_gctx,p,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_GSTRDUP(s) grn_strdup(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_FREE(p) grn_free(ctx,p,__FILE__,__LINE__,__FUNCTION__) -#define GRN_MALLOCN(t,n) ((t *)(GRN_MALLOC(sizeof(t) * (n)))) -#define GRN_GFREE(p) grn_free(&grn_gctx,p,__FILE__,__LINE__,__FUNCTION__) -#define GRN_GMALLOCN(t,n) ((t *)(GRN_GMALLOC(sizeof(t) * (n)))) - #ifdef DEBUG #define GRN_ASSERT(s) grn_assert(ctx,(s),__FILE__,__LINE__,__FUNCTION__) #else #define GRN_ASSERT(s) #endif -#define GRN_CTX_ALLOC(ctx,s) grn_ctx_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) -#define GRN_CTX_FREE(ctx,p) grn_ctx_free(ctx,p,__FILE__,__LINE__,__FUNCTION__) -#define GRN_CTX_ALLOC_L(ctx,s) grn_ctx_alloc_lifo(ctx,s,f,__FILE__,__LINE__,__FUNCTION__) -#define GRN_CTX_FREE_L(ctx,p) grn_ctx_free_lifo(ctx,p,__FILE__,__LINE__,__FUNCTION__) - -void *grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags, - const char* file, int line, const char *func); -void *grn_ctx_malloc(grn_ctx *ctx, size_t size, - const char* file, int line, const char *func); -void *grn_ctx_calloc(grn_ctx *ctx, size_t size, - const char* file, int line, const char *func); -void *grn_ctx_realloc(grn_ctx *ctx, void *ptr, size_t size, - const char* file, int line, const char *func); -char *grn_ctx_strdup(grn_ctx *ctx, const char *s, - const char* file, int line, const char *func); -void grn_ctx_free(grn_ctx *ctx, void *ptr, - const char* file, int line, const char *func); -void *grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, - const char* file, int line, const char *func); -void grn_ctx_free_lifo(grn_ctx *ctx, void *ptr, - const char* file, int line, const char *func); - -#ifdef USE_DYNAMIC_MALLOC_CHANGE -typedef void *(*grn_malloc_func) (grn_ctx *ctx, size_t size, - const char *file, int line, const char *func); -typedef void *(*grn_calloc_func) (grn_ctx *ctx, size_t size, - const char *file, int line, const char *func); -typedef void *(*grn_realloc_func) (grn_ctx *ctx, void *ptr, size_t size, - const char *file, int line, const char *func); -typedef char *(*grn_strdup_func) (grn_ctx *ctx, const char *string, - const char *file, int line, const char *func); -typedef void (*grn_free_func) (grn_ctx *ctx, void *ptr, - const char *file, int line, const char *func); -grn_malloc_func grn_ctx_get_malloc(grn_ctx *ctx); -void grn_ctx_set_malloc(grn_ctx *ctx, grn_malloc_func malloc_func); -grn_calloc_func grn_ctx_get_calloc(grn_ctx *ctx); -void grn_ctx_set_calloc(grn_ctx *ctx, grn_calloc_func calloc_func); -grn_realloc_func grn_ctx_get_realloc(grn_ctx *ctx); -void grn_ctx_set_realloc(grn_ctx *ctx, grn_realloc_func realloc_func); -grn_strdup_func grn_ctx_get_strdup(grn_ctx *ctx); -void grn_ctx_set_strdup(grn_ctx *ctx, grn_strdup_func strdup_func); -grn_free_func grn_ctx_get_free(grn_ctx *ctx); -void grn_ctx_set_free(grn_ctx *ctx, grn_free_func free_func); - -void *grn_malloc(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); -void *grn_calloc(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); -void *grn_realloc(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); -char *grn_strdup(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); -void grn_free(grn_ctx *ctx, void *ptr, const char *file, int line, const char *func); -#else -# define grn_malloc grn_malloc_default -# define grn_calloc grn_calloc_default -# define grn_realloc grn_realloc_default -# define grn_strdup grn_strdup_default -# define grn_free grn_free_default -#endif - -GRN_API void *grn_malloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); -void *grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); -void *grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); -GRN_API char *grn_strdup_default(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); -GRN_API void grn_free_default(grn_ctx *ctx, void *ptr, const char* file, int line, const char *func); - -#ifdef USE_FAIL_MALLOC -int grn_fail_malloc_check(size_t size, const char *file, int line, const char *func); -void *grn_malloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); -void *grn_calloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); -void *grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); -char *grn_strdup_fail(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); -#endif - void grn_assert(grn_ctx *ctx, int cond, const char* file, int line, const char* func); /**** grn_ctx ****/ @@ -543,10 +460,6 @@ void grn_log_reopen(grn_ctx *ctx); GRN_API grn_rc grn_ctx_sendv(grn_ctx *ctx, int argc, char **argv, int flags); GRN_API void grn_ctx_set_next_expr(grn_ctx *ctx, grn_obj *expr); -int grn_alloc_count(void); - -void grn_debug_dump_alloc_info(grn_ctx *ctx); - grn_content_type grn_get_ctype(grn_obj *var); /**** db_obj ****/ Modified: lib/proc.c (+1 -1) =================================================================== --- lib/proc.c 2016-04-11 23:40:30 +0900 (ba8ee3c) +++ lib/proc.c 2016-04-12 18:09:26 +0900 (41ff643) @@ -200,7 +200,7 @@ proc_status(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) GRN_OUTPUT_MAP_CLOSE(); #ifdef USE_MEMORY_DEBUG - grn_debug_dump_alloc_info(&grn_gctx); + grn_alloc_info_dump(&grn_gctx); #endif /* USE_MEMORY_DEBUG */ return NULL; Modified: lib/sources.am (+2 -0) =================================================================== --- lib/sources.am 2016-04-11 23:40:30 +0900 (a1d1266) +++ lib/sources.am 2016-04-12 18:09:26 +0900 (ec2c74d) @@ -1,4 +1,6 @@ libgroonga_la_SOURCES = \ + alloc.c \ + grn_alloc.h \ cache.c \ grn_cache.h \ com.c \