[Beignet] [PATCH 06/57] Add cl_alloc.h for new runtime.
junyan.he at inbox.com
junyan.he at inbox.com
Sun Jun 11 05:49:52 UTC 2017
From: Junyan He <junyan.he at 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.he at 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.segovia at 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
More information about the Beignet
mailing list