diff options
author | Michael Widenius <monty@askmonty.org> | 2013-01-23 16:16:14 +0100 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2013-01-23 16:16:14 +0100 |
commit | a260b155542179bec75a6bbe1e430bea57b70ad6 (patch) | |
tree | 761fdd82f49c9fc557398218a11d089961263ead /sql | |
parent | 09665bfd0e83efbc6c67f14852800fb4a0fe1e13 (diff) | |
download | mariadb-git-a260b155542179bec75a6bbe1e430bea57b70ad6.tar.gz |
MDEV-4011 Added per thread memory counting and usage
Base code and idea from a patch from by plinux at Taobao.
The idea is that we mark all memory that are thread specific with MY_THREAD_SPECIFIC.
Memory counting is done per thread in the my_malloc_size_cb_func callback function from my_malloc().
There are plenty of new asserts to ensure that for a debug server the counting is correct.
Information_schema.processlist gets two new columns: MEMORY_USED and EXAMINED_ROWS.
- The later is there mainly to show how query is progressing.
The following changes in interfaces was needed to get this to work:
- init_alloc_root() amd init_sql_alloc() has extra option so that one can mark memory with MY_THREAD_SPECIFIC
- One now have to use alloc_root_set_min_malloc() to set min memory to be allocated by alloc_root()
- my_init_dynamic_array() has extra option so that one can mark memory with MY_THREAD_SPECIFIC
- my_net_init() has extra option so that one can mark memory with MY_THREAD_SPECIFIC
- Added flag for hash_init() so that one can mark hash table to be thread specific.
- Added flags to init_tree() so that one can mark tree to be thread specific.
- Removed with_delete option to init_tree(). Now one should instead use MY_TREE_WITH_DELETE_FLAG.
- Added flag to Warning_info::Warning_info() if the structure should be fully initialized.
- String elements can now be marked as thread specific.
- Internal HEAP tables are now marking it's memory as MY_THREAD_SPECIFIC.
- Changed type of myf from int to ulong, as this is always a set of bit flags.
Other things:
- Removed calls to net_end() and thd->cleanup() as these are now done in ~THD()
- We now also show EXAMINED_ROWS in SHOW PROCESSLIST
- Added new variable 'memory_used'
- Fixed bug where kill_threads_for_user() was using the wrong mem_root to allocate memory.
- Removed calls to the obsoleted function init_dynamic_array()
- Use set_current_thd() instead of my_pthread_setspecific_ptr(THR_THD,...)
client/completion_hash.cc:
Updated call to init_alloc_root()
client/mysql.cc:
Updated call to init_alloc_root()
client/mysqlbinlog.cc:
init_dynamic_array() -> my_init_dynamic_array()
Updated call to init_alloc_root()
client/mysqlcheck.c:
Updated call to my_init_dynamic_array()
client/mysqldump.c:
Updated call to init_alloc_root()
client/mysqltest.cc:
Updated call to init_alloc_root()
Updated call to my_init_dynamic_array()
Fixed compiler warnings
extra/comp_err.c:
Updated call to my_init_dynamic_array()
extra/resolve_stack_dump.c:
Updated call to my_init_dynamic_array()
include/hash.h:
Added HASH_THREAD_SPECIFIC
include/heap.h:
Added flag is internal temporary table.
include/my_dir.h:
Safety fix: Ensure that MY_DONT_SORT and MY_WANT_STAT don't interfer with other mysys flags
include/my_global.h:
Changed type of myf from int to ulong, as this is always a set of bit flags.
include/my_sys.h:
Added MY_THREAD_SPECIFIC and MY_THREAD_MOVE
Added malloc_flags to DYNAMIC_ARRAY
Added extra mysys flag argument to my_init_dynamic_array()
Removed deprecated functions init_dynamic_array() and my_init_dynamic_array.._ci
Updated paramaters for init_alloc_root()
include/my_tree.h:
Added my_flags to allow one to use MY_THREAD_SPECIFIC with hash tables.
Removed with_delete. One should now instead use MY_TREE_WITH_DELETE_FLAG
Updated parameters to init_tree()
include/myisamchk.h:
Added malloc_flags to allow one to use MY_THREAD_SPECIFIC for checks.
include/mysql.h:
Added MYSQL_THREAD_SPECIFIC_MALLOC
Used 'unused1' to mark memory as thread specific.
include/mysql.h.pp:
Updated file
include/mysql_com.h:
Used 'unused1' to mark memory as thread specific.
Updated parameters for my_net_init()
libmysql/libmysql.c:
Updated call to init_alloc_root() to mark memory thread specific.
libmysqld/emb_qcache.cc:
Updated call to init_alloc_root()
libmysqld/lib_sql.cc:
Updated call to init_alloc_root()
mysql-test/r/create.result:
Updated results
mysql-test/r/user_var.result:
Updated results
mysql-test/suite/funcs_1/datadict/processlist_priv.inc:
Update to handle new format of SHOW PROCESSLIST
mysql-test/suite/funcs_1/datadict/processlist_val.inc:
Update to handle new format of SHOW PROCESSLIST
mysql-test/suite/funcs_1/r/is_columns_is.result:
Update to handle new format of SHOW PROCESSLIST
mysql-test/suite/funcs_1/r/processlist_priv_no_prot.result:
Updated results
mysql-test/suite/funcs_1/r/processlist_val_no_prot.result:
Updated results
mysql-test/t/show_explain.test:
Fixed usage of debug variable so that one can run test with --debug
mysql-test/t/user_var.test:
Added test of memory_usage variable.
mysys/array.c:
Added extra my_flags option to init_dynamic_array() and init_dynamic_array2() so that one can mark memory with MY_THREAD_SPECIFIC
All allocated memory is marked with the given my_flags.
Removed obsolete function init_dynamic_array()
mysys/default.c:
Updated call to init_alloc_root()
Updated call to my_init_dynamic_array()
mysys/hash.c:
Updated call to my_init_dynamic_array_ci().
Allocated memory is marked with MY_THREAD_SPECIFIC if HASH_THREAD_SPECIFIC is used.
mysys/ma_dyncol.c:
init_dynamic_array() -> my_init_dynamic_array()
Added #if to get rid of compiler warnings
mysys/mf_tempdir.c:
Updated call to my_init_dynamic_array()
mysys/my_alloc.c:
Added extra parameter to init_alloc_root() so that one can mark memory with MY_THREAD_SPECIFIC
Extend MEM_ROOT with a flag if memory is thread specific.
This is stored in block_size, to keep the size of the MEM_ROOT object identical as before.
Allocated memory is marked with MY_THREAD_SPECIFIC if used with init_alloc_root()
mysys/my_chmod.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_chsize.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_copy.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_create.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_delete.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_error.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_fopen.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_fstream.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_getwd.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_lib.c:
Updated call to init_alloc_root()
Updated call to my_init_dynamic_array()
Updated DBUG_PRINT because of change of myf type
mysys/my_lock.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_malloc.c:
Store at start of each allocated memory block the size of the block and if the block is thread specific.
Call malloc_size_cb_func, if set, with the memory allocated/freed.
Updated DBUG_PRINT because of change of myf type
mysys/my_open.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_pread.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_read.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_redel.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_rename.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_seek.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_sync.c:
Updated DBUG_PRINT because of change of myf type
mysys/my_thr_init.c:
Ensure that one can call my_thread_dbug_id() even if thread is not properly initialized.
mysys/my_write.c:
Updated DBUG_PRINT because of change of myf type
mysys/mysys_priv.h:
Updated parameters to sf_malloc and sf_realloc()
mysys/safemalloc.c:
Added checking that for memory marked with MY_THREAD_SPECIFIC that it's the same thread that is allocation and freeing the memory.
Added sf_malloc_dbug_id() to allow MariaDB to specify which THD is handling the memory.
Added my_flags arguments to sf_malloc() and sf_realloc() to be able to mark memory with MY_THREAD_SPECIFIC.
Added sf_report_leaked_memory() to get list of memory not freed by a thread.
mysys/tree.c:
Added flags to init_tree() so that one can mark tree to be thread specific.
Removed with_delete option to init_tree(). Now one should instead use MY_TREE_WITH_DELETE_FLAG.
Updated call to init_alloc_root()
All allocated memory is marked with the given malloc flags
mysys/waiting_threads.c:
Updated call to my_init_dynamic_array()
sql-common/client.c:
Updated call to init_alloc_root() and my_net_init() to mark memory thread specific.
Updated call to my_init_dynamic_array().
Added MYSQL_THREAD_SPECIFIC_MALLOC so that client can mark memory as MY_THREAD_SPECIFIC.
sql-common/client_plugin.c:
Updated call to init_alloc_root()
sql/debug_sync.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/event_scheduler.cc:
Removed calls to net_end() as this is now done in ~THD()
Call set_current_thd() to ensure that memory is assigned to right thread.
sql/events.cc:
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/filesort.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/filesort_utils.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/ha_ndbcluster.cc:
Updated call to init_alloc_root()
Updated call to my_net_init()
Removed calls to net_end() and thd->cleanup() as these are now done in ~THD()
sql/ha_ndbcluster_binlog.cc:
Updated call to my_net_init()
Updated call to init_sql_alloc()
Removed calls to net_end() and thd->cleanup() as these are now done in ~THD()
sql/ha_partition.cc:
Updated call to init_alloc_root()
sql/handler.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
Added missing call to my_dir_end()
sql/item_func.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/item_subselect.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/item_sum.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/log.cc:
More DBUG
Updated call to init_alloc_root()
sql/mdl.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/mysqld.cc:
Added total_memory_used
Updated call to init_alloc_root()
Move mysql_cond_broadcast() before my_thread_end()
Added mariadb_dbug_id() to count memory per THD instead of per thread.
Added my_malloc_size_cb_func() callback function for my_malloc() to count memory.
Move initialization of mysqld_server_started and mysqld_server_initialized earlier.
Updated call to my_init_dynamic_array().
Updated call to my_net_init().
Call my_pthread_setspecific_ptr(THR_THD,...) to ensure that memory is assigned to right thread.
Added status variable 'memory_used'.
Updated call to init_alloc_root()
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/mysqld.h:
Added set_current_thd()
sql/net_serv.cc:
Added new parameter to my_net_init() so that one can mark memory with MY_THREAD_SPECIFIC.
Store in net->thread_specific_malloc if memory is thread specific.
Mark memory to be thread specific if requested.
sql/opt_range.cc:
Updated call to my_init_dynamic_array()
Updated call to init_sql_alloc()
Added MY_THREAD_SPECIFIC to allocated memory.
sql/opt_subselect.cc:
Updated call to init_sql_alloc() to mark memory thread specific.
sql/protocol.cc:
Fixed compiler warning
sql/records.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/rpl_filter.cc:
Updated call to my_init_dynamic_array()
sql/rpl_handler.cc:
Updated call to my_init_dynamic_array2()
sql/rpl_handler.h:
Updated call to init_sql_alloc()
sql/rpl_mi.cc:
Updated call to my_init_dynamic_array()
sql/rpl_tblmap.cc:
Updated call to init_alloc_root()
sql/rpl_utility.cc:
Updated call to my_init_dynamic_array()
sql/slave.cc:
Initialize things properly before calling functions that allocate memory.
Removed calls to net_end() as this is now done in ~THD()
sql/sp_head.cc:
Updated call to init_sql_alloc()
Updated call to my_init_dynamic_array()
Added parameter to warning_info() that it should be fully initialized.
sql/sp_pcontext.cc:
Updated call to my_init_dynamic_array()
sql/sql_acl.cc:
Updated call to init_sql_alloc()
Updated call to my_init_dynamic_array()
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_admin.cc:
Added parameter to warning_info() that it should be fully initialized.
sql/sql_analyse.h:
Updated call to init_tree() to mark memory thread specific.
sql/sql_array.h:
Updated call to my_init_dynamic_array() to mark memory thread specific.
sql/sql_audit.cc:
Updated call to my_init_dynamic_array()
sql/sql_base.cc:
Updated call to init_sql_alloc()
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_cache.cc:
Updated comment
sql/sql_class.cc:
Added parameter to warning_info() that not initialize it until THD is fully created.
Updated call to init_sql_alloc()
Mark THD::user_vars has to be thread specific.
Updated call to my_init_dynamic_array()
Ensure that memory allocated by THD is assigned to the THD.
More DBUG
Always acll net_end() in ~THD()
Assert that all memory signed to this THD is really deleted at ~THD.
Fixed set_status_var_init() to not reset memory_used.
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_class.h:
Added MY_THREAD_SPECIFIC to allocated memory.
Added malloc_size to THD to record allocated memory per THD.
sql/sql_delete.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/sql_error.cc:
Added 'initialize' parameter to Warning_info() to say if should allocate memory for it's structures.
This is used by THD::THD() to not allocate memory until THD is ready.
Added Warning_info::free_memory()
sql/sql_error.h:
Updated Warning_info() class.
sql/sql_handler.cc:
Updated call to init_alloc_root() to mark memory thread specific.
sql/sql_insert.cc:
More DBUG
sql/sql_join_cache.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/sql_lex.cc:
Updated call to my_init_dynamic_array()
sql/sql_lex.h:
Updated call to my_init_dynamic_array()
sql/sql_load.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/sql_parse.cc:
Removed calls to net_end() and thd->cleanup() as these are now done in ~THD()
Ensure that examined_row_count() is reset before query.
Fixed bug where kill_threads_for_user() was using the wrong mem_root to allocate memory.
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
Don't restore thd->status_var.memory_used when restoring thd->status_var
sql/sql_plugin.cc:
Updated call to init_alloc_root()
Updated call to my_init_dynamic_array()
Don't allocate THD on the stack, as this causes problems with valgrind when doing thd memory counting.
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_prepare.cc:
Added parameter to warning_info() that it should be fully initialized.
Updated call to init_sql_alloc() to mark memory thread specific.
sql/sql_reload.cc:
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_select.cc:
Updated call to my_init_dynamic_array() and init_sql_alloc() to mark memory thread specific.
Added MY_THREAD_SPECIFIC to allocated memory.
More DBUG
sql/sql_servers.cc:
Updated call to init_sql_alloc() to mark memory some memory thread specific.
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_show.cc:
Updated call to my_init_dynamic_array()
Mark my_dir() memory thread specific.
Use my_pthread_setspecific_ptr(THR_THD,...) to mark that allocated memory should be allocated to calling thread.
More DBUG.
Added malloc_size and examined_row_count to SHOW PROCESSLIST.
Added MY_THREAD_SPECIFIC to allocated memory.
Updated call to init_sql_alloc()
Added parameter to warning_info() that it should be fully initialized.
sql/sql_statistics.cc:
Fixed compiler warning
sql/sql_string.cc:
String elements can now be marked as thread specific.
sql/sql_string.h:
String elements can now be marked as thread specific.
sql/sql_table.cc:
Updated call to init_sql_alloc() and my_malloc() to mark memory thread specific
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
Fixed compiler warning
sql/sql_test.cc:
Updated call to my_init_dynamic_array() to mark memory thread specific.
sql/sql_trigger.cc:
Updated call to init_sql_alloc()
sql/sql_udf.cc:
Updated call to init_sql_alloc()
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/sql_update.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
sql/table.cc:
Updated call to init_sql_alloc().
Mark memory used by temporary tables, that are not for slave threads, as MY_THREAD_SPECIFIC
Updated call to init_sql_alloc()
sql/thr_malloc.cc:
Added my_flags argument to init_sql_alloc() to be able to mark memory as MY_THREAD_SPECIFIC.
sql/thr_malloc.h:
Updated prototype for init_sql_alloc()
sql/tztime.cc:
Updated call to init_sql_alloc()
Updated call to init_alloc_root() to mark memory thread specific.
my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd()
sql/uniques.cc:
Updated calls to init_tree(), my_init_dynamic_array() and my_malloc() to mark memory thread specific.
sql/unireg.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
storage/csv/ha_tina.cc:
Updated call to init_alloc_root()
storage/federated/ha_federated.cc:
Updated call to init_alloc_root()
Updated call to my_init_dynamic_array()
Ensure that memory allocated by fedarated is registered for the system, not for the thread.
storage/federatedx/federatedx_io_mysql.cc:
Updated call to my_init_dynamic_array()
storage/federatedx/ha_federatedx.cc:
Updated call to init_alloc_root()
Updated call to my_init_dynamic_array()
storage/heap/ha_heap.cc:
Added MY_THREAD_SPECIFIC to allocated memory.
storage/heap/heapdef.h:
Added parameter to hp_get_new_block() to be able to do thread specific memory tagging.
storage/heap/hp_block.c:
Added parameter to hp_get_new_block() to be able to do thread specific memory tagging.
storage/heap/hp_create.c:
- Internal HEAP tables are now marking it's memory as MY_THREAD_SPECIFIC.
- Use MY_TREE_WITH_DELETE instead of removed option 'with_delete'.
storage/heap/hp_open.c:
Internal HEAP tables are now marking it's memory as MY_THREAD_SPECIFIC.
storage/heap/hp_write.c:
Added new parameter to hp_get_new_block()
storage/maria/ma_bitmap.c:
Updated call to my_init_dynamic_array()
storage/maria/ma_blockrec.c:
Updated call to my_init_dynamic_array()
storage/maria/ma_check.c:
Updated call to init_alloc_root()
storage/maria/ma_ft_boolean_search.c:
Updated calls to init_tree() and init_alloc_root()
storage/maria/ma_ft_nlq_search.c:
Updated call to init_tree()
storage/maria/ma_ft_parser.c:
Updated call to init_tree()
Updated call to init_alloc_root()
storage/maria/ma_loghandler.c:
Updated call to my_init_dynamic_array()
storage/maria/ma_open.c:
Updated call to my_init_dynamic_array()
storage/maria/ma_sort.c:
Updated call to my_init_dynamic_array()
storage/maria/ma_write.c:
Updated calls to my_init_dynamic_array() and init_tree()
storage/maria/maria_pack.c:
Updated call to init_tree()
storage/maria/unittest/sequence_storage.c:
Updated call to my_init_dynamic_array()
storage/myisam/ft_boolean_search.c:
Updated call to init_tree()
Updated call to init_alloc_root()
storage/myisam/ft_nlq_search.c:
Updated call to init_tree()
storage/myisam/ft_parser.c:
Updated call to init_tree()
Updated call to init_alloc_root()
storage/myisam/ft_stopwords.c:
Updated call to init_tree()
storage/myisam/mi_check.c:
Updated call to init_alloc_root()
storage/myisam/mi_write.c:
Updated call to my_init_dynamic_array()
Updated call to init_tree()
storage/myisam/myisamlog.c:
Updated call to init_tree()
storage/myisam/myisampack.c:
Updated call to init_tree()
storage/myisam/sort.c:
Updated call to my_init_dynamic_array()
storage/myisammrg/ha_myisammrg.cc:
Updated call to init_sql_alloc()
storage/perfschema/pfs_check.cc:
Rest current_thd
storage/perfschema/pfs_instr.cc:
Removed DBUG_ENTER/DBUG_VOID_RETURN as at this point my_thread_var is not allocated anymore, which can cause problems.
support-files/compiler_warnings.supp:
Disable compiler warning from offsetof macro.
Diffstat (limited to 'sql')
70 files changed, 521 insertions, 272 deletions
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 1c95869987d..28d1109a0b4 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -239,7 +239,8 @@ void debug_sync_init_thread(THD *thd) if (opt_debug_sync_timeout) { thd->debug_sync_control= (st_debug_sync_control*) - my_malloc(sizeof(st_debug_sync_control), MYF(MY_WME | MY_ZEROFILL)); + my_malloc(sizeof(st_debug_sync_control), + MYF(MY_WME | MY_ZEROFILL | MY_THREAD_SPECIFIC)); if (!thd->debug_sync_control) { /* diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index c41194d1a8d..a5dac4c154b 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -209,7 +209,7 @@ Event_basic::Event_basic() { DBUG_ENTER("Event_basic::Event_basic"); /* init memory root */ - init_sql_alloc(&mem_root, 256, 512); + init_sql_alloc(&mem_root, 256, 512, 0); dbname.str= name.str= NULL; dbname.length= name.length= 0; time_zone= NULL; diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index f107914f738..8c3e57778ab 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -153,8 +153,6 @@ void deinit_event_thread(THD *thd) { thd->proc_info= "Clearing"; - DBUG_ASSERT(thd->net.buff != 0); - net_end(&thd->net); DBUG_PRINT("exit", ("Event thread finishing")); mysql_mutex_lock(&LOCK_thread_count); thread_count--; @@ -182,12 +180,15 @@ deinit_event_thread(THD *thd) void pre_init_event_thread(THD* thd) { + THD *orig_thd= current_thd; DBUG_ENTER("pre_init_event_thread"); + + set_current_thd(thd); thd->client_capabilities= 0; thd->security_ctx->master_access= 0; thd->security_ctx->db_access= 0; thd->security_ctx->host_or_ip= (char*)my_localhost; - my_net_init(&thd->net, NULL); + my_net_init(&thd->net, NULL, MYF(MY_THREAD_SPECIFIC)); thd->security_ctx->set_user((char*)"event_scheduler"); thd->net.read_timeout= slave_net_timeout; thd->variables.option_bits|= OPTION_AUTO_IS_NULL; @@ -207,6 +208,7 @@ pre_init_event_thread(THD* thd) /* Do not use user-supplied timeout value for system threads. */ thd->variables.lock_wait_timeout= LONG_TIMEOUT; + set_current_thd(orig_thd); DBUG_VOID_RETURN; } @@ -402,6 +404,7 @@ Event_scheduler::start() ret= TRUE; goto end; } + pre_init_event_thread(new_thd); new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER; new_thd->command= COM_DAEMON; @@ -413,6 +416,7 @@ Event_scheduler::start() */ new_thd->security_ctx->master_access |= SUPER_ACL; + /* This should not be marked with MY_THREAD_SPECIFIC */ scheduler_param_value= (struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0)); scheduler_param_value->thd= new_thd; @@ -432,8 +436,6 @@ Event_scheduler::start() ret= TRUE; new_thd->proc_info= "Clearing"; - DBUG_ASSERT(new_thd->net.buff != 0); - net_end(&new_thd->net); mysql_mutex_lock(&LOCK_thread_count); thread_count--; dec_thread_running(); @@ -533,6 +535,7 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name) pthread_t th; int res= 0; DBUG_ENTER("Event_scheduler::execute_top"); + if (!(new_thd= new THD())) goto error; @@ -567,8 +570,6 @@ error: if (new_thd) { new_thd->proc_info= "Clearing"; - DBUG_ASSERT(new_thd->net.buff != 0); - net_end(&new_thd->net); mysql_mutex_lock(&LOCK_thread_count); thread_count--; dec_thread_running(); diff --git a/sql/events.cc b/sql/events.cc index d8caa059c64..46b13056d7d 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -879,7 +879,7 @@ end: } delete thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, NULL); + set_current_thd(0); DBUG_RETURN(res); } diff --git a/sql/filesort.cc b/sql/filesort.cc index 9c40ab877a4..3f735e94a11 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -200,7 +200,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, table_sort.unpack= unpack_addon_fields; if (param.addon_field && !(table_sort.addon_buf= - (uchar *) my_malloc(param.addon_length, MYF(MY_WME)))) + (uchar *) my_malloc(param.addon_length, MYF(MY_WME | + MY_THREAD_SPECIFIC)))) goto err; if (select && select->quick) @@ -213,7 +214,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, num_rows= table->file->estimate_rows_upper_bound(); if (multi_byte_charset && - !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME)))) + !(param.tmp_buffer= (char*) my_malloc(param.sort_length, + MYF(MY_WME | MY_THREAD_SPECIFIC)))) goto err; if (check_if_pq_applicable(¶m, &table_sort, @@ -453,7 +455,7 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, if (count > UINT_MAX/sizeof(BUFFPEK)) return 0; /* sizeof(BUFFPEK)*count will overflow */ if (!tmp) - tmp= (uchar *)my_malloc(length, MYF(MY_WME)); + tmp= (uchar *)my_malloc(length, MYF(MY_WME | MY_THREAD_SPECIFIC)); if (tmp) { if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) || @@ -1155,7 +1157,8 @@ static bool save_index(Sort_param *param, uint count, Filesort_info *table_sort) res_length= param->res_length; offset= param->rec_length-res_length; if (!(to= table_sort->record_pointers= - (uchar*) my_malloc(res_length*count, MYF(MY_WME)))) + (uchar*) my_malloc(res_length*count, + MYF(MY_WME | MY_THREAD_SPECIFIC)))) DBUG_RETURN(1); /* purecov: inspected */ uchar **sort_keys= table_sort->get_sort_keys(); for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++) @@ -1897,7 +1900,9 @@ get_addon_fields(ulong max_length_for_sort_data, if (length+sortlength > max_length_for_sort_data || !(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)* - (fields+1), MYF(MY_WME)))) + (fields+1), + MYF(MY_WME | + MY_THREAD_SPECIFIC)))) return 0; *plength= length; diff --git a/sql/filesort_utils.cc b/sql/filesort_utils.cc index c4480a6376d..f8f6d5c9420 100644 --- a/sql/filesort_utils.cc +++ b/sql/filesort_utils.cc @@ -99,7 +99,7 @@ uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, uint record_length) sort_buff_sz= num_records * (record_length + sizeof(uchar*)); set_if_bigger(sort_buff_sz, record_length * MERGEBUFF2); uchar **sort_keys= - (uchar**) my_malloc(sort_buff_sz, MYF(0)); + (uchar**) my_malloc(sort_buff_sz, MYF(MY_THREAD_SPECIFIC)); m_idx_array= Idx_array(sort_keys, num_records); m_record_length= record_length; uchar **start_of_data= m_idx_array.array() + m_idx_array.size(); @@ -130,7 +130,8 @@ void Filesort_buffer::sort_buffer(const Sort_param *param, uint count) uchar **keys= get_sort_keys(); uchar **buffer= NULL; if (radixsort_is_appliccable(count, param->sort_length) && - (buffer= (uchar**) my_malloc(count*sizeof(char*), MYF(0)))) + (buffer= (uchar**) my_malloc(count*sizeof(char*), + MYF(MY_THREAD_SPECIFIC)))) { radixsort_for_str_ptr(keys, count, param->sort_length, buffer); my_free(buffer); @@ -140,4 +141,3 @@ void Filesort_buffer::sort_buffer(const Sort_param *param, uint count) size_t size= param->sort_length; my_qsort2(keys, count, sizeof(uchar*), get_ptr_compare(size), &size); } - diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 6ba4fe46441..44d384e7f2d 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -8649,7 +8649,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, MEM_ROOT **root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); MEM_ROOT *old_root= *root_ptr; - init_sql_alloc(&share->mem_root, 1024, 0); + init_sql_alloc(&share->mem_root, 1024, 0, 0); *root_ptr= &share->mem_root; // remember to reset before return share->state= NSS_INITIAL; /* enough space for key, db, and table_name */ @@ -9493,7 +9493,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) thd->init_for_queries(); thd->main_security_ctx.host_or_ip= ""; thd->client_capabilities = 0; - my_net_init(&thd->net, 0); + my_net_init(&thd->net, 0, MYF(MY_THREAD_SPECIFIC)); thd->main_security_ctx.master_access= ~0; thd->main_security_ctx.priv_user[0] = 0; /* Do not use user-supplied timeout value for system threads. */ @@ -9730,11 +9730,9 @@ next: mysql_mutex_lock(&LOCK_ndb_util_thread); ndb_util_thread_end: - net_end(&thd->net); ndb_util_thread_fail: if (share_list) delete [] share_list; - thd->cleanup(); delete thd; /* signal termination */ diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 59b9d6eab6b..e7582d695ce 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -3665,7 +3665,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) thd->system_thread= SYSTEM_THREAD_NDBCLUSTER_BINLOG; thd->main_security_ctx.host_or_ip= ""; thd->client_capabilities= 0; - my_net_init(&thd->net, 0); + my_net_init(&thd->net, 0, MYF(MY_THREAD_SPECIFIC)); thd->main_security_ctx.master_access= ~0; thd->main_security_ctx.priv_user[0]= 0; /* Do not use user-supplied timeout value for system threads. */ @@ -3964,7 +3964,7 @@ restart: my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); MEM_ROOT *old_root= *root_ptr; MEM_ROOT mem_root; - init_sql_alloc(&mem_root, 4096, 0); + init_sql_alloc(&mem_root, 4096, 0, 0); List<Cluster_schema> post_epoch_log_list; List<Cluster_schema> post_epoch_unlock_list; *root_ptr= &mem_root; @@ -4364,8 +4364,6 @@ err: my_hash_free(&ndb_schema_objects); - net_end(&thd->net); - thd->cleanup(); delete thd; ndb_binlog_thread_running= -1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b87192db69f..e28c461f4ce 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -168,7 +168,7 @@ ha_partition::ha_partition(handlerton *hton, TABLE_SHARE *share) :handler(hton, share) { DBUG_ENTER("ha_partition::ha_partition(table)"); - init_alloc_root(&m_mem_root, 512, 512); + init_alloc_root(&m_mem_root, 512, 512, 0); init_handler_variables(); DBUG_VOID_RETURN; } @@ -190,7 +190,7 @@ ha_partition::ha_partition(handlerton *hton, partition_info *part_info) { DBUG_ENTER("ha_partition::ha_partition(part_info)"); DBUG_ASSERT(part_info); - init_alloc_root(&m_mem_root, 512, 512); + init_alloc_root(&m_mem_root, 512, 512, 0); init_handler_variables(); m_part_info= part_info; m_create_handler= TRUE; @@ -217,7 +217,7 @@ ha_partition::ha_partition(handlerton *hton, TABLE_SHARE *share, :handler(hton, share) { DBUG_ENTER("ha_partition::ha_partition(clone)"); - init_alloc_root(&m_mem_root, 512, 512); + init_alloc_root(&m_mem_root, 512, 512, 0); init_handler_variables(); m_part_info= part_info_arg; m_create_handler= TRUE; diff --git a/sql/handler.cc b/sql/handler.cc index 6634bd6fb7a..0fac0d756ca 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5352,7 +5352,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator) /* to be able to make my_free without crash in case of error */ iterator->buffer= 0; - if (!(dirp = my_dir(fl_dir, MYF(0)))) + if (!(dirp = my_dir(fl_dir, MYF(MY_THREAD_SPECIFIC)))) { return HA_ITERATOR_ERROR; } @@ -5361,7 +5361,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator) sizeof(enum log_status) + + FN_REFLEN + 1) * (uint) dirp->number_off_files), - MYF(0))) == 0) + MYF(MY_THREAD_SPECIFIC))) == 0) { return HA_ITERATOR_ERROR; } @@ -5395,6 +5395,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator) iterator->buffer= buff; iterator->next= &fl_log_iterator_next; iterator->destroy= &fl_log_iterator_destroy; + my_dirend(dirp); return HA_ITERATOR_OK; } diff --git a/sql/item_func.cc b/sql/item_func.cc index f0ca37152a3..520b5522d38 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4343,7 +4343,9 @@ user_var_entry *get_variable(HASH *hash, LEX_STRING &name, uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size; if (!my_hash_inited(hash)) return 0; - if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR)))) + if (!(entry = (user_var_entry*) my_malloc(size, + MYF(MY_WME | ME_FATALERROR | + MY_THREAD_SPECIFIC)))) return 0; entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+ extra_size; @@ -4571,7 +4573,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length, entry->value=0; entry->value= (char*) my_realloc(entry->value, length, MYF(MY_ALLOW_ZERO_PTR | MY_WME | - ME_FATALERROR)); + ME_FATALERROR | + MY_THREAD_SPECIFIC)); if (!entry->value) return 1; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ab77bb0e59c..2ee513320ce 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -5053,7 +5053,7 @@ bool Ordered_key::alloc_keys_buffers() DBUG_ASSERT(key_buff_elements > 0); if (!(key_buff= (rownum_t*) my_malloc((size_t)(key_buff_elements * - sizeof(rownum_t)), MYF(MY_WME)))) + sizeof(rownum_t)), MYF(MY_WME | MY_THREAD_SPECIFIC)))) return TRUE; /* @@ -5480,7 +5480,7 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts, !(null_bitmaps= (MY_BITMAP**) thd->alloc(merge_keys_count * sizeof(MY_BITMAP*))) || !(row_num_to_rowid= (uchar*) my_malloc((size_t)(row_count * rowid_length), - MYF(MY_WME)))) + MYF(MY_WME | MY_THREAD_SPECIFIC)))) return TRUE; /* Create the only non-NULL key if there is any. */ diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 217e65e401f..b1e248032bc 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3485,7 +3485,8 @@ bool Item_func_group_concat::setup(THD *thd) init_tree(tree, (uint) min(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, tree_key_length, - group_concat_key_cmp_with_order , 0, NULL, (void*) this); + group_concat_key_cmp_with_order, NULL, (void*) this, + MYF(MY_THREAD_SPECIFIC)); } if (distinct) diff --git a/sql/log.cc b/sql/log.cc index 1ffceaf05a3..c6d91b1f67e 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8194,8 +8194,9 @@ binlog_background_thread(void *arg __attribute__((unused))) bool stop; MYSQL_BIN_LOG::xid_count_per_binlog *queue, *next; THD *thd; - my_thread_init(); + DBUG_ENTER("binlog_background_thread"); + thd= new THD; thd->system_thread= SYSTEM_THREAD_BINLOG_BACKGROUND; thd->thread_stack= (char*) &thd; /* Set approximate stack start */ @@ -8259,7 +8260,7 @@ binlog_background_thread(void *arg __attribute__((unused))) mysql_cond_signal(&mysql_bin_log.COND_binlog_background_thread_end); mysql_mutex_unlock(&mysql_bin_log.LOCK_binlog_background_thread); - return 0; + DBUG_RETURN(0); } #ifdef HAVE_PSI_INTERFACE @@ -8310,7 +8311,7 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name, sizeof(my_xid), 0, 0, MYF(0))) goto err1; - init_alloc_root(&mem_root, TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE); + init_alloc_root(&mem_root, TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE, 0); fdle->flags&= ~LOG_EVENT_BINLOG_IN_USE_F; // abort on the first error diff --git a/sql/mdl.cc b/sql/mdl.cc index 5e297051377..97858646652 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -2200,7 +2200,8 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests, /* Sort requests according to MDL_key. */ if (! (sort_buf= (MDL_request **)my_malloc(req_count * sizeof(MDL_request*), - MYF(MY_WME)))) + MYF(MY_WME | + MY_THREAD_SPECIFIC)))) DBUG_RETURN(TRUE); for (p_req= sort_buf; p_req < sort_buf + req_count; p_req++) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6d3c5980280..ca68f8c9ae2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1121,7 +1121,7 @@ private: void Buffered_logs::init() { - init_alloc_root(&m_root, 1024, 0); + init_alloc_root(&m_root, 1024, 0, 0); } void Buffered_logs::cleanup() @@ -1765,6 +1765,7 @@ extern "C" void unireg_abort(int exit_code) static void mysqld_exit(int exit_code) { + DBUG_ENTER("mysqld_exit"); /* Important note: we wait for the signal thread to end, but if a kill -15 signal was sent, the signal thread did @@ -1776,6 +1777,7 @@ static void mysqld_exit(int exit_code) clean_up_error_log_mutex(); my_end((opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0)); shutdown_performance_schema(); // we do it as late as possible + DBUG_LEAVE; exit(exit_code); /* purecov: inspected */ } @@ -2485,9 +2487,13 @@ void unlink_thd(THD *thd) sync feature has been shut down at this point. */ DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5);); + /* + We must delete thd inside the lock to ensure that we don't start cleanup + before THD is deleted + */ + delete thd; mysql_mutex_unlock(&LOCK_thread_count); - delete thd; DBUG_VOID_RETURN; } @@ -2594,7 +2600,7 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) DBUG_ENTER("one_thread_per_connection_end"); unlink_thd(thd); /* Mark that current_thd is not valid anymore */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); if (put_in_cache) { mysql_mutex_lock(&LOCK_thread_count); @@ -2606,9 +2612,10 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) /* It's safe to broadcast outside a lock (COND... is not deleted here) */ DBUG_PRINT("signal", ("Broadcasting COND_thread_count")); + mysql_cond_broadcast(&COND_thread_count); + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); - mysql_cond_broadcast(&COND_thread_count); pthread_exit(0); return 0; // Avoid compiler warnings @@ -3142,9 +3149,9 @@ void my_message_sql(uint error, const char *str, myf MyFlags) THD *thd= current_thd; MYSQL_ERROR::enum_warning_level level; sql_print_message_func func; - DBUG_ENTER("my_message_sql"); - DBUG_PRINT("error", ("error: %u message: '%s' Flag: %d", error, str, MyFlags)); + DBUG_PRINT("error", ("error: %u message: '%s' Flag: %lu", error, str, + MyFlags)); DBUG_ASSERT(str != NULL); DBUG_ASSERT(error != 0); @@ -3430,6 +3437,28 @@ SHOW_VAR com_status_vars[]= { {NullS, NullS, SHOW_LONG} }; +#ifdef SAFEMALLOC +/* + Return the id for the current THD, to allow safemalloc to associate + the memory with the right id. +*/ + +extern "C" my_thread_id mariadb_dbug_id() +{ + THD *thd; + if ((thd= current_thd)) + { + return thd->thread_id; + } + return my_thread_dbug_id(); +} +#endif /* SAFEMALLOC */ + + +/* + Init common variables +*/ + static int init_common_variables() { umask(((~my_umask) & 0666)); @@ -3438,6 +3467,9 @@ static int init_common_variables() tzset(); // Set tzname sf_leaking_memory= 0; // no memory leaks from now on +#ifdef SAFEMALLOC + sf_malloc_dbug_id= mariadb_dbug_id; +#endif max_system_variables.pseudo_thread_id= (ulong)~0; server_start_time= flush_status_time= my_time(0); @@ -3897,6 +3929,7 @@ You should consider changing lower_case_table_names to 1 or 2", static int init_thread_environment() { + DBUG_ENTER("init_thread_environment"); mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_delayed_insert, @@ -3975,9 +4008,9 @@ static int init_thread_environment() pthread_key_create(&THR_MALLOC,NULL)) { sql_print_error("Can't create thread-keys"); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } @@ -4641,6 +4674,37 @@ static void test_lc_time_sz() } #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__ int win_main(int argc, char **argv) #else @@ -4653,6 +4717,9 @@ int mysqld_main(int argc, char **argv) */ my_progname= argv[0]; 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; + #ifdef HAVE_NPTL ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0); #endif @@ -4665,7 +4732,6 @@ int mysqld_main(int argc, char **argv) } #endif - mysqld_server_started= mysqld_server_initialized= 0; orig_argc= argc; orig_argv= argv; my_getopt_use_args_separator= TRUE; @@ -4695,7 +4761,7 @@ int mysqld_main(int argc, char **argv) my_getopt_skip_unknown= TRUE; /* prepare all_early_options array */ - my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25); + my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25, 0); sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY); add_terminator(&all_early_options); @@ -4956,8 +5022,6 @@ int mysqld_main(int argc, char **argv) if (Events::init(opt_noacl || opt_bootstrap)) unireg_abort(1); - mysqld_server_initialized= 1; - if (opt_bootstrap) { select_thread_in_use= 0; // Allow 'kill' to work @@ -4971,6 +5035,9 @@ int mysqld_main(int argc, char **argv) } } + /* It's now safe to use thread specific memory */ + mysqld_server_initialized= 1; + create_shutdown_thread(); start_handle_manager(); @@ -5000,7 +5067,6 @@ int mysqld_main(int argc, char **argv) Service.SetRunning(); #endif - /* Signal threads waiting for server to be started */ mysql_mutex_lock(&LOCK_server_started); mysqld_server_started= 1; @@ -5180,6 +5246,7 @@ int mysqld_main(int argc, char **argv) /* Must be initialized early for comparison of service name */ system_charset_info= &my_charset_utf8_general_ci; + set_malloc_size_cb(my_malloc_size_cb_func); if (my_init()) { @@ -5288,7 +5355,7 @@ static void bootstrap(MYSQL_FILE *file) THD *thd= new THD; thd->bootstrap=1; - my_net_init(&thd->net,(st_vio*) 0); + my_net_init(&thd->net,(st_vio*) 0, 0); thd->max_client_packet_length= thd->net.max_packet; thd->security_ctx->master_access= ~(ulong)0; thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; @@ -5705,17 +5772,20 @@ void handle_connections_sockets() ** Don't allow too many connections */ + DBUG_PRINT("info", ("Creating THD for new connection")); if (!(thd= new THD)) { (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } + /* Set to get io buffers to be part of THD */ + set_current_thd(thd); if (!(vio_tmp=vio_new(new_sock, sock == unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, sock == unix_sock ? VIO_LOCALHOST: 0)) || - my_net_init(&thd->net,vio_tmp)) + my_net_init(&thd->net, vio_tmp, MYF(MY_THREAD_SPECIFIC))) { /* Only delete the temporary vio if we didn't already attach it to the @@ -5730,6 +5800,7 @@ void handle_connections_sockets() (void) closesocket(new_sock); } delete thd; + set_current_thd(0); continue; } if (sock == unix_sock) @@ -5741,6 +5812,7 @@ void handle_connections_sockets() thd->scheduler= extra_thread_scheduler; } create_new_thread(thd); + set_current_thd(0); } DBUG_VOID_RETURN; } @@ -5834,16 +5906,19 @@ pthread_handler_t handle_connections_namedpipes(void *arg) CloseHandle(hConnectedPipe); continue; } + set_current_thd(thd); if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || - my_net_init(&thd->net, thd->net.vio)) + my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) { close_connection(thd, ER_OUT_OF_RESOURCES); delete thd; + set_current_thd(0); continue; } /* Host is unknown */ thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); create_new_thread(thd); + set_current_thd(0); } CloseHandle(connectOverlapped.hEvent); DBUG_LEAVE; @@ -6023,6 +6098,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) errmsg= "Could not set client to read mode"; goto errorconn; } + set_current_thd(thd); if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map, handle_client_map, event_client_wrote, @@ -6030,7 +6106,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) event_server_wrote, event_server_read, event_conn_closed)) || - my_net_init(&thd->net, thd->net.vio)) + my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) { close_connection(thd, ER_OUT_OF_RESOURCES); errmsg= 0; @@ -6039,6 +6115,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ create_new_thread(thd); connect_number++; + set_current_thd(thd); continue; errorconn: @@ -6066,6 +6143,7 @@ errorconn: CloseHandle(event_conn_closed); delete thd; } + set_current_thd(0); /* End shared memory handling */ error: @@ -7024,6 +7102,7 @@ SHOW_VAR status_vars[]= { {"Key", (char*) &show_default_keycache, SHOW_FUNC}, {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, + {"Memory_used", (char*) offsetof(STATUS_VAR, memory_used), SHOW_LONGLONG_STATUS}, {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}, {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH}, @@ -7170,7 +7249,7 @@ static int option_cmp(my_option *a, my_option *b) static void print_help() { MEM_ROOT mem_root; - init_alloc_root(&mem_root, 4096, 4096); + init_alloc_root(&mem_root, 4096, 4096, 0); pop_dynamic(&all_options); sys_var_add_options(&all_options, sys_var::PARSE_EARLY); @@ -7862,7 +7941,7 @@ static int get_options(int *argc_ptr, char ***argv_ptr) /* prepare all_options array */ my_init_dynamic_array(&all_options, sizeof(my_option), array_elements(my_long_options), - array_elements(my_long_options)/4); + array_elements(my_long_options)/4, 0); for (my_option *opt= my_long_options; opt < my_long_options + array_elements(my_long_options) - 1; opt++) @@ -8364,7 +8443,7 @@ void refresh_status(THD *thd) add_to_status(&global_status_var, &thd->status_var); /* Reset thread's status variables */ - bzero((uchar*) &thd->status_var, sizeof(thd->status_var)); + thd->set_status_var_init(); bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); thd->start_bytes_received= 0; diff --git a/sql/mysqld.h b/sql/mysqld.h index a9b41a5e116..e9c4f713182 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -534,6 +534,7 @@ inline THD *_current_thd(void) } #endif #define current_thd _current_thd() +#define set_current_thd(X) my_pthread_setspecific_ptr(THR_THD, (X)) /* @todo remove, make it static in ha_maria.cc diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 08ac93f3091..cf3e962053c 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -120,14 +120,15 @@ static my_bool net_write_buff(NET *net,const uchar *packet,ulong len); /** Init with packet info. */ -my_bool my_net_init(NET *net, Vio* vio) +my_bool my_net_init(NET *net, Vio* vio, uint my_flags) { DBUG_ENTER("my_net_init"); + DBUG_PRINT("enter", ("my_flags: %u", my_flags)); net->vio = vio; my_net_local_init(net); /* Set some limits */ if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+ NET_HEADER_SIZE + COMP_HEADER_SIZE +1, - MYF(MY_WME)))) + MYF(MY_WME | my_flags)))) DBUG_RETURN(1); net->buff_end=net->buff+net->max_packet; net->error=0; net->return_status=0; @@ -139,6 +140,7 @@ my_bool my_net_init(NET *net, Vio* vio) net->net_skip_rest_factor= 0; net->last_errno=0; net->unused= 0; + net->thread_specific_malloc= test(my_flags & MY_THREAD_SPECIFIC); if (vio != 0) /* If real connection */ { @@ -193,7 +195,9 @@ my_bool net_realloc(NET *net, size_t length) */ if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1, - MYF(MY_WME)))) + MYF(MY_WME | + (net->thread_specific_malloc ? + MY_THREAD_SPECIFIC : 0))))) { /* @todo: 1 and 2 codes are identical. */ net->error= 1; @@ -603,7 +607,10 @@ net_real_write(NET *net,const uchar *packet, size_t len) uchar *b; uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE + - COMP_HEADER_SIZE + 1, MYF(MY_WME)))) + COMP_HEADER_SIZE + 1, + MYF(MY_WME | + (net->thread_specific_malloc ? + MY_THREAD_SPECIFIC : 0))))) { net->error= 2; net->last_errno= ER_OUT_OF_RESOURCES; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7f8d527564b..d3c2ec5a132 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1772,7 +1772,8 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, index= key_nr; head= table; key_part_info= head->key_info[index].key_part; - my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16); + my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16, + MYF(MY_THREAD_SPECIFIC)); /* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */ mrr_buf_size= thd->variables.mrr_buff_size; @@ -1781,7 +1782,8 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, if (!no_alloc && !parent_alloc) { // Allocates everything through the internal memroot - init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); thd->mem_root= &alloc; } else @@ -1793,7 +1795,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, /* Allocate a bitmap for used columns (Q: why not on MEM_ROOT?) */ if (!(bitmap= (my_bitmap_map*) my_malloc(head->s->column_bitmap_size, - MYF(MY_WME)))) + MYF(MY_WME | MY_THREAD_SPECIFIC)))) { column_bitmap.bitmap= 0; *create_error= 1; @@ -1879,7 +1881,8 @@ QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT(THD *thd_param, index= MAX_KEY; head= table; bzero(&read_record, sizeof(read_record)); - init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); DBUG_VOID_RETURN; } @@ -1949,7 +1952,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param, head= table; record= head->record[0]; if (!parent_alloc) - init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); else bzero(&alloc, sizeof(MEM_ROOT)); last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc, @@ -2232,7 +2236,8 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param, head= table; rowid_length= table->file->ref_length; record= head->record[0]; - init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); thd_param->mem_root= &alloc; } @@ -2966,7 +2971,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, param.force_default_mrr= ordered_output; thd->no_errors=1; // Don't warn about NULL - init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); if (!(param.key_parts= (KEY_PART*) alloc_root(&alloc, sizeof(KEY_PART) * @@ -3411,7 +3417,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) my_bitmap_map *old_sets[2]; prune_param.part_info= part_info; - init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); range_par->mem_root= &alloc; range_par->old_root= thd->mem_root; @@ -12859,7 +12866,8 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, DBUG_ASSERT(!parent_alloc); if (!parent_alloc) { - init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0); + init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); join->thd->mem_root= &alloc; } else @@ -12914,7 +12922,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::init() if (min_max_arg_part) { - if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16)) + if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16, + MYF(MY_THREAD_SPECIFIC))) return 1; if (have_min) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 1c2e037e8cc..75566b97d3b 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3872,7 +3872,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) using_unique_constraint= TRUE; /* STEP 3: Allocate memory for temptable description */ - init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); if (!multi_alloc_root(&own_root, &table, sizeof(*table), &share, sizeof(*share), diff --git a/sql/protocol.cc b/sql/protocol.cc index 3af7dc88b88..f6e9e9e62e1 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -776,7 +776,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags) pos= (char*) local_packet->ptr()+local_packet->length(); *pos++= 12; // Length of packed fields /* inject a NULL to test the client */ - DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= 0xfb;); + DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= (char) 0xfb;); if (item->charset_for_protocol() == &my_charset_bin || thd_charset == NULL) { /* No conversion */ diff --git a/sql/records.cc b/sql/records.cc index d52481c36f5..c98532c1424 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -588,7 +588,7 @@ static int init_rr_cache(THD *thd, READ_RECORD *info) if (info->cache_records <= 2 || !(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records* info->struct_length+1, - MYF(0)))) + MYF(MY_THREAD_SPECIFIC)))) DBUG_RETURN(1); #ifdef HAVE_valgrind // Avoid warnings in qsort diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc index 0380bc323a3..b44c3c7504c 100644 --- a/sql/rpl_filter.cc +++ b/sql/rpl_filter.cc @@ -573,7 +573,7 @@ void Rpl_filter::init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited) { my_init_dynamic_array(a, sizeof(TABLE_RULE_ENT*), TABLE_RULE_ARR_SIZE, - TABLE_RULE_ARR_SIZE); + TABLE_RULE_ARR_SIZE, 0); *a_inited = 1; } diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc index 9267190605c..07eeef57842 100644 --- a/sql/rpl_handler.cc +++ b/sql/rpl_handler.cc @@ -189,7 +189,7 @@ void delegates_destroy() DYNAMIC_ARRAY *plugins= &s.plugins; \ plugin_ref *plugins_buffer= s.plugins_buffer; \ my_init_dynamic_array2(plugins, sizeof(plugin_ref), \ - plugins_buffer, 8, 8); \ + plugins_buffer, 8, 8, 0); \ read_lock(); \ Observer_info_iterator iter= observer_info_iter(); \ Observer_info *info= iter++; \ diff --git a/sql/rpl_handler.h b/sql/rpl_handler.h index 4743fffb9a0..e955707f5c3 100644 --- a/sql/rpl_handler.h +++ b/sql/rpl_handler.h @@ -124,7 +124,7 @@ public: inited= FALSE; if (my_rwlock_init(&lock, NULL)) return; - init_sql_alloc(&memroot, 1024, 0); + init_sql_alloc(&memroot, 1024, 0, 0); inited= TRUE; } ~Delegate() diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index fc13fb2c762..73a2e26faba 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -61,7 +61,7 @@ Master_info::Master_info(LEX_STRING *connection_name_arg, my_casedn_str(system_charset_info, cmp_connection_name.str); } - my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16); + my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16, 0); bzero((char*) &file, sizeof(file)); mysql_mutex_init(key_master_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_master_info_data_lock, &data_lock, MY_MUTEX_INIT_FAST); diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc index b7ac1b2d091..92d8ca228b0 100644 --- a/sql/rpl_tblmap.cc +++ b/sql/rpl_tblmap.cc @@ -46,7 +46,7 @@ table_mapping::table_mapping() offsetof(entry,table_id),sizeof(ulong), 0,0,0); /* We don't preallocate any block, this is consistent with m_free=0 above */ - init_alloc_root(&m_mem_root, TABLE_ID_HASH_SIZE*sizeof(entry), 0); + init_alloc_root(&m_mem_root, TABLE_ID_HASH_SIZE*sizeof(entry), 0, 0); DBUG_VOID_RETURN; } diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 069fac1c3ec..321aead841e 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -1117,7 +1117,7 @@ bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg) Deferred_log_events::Deferred_log_events(Relay_log_info *rli) : last_added(NULL) { - my_init_dynamic_array(&array, sizeof(Log_event *), 32, 16); + my_init_dynamic_array(&array, sizeof(Log_event *), 32, 16, 0); } Deferred_log_events::~Deferred_log_events() diff --git a/sql/slave.cc b/sql/slave.cc index 1db0261c73e..9e552e64a9e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1779,7 +1779,9 @@ past_checksum: } } } +#ifndef DBUG_OFF after_set_capability: +#endif err: if (errmsg) @@ -2426,10 +2428,22 @@ static int init_slave_thread(THD* thd, Master_info *mi, #if !defined(DBUG_OFF) int simulate_error= 0; #endif + DBUG_EXECUTE_IF("simulate_io_slave_error_on_init", + simulate_error|= (1 << SLAVE_THD_IO);); + DBUG_EXECUTE_IF("simulate_sql_slave_error_on_init", + simulate_error|= (1 << SLAVE_THD_SQL);); + /* We must call store_globals() before doing my_net_init() */ + if (init_thr_lock() || thd->store_globals() || + my_net_init(&thd->net, 0, MYF(MY_THREAD_SPECIFIC)) || + IF_DBUG(simulate_error & (1<< thd_type), 0)) + { + thd->cleanup(); + DBUG_RETURN(-1); + } + thd->system_thread = (thd_type == SLAVE_THD_SQL) ? SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; thd->security_ctx->skip_grants(); - my_net_init(&thd->net, 0); /* Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all slave threads, since a replication event can become this much larger @@ -2446,17 +2460,6 @@ static int init_slave_thread(THD* thd, Master_info *mi, thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; mysql_mutex_unlock(&LOCK_thread_count); - DBUG_EXECUTE_IF("simulate_io_slave_error_on_init", - simulate_error|= (1 << SLAVE_THD_IO);); - DBUG_EXECUTE_IF("simulate_sql_slave_error_on_init", - simulate_error|= (1 << SLAVE_THD_SQL);); - if (init_thr_lock() || thd->store_globals() || - IF_DBUG(simulate_error & (1<< thd_type), 0)) - { - thd->cleanup(); - DBUG_RETURN(-1); - } - if (thd_type == SLAVE_THD_SQL) thd_proc_info(thd, "Waiting for the next event in relay log"); else @@ -3494,8 +3497,6 @@ err_during_init: mi->rli.relay_log.description_event_for_queue= 0; // TODO: make rpl_status part of Master_info change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE); - DBUG_ASSERT(thd->net.buff != 0); - net_end(&thd->net); // destructor will not free it, because net.vio is 0 mysql_mutex_lock(&LOCK_thread_count); THD_CHECK_SENTRY(thd); delete thd; @@ -3901,8 +3902,6 @@ err_during_init: to avoid unneeded position re-init */ thd->temporary_tables = 0; // remove tempation from destructor to close them - DBUG_ASSERT(thd->net.buff != 0); - net_end(&thd->net); // destructor will not free it, because we are weird DBUG_ASSERT(rli->sql_thd == thd); THD_CHECK_SENTRY(thd); rli->sql_thd= 0; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a24da193c00..1d6aa73fdb0 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -510,7 +510,7 @@ sp_head::operator new(size_t size) throw() MEM_ROOT own_root; sp_head *sp; - init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); + init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC, 0); sp= (sp_head *) alloc_root(&own_root, size); if (sp == NULL) DBUG_RETURN(NULL); @@ -594,7 +594,7 @@ sp_head::init(LEX *lex) types of stored procedures to simplify reset_lex()/restore_lex() code. */ lex->trg_table_fields.empty(); - my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8); + my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8, 0); m_param_begin= NULL; m_param_end= NULL; @@ -1224,7 +1224,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; Object_creation_ctx *saved_creation_ctx; Warning_info *saved_warning_info; - Warning_info warning_info(thd->warning_info->warn_id(), false); + Warning_info warning_info(thd->warning_info->warn_id(), false, true); /* Just reporting a stack overrun error @@ -1254,7 +1254,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) DBUG_RETURN(TRUE); /* init per-instruction memroot */ - init_sql_alloc(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0); + init_sql_alloc(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0, 0); DBUG_ASSERT(!(m_flags & IS_INVOKED)); m_flags|= IS_INVOKED; @@ -1711,7 +1711,7 @@ sp_head::execute_trigger(THD *thd, TODO: we should create sp_rcontext once per command and reuse it on subsequent executions of a trigger. */ - init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); + init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, 0); thd->set_n_backup_active_arena(&call_arena, &backup_arena); if (!(nctx= new sp_rcontext(m_pcont, 0, octx)) || @@ -1828,7 +1828,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, TODO: we should create sp_rcontext once per command and reuse it on subsequent executions of a function/trigger. */ - init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); + init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, 0); thd->set_n_backup_active_arena(&call_arena, &backup_arena); if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) || diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 4c5087eaf27..cdafc5cd819 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -61,20 +61,20 @@ sp_pcontext::sp_pcontext() m_label_scope(LABEL_DEFAULT_SCOPE) { (void) my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); m_label.empty(); m_children.empty(); @@ -89,20 +89,20 @@ sp_pcontext::sp_pcontext(sp_pcontext *prev, label_scope_type label_scope) m_label_scope(label_scope) { (void) my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); (void) my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), - PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC); + PCONTEXT_ARRAY_INIT_ALLOC, + PCONTEXT_ARRAY_INCREMENT_ALLOC, 0); m_label.empty(); m_children.empty(); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 31627189296..9fa908c43e2 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -688,7 +688,7 @@ my_bool acl_init(bool dont_read_acl_tables) return_val= acl_reload(thd); delete thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); DBUG_RETURN(return_val); } @@ -749,13 +749,13 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) acl_cache->clear(1); // Clear locked hostname cache - init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0, 0); if (init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0, FALSE)) goto end; table->use_all_columns(); - (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50); + (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST), 20, 50, 0); while (!(read_record_info.read_record(&read_record_info))) { ACL_HOST host; @@ -807,7 +807,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) goto end; table->use_all_columns(); - (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100); + (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, 0); password_length= table->field[2]->field_length / table->field[2]->charset()->mbmaxlen; if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) @@ -1009,7 +1009,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) goto end; table->use_all_columns(); - (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100); + (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB), 50, 100, 0); while (!(read_record_info.read_record(&read_record_info))) { ACL_DB db; @@ -1067,7 +1067,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) freeze_size(&acl_dbs); (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), - 50, 100); + 50, 100, 0); if (tables[3].table) { init_read_record(&read_record_info, thd, table= tables[3].table, NULL, 1, @@ -1722,7 +1722,7 @@ static void init_check_host(void) { DBUG_ENTER("init_check_host"); (void) my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), - acl_users.elements,1); + acl_users.elements, 1, 0); (void) my_hash_init(&acl_check_hosts,system_charset_info, acl_users.elements, 0, 0, (my_hash_get_key) check_get_key, 0, 0); @@ -4121,7 +4121,7 @@ my_bool grant_init() return_val= grant_reload(thd); delete thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); DBUG_RETURN(return_val); } @@ -4412,7 +4412,7 @@ my_bool grant_reload(THD *thd) opertion possible in case of failure. */ old_mem= memex; - init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0, 0); if ((return_val= grant_load(thd, tables))) { // Error. Revert to old hash diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index e6bbef482a7..ba1ea01efcc 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -398,7 +398,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, because it's already known that the table is badly damaged. */ - Warning_info wi(thd->query_id, false); + Warning_info wi(thd->query_id, false, true); Warning_info *wi_saved= thd->warning_info; thd->warning_info= &wi; diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h index 34c8e2da3d4..8bac29de5a3 100644 --- a/sql/sql_analyse.h +++ b/sql/sql_analyse.h @@ -121,7 +121,8 @@ public: must_be_blob(0), was_zero_fill(0), was_maybe_zerofill(0), can_be_still_num(1) { init_tree(&tree, 0, 0, sizeof(String), (qsort_cmp2) sortcmp2, - 0, (tree_element_free) free_string, NULL); }; + (tree_element_free) free_string, NULL, + MYF(MY_THREAD_SPECIFIC)); }; void add(); void get_opt_type(String*, ha_rows); @@ -162,7 +163,7 @@ public: { bin_size= my_decimal_get_binary_size(a->max_length, a->decimals); init_tree(&tree, 0, 0, bin_size, (qsort_cmp2)compare_decimal2, - 0, 0, (void *)&bin_size); + 0, (void *)&bin_size, MYF(MY_THREAD_SPECIFIC)); }; void add(); @@ -190,7 +191,8 @@ public: field_real(Item* a, analyse* b) :field_info(a,b), min_arg(0), max_arg(0), sum(0), sum_sqr(0), max_notzero_dec_len(0) { init_tree(&tree, 0, 0, sizeof(double), - (qsort_cmp2) compare_double2, 0, NULL, NULL); } + (qsort_cmp2) compare_double2, NULL, NULL, + MYF(MY_THREAD_SPECIFIC)); } void add(); void get_opt_type(String*, ha_rows); @@ -244,7 +246,8 @@ public: field_longlong(Item* a, analyse* b) :field_info(a,b), min_arg(0), max_arg(0), sum(0), sum_sqr(0) { init_tree(&tree, 0, 0, sizeof(longlong), - (qsort_cmp2) compare_longlong2, 0, NULL, NULL); } + (qsort_cmp2) compare_longlong2, NULL, NULL, + MYF(MY_THREAD_SPECIFIC)); } void add(); void get_opt_type(String*, ha_rows); @@ -289,7 +292,8 @@ public: field_ulonglong(Item* a, analyse * b) :field_info(a,b), min_arg(0), max_arg(0), sum(0),sum_sqr(0) { init_tree(&tree, 0, 0, sizeof(ulonglong), - (qsort_cmp2) compare_ulonglong2, 0, NULL, NULL); } + (qsort_cmp2) compare_ulonglong2, NULL, NULL, + MYF(MY_THREAD_SPECIFIC)); } void add(); void get_opt_type(String*, ha_rows); String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; } diff --git a/sql/sql_array.h b/sql/sql_array.h index 98a4a4815af..18881d2c345 100644 --- a/sql/sql_array.h +++ b/sql/sql_array.h @@ -100,7 +100,8 @@ template <class Elem> class Dynamic_array public: Dynamic_array(uint prealloc=16, uint increment=16) { - my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment); + my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment, + MY_THREAD_SPECIFIC); } Elem& at(int idx) diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc index 131a71c1d6b..4403034bca8 100644 --- a/sql/sql_audit.cc +++ b/sql/sql_audit.cc @@ -156,7 +156,7 @@ static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg) { /* specify some reasonable initialization defaults */ my_init_dynamic_array(&thd->audit_class_plugins, - sizeof(plugin_ref), 16, 16); + sizeof(plugin_ref), 16, 16, 0); } /* lock the plugin and add it to the list */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9f21b7f006b..fd0d0603395 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4973,7 +4973,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, anything yet, to avoid penalty for statements which don't use views and thus new .FRM format. */ - init_sql_alloc(&new_frm_mem, 8024, 0); + init_sql_alloc(&new_frm_mem, 8024, 0, 0); thd->current_tablenr= 0; restart: @@ -9265,7 +9265,7 @@ my_bool mysql_rm_tmp_tables(void) my_dirend(dirp); } delete thd; - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); DBUG_RETURN(0); } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 191cc4e01c8..ddc75254c9e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1035,8 +1035,8 @@ void query_cache_insert(const char *packet, ulong length, /* Current_thd can be NULL when a new connection is immediately ended due to "Too many connections". thd->store_globals() has not been - called at this time and hence my_pthread_setspecific_ptr(THR_THD, - this) has not been called for this thread. + called at this time and hence set_current_thd(this) has not been + called for this thread. */ if (!thd) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d6a0eaf9b52..1d0d23a2390 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -807,17 +807,28 @@ THD::THD() #if defined(ENABLED_DEBUG_SYNC) debug_sync_control(0), #endif /* defined(ENABLED_DEBUG_SYNC) */ - main_warning_info(0, false) + main_warning_info(0, false, false) { ulong tmp; mdl_context.init(this); /* + We set THR_THD to temporally point to this THD to register all the + variables that allocates memory for this THD + */ + THD *old_THR_THD= current_thd; + set_current_thd(this); + status_var.memory_used= 0; + + main_warning_info.init(); + /* Pass nominal parameters to init_alloc_root only to ensure that the destructor works OK in case of an error. The main_mem_root will be re-initialized in init_for_queries(). */ - init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); + init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0, + MYF(MY_THREAD_SPECIFIC)); + stmt_arena= this; thread_stack= 0; scheduler= thread_scheduler; // Will be fixed later @@ -874,6 +885,7 @@ THD::THD() mysql_audit_init_thd(this); #endif net.vio=0; + net.buff= 0; client_capabilities= 0; // minimalistic client ull=0; system_thread= NON_SYSTEM_THREAD; @@ -915,7 +927,7 @@ THD::THD() user_connect=(USER_CONN *)0; my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key, - (my_hash_free_key) free_user_var, 0); + (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC); sp_proc_cache= NULL; sp_func_cache= NULL; @@ -923,7 +935,7 @@ THD::THD() /* For user vars replication*/ if (opt_bin_log) my_init_dynamic_array(&user_var_events, - sizeof(BINLOG_USER_VAR_EVENT *), 16, 16); + sizeof(BINLOG_USER_VAR_EVENT *), 16, 16, 0); else bzero((char*) &user_var_events, sizeof(user_var_events)); @@ -946,6 +958,8 @@ THD::THD() prepare_derived_at_open= FALSE; create_tmp_table_for_derived= FALSE; save_prep_leaf_list= FALSE; + /* Restore THR_THD */ + set_current_thd(old_THR_THD); } @@ -1214,6 +1228,7 @@ extern "C" THD *_current_thd_noinline(void) void THD::init(void) { + DBUG_ENTER("thd::init"); mysql_mutex_lock(&LOCK_global_system_variables); plugin_thdvar_init(this); /* @@ -1243,7 +1258,7 @@ void THD::init(void) tx_isolation= (enum_tx_isolation) variables.tx_isolation; update_charset(); reset_current_stmt_binlog_format_row(); - bzero((char *) &status_var, sizeof(status_var)); + set_status_var_init(); bzero((char *) &org_status_var, sizeof(org_status_var)); if (variables.sql_log_bin) @@ -1260,6 +1275,7 @@ void THD::init(void) debug_sync_init_thread(this); #endif /* defined(ENABLED_DEBUG_SYNC) */ apc_target.init(&LOCK_thd_data); + DBUG_VOID_RETURN; } @@ -1433,8 +1449,16 @@ void THD::cleanup(void) THD::~THD() { + THD *orig_thd= current_thd; THD_CHECK_SENTRY(this); DBUG_ENTER("~THD()"); + + /* + In error cases, thd may not be current thd. We have to fix this so + that memory allocation counting is done correctly + */ + set_current_thd(this); + /* Ensure that no one is using THD */ mysql_mutex_lock(&LOCK_thd_data); mysys_var=0; // Safety (shouldn't be needed) @@ -1443,10 +1467,8 @@ THD::~THD() /* Close connection */ #ifndef EMBEDDED_LIBRARY if (net.vio) - { vio_delete(net.vio); - net_end(&net); - } + net_end(&net); #endif stmt_map.reset(); /* close all prepared statements */ if (!cleanup_done) @@ -1481,6 +1503,15 @@ THD::~THD() #endif free_root(&main_mem_root, MYF(0)); + main_warning_info.free_memory(); + if (status_var.memory_used != 0) + { + DBUG_PRINT("error", ("memory_used: %lld", status_var.memory_used)); + SAFEMALLOC_REPORT_MEMORY(my_thread_dbug_id()); + DBUG_ASSERT(status_var.memory_used == 0); // Ensure everything is freed + } + + set_current_thd(orig_thd); DBUG_VOID_RETURN; } @@ -1752,7 +1783,7 @@ bool THD::store_globals() */ DBUG_ASSERT(thread_stack); - if (my_pthread_setspecific_ptr(THR_THD, this) || + if (set_current_thd(this) || my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)) return 1; /* @@ -1796,7 +1827,7 @@ void THD::reset_globals() mysql_mutex_unlock(&LOCK_thd_data); /* Undocking the thread specific data. */ - my_pthread_setspecific_ptr(THR_THD, NULL); + set_current_thd(0); my_pthread_setspecific_ptr(THR_MALLOC, NULL); } @@ -3652,7 +3683,8 @@ void thd_increment_net_big_packet_count(ulong length) void THD::set_status_var_init() { - bzero((char*) &status_var, sizeof(status_var)); + bzero((char*) &status_var, offsetof(STATUS_VAR, + last_cleared_system_status_var)); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 9ac70d4bcee..f10b517a606 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -683,6 +683,8 @@ typedef struct system_status_var ulonglong binlog_bytes_written; double last_query_cost; double cpu_time, busy_time; + /* Don't initialize */ + volatile int64 memory_used; /* This shouldn't be accumulated */ } STATUS_VAR; /* @@ -692,6 +694,7 @@ typedef struct system_status_var */ #define last_system_status_var questions +#define last_cleared_system_status_var memory_used void mark_transaction_to_rollback(THD *thd, bool all); @@ -1425,7 +1428,8 @@ public: m_reopen_array(NULL), m_locked_tables_count(0) { - init_sql_alloc(&m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0); + init_sql_alloc(&m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0, + MY_THREAD_SPECIFIC); } void unlock_locked_tables(THD *thd); ~Locked_tables_list() @@ -1881,7 +1885,8 @@ public: { bzero((char*)this, sizeof(*this)); xid_state.xid.null(); - init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); + init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0, + MY_THREAD_SPECIFIC); } } transaction; Global_read_lock global_read_lock; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 4e2b5621aca..4bcb62ef764 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -264,7 +264,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, { DBUG_ASSERT(usable_index == MAX_KEY); table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); + MYF(MY_FAE | MY_ZEROFILL | + MY_THREAD_SPECIFIC)); if (!(sortorder= make_unireg_sortorder(order, &length, NULL)) || (table->sort.found_records= filesort(thd, table, sortorder, length, diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 06da6250e71..23a60267737 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -457,23 +457,38 @@ Diagnostics_area::disable_status() m_status= DA_DISABLED; } -Warning_info::Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings) +Warning_info::Warning_info(ulonglong warn_id_arg, + bool allow_unlimited_warnings, bool initialize) :m_statement_warn_count(0), m_current_row_for_warning(1), m_warn_id(warn_id_arg), m_allow_unlimited_warnings(allow_unlimited_warnings), + initialized(0), m_read_only(FALSE) { - /* Initialize sub structures */ - init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); m_warn_list.empty(); bzero((char*) m_warn_count, sizeof(m_warn_count)); + if (initialize) + init(); } +void Warning_info::init() +{ + /* Initialize sub structures */ + init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, + WARN_ALLOC_PREALLOC_SIZE, MYF(MY_THREAD_SPECIFIC)); + initialized= 1; +} + +void Warning_info::free_memory() +{ + if (initialized) + free_root(&m_warn_root,MYF(0)); +} Warning_info::~Warning_info() { - free_root(&m_warn_root,MYF(0)); + free_memory(); } @@ -484,7 +499,7 @@ Warning_info::~Warning_info() void Warning_info::clear_warning_info(ulonglong warn_id_arg) { m_warn_id= warn_id_arg; - free_root(&m_warn_root, MYF(0)); + free_memory(); bzero((char*) m_warn_count, sizeof(m_warn_count)); m_warn_list.empty(); m_statement_warn_count= 0; diff --git a/sql/sql_error.h b/sql/sql_error.h index 00ade934226..17ec3aa7b56 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -355,15 +355,21 @@ class Warning_info /** Indicates if push_warning() allows unlimited number of warnings. */ bool m_allow_unlimited_warnings; + bool initialized; /* Set to 1 if init() has been called */ private: Warning_info(const Warning_info &rhs); /* Not implemented */ Warning_info& operator=(const Warning_info &rhs); /* Not implemented */ public: - Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings); + Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings, + bool initialize); ~Warning_info(); + /* Allocate memory for structures */ + void init(); + void free_memory(); + /** Reset the warning information. Clear all warnings, the number of warnings, reset current row counter diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index d03b38171fc..c4055a9221f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -323,7 +323,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen) /* copy data to sql_handler */ if (!(sql_handler= new SQL_HANDLER(thd))) goto err; - init_alloc_root(&sql_handler->mem_root, 1024, 0); + init_alloc_root(&sql_handler->mem_root, 1024, 0, MYF(MY_THREAD_SPECIFIC)); sql_handler->db.length= strlen(tables->db); sql_handler->table_name.length= strlen(tables->table_name); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 61a7a56c413..c0eabd3a2f2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2481,7 +2481,9 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, goto err; } - if (!(row->record= (char*) my_malloc(table->s->reclength, MYF(MY_WME)))) + /* This can't be THREAD_SPECIFIC as it's freed in delayed thread */ + if (!(row->record= (char*) my_malloc(table->s->reclength, + MYF(MY_WME)))) goto err; memcpy(row->record, table->record[0], table->s->reclength); row->start_time= thd->start_time; @@ -2898,24 +2900,28 @@ pthread_handler_t handle_delayed_insert(void *arg) DBUG_LEAVE; } - di->table=0; - thd->killed= KILL_CONNECTION; // If error - mysql_mutex_unlock(&di->mutex); + { + DBUG_ENTER("handle_delayed_insert-cleanup"); + di->table=0; + thd->killed= KILL_CONNECTION; // If error + mysql_mutex_unlock(&di->mutex); - close_thread_tables(thd); // Free the table - thd->mdl_context.release_transactional_locks(); - mysql_cond_broadcast(&di->cond_client); // Safety + close_thread_tables(thd); // Free the table + thd->mdl_context.release_transactional_locks(); + mysql_cond_broadcast(&di->cond_client); // Safety - mysql_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table - mysql_mutex_lock(&LOCK_delayed_insert); - /* - di should be unlinked from the thread handler list and have no active - clients - */ - delete di; - mysql_mutex_unlock(&LOCK_delayed_insert); - mysql_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table + mysql_mutex_lock(&LOCK_delayed_insert); + /* + di should be unlinked from the thread handler list and have no active + clients + */ + delete di; + mysql_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_create); + DBUG_LEAVE; + } my_thread_end(); pthread_exit(0); diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 4626f30df28..fde9f70fa79 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -934,7 +934,7 @@ int JOIN_CACHE::alloc_buffer() { ulong next_buff_size; - if ((buff= (uchar*) my_malloc(buff_size, MYF(0)))) + if ((buff= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC)))) break; next_buff_size= buff_size > buff_size_decr ? buff_size-buff_size_decr : 0; @@ -1012,7 +1012,7 @@ int JOIN_CACHE::realloc_buffer() { int rc; free(); - rc= test(!(buff= (uchar*) my_malloc(buff_size, MYF(0)))); + rc= test(!(buff= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC)))); reset(TRUE); return rc; } @@ -2801,7 +2801,7 @@ int JOIN_CACHE_HASHED::realloc_buffer() { int rc; free(); - rc= test(!(buff= (uchar*) my_malloc(buff_size, MYF(0)))); + rc= test(!(buff= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC)))); init_hash_table(); reset(TRUE); return rc; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index fb4d4defe9c..93e3eb51518 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2552,7 +2552,7 @@ LEX::LEX() my_init_dynamic_array2(&plugins, sizeof(plugin_ref), plugins_static_buffer, INITIAL_LEX_PLUGIN_LIST_SIZE, - INITIAL_LEX_PLUGIN_LIST_SIZE); + INITIAL_LEX_PLUGIN_LIST_SIZE, 0); reset_query_tables_list(TRUE); mi.init(); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 492909ee3d5..e1c0940c461 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -305,7 +305,7 @@ struct LEX_MASTER_INFO { bzero(this, sizeof(*this)); my_init_dynamic_array(&repl_ignore_server_ids, - sizeof(::server_id), 0, 16); + sizeof(::server_id), 0, 16, 0); } void reset() { diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 4fdabef37ed..7d030329419 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1371,7 +1371,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, set_if_bigger(length,line_start.length()); stack=stack_pos=(int*) sql_alloc(sizeof(int)*length); - if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0)))) + if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(MY_THREAD_SPECIFIC)))) error=1; /* purecov: inspected */ else { @@ -1379,7 +1379,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, if (init_io_cache(&cache,(get_it_from_net) ? -1 : file, 0, (get_it_from_net) ? READ_NET : (is_fifo ? READ_FIFO : READ_CACHE),0L,1, - MYF(MY_WME))) + MYF(MY_WME | MY_THREAD_SPECIFIC))) { my_free(buffer); /* purecov: inspected */ buffer= NULL; @@ -1605,7 +1605,7 @@ int READ_INFO::read_field() ** We come here if buffer is too small. Enlarge it and continue */ if (!(new_buffer=(uchar*) my_realloc((char*) buffer,buff_length+1+IO_SIZE, - MYF(MY_WME)))) + MYF(MY_WME | MY_THREAD_SPECIFIC)))) return (error=1); to=new_buffer + (to-buffer); buffer=new_buffer; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 472273a0a33..2d3d91ff9d8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -642,8 +642,6 @@ void do_handle_bootstrap(THD *thd) handle_bootstrap_impl(thd); end: - net_end(&thd->net); - thd->cleanup(); delete thd; #ifndef EMBEDDED_LIBRARY @@ -1291,10 +1289,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, and flushes tables. */ bool res; - my_pthread_setspecific_ptr(THR_THD, NULL); + set_current_thd(0); res= reload_acl_and_cache(NULL, options | REFRESH_FAST, NULL, ¬_used); - my_pthread_setspecific_ptr(THR_THD, thd); + set_current_thd(thd); if (res) break; } @@ -1465,6 +1463,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd_proc_info(thd, "cleaning up"); thd->reset_query(); + thd->examined_row_count= 0; // For processlist thd->command=COM_SLEEP; dec_thread_running(); thd_proc_info(thd, 0); @@ -4794,7 +4793,8 @@ static bool execute_show_status(THD *thd, TABLE_LIST *all_tables) mysql_mutex_lock(&LOCK_status); add_diff_to_status(&global_status_var, &thd->status_var, &old_status_var); - thd->status_var= old_status_var; + memcpy(&thd->status_var, &old_status_var, + offsetof(STATUS_VAR, last_cleared_system_status_var)); mysql_mutex_unlock(&LOCK_status); return res; } @@ -6843,7 +6843,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, mysql_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(ER_KILL_DENIED_ERROR); } - if (!threads_to_kill.push_back(tmp, tmp->mem_root)) + if (!threads_to_kill.push_back(tmp, thd->mem_root)) mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete } } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 45e8adf1f5f..e24b43c0cf6 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1114,7 +1114,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, plugin_array_version++; if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) tmp_plugin_ptr->state= PLUGIN_IS_FREED; - init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); + init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096, 0); if (name->str) DBUG_RETURN(FALSE); // all done @@ -1507,8 +1507,8 @@ int plugin_init(int *argc, char **argv, int flags) init_plugin_psi_keys(); #endif - init_alloc_root(&plugin_mem_root, 4096, 4096); - init_alloc_root(&tmp_root, 4096, 4096); + init_alloc_root(&plugin_mem_root, 4096, 4096, 0); + init_alloc_root(&tmp_root, 4096, 4096, 0); if (my_hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0, get_bookmark_hash_key, NULL, HASH_UNIQUE)) @@ -1518,9 +1518,9 @@ int plugin_init(int *argc, char **argv, int flags) mysql_mutex_init(key_LOCK_plugin, &LOCK_plugin, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&plugin_dl_array, - sizeof(struct st_plugin_dl *),16,16) || + sizeof(struct st_plugin_dl *),16,16,0) || my_init_dynamic_array(&plugin_array, - sizeof(struct st_plugin_int *),16,16)) + sizeof(struct st_plugin_int *),16,16,0)) goto err; for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) @@ -1716,12 +1716,11 @@ static bool register_builtin(struct st_maria_plugin *plugin, */ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) { - THD thd; TABLE_LIST tables; TABLE *table; READ_RECORD read_record_info; int error; - THD *new_thd= &thd; + THD *new_thd= new THD; bool result; #ifdef EMBEDDED_LIBRARY No_such_table_error_handler error_handler; @@ -1732,7 +1731,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) new_thd->store_globals(); new_thd->db= my_strdup("mysql", MYF(0)); new_thd->db_length= 5; - bzero((char*) &thd.net, sizeof(thd.net)); + bzero((char*) &new_thd->net, sizeof(new_thd->net)); tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_READ); #ifdef EMBEDDED_LIBRARY @@ -1799,7 +1798,8 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) close_mysql_tables(new_thd); end: /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + delete new_thd; + set_current_thd(0); DBUG_VOID_RETURN; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 96b7d825bd3..e2398536783 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2963,7 +2963,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) param= stmt->param_array[param_number]; Diagnostics_area new_stmt_da, *save_stmt_da= thd->stmt_da; - Warning_info new_warnning_info(thd->query_id, false); + Warning_info new_warnning_info(thd->query_id, false, true); Warning_info *save_warinig_info= thd->warning_info; thd->stmt_da= &new_stmt_da; @@ -3141,7 +3141,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg) flags((uint) IS_IN_USE) { init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size, - thd_arg->variables.query_prealloc_size); + thd_arg->variables.query_prealloc_size, MYF(MY_THREAD_SPECIFIC)); *last_error= '\0'; } @@ -4031,7 +4031,7 @@ Ed_result_set::Ed_result_set(List<Ed_row> *rows_arg, */ Ed_connection::Ed_connection(THD *thd) - :m_warning_info(thd->query_id, false), + :m_warning_info(thd->query_id, false, true), m_thd(thd), m_rsets(0), m_current_rset(0) @@ -4455,7 +4455,7 @@ bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint) { DBUG_ASSERT(m_rset == 0 && !alloc_root_inited(&m_rset_root)); - init_sql_alloc(&m_rset_root, MEM_ROOT_BLOCK_SIZE, 0); + init_sql_alloc(&m_rset_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); if (! (m_rset= new (&m_rset_root) List<Ed_row>)) return TRUE; diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 99fe9267589..2720dc7cd74 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -97,7 +97,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, { delete tmp_thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); thd= 0; } reset_mqh((LEX_USER *)NULL, TRUE); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4ef4311a68a..63718dc9d55 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4947,7 +4947,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, /* set a barrier for the array of SARGABLE_PARAM */ (*sargables)[0].field= 0; - if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) + if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64, + MYF(MY_THREAD_SPECIFIC))) return TRUE; if (cond) @@ -14362,7 +14363,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, if (param->precomputed_group_by) copy_func_count+= param->sum_func_count; - init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); if (!multi_alloc_root(&own_root, &table, sizeof(*table), @@ -19171,7 +19172,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, goto err; /* purecov: inspected */ table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_WME | MY_ZEROFILL)); + MYF(MY_WME | MY_ZEROFILL| + MY_THREAD_SPECIFIC)); table->status=0; // May be wrong if quick_select // If table has a range, move it to select @@ -22418,6 +22420,7 @@ static void print_join(THD *thd, List_iterator_fast<TABLE_LIST> ti(*tables); TABLE_LIST **table; uint non_const_tables= 0; + DBUG_ENTER("print_join"); for (TABLE_LIST *t= ti++; t ; t= ti++) { @@ -22431,13 +22434,13 @@ static void print_join(THD *thd, if (!non_const_tables) { str->append(STRING_WITH_LEN("dual")); - return; // all tables were optimized away + DBUG_VOID_RETURN; // all tables were optimized away } ti.rewind(); if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) * non_const_tables))) - return; // out of memory + DBUG_VOID_RETURN; // out of memory TABLE_LIST *tmp, **t= table + (non_const_tables - 1); while ((tmp= ti++)) @@ -22476,6 +22479,7 @@ static void print_join(THD *thd, } print_table_array(thd, eliminated_tables, str, table, table + non_const_tables, query_type); + DBUG_VOID_RETURN; } /** @@ -22984,7 +22988,8 @@ JOIN::reoptimize(Item *added_where, table_map join_tables, reset_query_plan(); if (!keyuse.buffer && - my_init_dynamic_array(&keyuse, sizeof(KEYUSE), 20, 64)) + my_init_dynamic_array(&keyuse, sizeof(KEYUSE), 20, 64, + MYF(MY_THREAD_SPECIFIC))) { delete_dynamic(&added_keyuse); return REOPT_ERROR; diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index dce679a883f..63f3e6c9d63 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -158,7 +158,7 @@ bool servers_init(bool dont_read_servers_table) } /* Initialize the mem root for data */ - init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); if (dont_read_servers_table) goto end; @@ -178,7 +178,7 @@ bool servers_init(bool dont_read_servers_table) return_val= servers_reload(thd); delete thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); end: DBUG_RETURN(return_val); @@ -209,7 +209,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables) my_hash_reset(&servers_cache); free_root(&mem, MYF(0)); - init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0, 0); if (init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0, FALSE)) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5d57edc53ae..f9458fa8588 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -458,7 +458,7 @@ bool ignore_db_dirs_init() { return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *), - 0, 0); + 0, 0, 0); } @@ -737,7 +737,8 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db, bzero((char*) &table_list,sizeof(table_list)); - if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0)))) + if (!(dirp = my_dir(path,MYF((dir ? MY_WANT_STAT : 0) | + MY_THREAD_SPECIFIC)))) { if (my_errno == ENOENT) my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db); @@ -2334,11 +2335,14 @@ void Show_explain_request::call_in_target_thread() target_thd->query_length(), target_thd->query_charset()); + DBUG_ASSERT(current_thd == target_thd); + set_current_thd(request_thd); if (target_thd->lex->unit.print_explain(explain_buf, 0 /* explain flags*/, &printed_anything)) { failed_to_produce= TRUE; } + set_current_thd(target_thd); if (!printed_anything) failed_to_produce= TRUE; @@ -2349,10 +2353,20 @@ void Show_explain_request::call_in_target_thread() int select_result_explain_buffer::send_data(List<Item> &items) { + int res; + THD *cur_thd= current_thd; + DBUG_ENTER("select_result_explain_buffer::send_data"); + + /* + Switch to the recieveing thread, so that we correctly count memory used + by it. This is needed as it's the receiving thread that will free the + memory. + */ + set_current_thd(thd); fill_record(thd, dst_table, dst_table->field, items, TRUE, FALSE); - if ((dst_table->file->ha_write_tmp_row(dst_table->record[0]))) - return 1; - return 0; + res= dst_table->file->ha_write_tmp_row(dst_table->record[0]); + set_current_thd(cur_thd); + DBUG_RETURN(test(res)); } @@ -2578,6 +2592,18 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) } mysql_mutex_unlock(&tmp->LOCK_thd_data); + /* + This may become negative if we free a memory allocated by another + thread in this thread. However it's better that we notice it eventually + than hide it. + */ + table->field[12]->store((longlong) (tmp->status_var.memory_used + + sizeof(THD)), + FALSE); + table->field[12]->set_notnull(); + table->field[13]->store((longlong) tmp->examined_row_count, TRUE); + table->field[13]->set_notnull(); + if (schema_table_store_record(thd, table)) { mysql_mutex_unlock(&LOCK_thread_count); @@ -2650,7 +2676,7 @@ int add_status_vars(SHOW_VAR *list) if (status_vars_inited) mysql_mutex_lock(&LOCK_status); if (!all_status_vars.buffer && // array is not allocated yet - do it now - my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20)) + my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20, 0)) { res= 1; goto err; @@ -2999,7 +3025,8 @@ static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats) { // First entry for this role. if (!(agg_user= (USER_STATS*) my_malloc(sizeof(USER_STATS), - MYF(MY_WME | MY_ZEROFILL)))) + MYF(MY_WME | MY_ZEROFILL| + MY_THREAD_SPECIFIC)))) { sql_print_error("Malloc in aggregate_user_stats failed"); DBUG_RETURN(1); @@ -4372,7 +4399,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables, if (schema_table->i_s_requested_object & OPEN_TRIGGER_ONLY) { - init_sql_alloc(&tbl.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&tbl.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, 0); if (!Table_triggers_list::check_n_load(thd, db_name->str, table_name->str, &tbl, 1)) { @@ -7878,7 +7905,7 @@ static bool do_fill_table(THD *thd, // Warning_info, so "useful warnings" get rejected. In order to avoid // that problem we create a Warning_info instance, which is capable of // storing "unlimited" number of warnings. - Warning_info wi(thd->query_id, true); + Warning_info wi(thd->query_id, true, true); Warning_info *wi_saved= thd->warning_info; thd->warning_info= &wi; @@ -8612,6 +8639,8 @@ ST_FIELD_INFO processlist_fields_info[]= {"MAX_STAGE", 2, MYSQL_TYPE_TINY, 0, 0, "Max_stage", SKIP_OPEN_TABLE}, {"PROGRESS", 703, MYSQL_TYPE_DECIMAL, 0, 0, "Progress", SKIP_OPEN_TABLE}, + {"MEMORY_USED", 7, MYSQL_TYPE_LONG, 0, 0, "Memory_used", SKIP_OPEN_TABLE}, + {"EXAMINED_ROWS", 7, MYSQL_TYPE_LONG, 0, 0, "Examined_rows", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -8941,7 +8970,7 @@ int initialize_schema_table(st_plugin_int *plugin) DBUG_ENTER("initialize_schema_table"); if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE), - MYF(MY_WME | MY_ZEROFILL)))) + MYF(MY_WME | MY_ZEROFILL)))) DBUG_RETURN(1); /* Historical Requirement */ plugin->data= schema_table; // shortcut for the future diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 70ba6897333..687fdf26228 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1387,7 +1387,8 @@ public: is_single_comp_pk= FALSE; uint pk= table->s->primary_key; - if (table->key_info - key_info == pk && table->key_info[pk].key_parts == 1) + if ((uint) (table->key_info - key_info) == pk && + table->key_info[pk].key_parts == 1) { prefixes= 1; is_single_comp_pk= TRUE; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 126139cd219..9d11677666f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -42,7 +42,9 @@ bool String::real_alloc(uint32 length) if (Alloced_length < arg_length) { free(); - if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME)))) + if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME | + (thread_specific ? + MY_THREAD_SPECIFIC : 0))))) return TRUE; Alloced_length=arg_length; alloced=1; @@ -90,10 +92,16 @@ bool String::realloc_raw(uint32 alloc_length) return TRUE; /* Overflow */ if (alloced) { - if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) + if (!(new_ptr= (char*) my_realloc(Ptr,len, + MYF(MY_WME | + (thread_specific ? + MY_THREAD_SPECIFIC : 0))))) return TRUE; // Signal error } - else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) + else if ((new_ptr= (char*) my_malloc(len, + MYF(MY_WME | + (thread_specific ? + MY_THREAD_SPECIFIC : 0))))) { if (str_length > len - 1) str_length= 0; diff --git a/sql/sql_string.h b/sql/sql_string.h index 2966fc2a920..58cda343dac 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -56,23 +56,26 @@ class String { char *Ptr; uint32 str_length,Alloced_length, extra_alloc; - bool alloced; + bool alloced,thread_specific; CHARSET_INFO *str_charset; public: String() { - Ptr=0; str_length=Alloced_length=extra_alloc=0; alloced=0; + Ptr=0; str_length=Alloced_length=extra_alloc=0; + alloced= thread_specific= 0; str_charset= &my_charset_bin; } String(uint32 length_arg) { - alloced=0; Alloced_length= extra_alloc= 0; (void) real_alloc(length_arg); + alloced= thread_specific= 0; + Alloced_length= extra_alloc= 0; (void) real_alloc(length_arg); str_charset= &my_charset_bin; } String(const char *str, CHARSET_INFO *cs) { Ptr=(char*) str; str_length= (uint32) strlen(str); - Alloced_length= extra_alloc= 0; alloced=0; + Alloced_length= extra_alloc= 0; + alloced= thread_specific= 0; str_charset=cs; } /* @@ -82,18 +85,21 @@ public: */ String(const char *str,uint32 len, CHARSET_INFO *cs) { - Ptr=(char*) str; str_length=len; Alloced_length= extra_alloc=0; alloced=0; + Ptr=(char*) str; str_length=len; Alloced_length= extra_alloc=0; + alloced= thread_specific= 0; str_charset=cs; } String(char *str,uint32 len, CHARSET_INFO *cs) { - Ptr=(char*) str; Alloced_length=str_length=len; extra_alloc= 0; alloced=0; + Ptr=(char*) str; Alloced_length=str_length=len; extra_alloc= 0; + alloced= thread_specific= 0; str_charset=cs; } String(const String &str) { Ptr=str.Ptr ; str_length=str.str_length ; - Alloced_length=str.Alloced_length; extra_alloc= 0; alloced=0; + Alloced_length=str.Alloced_length; extra_alloc= 0; + alloced= thread_specific= 0; str_charset=str.str_charset; } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () @@ -108,6 +114,12 @@ public: { /* never called */ } ~String() { free(); } + /* Mark variable thread specific it it's not allocated already */ + inline void set_thread_specific() + { + if (!alloced) + thread_specific= 1; + } inline void set_charset(CHARSET_INFO *charset_arg) { str_charset= charset_arg; } inline CHARSET_INFO *charset() const { return str_charset; } @@ -332,6 +344,7 @@ public: Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; extra_alloc= s.extra_alloc; alloced= s.alloced; + thread_specific= s.thread_specific; s.alloced= 0; } bool append(const String &s); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 57d0bf375da..d0a4aedfa4f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -961,7 +961,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) ddl_log_entry->handler_name)); handler_name.str= (char*)ddl_log_entry->handler_name; handler_name.length= strlen(ddl_log_entry->handler_name); - init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); if (!strcmp(ddl_log_entry->handler_name, reg_ext)) frm_action= TRUE; else @@ -1521,7 +1521,7 @@ void execute_ddl_log_recovery() global_ddl_log.recovery_phase= FALSE; delete thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); DBUG_VOID_RETURN; } @@ -5380,7 +5380,7 @@ mysql_compare_tables(TABLE *table, if (table->s->tmp_table == NO_TMP_TABLE) { (void) delete_statistics_for_index(thd, table, table_key, FALSE); - if (table_key - table->key_info == table->s->primary_key) + if ((uint) (table_key - table->key_info) == table->s->primary_key) { KEY *tab_key_info= table->key_info; for (uint j=0; j < table->s->keys; j++, tab_key_info++) @@ -7542,7 +7542,8 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, else { from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); + MYF(MY_FAE | MY_ZEROFILL | + MY_THREAD_SPECIFIC)); bzero((char *) &tables, sizeof(tables)); tables.table= from; tables.alias= tables.table_name= from->s->table_name.str; diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 25ab84fe4db..5b3286d77b0 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -484,7 +484,9 @@ static void display_table_locks(void) void *saved_base; DYNAMIC_ARRAY saved_table_locks; - (void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO), cached_open_tables() + 20,50); + (void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO), + cached_open_tables() + 20, 50, + MYF(MY_THREAD_SPECIFIC)); mysql_mutex_lock(&THR_LOCK_lock); for (list= thr_lock_thread_list; list; list= list_rest(list)) { diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index aff00f9fcf4..fa509835dae 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1779,7 +1779,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name) DBUG_ENTER("drop_all_triggers"); bzero(&table, sizeof(table)); - init_sql_alloc(&table.mem_root, 8192, 0); + init_sql_alloc(&table.mem_root, 8192, 0, 0); if (Table_triggers_list::check_n_load(thd, db, name, &table, 1)) { @@ -1999,7 +1999,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, DBUG_ENTER("change_table_name"); bzero(&table, sizeof(table)); - init_sql_alloc(&table.mem_root, 8192, 0); + init_sql_alloc(&table.mem_root, 8192, 0, 0); /* This method interfaces the mysql server code protected by diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 9069d876609..9832f240fb5 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -151,7 +151,7 @@ void udf_init() mysql_rwlock_init(key_rwlock_THR_LOCK_udf, &THR_LOCK_udf); - init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0, 0); THD *new_thd = new THD; if (!new_thd || my_hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0)) @@ -258,7 +258,7 @@ end: close_mysql_tables(new_thd); delete new_thd; /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); DBUG_VOID_RETURN; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index e320c1a3b86..8a0d95722e8 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -492,7 +492,8 @@ int mysql_update(THD *thd, ha_rows found_rows; table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); + MYF(MY_FAE | MY_ZEROFILL | + MY_THREAD_SPECIFIC)); if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) || (table->sort.found_records= filesort(thd, table, sortorder, length, select, limit, diff --git a/sql/table.cc b/sql/table.cc index 6eafdc916f9..6fc6bd44b22 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -307,7 +307,7 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, path_length= build_table_filename(path, sizeof(path) - 1, table_list->db, table_list->table_name, "", 0); - init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, 0); if (multi_alloc_root(&mem_root, &share, sizeof(*share), &key_buff, key_length, @@ -340,7 +340,7 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, share->free_tables.empty(); share->m_flush_tickets.empty(); - init_sql_alloc(&share->stats_cb.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&share->stats_cb.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, 0); memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root)); mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data, @@ -381,7 +381,12 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, DBUG_PRINT("enter", ("table: '%s'.'%s'", key, table_name)); bzero((char*) share, sizeof(*share)); - init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + /* + This can't be MY_THREAD_SPECIFIC for slaves as they are freed + during cleanup() from Relay_log_info::close_temporary_tables() + */ + init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, + MYF(thd->slave_thread ? 0 : MY_THREAD_SPECIFIC)); share->table_category= TABLE_CATEGORY_TEMPORARY; share->tmp_table= INTERNAL_TMP_TABLE; share->db.str= (char*) key; @@ -2341,6 +2346,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, share->table_name.str, (long) outparam)); + LINT_INIT(dfield_ptr); + LINT_INIT(vfield_ptr); thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_VIEW; // not a view @@ -2351,7 +2358,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam->db_stat= db_stat; outparam->write_row_record= NULL; - init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, 0); if (outparam->alias.copy(alias, strlen(alias), table_alias_charset)) goto err; diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index cedcbefc26f..8c7db0673ac 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -61,9 +61,10 @@ extern "C" { } } -void init_sql_alloc(MEM_ROOT *mem_root, uint block_size, uint pre_alloc) +void init_sql_alloc(MEM_ROOT *mem_root, uint block_size, uint pre_alloc, + myf my_flags) { - init_alloc_root(mem_root, block_size, pre_alloc); + init_alloc_root(mem_root, block_size, pre_alloc, my_flags); mem_root->error_handler=sql_alloc_error_handler; } diff --git a/sql/thr_malloc.h b/sql/thr_malloc.h index 81b7d3cc238..0b17c5cdaf1 100644 --- a/sql/thr_malloc.h +++ b/sql/thr_malloc.h @@ -20,7 +20,8 @@ typedef struct st_mem_root MEM_ROOT; -void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size); +void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size, + myf my_flags); void *sql_alloc(size_t); void *sql_calloc(size_t); char *sql_strdup(const char *str); diff --git a/sql/tztime.cc b/sql/tztime.cc index ba24cab9ca7..525fc96241c 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1637,7 +1637,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) my_hash_free(&tz_names); goto end; } - init_sql_alloc(&tz_storage, 32 * 1024, 0); + init_sql_alloc(&tz_storage, 32 * 1024, 0, 0); mysql_mutex_init(key_tz_LOCK, &tz_LOCK, MY_MUTEX_INIT_FAST); tz_inited= 1; @@ -1803,7 +1803,7 @@ end: else { /* Remember that we don't have a THD */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); my_pthread_setspecific_ptr(THR_MALLOC, 0); } @@ -2541,7 +2541,7 @@ scan_tz_dir(char * name_end) } else if (MY_S_ISREG(cur_dir->dir_entry[i].mystat->st_mode)) { - init_alloc_root(&tz_storage, 32768, 0); + init_alloc_root(&tz_storage, 32768, 0, MYF(MY_THREAD_SPECIFIC)); if (!tz_load(fullname, &tz_info, &tz_storage)) print_tz_as_sql(root_name_end + 1, &tz_info); else @@ -2599,7 +2599,7 @@ main(int argc, char **argv) } else { - init_alloc_root(&tz_storage, 32768, 0); + init_alloc_root(&tz_storage, 32768, 0, 0); if (strcmp(argv[1], "--leap") == 0) { diff --git a/sql/uniques.cc b/sql/uniques.cc index c246cd637bd..22f098f8f9a 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -84,10 +84,11 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, if (min_dupl_count_arg) full_size+= sizeof(element_count); my_b_clear(&file); - init_tree(&tree, (ulong) (max_in_memory_size / 16), 0, size, comp_func, 0, - NULL, comp_func_fixed_arg); + init_tree(&tree, (ulong) (max_in_memory_size / 16), 0, size, comp_func, + NULL, comp_func_fixed_arg, MYF(MY_THREAD_SPECIFIC)); /* If the following fail's the next add will also fail */ - my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); + my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16, + MYF(MY_THREAD_SPECIFIC)); /* If you change the following, change it in get_max_elements function, too. */ @@ -602,7 +603,8 @@ bool Unique::walk(tree_walk_action action, void *walk_action_arg) return 1; if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) return 1; - if (!(merge_buffer= (uchar *) my_malloc((ulong) max_in_memory_size, MYF(0)))) + if (!(merge_buffer= (uchar *) my_malloc((ulong) max_in_memory_size, + MYF(MY_THREAD_SPECIFIC)))) return 1; res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size, (BUFFPEK *) file_ptrs.buffer, @@ -625,7 +627,7 @@ bool Unique::get(TABLE *table) { /* Whole tree is in memory; Don't use disk if you don't need to */ if ((record_pointers=table->sort.record_pointers= (uchar*) - my_malloc(size * tree.elements_in_tree, MYF(0)))) + my_malloc(size * tree.elements_in_tree, MYF(MY_THREAD_SPECIFIC)))) { tree_walk_action action= min_dupl_count ? (tree_walk_action) unique_intersect_write_to_ptrs : @@ -650,7 +652,8 @@ bool Unique::get(TABLE *table) /* Open cached file if it isn't open */ outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_ZEROFILL)); + MYF(MY_ZEROFILL | + MY_THREAD_SPECIFIC)); if (!outfile || (! my_b_inited(outfile) && @@ -673,7 +676,7 @@ bool Unique::get(TABLE *table) if (!(sort_buffer=(uchar*) my_malloc((sort_param.max_keys_per_buffer+1) * sort_param.sort_length, - MYF(0)))) + MYF(MY_THREAD_SPECIFIC)))) return 1; sort_param.unique_buff= sort_buffer+(sort_param.max_keys_per_buffer * sort_param.sort_length); diff --git a/sql/unireg.cc b/sql/unireg.cc index edcfe9eb934..20d101be1a3 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -282,7 +282,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, } key_buff_length= uint4korr(fileinfo+47); - keybuff=(uchar*) my_malloc(key_buff_length, MYF(0)); + keybuff=(uchar*) my_malloc(key_buff_length, MYF(MY_THREAD_SPECIFIC)); key_info_length= pack_keys(keybuff, keys, key_info, data_offset); /* @@ -534,7 +534,7 @@ static uchar *pack_screens(List<Create_field> &create_fields, while ((field=it++)) length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2; - if (!(info=(uchar*) my_malloc(length,MYF(MY_WME)))) + if (!(info=(uchar*) my_malloc(length,MYF(MY_WME | MY_THREAD_SPECIFIC)))) DBUG_RETURN(0); start_screen=0; @@ -1108,7 +1108,9 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, bzero((char*) &share, sizeof(share)); table.s= &share; - if (!(buff=(uchar*) my_malloc((size_t) reclength,MYF(MY_WME | MY_ZEROFILL)))) + if (!(buff=(uchar*) my_malloc((size_t) reclength, + MYF(MY_WME | MY_ZEROFILL | + MY_THREAD_SPECIFIC)))) { DBUG_RETURN(1); } |