Commit c71fad99 authored by Sergei Golubchik's avatar Sergei Golubchik

cleanup:

* don't use 'myf flags', when 'my_bool is_thread_specific' is meant
* call set_malloc_size_cb() for embedded too
* warn in safemalloc if the memory is freed by a wrong thread

sql/mysqld.cc:
  move set_malloc_size_cb() to a function that is also called for embedded
sql/mysqld.h:
  gdb-friendly, one can put breakpoint on a function, but not on a macro
sql/sql_class.cc:
  initialize thread_id earlier
parent 52051882
...@@ -161,7 +161,7 @@ extern my_thread_id (*sf_malloc_dbug_id)(void); ...@@ -161,7 +161,7 @@ extern my_thread_id (*sf_malloc_dbug_id)(void);
#define SAFEMALLOC_REPORT_MEMORY(X) do {} while(0) #define SAFEMALLOC_REPORT_MEMORY(X) do {} while(0)
#endif #endif
typedef void (*MALLOC_SIZE_CB) (long long size, myf my_flags); typedef void (*MALLOC_SIZE_CB) (long long size, my_bool is_thread_specific);
extern void set_malloc_size_cb(MALLOC_SIZE_CB func); extern void set_malloc_size_cb(MALLOC_SIZE_CB func);
/* defines when allocating data */ /* defines when allocating data */
......
...@@ -37,10 +37,10 @@ ...@@ -37,10 +37,10 @@
*(size_t*) p= (size) | (flag); \ *(size_t*) p= (size) | (flag); \
(p)= (type_of_p) (((char*) (p)) + MALLOC_PREFIX_SIZE); \ (p)= (type_of_p) (((char*) (p)) + MALLOC_PREFIX_SIZE); \
} }
static inline size_t malloc_size_and_flag(void *p, myf *flags) static inline size_t malloc_size_and_flag(void *p, my_bool *is_thread_specific)
{ {
size_t size= MALLOC_SIZE(p); size_t size= MALLOC_SIZE(p);
*flags= (size & 1); *is_thread_specific= (size & 1);
return size & ~ (ulonglong) 1; return size & ~ (ulonglong) 1;
} }
#define MALLOC_SIZE_AND_FLAG(p,b) malloc_size_and_flag(p, b); #define MALLOC_SIZE_AND_FLAG(p,b) malloc_size_and_flag(p, b);
...@@ -60,10 +60,10 @@ static MALLOC_SIZE_CB malloc_size_cb_func= NULL; ...@@ -60,10 +60,10 @@ static MALLOC_SIZE_CB malloc_size_cb_func= NULL;
decrement the memory usage decrement the memory usage
*/ */
static void update_malloc_size(long long size, myf my_flags) static void update_malloc_size(long long size, my_bool is_thread_specific)
{ {
if (malloc_size_cb_func) if (malloc_size_cb_func)
malloc_size_cb_func(size, my_flags); malloc_size_cb_func(size, is_thread_specific);
} }
void set_malloc_size_cb(MALLOC_SIZE_CB func) void set_malloc_size_cb(MALLOC_SIZE_CB func)
...@@ -145,7 +145,7 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags) ...@@ -145,7 +145,7 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags)
{ {
void *point; void *point;
size_t old_size; size_t old_size;
myf old_flags; my_bool old_flags;
DBUG_ENTER("my_realloc"); DBUG_ENTER("my_realloc");
DBUG_PRINT("my",("ptr: %p size: %lu my_flags: %lu", oldpoint, DBUG_PRINT("my",("ptr: %p size: %lu my_flags: %lu", oldpoint,
(ulong) size, my_flags)); (ulong) size, my_flags));
...@@ -210,7 +210,7 @@ void my_free(void *ptr) ...@@ -210,7 +210,7 @@ void my_free(void *ptr)
if (ptr) if (ptr)
{ {
size_t old_size; size_t old_size;
myf old_flags; my_bool old_flags;
old_size= MALLOC_SIZE_AND_FLAG(ptr, &old_flags); old_size= MALLOC_SIZE_AND_FLAG(ptr, &old_flags);
update_malloc_size(- (longlong) old_size - MALLOC_PREFIX_SIZE, old_flags); update_malloc_size(- (longlong) old_size - MALLOC_PREFIX_SIZE, old_flags);
sf_free(MALLOC_FIX_POINTER_FOR_FREE(ptr)); sf_free(MALLOC_FIX_POINTER_FOR_FREE(ptr));
......
...@@ -73,7 +73,7 @@ extern PSI_file_key key_file_charset, key_file_cnf; ...@@ -73,7 +73,7 @@ extern PSI_file_key key_file_charset, key_file_cnf;
void *sf_malloc(size_t size, myf my_flags); void *sf_malloc(size_t size, myf my_flags);
void *sf_realloc(void *ptr, size_t size, myf my_flags); void *sf_realloc(void *ptr, size_t size, myf my_flags);
void sf_free(void *ptr); void sf_free(void *ptr);
size_t sf_malloc_usable_size(void *ptr, myf *my_flags); size_t sf_malloc_usable_size(void *ptr, my_bool *is_thread_specific);
#else #else
#define sf_malloc(X,Y) malloc(X) #define sf_malloc(X,Y) malloc(X)
#define sf_realloc(X,Y,Z) realloc(X,Y) #define sf_realloc(X,Y,Z) realloc(X,Y)
......
...@@ -207,47 +207,16 @@ void sf_free(void *ptr) ...@@ -207,47 +207,16 @@ void sf_free(void *ptr)
@return Size of block @return Size of block
*/ */
size_t sf_malloc_usable_size(void *ptr, myf *flags) size_t sf_malloc_usable_size(void *ptr, my_bool *is_thread_specific)
{ {
struct st_irem *irem= (struct st_irem *)ptr - 1; struct st_irem *irem= (struct st_irem *)ptr - 1;
DBUG_ENTER("sf_malloc_usable_size"); DBUG_ENTER("sf_malloc_usable_size");
*flags= test(irem->flags & MY_THREAD_SPECIFIC); *is_thread_specific= test(irem->flags & MY_THREAD_SPECIFIC);
DBUG_PRINT("exit", ("size: %lu flags: %lu", (ulong) irem->datasize, DBUG_PRINT("exit", ("size: %lu flags: %lu", (ulong) irem->datasize,
*flags)); (ulong)irem->flags));
DBUG_RETURN(irem->datasize); DBUG_RETURN(irem->datasize);
} }
static void free_memory(void *ptr)
{
struct st_irem *irem= (struct st_irem *)ptr - 1;
if ((irem->flags & MY_THREAD_SPECIFIC) &&
irem->thread_id != sf_malloc_dbug_id())
{
DBUG_PRINT("warning",
("Memory: %p was allocated by thread %lu and freed by thread %lu", ptr, (ulong) irem->thread_id, (ulong) sf_malloc_dbug_id()));
}
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;
}
#ifdef HAVE_BACKTRACE #ifdef HAVE_BACKTRACE
static void print_stack(void **frame) static void print_stack(void **frame)
{ {
...@@ -277,6 +246,39 @@ static void print_stack(void **frame) ...@@ -277,6 +246,39 @@ static void print_stack(void **frame)
#define print_stack(X) fprintf(stderr, "???\n") #define print_stack(X) fprintf(stderr, "???\n")
#endif #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,...) static void warn(const char *format,...)
{ {
va_list args; va_list args;
...@@ -371,8 +373,10 @@ void sf_report_leaked_memory(my_thread_id id) ...@@ -371,8 +373,10 @@ void sf_report_leaked_memory(my_thread_id id)
{ {
if (!id || (irem->thread_id == id && irem->flags & MY_THREAD_SPECIFIC)) if (!id || (irem->thread_id == id && irem->flags & MY_THREAD_SPECIFIC))
{ {
fprintf(stderr, "Warning: %4lu bytes lost, allocated at ", my_thread_id tid = irem->thread_id && irem->flags & MY_THREAD_SPECIFIC ?
(ulong) irem->datasize); irem->thread_id : 0;
fprintf(stderr, "Warning: %4lu bytes lost, allocated by T@%lu at ",
(ulong) irem->datasize,tid);
print_stack(irem->frame); print_stack(irem->frame);
total+= irem->datasize; total+= irem->datasize;
} }
......
...@@ -3454,6 +3454,36 @@ extern "C" my_thread_id mariadb_dbug_id() ...@@ -3454,6 +3454,36 @@ extern "C" my_thread_id mariadb_dbug_id()
} }
#endif /* SAFEMALLOC */ #endif /* SAFEMALLOC */
/* Thread Mem Usage By P.Linux */
extern "C" {
static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific)
{
/* If thread specific memory */
if (is_thread_specific)
{
THD *thd= current_thd;
if (mysqld_server_initialized || thd)
{
/*
THD may not be set if we are called from my_net_init() before THD
thread has started.
However, this should never happen, so better to assert and
fix this.
*/
DBUG_ASSERT(thd);
if (thd)
{
DBUG_PRINT("info", ("memory_used: %lld size: %lld",
(longlong) thd->status_var.memory_used, size));
thd->status_var.memory_used+= size;
DBUG_ASSERT((longlong) thd->status_var.memory_used >= 0);
}
}
}
my_atomic_add64(&global_status_var.memory_used, size);
}
}
/* /*
Init common variables Init common variables
...@@ -3464,6 +3494,8 @@ static int init_common_variables() ...@@ -3464,6 +3494,8 @@ static int init_common_variables()
umask(((~my_umask) & 0666)); umask(((~my_umask) & 0666));
my_decimal_set_zero(&decimal_zero); // set decimal_zero constant; my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
set_malloc_size_cb(my_malloc_size_cb_func);
tzset(); // Set tzname tzset(); // Set tzname
sf_leaking_memory= 0; // no memory leaks from now on sf_leaking_memory= 0; // no memory leaks from now on
...@@ -4675,36 +4707,6 @@ static void test_lc_time_sz() ...@@ -4675,36 +4707,6 @@ static void test_lc_time_sz()
#endif//DBUG_OFF #endif//DBUG_OFF
/* Thread Mem Usage By P.Linux */
extern "C"
void my_malloc_size_cb_func(long long size, myf my_flags)
{
/* If thread specific memory */
if (my_flags)
{
THD *thd= current_thd;
if (mysqld_server_initialized || thd)
{
/*
THD may not be set if we are called from my_net_init() before THD
thread has started.
However, this should never happen, so better to assert and
fix this.
*/
DBUG_ASSERT(thd);
if (thd)
{
DBUG_PRINT("info", ("memory_used: %lld size: %lld",
(longlong) thd->status_var.memory_used, size));
thd->status_var.memory_used+= size;
DBUG_ASSERT((longlong) thd->status_var.memory_used >= 0);
}
}
}
my_atomic_add64(&global_status_var.memory_used, size);
}
#ifdef __WIN__ #ifdef __WIN__
int win_main(int argc, char **argv) int win_main(int argc, char **argv)
#else #else
...@@ -4717,7 +4719,6 @@ int mysqld_main(int argc, char **argv) ...@@ -4717,7 +4719,6 @@ int mysqld_main(int argc, char **argv)
*/ */
my_progname= argv[0]; my_progname= argv[0];
sf_leaking_memory= 1; // no safemalloc memory leak reports if we exit early sf_leaking_memory= 1; // no safemalloc memory leak reports if we exit early
set_malloc_size_cb(my_malloc_size_cb_func);
mysqld_server_started= mysqld_server_initialized= 0; mysqld_server_started= mysqld_server_initialized= 0;
#ifdef HAVE_NPTL #ifdef HAVE_NPTL
...@@ -5246,7 +5247,6 @@ int mysqld_main(int argc, char **argv) ...@@ -5246,7 +5247,6 @@ int mysqld_main(int argc, char **argv)
/* Must be initialized early for comparison of service name */ /* Must be initialized early for comparison of service name */
system_charset_info= &my_charset_utf8_general_ci; system_charset_info= &my_charset_utf8_general_ci;
set_malloc_size_cb(my_malloc_size_cb_func);
if (my_init()) if (my_init())
{ {
......
...@@ -534,7 +534,10 @@ inline THD *_current_thd(void) ...@@ -534,7 +534,10 @@ inline THD *_current_thd(void)
} }
#endif #endif
#define current_thd _current_thd() #define current_thd _current_thd()
#define set_current_thd(X) my_pthread_setspecific_ptr(THR_THD, (X)) inline int set_current_thd(THD *thd)
{
return my_pthread_setspecific_ptr(THR_THD, thd);
}
/* /*
@todo remove, make it static in ha_maria.cc @todo remove, make it static in ha_maria.cc
......
...@@ -793,6 +793,7 @@ THD::THD() ...@@ -793,6 +793,7 @@ THD::THD()
accessed_rows_and_keys(0), accessed_rows_and_keys(0),
warning_info(&main_warning_info), warning_info(&main_warning_info),
stmt_da(&main_da), stmt_da(&main_da),
thread_id(0),
global_disable_checkpoint(0), global_disable_checkpoint(0),
is_fatal_error(0), is_fatal_error(0),
transaction_rollback_request(0), transaction_rollback_request(0),
...@@ -867,7 +868,6 @@ THD::THD() ...@@ -867,7 +868,6 @@ THD::THD()
connection_name.length= 0; connection_name.length= 0;
bzero(&variables, sizeof(variables)); bzero(&variables, sizeof(variables));
thread_id= 0;
one_shot_set= 0; one_shot_set= 0;
file_id = 0; file_id = 0;
query_id= 0; query_id= 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment