summaryrefslogtreecommitdiff
path: root/mysys/safemalloc.c
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-01-31 09:48:19 +0100
committerSergei Golubchik <sergii@pisem.net>2013-01-31 09:48:19 +0100
commitab83952f293ea46c00e421c81b81a394c9cae2b4 (patch)
tree6a3e995bd1330828a0e988d896bca218863fc74c /mysys/safemalloc.c
parent055b62f404ee0a0463ee8ff98a0e24c083b95f1d (diff)
parent5267af5e9e5e601d4f4b1ef40730da1e36d38d9d (diff)
downloadmariadb-git-ab83952f293ea46c00e421c81b81a394c9cae2b4.tar.gz
10.0-base merge
Diffstat (limited to 'mysys/safemalloc.c')
-rw-r--r--mysys/safemalloc.c116
1 files changed, 86 insertions, 30 deletions
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 2f01573fee7..bdcfe4480db 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -58,6 +58,8 @@ struct st_irem
#ifdef HAVE_BACKTRACE
void *frame[SF_REMEMBER_FRAMES]; /* call stack */
#endif
+ uint32 flags; /* Flags passed to malloc */
+ my_thread_id thread_id; /* Which thread did the allocation */
uint32 marker; /* Underrun marker value */
};
@@ -79,11 +81,21 @@ static int bad_ptr(const char *where, void *ptr);
static void free_memory(void *ptr);
static void sf_terminate();
+/* Setup default call to get a thread id for the memory */
+
+my_thread_id default_sf_malloc_dbug_id(void)
+{
+ return my_thread_dbug_id();
+}
+
+my_thread_id (*sf_malloc_dbug_id)(void)= default_sf_malloc_dbug_id;
+
+
/**
allocates memory
*/
-void *sf_malloc(size_t size)
+void *sf_malloc(size_t size, myf my_flags)
{
struct st_irem *irem;
uchar *data;
@@ -112,7 +124,9 @@ void *sf_malloc(size_t size)
data= (uchar*) (irem + 1);
irem->datasize= size;
irem->prev= 0;
+ irem->flags= my_flags;
irem->marker= MAGICSTART;
+ irem->thread_id= sf_malloc_dbug_id();
data[size + 0]= MAGICEND0;
data[size + 1]= MAGICEND1;
data[size + 2]= MAGICEND2;
@@ -152,17 +166,17 @@ void *sf_malloc(size_t size)
return data;
}
-void *sf_realloc(void *ptr, size_t size)
+void *sf_realloc(void *ptr, size_t size, myf my_flags)
{
char *data;
if (!ptr)
- return sf_malloc(size);
+ return sf_malloc(size, my_flags);
if (bad_ptr("Reallocating", ptr))
return 0;
- if ((data= sf_malloc(size)))
+ if ((data= sf_malloc(size, my_flags)))
{
struct st_irem *irem= (struct st_irem *)ptr - 1;
set_if_smaller(size, irem->datasize);
@@ -180,28 +194,25 @@ void sf_free(void *ptr)
free_memory(ptr);
}
-static void free_memory(void *ptr)
-{
- struct st_irem *irem= (struct st_irem *)ptr - 1;
-
- pthread_mutex_lock(&sf_mutex);
- /* Remove this structure from the linked list */
- if (irem->prev)
- irem->prev->next= irem->next;
- else
- sf_malloc_root= irem->next;
+/**
+ Return size of memory block and if block is thread specific
- if (irem->next)
- irem->next->prev= irem->prev;
+ sf_malloc_usable_size()
+ @param ptr Pointer to malloced block
+ @param flags We will store 1 here if block is marked as MY_THREAD_SPECIFIC
+ otherwise 0
- /* Handle the statistics */
- sf_malloc_count--;
- pthread_mutex_unlock(&sf_mutex);
+ @return Size of block
+*/
- /* only trash the data and magic values, but keep the stack trace */
- TRASH_FREE((uchar*)(irem + 1) - 4, irem->datasize + 8);
- free(irem);
- return;
+size_t sf_malloc_usable_size(void *ptr, my_bool *is_thread_specific)
+{
+ struct st_irem *irem= (struct st_irem *)ptr - 1;
+ DBUG_ENTER("sf_malloc_usable_size");
+ *is_thread_specific= test(irem->flags & MY_THREAD_SPECIFIC);
+ DBUG_PRINT("exit", ("size: %lu flags: %lu", (ulong) irem->datasize,
+ (ulong)irem->flags));
+ DBUG_RETURN(irem->datasize);
}
#ifdef HAVE_BACKTRACE
@@ -233,6 +244,39 @@ static void print_stack(void **frame)
#define print_stack(X) fprintf(stderr, "???\n")
#endif
+static void free_memory(void *ptr)
+{
+ struct st_irem *irem= (struct st_irem *)ptr - 1;
+
+ if ((irem->flags & MY_THREAD_SPECIFIC) && irem->thread_id &&
+ irem->thread_id != sf_malloc_dbug_id())
+ {
+ fprintf(stderr, "Warning: %4lu bytes freed by T@%lu, allocated by T@%lu at ",
+ (ulong) irem->datasize,
+ (ulong) sf_malloc_dbug_id(), (ulong) irem->thread_id);
+ print_stack(irem->frame);
+ }
+
+ pthread_mutex_lock(&sf_mutex);
+ /* Remove this structure from the linked list */
+ if (irem->prev)
+ irem->prev->next= irem->next;
+ else
+ sf_malloc_root= irem->next;
+
+ if (irem->next)
+ irem->next->prev= irem->prev;
+
+ /* Handle the statistics */
+ sf_malloc_count--;
+ pthread_mutex_unlock(&sf_mutex);
+
+ /* only trash the data and magic values, but keep the stack trace */
+ TRASH_FREE((uchar*)(irem + 1) - 4, irem->datasize + 8);
+ free(irem);
+ return;
+}
+
static void warn(const char *format,...)
{
va_list args;
@@ -310,9 +354,11 @@ static int sf_sanity()
/**
report on all the memory pieces that have not been free'd
+
+ @param id Id of thread to report. 0 if all
*/
-static void sf_terminate()
+void sf_report_leaked_memory(my_thread_id id)
{
size_t total= 0;
struct st_irem *irem;
@@ -320,21 +366,31 @@ static void sf_terminate()
sf_sanity();
/* Report on all the memory that was allocated but not free'd */
- if (!sf_leaking_memory && sf_malloc_root)
+
+ for (irem= sf_malloc_root; irem; irem= irem->next)
{
- for (irem= sf_malloc_root; irem; irem= irem->next)
+ if (!id || (irem->thread_id == id && irem->flags & MY_THREAD_SPECIFIC))
{
- fprintf(stderr, "Warning: %4lu bytes lost, allocated at ",
- (ulong) irem->datasize);
+ my_thread_id tid = irem->thread_id && irem->flags & MY_THREAD_SPECIFIC ?
+ irem->thread_id : 0;
+ fprintf(stderr, "Warning: %4lu bytes lost, allocated by T@%lu at ",
+ (ulong) irem->datasize,tid);
print_stack(irem->frame);
total+= irem->datasize;
}
+ }
+ if (total)
fprintf(stderr, "Memory lost: %lu bytes in %d chunks\n",
(ulong) total, sf_malloc_count);
- }
+ return;
+}
+
+static void sf_terminate()
+{
+ if (!sf_leaking_memory)
+ sf_report_leaked_memory(0);
pthread_mutex_destroy(&sf_mutex);
- return;
}
#endif