From: Junyan He <junyan...@intel.com> Define malloc and calloc for debuging. We can enable CL_ALLOC_DEBUG to find memory leak points in CL runtime. All the mem alloc operations in runtime need to use these macro rather than direct call the system alloc functions.
Signed-off-by: Junyan He <junyan...@intel.com> --- runtime/cl_alloc.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++ runtime/cl_alloc.h | 72 ++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 runtime/cl_alloc.c create mode 100644 runtime/cl_alloc.h diff --git a/runtime/cl_alloc.c b/runtime/cl_alloc.c new file mode 100644 index 0000000..08b0abc --- /dev/null +++ b/runtime/cl_alloc.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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, see <http://www.gnu.org/licenses/>. + * + */ +#include "cl_alloc.h" +#include "cl_utils.h" +#include "cl_device_id.h" +#include <stdlib.h> +#include <assert.h> +#include <malloc.h> +#include <pthread.h> +#include <string.h> + +#ifdef CL_ALLOC_DEBUG + +static pthread_mutex_t cl_alloc_log_lock; +#define MAX_ALLOC_LOG_NUM 1024 * 1024 +static unsigned int cl_alloc_log_num; + +typedef struct _cl_alloc_log_item { + void *ptr; + size_t size; + char *file; + int line; +} _cl_alloc_log_item; +typedef struct _cl_alloc_log_item *cl_alloc_log_item; + +#define ALLOC_LOG_BUCKET_SZ 128 +static cl_alloc_log_item *cl_alloc_log_map[ALLOC_LOG_BUCKET_SZ]; +static int cl_alloc_log_map_size[ALLOC_LOG_BUCKET_SZ]; + +LOCAL void cl_alloc_debug_init(void) +{ + static int inited = 0; + int i; + if (inited) + return; + + pthread_mutex_init(&cl_alloc_log_lock, NULL); + + for (i = 0; i < ALLOC_LOG_BUCKET_SZ; i++) { + cl_alloc_log_map_size[i] = 128; + cl_alloc_log_map[i] = malloc(cl_alloc_log_map_size[i] * sizeof(cl_alloc_log_item)); + memset(cl_alloc_log_map[i], 0, cl_alloc_log_map_size[i] * sizeof(cl_alloc_log_item)); + } + cl_alloc_log_num = 0; + + atexit(cl_alloc_report_unfreed); + atexit(cl_device_gen_cleanup); + inited = 1; +} + +static void insert_alloc_log_item(void *ptr, size_t sz, char *file, int line) +{ + cl_long slot; + int i; + + if (cl_alloc_log_num > MAX_ALLOC_LOG_NUM) { + // To many alloc without free. We consider already leaks a lot. + cl_alloc_report_unfreed(); + assert(0); + } + + slot = (cl_long)ptr; + slot = (slot >> 5) & 0x07f; + assert(slot < ALLOC_LOG_BUCKET_SZ); + + cl_alloc_log_item it = malloc(sizeof(_cl_alloc_log_item)); + assert(it); + it->ptr = ptr; + it->size = sz; + it->file = file; + it->line = line; + + pthread_mutex_lock(&cl_alloc_log_lock); + for (i = 0; i < cl_alloc_log_map_size[slot]; i++) { + if (cl_alloc_log_map[slot][i] == NULL) { + break; + } + } + + if (i == cl_alloc_log_map_size[slot]) { + cl_alloc_log_map[slot] = + realloc(cl_alloc_log_map[slot], 2 * cl_alloc_log_map_size[slot] * sizeof(cl_alloc_log_item)); + memset(cl_alloc_log_map[slot] + cl_alloc_log_map_size[slot], 0, + cl_alloc_log_map_size[slot] * sizeof(cl_alloc_log_item)); + cl_alloc_log_map_size[slot] = cl_alloc_log_map_size[slot] * 2; + } + + cl_alloc_log_map[slot][i] = it; + cl_alloc_log_num++; + pthread_mutex_unlock(&cl_alloc_log_lock); +} + +static void delete_alloc_log_item(void *ptr, char *file, int line) +{ + cl_long slot; + int i; + + slot = (cl_long)ptr; + slot = (slot >> 5) & 0x07f; + assert(slot < ALLOC_LOG_BUCKET_SZ); + + pthread_mutex_lock(&cl_alloc_log_lock); + for (i = 0; i < cl_alloc_log_map_size[slot]; i++) { + if (cl_alloc_log_map[slot][i] && cl_alloc_log_map[slot][i]->ptr == ptr) { + break; + } + } + + if (i == cl_alloc_log_map_size[slot]) { + printf("Free at file: %s, line: %d, We can not find the malloc log for this ptr:%p, fatal\n", + file, line, ptr); + assert(0); + } + + free(cl_alloc_log_map[slot][i]); + cl_alloc_log_map[slot][i] = NULL; + + cl_alloc_log_num--; + pthread_mutex_unlock(&cl_alloc_log_lock); +} + +LOCAL void cl_register_alloc_ptr(void *ptr, size_t sz, char *file, int line) +{ + assert(ptr); + insert_alloc_log_item(ptr, sz, file, line); +} + +LOCAL void *cl_malloc(size_t sz, char *file, int line) +{ + void *p = malloc(sz); + assert(p); + insert_alloc_log_item(p, sz, file, line); + return p; +} + +LOCAL void *cl_memalign(size_t align, size_t sz, char *file, int line) +{ + void *p = NULL; + p = memalign(align, sz); + assert(p); + insert_alloc_log_item(p, ((sz + align - 1) / align) * align, file, line); + return p; +} + +LOCAL void *cl_calloc(size_t n, size_t elem_size, char *file, int line) +{ + void *p = NULL; + p = calloc(n, elem_size); + assert(p); + insert_alloc_log_item(p, n * elem_size, file, line); + return p; +} + +LOCAL void *cl_realloc(void *ptr, size_t sz, char *file, int line) +{ + void *p = NULL; + + if (ptr != NULL) { + delete_alloc_log_item(ptr, file, line); + } + + p = realloc(ptr, sz); + assert(p); + insert_alloc_log_item(p, sz, file, line); + return p; +} + +LOCAL void cl_free(void *ptr, char *file, int line) +{ + if (ptr == NULL) + return; + + delete_alloc_log_item(ptr, file, line); + free(ptr); +} + +void cl_alloc_report_unfreed(void) +{ + int i, slot, num; + pthread_mutex_lock(&cl_alloc_log_lock); + if (cl_alloc_log_num == 0) { + pthread_mutex_unlock(&cl_alloc_log_lock); + return; + } + + printf("-------------------------------------------------------------------\n"); + num = 0; + for (slot = 0; slot < ALLOC_LOG_BUCKET_SZ; slot++) { + for (i = 0; i < cl_alloc_log_map_size[slot]; i++) { + if (cl_alloc_log_map[slot][i]) { + printf("Leak point at file:%s, line: %d, ptr is %p, alloc size is %ld\n", + cl_alloc_log_map[slot][i]->file, cl_alloc_log_map[slot][i]->line, + cl_alloc_log_map[slot][i]->ptr, cl_alloc_log_map[slot][i]->size); + num++; + } + } + } + printf("-------------------------------------------------------------------\n"); + assert(num == cl_alloc_log_num); + pthread_mutex_unlock(&cl_alloc_log_lock); +} + +#endif diff --git a/runtime/cl_alloc.h b/runtime/cl_alloc.h new file mode 100644 index 0000000..61a904e --- /dev/null +++ b/runtime/cl_alloc.h @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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, see <http://www.gnu.org/licenses/>. + * + * Author: Benjamin Segovia <benjamin.sego...@intel.com> + */ + +#ifndef __CL_ALLOC_H__ +#define __CL_ALLOC_H__ + +#include <stdlib.h> +#include <malloc.h> + +//#define CL_ALLOC_DEBUG 1 +#ifdef CL_ALLOC_DEBUG + +/* Register some ptr allocated by other part */ +extern void cl_register_alloc_ptr(void *ptr, size_t sz, char *file, int line); +#define CL_REGISTER_ALLOC_PTR(PTR, SZ) cl_register_alloc_ptr(PTR, SZ, __FILE__, __LINE__) + +/* Return a valid pointer for the requested memory block size */ +extern void *cl_malloc(size_t sz, char *file, int line); +#define CL_MALLOC(SZ) cl_malloc(SZ, __FILE__, __LINE__) + +/* Aligned malloc */ +extern void *cl_memalign(size_t align, size_t sz, char *file, int line); +#define CL_MEMALIGN(ALIGN, SZ) cl_memalign(ALIGN, SZ, __FILE__, __LINE__) + +/* malloc + memzero */ +extern void *cl_calloc(size_t n, size_t elem_size, char *file, int line); +#define CL_CALLOC(N, ELEM_SIZE) cl_calloc(N, ELEM_SIZE, __FILE__, __LINE__) + +/* Regular realloc */ +extern void *cl_realloc(void *ptr, size_t sz, char *file, int line); +#define CL_REALLOC(PTR, SZ) cl_realloc(PTR, SZ, __FILE__, __LINE__) + +/* Free a pointer allocated with cl_*alloc */ +extern void cl_free(void *ptr, char *file, int line); +#define CL_FREE(PTR) cl_free(PTR, __FILE__, __LINE__) + +/* We count the number of allocation. This function report the number of + * allocation still unfreed + */ +extern void cl_alloc_report_unfreed(void); +#define CL_ALLOC_REPORT_UNFREED() cl_alloc_report_unfreed() + +extern void cl_alloc_debug_init(void); +#define CL_ALLOC_DEBUG_INIT() cl_alloc_debug_init() + +#else +#define CL_REGISTER_ALLOC_PTR(PTR, SZ) +#define CL_MALLOC(SZ) malloc(SZ) +#define CL_MEMALIGN(ALIGN, SZ) memalign(ALIGN, SZ) +#define CL_CALLOC(N, ELEM_SIZE) calloc(N, ELEM_SIZE) +#define CL_REALLOC(PTR, SZ) realloc(PTR, SZ) +#define CL_FREE(PTR) free(PTR) +#define CL_ALLOC_REPORT_UNFREED() +#define CL_ALLOC_DEBUG_INIT() +#endif /* end of CL_ALLOC_DEBUG */ +#endif /* __CL_ALLOC_H__ */ -- 2.7.4 _______________________________________________ Beignet mailing list Beignet@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/beignet