diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-01-31 09:48:19 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-01-31 09:48:19 +0100 |
commit | ab83952f293ea46c00e421c81b81a394c9cae2b4 (patch) | |
tree | 6a3e995bd1330828a0e988d896bca218863fc74c /mysys/safemalloc.c | |
parent | 055b62f404ee0a0463ee8ff98a0e24c083b95f1d (diff) | |
parent | 5267af5e9e5e601d4f4b1ef40730da1e36d38d9d (diff) | |
download | mariadb-git-ab83952f293ea46c00e421c81b81a394c9cae2b4.tar.gz |
10.0-base merge
Diffstat (limited to 'mysys/safemalloc.c')
-rw-r--r-- | mysys/safemalloc.c | 116 |
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 |