diff options
author | Monty <monty@mariadb.org> | 2016-02-01 12:45:39 +0200 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2016-02-07 10:34:03 +0200 |
commit | 3d4a7390c1a94ef6e07b04b52ea94a95878cda1b (patch) | |
tree | a53179de37b318e27e48546ed3bc8a723148104a | |
parent | 076aa182c2d2ee67c233d0e79c900dfba6f593c1 (diff) | |
download | mariadb-git-3d4a7390c1a94ef6e07b04b52ea94a95878cda1b.tar.gz |
MDEV-6150 Speed up connection speed by moving creation of THD to new thread
Creating a CONNECT object on client connect and pass this to the working thread which creates the THD.
Split LOCK_thread_count to different mutexes
Added LOCK_thread_start to syncronize threads
Moved most usage of LOCK_thread_count to dedicated functions
Use next_thread_id() instead of thread_id++
Other things:
- Thread id now starts from 1 instead of 2
- Added cast for thread_id as thread id is now of type my_thread_id
- Made THD->host const (To ensure it's not changed)
- Removed some DBUG_PRINT() about entering/exiting mutex as these was already logged by mutex code
- Fixed that aborted_connects and connection_errors_internal are counted in all cases
- Don't take locks for current_linfo when we set it (not needed as it was 0 before)
50 files changed, 872 insertions, 545 deletions
diff --git a/include/my_atomic.h b/include/my_atomic.h index c75b65db38d..2034bf48987 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -280,6 +280,12 @@ make_atomic_store(32) make_atomic_store(64) make_atomic_store(ptr) +#if SIZEOF_LONG == 4 +#define my_atomic_addlong(A,B) my_atomic_add32((int32*) (A), (B)) +#else +#define my_atomic_addlong(A,B) my_atomic_add64((int64*) (A), (B)) +#endif + #ifdef _atomic_h_cleanup_ #include _atomic_h_cleanup_ #undef _atomic_h_cleanup_ diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h index 202dc636eee..619f600a776 100644 --- a/include/mysql/psi/mysql_socket.h +++ b/include/mysql/psi/mysql_socket.h @@ -19,8 +19,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA #ifndef MYSQL_SOCKET_H #define MYSQL_SOCKET_H -/* For strlen() */ -#include <string.h> /* For MY_STAT */ #include <my_dir.h> /* For my_chsize */ diff --git a/include/thread_pool_priv.h b/include/thread_pool_priv.h index 4270c32c826..afa2848ae88 100644 --- a/include/thread_pool_priv.h +++ b/include/thread_pool_priv.h @@ -100,8 +100,6 @@ bool thd_is_connection_alive(THD *thd); void close_connection(THD *thd, uint errcode); /* End the connection before closing it */ void end_connection(THD *thd); -/* Cleanup the THD object */ -void thd_cleanup(THD *thd); /* Decrement connection counter */ void dec_connection_count(); /* Destroy THD object */ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 5035064b8e0..1156d85bf83 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -664,7 +664,7 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag) void *create_embedded_thd(int client_flag) { THD * thd= new THD; - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); thd->thread_stack= (char*) &thd; if (thd->store_globals()) diff --git a/mysql-test/r/connect2.result b/mysql-test/r/connect2.result new file mode 100644 index 00000000000..5e529db9376 --- /dev/null +++ b/mysql-test/r/connect2.result @@ -0,0 +1,45 @@ +SET @old_debug= @@session.debug; +set @old_thread_cache_size=@@global.thread_cache_size; +select 1; +1 +1 +set global debug_dbug='+d,simulate_failed_connection_1'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +ERROR HY000: Lost connection to MySQL server at 'reading initial communication packet', system error: 95 "Operation not supported" +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +ERROR HY000: Lost connection to MySQL server at 'reading initial communication packet', system error: 95 "Operation not supported" +set global debug_dbug=@old_debug; +select 1; +1 +1 +select 1; +1 +1 +set global debug_dbug='+d,simulate_failed_connection_1'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +ERROR HY000: Lost connection to MySQL server at 'reading initial communication packet', system error: 95 "Operation not supported" +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +ERROR HY000: Lost connection to MySQL server at 'reading initial communication packet', system error: 95 "Operation not supported" +set global debug_dbug=@old_debug; +select 1; +1 +1 +set @@global.thread_cache_size=2; +select 1; +1 +1 +select 1; +1 +1 +set global debug_dbug='+d,simulate_failed_connection_2'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +ERROR HY000: Lost connection to MySQL server at 'reading initial communication packet', system error: 95 "Operation not supported" +show status like "Threads_connected"; +Variable_name Value +Threads_connected 1 +set global debug_dbug=@old_debug; +set global thread_cache_size=@old_thread_cache_size; diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index ff5055e1ae4..b37ea359953 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -436,9 +436,9 @@ My own slow query sleep(2) My own slow query 0 SELECT * FROM mysql.slow_log WHERE seq >= 2 LIMIT 3; start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text thread_id rows_affected seq -START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 3 0 2 -START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 3 0 3 -START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 3 0 4 +START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 2 0 2 +START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 2 0 3 +START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 2 0 4 SET GLOBAL slow_query_log = 0; SET SESSION long_query_time =@saved_long_query_time; FLUSH LOGS; diff --git a/mysql-test/r/mdev375.result b/mysql-test/r/mdev375.result index 32580804686..426336e5939 100644 --- a/mysql-test/r/mdev375.result +++ b/mysql-test/r/mdev375.result @@ -10,5 +10,8 @@ ERROR HY000: Too many connections SELECT 0; 0 0 +show status like "Threads_connected"; +Variable_name Value +Threads_connected 3 SET GLOBAL log_warnings=default; SET GLOBAL max_connections=default; diff --git a/mysql-test/r/mysqlbinlog_row_minimal.result b/mysql-test/r/mysqlbinlog_row_minimal.result index 6ffaeeafc53..69b5a151d41 100644 --- a/mysql-test/r/mysqlbinlog_row_minimal.result +++ b/mysql-test/r/mysqlbinlog_row_minimal.result @@ -27,10 +27,10 @@ ROLLBACK/*!*/; /*!100001 SET @@session.server_id=1*//*!*/; /*!100001 SET @@session.gtid_seq_no=1*//*!*/; # at 352 -#<date> server id 1 end_log_pos 532 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 532 Query thread_id=3 exec_time=x error_code=0 use `test`/*!*/; SET TIMESTAMP=X/*!*/; -SET @@session.pseudo_thread_id=4/*!*/; +SET @@session.pseudo_thread_id=3/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; SET @@session.sql_mode=1342177280/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; @@ -44,7 +44,7 @@ CREATE TABLE t1 (pk INT PRIMARY KEY, f1 INT, f2 INT, f3 TINYINT, f4 MEDIUMINT, f #<date> server id 1 end_log_pos 570 GTID 0-1-2 ddl /*!100001 SET @@session.gtid_seq_no=2*//*!*/; # at 570 -#<date> server id 1 end_log_pos 743 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 743 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; CREATE TABLE t2 (pk INT PRIMARY KEY, f1 INT, f2 INT, f3 INT, f4 INT, f5 MEDIUMINT, f6 INT, f7 INT, f8 char(1)) /*!*/; @@ -69,7 +69,7 @@ BEGIN ### @8=7 /* INT meta=0 nullable=1 is_null=0 */ ### @9='' /* STRING(1) meta=65025 nullable=1 is_null=0 */ # at 898 -#<date> server id 1 end_log_pos 967 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 967 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -94,7 +94,7 @@ BEGIN ### @8=7 /* INT meta=0 nullable=1 is_null=0 */ ### @9=NULL /* STRING(1) meta=65025 nullable=1 is_null=1 */ # at 1121 -#<date> server id 1 end_log_pos 1190 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 1190 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -119,7 +119,7 @@ BEGIN ### @8=7 /* INT meta=0 nullable=1 is_null=0 */ ### @9='A' /* STRING(1) meta=65025 nullable=1 is_null=0 */ # at 1343 -#<date> server id 1 end_log_pos 1412 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 1412 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -144,7 +144,7 @@ BEGIN ### @8=7 /* INT meta=0 nullable=1 is_null=0 */ ### @9='A' /* STRING(1) meta=65025 nullable=1 is_null=0 */ # at 1568 -#<date> server id 1 end_log_pos 1637 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 1637 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -202,7 +202,7 @@ BEGIN ### @8=7 /* INT meta=0 nullable=1 is_null=0 */ ### @9='A' /* STRING(1) meta=65025 nullable=1 is_null=0 */ # at 1890 -#<date> server id 1 end_log_pos 1959 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 1959 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -234,7 +234,7 @@ BEGIN ### SET ### @5=5 /* INT meta=0 nullable=1 is_null=0 */ # at 2119 -#<date> server id 1 end_log_pos 2188 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 2188 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -260,7 +260,7 @@ BEGIN ### WHERE ### @1=13 /* INT meta=0 nullable=0 is_null=0 */ # at 2328 -#<date> server id 1 end_log_pos 2397 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 2397 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; @@ -286,7 +286,7 @@ BEGIN ### WHERE ### @1=13 /* INT meta=0 nullable=0 is_null=0 */ # at 2537 -#<date> server id 1 end_log_pos 2606 Query thread_id=4 exec_time=x error_code=0 +#<date> server id 1 end_log_pos 2606 Query thread_id=3 exec_time=x error_code=0 SET TIMESTAMP=X/*!*/; COMMIT /*!*/; diff --git a/mysql-test/suite/binlog/r/binlog_reset_master.result b/mysql-test/suite/binlog/r/binlog_reset_master.result deleted file mode 100644 index b3d605560ff..00000000000 --- a/mysql-test/suite/binlog/r/binlog_reset_master.result +++ /dev/null @@ -1 +0,0 @@ -RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_reset_master.test b/mysql-test/suite/binlog/t/binlog_reset_master.test deleted file mode 100644 index 33b549ad357..00000000000 --- a/mysql-test/suite/binlog/t/binlog_reset_master.test +++ /dev/null @@ -1,26 +0,0 @@ -# ==== Purpose ==== -# -# Test bugs in RESET MASTER. - ---source include/have_debug.inc ---source include/have_log_bin.inc - -####################################################################### -# BUG#12574820: binlog.binlog_tmp_table timing out in daily and weekly trunk run -# Problem: MYSQL_BIN_LOG::reset_logs acquired LOCK_thread_count and -# LOCK_log in the wrong order. This could cause a deadlock when -# RESET MASTER was run concurrently with a disconnecting thread. -####################################################################### - -# We use sleep, not debug_sync, because the sync point needs to be in -# the thread shut down code after the debug sync facility has been -# shut down. ---let $write_var= SET debug_dbug="+d,sleep_after_lock_thread_count_before_delete_thd"; CREATE TEMPORARY TABLE test.t1 (a INT); ---let $write_to_file= GENERATE ---disable_query_log ---source include/write_var_to_file.inc ---enable_query_log - ---exec $MYSQL < $write_to_file -RESET MASTER; ---remove_file $write_to_file diff --git a/mysql-test/t/connect2.cnf b/mysql-test/t/connect2.cnf new file mode 100644 index 00000000000..0acd221b871 --- /dev/null +++ b/mysql-test/t/connect2.cnf @@ -0,0 +1,9 @@ +!include include/default_my.cnf + +[mysqld.1] +extra-port= @ENV.MASTER_EXTRA_PORT +extra-max-connections=2 +thread_handling=pool-of-threads + +[ENV] +MASTER_EXTRA_PORT= @OPT.port diff --git a/mysql-test/t/connect2.test b/mysql-test/t/connect2.test new file mode 100644 index 00000000000..7427afaeffd --- /dev/null +++ b/mysql-test/t/connect2.test @@ -0,0 +1,81 @@ +# This test is to check various cases of connections, some which require +# DBUG + +# This test makes no sense with the embedded server +--source include/not_embedded.inc +--source include/have_debug.inc + +SET @old_debug= @@session.debug; +set @old_thread_cache_size=@@global.thread_cache_size; + +# Test connections to the + +connect(con1,localhost,root,,test,,); +select 1; +disconnect con1; +connection default; +set global debug_dbug='+d,simulate_failed_connection_1'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 2013 +connect(con1,localhost,root,,test,,); +connection default; +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 2013 +connect(con1,localhost,root,,test,,); +connection default; +set global debug_dbug=@old_debug; +connect(con1,localhost,root,,test,,); +select 1; +disconnect con1; + +# Test connections to the extra port. + +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +disconnect con1; +connection default; +set global debug_dbug='+d,simulate_failed_connection_1'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_EXTRA_PORT MASTER_PORT +--error 2013 +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +connection default; +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_EXTRA_PORT MASTER_PORT +--error 2013 +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +connection default; +set global debug_dbug=@old_debug; +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +disconnect con1; +connection default; + +# +# Test thread cache +# +set @@global.thread_cache_size=2; +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +connect(con2,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +disconnect con1; +disconnect con2; +connection default; +set global debug_dbug='+d,simulate_failed_connection_2'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_EXTRA_PORT MASTER_PORT +--error 2013 +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +connection default; + +# Check that threads_connected didn't count aborted connections +show status like "Threads_connected"; + +# +# Cleanup +# + +set global debug_dbug=@old_debug; +set global thread_cache_size=@old_thread_cache_size; diff --git a/mysql-test/t/mdev375.test b/mysql-test/t/mdev375.test index fe259b37808..92e403b6513 100644 --- a/mysql-test/t/mdev375.test +++ b/mysql-test/t/mdev375.test @@ -17,6 +17,7 @@ SELECT 2; --connection default SELECT 0; +show status like "Threads_connected"; SET GLOBAL log_warnings=default; SET GLOBAL max_connections=default; diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index d9bc0e9094e..188a8d0429e 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1068,7 +1068,7 @@ static void link_into_queue(KEYCACHE_WQUEUE *wqueue, static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, struct st_my_thread_var *thread) { - KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", (ulong) thread->id)); DBUG_ASSERT(thread->next && thread->prev); if (thread->next == thread) @@ -1145,7 +1145,7 @@ static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, */ do { - KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, mutex); } while (thread->next); @@ -1184,7 +1184,7 @@ static void release_whole_queue(KEYCACHE_WQUEUE *wqueue) thread=next; DBUG_ASSERT(thread && thread->init == 1); KEYCACHE_DBUG_PRINT("release_whole_queue: signal", - ("thread %ld", thread->id)); + ("thread %ld", (ulong) thread->id)); /* Take thread from queue. */ next= thread->next; thread->next= NULL; @@ -1388,7 +1388,8 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block, */ if ((HASH_LINK *) thread->keycache_link == hash_link) { - KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("link_block: signal", + ("thread %ld", (ulong) thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_block, thread); block->requests++; @@ -1677,7 +1678,7 @@ static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache, { KEYCACHE_DBUG_PRINT("wait_for_readers: wait", ("suspend thread %ld block %u", - thread->id, BLOCK_NUMBER(block))); + (ulong) thread->id, BLOCK_NUMBER(block))); /* There must be no other waiter. We have no queue here. */ DBUG_ASSERT(!block->condvar); block->condvar= &thread->suspend; @@ -1737,7 +1738,8 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link) */ if (page->file == hash_link->file && page->filepos == hash_link->diskpos) { - KEYCACHE_DBUG_PRINT("unlink_hash: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("unlink_hash: signal", + ("thread %ld", (ulong) thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_hash_link, thread); } @@ -1821,7 +1823,7 @@ restart: thread->keycache_link= (void *) &page; link_into_queue(&keycache->waiting_for_hash_link, thread); KEYCACHE_DBUG_PRINT("get_hash_link: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); thread->keycache_link= NULL; @@ -1987,7 +1989,7 @@ restart: do { KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } while (thread->next); @@ -2334,7 +2336,7 @@ restart: do { KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -4585,7 +4587,7 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) KEYCACHE_PAGE *page; uint i; - fprintf(keycache_dump_file, "thread:%u\n", thread->id); + fprintf(keycache_dump_file, "thread:%lu\n", (ulong) thread->id); i=0; thread=last=waiting_for_hash_link.last_thread; @@ -4596,8 +4598,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) thread=thread->next; page= (KEYCACHE_PAGE *) thread->keycache_link; fprintf(keycache_dump_file, - "thread:%u, (file,filepos)=(%u,%lu)\n", - thread->id,(uint) page->file,(ulong) page->filepos); + "thread:%lu, (file,filepos)=(%u,%lu)\n", + (ulong) thread->id,(uint) page->file,(ulong) page->filepos); if (++i == MAX_QUEUE_LEN) break; } @@ -4612,8 +4614,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) thread=thread->next; hash_link= (HASH_LINK *) thread->keycache_link; fprintf(keycache_dump_file, - "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n", - thread->id, (uint) HASH_LINK_NUMBER(hash_link), + "thread:%lu hash_link:%u (file,filepos)=(%u,%lu)\n", + (ulong) thread->id, (uint) HASH_LINK_NUMBER(hash_link), (uint) hash_link->file,(ulong) hash_link->diskpos); if (++i == MAX_QUEUE_LEN) break; @@ -4640,7 +4642,7 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) { thread=thread->next; fprintf(keycache_dump_file, - "thread:%u\n", thread->id); + "thread:%lu\n", (ulong) thread->id); if (++i == MAX_QUEUE_LEN) break; } diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 8990cbd5a14..da653b12314 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -772,7 +772,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) mysql_mutex_lock(&lock->mutex); DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", - (long) data, data->owner->thread_id, + (long) data, (ulong) data->owner->thread_id, (long) lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? "enter read_lock" : "enter write_lock", lock_type, 0); @@ -809,7 +809,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) */ DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", - lock->write.data->owner->thread_id)); + (ulong) lock->write.data->owner->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || @@ -968,7 +968,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) goto end; } DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx", - lock->write.data->owner->thread_id)); + (ulong) lock->write.data->owner->thread_id)); } else { @@ -1004,7 +1004,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) } } DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d", - lock->read.data->owner->thread_id, data->type)); + (ulong) lock->read.data->owner->thread_id, + data->type)); } #ifdef WITH_WSREP if (wsrep_break_lock(data, &lock->write, &lock->write_wait)) @@ -1069,7 +1070,7 @@ static inline void free_all_read_locks(THR_LOCK *lock, } /* purecov: begin inspected */ DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", - data->owner->thread_id)); + (ulong) data->owner->thread_id)); /* purecov: end */ data->cond=0; /* Mark thread free */ mysql_cond_signal(cond); @@ -1087,8 +1088,9 @@ void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags) THR_LOCK *lock=data->lock; enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); - DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) data, data->owner->thread_id, (long) lock)); + DBUG_PRINT("lock",("data: %p thread: 0x%lx lock: %p", + data, (ulong) data->owner->thread_id, + lock)); mysql_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock", lock_type, 0); @@ -1181,7 +1183,7 @@ static void wake_up_waiters(THR_LOCK *lock) data->type=TL_WRITE; /* Upgrade lock */ /* purecov: begin inspected */ DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", - data->type, data->owner->thread_id)); + data->type, (ulong) data->owner->thread_id)); /* purecov: end */ { mysql_cond_t *cond= data->cond; @@ -1423,9 +1425,9 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count, uint unlock_flags) thr_unlock(*pos, unlock_flags); else { - DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) *pos, (*pos)->owner->thread_id, - (long) (*pos)->lock)); + DBUG_PRINT("lock",("Free lock: data: %p thread: 0x%lx lock: %p", + *pos, (ulong) (*pos)->owner->thread_id, + (*pos)->lock)); } } DBUG_VOID_RETURN; @@ -1673,7 +1675,7 @@ static void thr_print_lock(const char* name,struct st_lock_list *list) prev= &list->data; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { - printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->thread_id, + printf("%p (%lu:%d); ", data, (ulong) data->owner->thread_id, (int) data->type); if (data->prev != prev) printf("\nWarning: prev didn't point at previous lock\n"); diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 4d6abd4ba66..f1e83db2bb6 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -510,7 +510,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex %s " "at %s, line %d\n", - mp->count-1, my_thread_dbug_id(), mp->name, file, line); + mp->count-1, (ulong) my_thread_dbug_id(), mp->name, file, line); fflush(stderr); abort(); } @@ -564,7 +564,7 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex " "%s at %s, line %d (error: %d (%d))\n", - mp->count-1, my_thread_dbug_id(), mp->name, file, line, + mp->count-1, (ulong) my_thread_dbug_id(), mp->name, file, line, error, error); fflush(stderr); abort(); diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 773ae887891..ebb5d3217ad 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -280,9 +280,7 @@ pthread_handler_t background_thread(void *arg __attribute__((unused))) if (my_thread_init()) return 0; - mysql_mutex_lock(&LOCK_thread_count); - thd_thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd_thread_id= next_thread_id(); if (slept_ok(startup_interval)) { diff --git a/plugin/handler_socket/handlersocket/database.cpp b/plugin/handler_socket/handlersocket/database.cpp index 8ea7b5061a1..cfed9c42c0a 100644 --- a/plugin/handler_socket/handlersocket/database.cpp +++ b/plugin/handler_socket/handlersocket/database.cpp @@ -308,11 +308,9 @@ dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag) DBG_THR(fprintf(stderr, "HNDSOCK x0 %p\n", thd)); } { - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = thread_id++; - threads.append(thd); - ++thread_count; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); + thread_safe_increment32(&thread_count); + add_to_active_threads(thd); } DBG_THR(fprintf(stderr, "HNDSOCK init thread wsts\n")); diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 95c5f6d9047..6a8bdabb948 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -135,9 +135,7 @@ post_init_event_thread(THD *thd) } thread_safe_increment32(&thread_count); - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); inc_thread_running(); return FALSE; } @@ -191,9 +189,7 @@ pre_init_event_thread(THD* thd) thd->net.read_timeout= slave_net_timeout; thd->variables.option_bits|= OPTION_AUTO_IS_NULL; thd->client_capabilities|= CLIENT_MULTI_RESULTS; - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); /* Guarantees that we will see the thread in SHOW PROCESSLIST though its @@ -479,7 +475,7 @@ Event_scheduler::run(THD *thd) DBUG_ENTER("Event_scheduler::run"); sql_print_information("Event Scheduler: scheduler thread started with id %lu", - thd->thread_id); + (ulong) thd->thread_id); /* Recalculate the values in the queue because there could have been stops in executions of the scheduler and some times could have passed by. @@ -669,13 +665,13 @@ Event_scheduler::stop() state= STOPPING; DBUG_PRINT("info", ("Scheduler thread has id %lu", - scheduler_thd->thread_id)); + (ulong) scheduler_thd->thread_id)); /* Lock from delete */ mysql_mutex_lock(&scheduler_thd->LOCK_thd_data); /* This will wake up the thread if it waits on Queue's conditional */ sql_print_information("Event Scheduler: Killing the scheduler thread, " "thread id %lu", - scheduler_thd->thread_id); + (ulong) scheduler_thd->thread_id); scheduler_thd->awake(KILL_CONNECTION); mysql_mutex_unlock(&scheduler_thd->LOCK_thd_data); @@ -832,7 +828,8 @@ Event_scheduler::dump_internal_status() puts(""); puts("Event scheduler status:"); printf("State : %s\n", scheduler_states_names[state].str); - printf("Thread id : %lu\n", scheduler_thd? scheduler_thd->thread_id : 0); + printf("Thread id : %lu\n", scheduler_thd ? + (ulong) scheduler_thd->thread_id : (ulong) 0); printf("LLA : %s:%u\n", mutex_last_locked_in_func, mutex_last_locked_at_line); printf("LUA : %s:%u\n", mutex_last_unlocked_in_func, diff --git a/sql/hostname.cc b/sql/hostname.cc index 6aef84f1b26..a84aebdf3c8 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -412,7 +412,7 @@ static inline bool is_hostname_valid(const char *hostname) int ip_to_hostname(struct sockaddr_storage *ip_storage, const char *ip_string, - char **hostname, + const char **hostname, uint *connect_errors) { const struct sockaddr *ip= (const sockaddr *) ip_storage; @@ -436,7 +436,7 @@ int ip_to_hostname(struct sockaddr_storage *ip_storage, DBUG_PRINT("info", ("Loopback address detected.")); /* Do not count connect errors from localhost. */ - *hostname= (char *) my_localhost; + *hostname= my_localhost; DBUG_RETURN(0); } diff --git a/sql/hostname.h b/sql/hostname.h index 81a1d0de88d..d6137b7c260 100644 --- a/sql/hostname.h +++ b/sql/hostname.h @@ -168,7 +168,7 @@ extern ulong host_cache_size; #define RC_BLOCKED_HOST 1 int ip_to_hostname(struct sockaddr_storage *ip_storage, const char *ip_string, - char **hostname, uint *connect_errors); + const char **hostname, uint *connect_errors); void inc_host_errors(const char *ip_string, Host_errors *errors); void reset_host_connect_errors(const char *ip_string); diff --git a/sql/log.cc b/sql/log.cc index 79eb9accdff..a3321a81018 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6582,7 +6582,6 @@ int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate) DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge"); bool check_purge= false; - //todo: fix the macro def and restore safe_mutex_assert_not_owner(&LOCK_log); mysql_mutex_lock(&LOCK_log); prev_binlog_id= current_binlog_id; if ((error= rotate(force_rotate, &check_purge))) @@ -9508,9 +9507,7 @@ binlog_background_thread(void *arg __attribute__((unused))) thd= new THD; thd->system_thread= SYSTEM_THREAD_BINLOG_BACKGROUND; thd->thread_stack= (char*) &thd; /* Set approximate stack start */ - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= next_thread_id(); thd->store_globals(); thd->security_ctx->skip_grants(); thd->set_command(COM_DAEMON); @@ -9597,9 +9594,8 @@ binlog_background_thread(void *arg __attribute__((unused))) THD_STAGE_INFO(thd, stage_binlog_stopping_background_thread); - mysql_mutex_lock(&LOCK_thread_count); + /* No need to use mutex as thd is not linked into other threads */ delete thd; - mysql_mutex_unlock(&LOCK_thread_count); my_thread_end(); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c2da0a6e542..45d25ac3bf5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -377,7 +377,7 @@ static char *default_collation_name; char *default_storage_engine, *default_tmp_storage_engine; char *enforced_storage_engine=NULL; static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME; -static I_List<THD> thread_cache; +static I_List<CONNECT> thread_cache; static bool binlog_format_used= false; LEX_STRING opt_init_connect, opt_init_slave; mysql_cond_t COND_thread_cache; @@ -409,8 +409,7 @@ uint volatile global_disable_checkpoint; ulong slow_start_timeout; #endif /* - True if the bootstrap thread is running. Protected by LOCK_thread_count, - just like thread_count. + True if the bootstrap thread is running. Protected by LOCK_start_thread. Used in bootstrap() function to determine if the bootstrap thread has completed. Note, that we can't use 'thread_count' instead, since in 5.1, in presence of the Event Scheduler, there may be @@ -422,7 +421,7 @@ ulong slow_start_timeout; bootstrap either, since we want to be able to process event-related SQL commands in the init file and in --bootstrap mode. */ -bool in_bootstrap= FALSE; +bool volatile in_bootstrap= FALSE; /** @brief 'grant_option' is used to indicate if privileges needs to be checked, in which case the lock, LOCK_grant, is used @@ -556,7 +555,8 @@ ulong max_prepared_stmt_count; statements. */ ulong prepared_stmt_count=0; -ulong thread_id=1L,current_pid; +my_thread_id global_thread_id= 0; +ulong current_pid; ulong slow_launch_threads = 0; uint sync_binlog_period= 0, sync_relaylog_period= 0, sync_relayloginfo_period= 0, sync_masterinfo_period= 0; @@ -712,7 +712,33 @@ SHOW_COMP_OPTION have_openssl; /* Thread specific variables */ pthread_key(THD*, THR_THD); -mysql_mutex_t LOCK_thread_count, LOCK_thread_cache; + +/* + LOCK_thread_count protects the following variables: + thread_count Number of threads with THD that servers queries. + threads Linked list of active THD's. + The effect of this is that one can't unlink and + delete a THD as long as one has locked + LOCK_thread_count. + ready_to_exit + delayed_insert_threads +*/ +mysql_mutex_t LOCK_thread_count; + +/* + LOCK_start_thread is used to syncronize thread start and stop with + other threads. + + It also protects these variables: + handler_count + in_bootstrap + select_thread_in_use + slave_init_thread_running + check_temp_dir() call +*/ +mysql_mutex_t LOCK_start_thread; + +mysql_mutex_t LOCK_thread_cache; mysql_mutex_t LOCK_status, LOCK_show_status, LOCK_error_log, LOCK_short_uuid_generator, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, @@ -737,7 +763,7 @@ mysql_mutex_t LOCK_des_key_file; #endif mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; mysql_rwlock_t LOCK_system_variables_hash; -mysql_cond_t COND_thread_count; +mysql_cond_t COND_thread_count, COND_start_thread; pthread_t signal_thread; pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; @@ -887,6 +913,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages, key_LOG_INFO_lock, + key_LOCK_start_thread, key_LOCK_thread_count, key_LOCK_thread_cache, key_PARTITION_LOCK_auto_inc; PSI_mutex_key key_RELAYLOG_LOCK_index; @@ -973,6 +1000,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL}, { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}, { &key_LOCK_slave_state, "LOCK_slave_state", 0}, + { &key_LOCK_start_thread, "LOCK_start_thread", PSI_FLAG_GLOBAL}, { &key_LOCK_binlog_state, "LOCK_binlog_state", 0}, { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0}, { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0}, @@ -1014,6 +1042,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, + key_COND_start_thread, key_BINLOG_COND_queue_busy; PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, key_COND_wait_commit; @@ -1073,6 +1102,7 @@ static PSI_cond_info all_server_conds[]= { &key_COND_group_commit_orderer, "COND_group_commit_orderer", 0}, { &key_COND_prepare_ordered, "COND_prepare_ordered", 0}, { &key_COND_slave_init, "COND_slave_init", 0}, + { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL}, { &key_COND_wait_gtid, "COND_wait_gtid", 0}, { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0} }; @@ -1199,8 +1229,13 @@ void init_net_server_extension(THD *thd) /* Activate this private extension for the mysqld server. */ thd->net.extension= & thd->m_net_server_extension; } +#else +void init_net_server_extension(THD *thd) +{ +} #endif /* EMBEDDED_LIBRARY */ + /** A log message for the error log, buffered in memory. Log messages are temporarily buffered when generated before the error log @@ -1545,8 +1580,8 @@ static void close_connections(void) #if !defined(__WIN__) DBUG_PRINT("quit", ("waiting for select thread: 0x%lx", (ulong) select_thread)); - mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_start_thread); while (select_thread_in_use) { struct timespec abstime; @@ -1560,7 +1595,7 @@ static void close_connections(void) set_timespec(abstime, 2); for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++) { - error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count, + error= mysql_cond_timedwait(&COND_start_thread, &LOCK_start_thread, &abstime); if (error != EINTR) break; @@ -1571,7 +1606,7 @@ static void close_connections(void) #endif close_server_sock(); } - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_start_thread); #endif /* __WIN__ */ @@ -1640,7 +1675,7 @@ static void close_connections(void) while ((tmp=it++)) { DBUG_PRINT("quit",("Informing thread %ld that it's time to die", - tmp->thread_id)); + (ulong) tmp->thread_id)); /* We skip slave threads & scheduler on this first loop through. */ if (tmp->slave_thread) continue; @@ -1696,6 +1731,8 @@ static void close_connections(void) much smaller than even 2 seconds, this is only a safety fallback against stuck threads so server shutdown is not held up forever. */ + DBUG_PRINT("info", ("thread_count: %d", thread_count)); + for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++) my_sleep(20000); @@ -1707,11 +1744,9 @@ static void close_connections(void) for (;;) { - DBUG_PRINT("quit",("Locking LOCK_thread_count")); mysql_mutex_lock(&LOCK_thread_count); // For unlink from list if (!(tmp=threads.get())) { - DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); mysql_mutex_unlock(&LOCK_thread_count); break; } @@ -1720,12 +1755,13 @@ static void close_connections(void) { if (global_system_variables.log_warnings) sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname, - tmp->thread_id, + (ulong) tmp->thread_id, (tmp->main_security_ctx.user ? tmp->main_security_ctx.user : "")); close_connection(tmp,ER_SERVER_SHUTDOWN); } #endif + #ifdef WITH_WSREP /* * WSREP_TODO: @@ -1992,7 +2028,8 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused))) extern "C" sig_handler print_signal_warning(int sig) { if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id()); + sql_print_warning("Got signal %d from thread %ld", sig, + (ulong) my_thread_id()); #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif @@ -2207,10 +2244,14 @@ void clean_up(bool print_message) logger.cleanup_end(); sys_var_end(); free_charsets(); + + /* + Signal mysqld_main() that it can exit + do the broadcast inside the lock to ensure that my_end() is not called + during broadcast() + */ mysql_mutex_lock(&LOCK_thread_count); - DBUG_PRINT("quit", ("got thread count lock")); ready_to_exit=1; - /* do the broadcast inside the lock to ensure that my_end() is not called */ mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); @@ -2258,6 +2299,7 @@ static void clean_up_mutexes() mysql_rwlock_destroy(&LOCK_grant); mysql_mutex_destroy(&LOCK_thread_count); mysql_mutex_destroy(&LOCK_thread_cache); + mysql_mutex_destroy(&LOCK_start_thread); mysql_mutex_destroy(&LOCK_status); mysql_mutex_destroy(&LOCK_show_status); mysql_mutex_destroy(&LOCK_delayed_insert); @@ -2291,6 +2333,7 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_error_messages); mysql_cond_destroy(&COND_thread_count); mysql_cond_destroy(&COND_thread_cache); + mysql_cond_destroy(&COND_start_thread); mysql_cond_destroy(&COND_flush_thread_cache); mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); @@ -2312,7 +2355,9 @@ static void clean_up_mutexes() static void set_ports() { } - +void close_connection(THD *thd, uint sql_errno) +{ +} #else static void set_ports() { @@ -2794,6 +2839,7 @@ static void network_init(void) @note For the connection that is doing shutdown, this is called twice */ + void close_connection(THD *thd, uint sql_errno) { DBUG_ENTER("close_connection"); @@ -2829,20 +2875,6 @@ extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused))) DBUG_VOID_RETURN; /* purecov: deadcode */ } - -/* - Cleanup THD object - - SYNOPSIS - thd_cleanup() - thd Thread handler -*/ - -void thd_cleanup(THD *thd) -{ - thd->cleanup(); -} - /* Decrease number of connections @@ -2850,43 +2882,49 @@ void thd_cleanup(THD *thd) dec_connection_count() */ -void dec_connection_count(THD *thd) +void dec_connection_count(scheduler_functions *scheduler) { -#ifdef WITH_WSREP - /* - Do not decrement when its wsrep system thread. wsrep_applier is set for - applier as well as rollbacker threads. - */ - if (thd->wsrep_applier) - return; -#endif /* WITH_WSREP */ - - DBUG_ASSERT(*thd->scheduler->connection_count > 0); mysql_mutex_lock(&LOCK_connection_count); - (*thd->scheduler->connection_count)--; + (*scheduler->connection_count)--; mysql_mutex_unlock(&LOCK_connection_count); } /* Delete THD and decrement thread counters, including thread_running + + This is mainly used to delete event threads which are not increasing + global counters. */ void delete_running_thd(THD *thd) { - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); - mysql_mutex_unlock(&LOCK_thread_count); + thd->add_status_to_global(); + unlink_not_visible_thd(thd); delete thd; dec_thread_running(); + dec_thread_count(); +} + +/* + Decrease number of threads. Signal when it reaches 0 + + SYNOPSIS + dec_thread_count() +*/ + +void dec_thread_count(void) +{ + DBUG_ASSERT(thread_count > 0); thread_safe_decrement32(&thread_count); signal_thd_deleted(); } + /* - Send a signal to unblock close_conneciton() if there is no more - threads running with a THD attached + Send a signal to unblock close_conneciton() / rpl_slave_init_thread() + if there is no more threads running with a THD attached It's safe to check for thread_count and service_thread_count outside of a mutex as we are only interested to see if they where decremented @@ -2898,7 +2936,7 @@ void delete_running_thd(THD *thd) void signal_thd_deleted() { - if (!thread_count && ! service_thread_count) + if (!thread_count && !service_thread_count) { /* Signal close_connections() that all THD's are freed */ mysql_mutex_lock(&LOCK_thread_count); @@ -2914,9 +2952,6 @@ void signal_thd_deleted() SYNOPSIS unlink_thd() thd Thread handler - - NOTES - LOCK_thread_count is locked and left locked */ void unlink_thd(THD *thd) @@ -2924,23 +2959,18 @@ void unlink_thd(THD *thd) DBUG_ENTER("unlink_thd"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); - thd_cleanup(thd); - dec_connection_count(thd); - - thd->add_status_to_global(); - - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); /* - Used by binlog_reset_master. It would be cleaner to use - DEBUG_SYNC here, but that's not possible because the THD's debug - sync feature has been shut down at this point. + Do not decrement when its wsrep system thread. wsrep_applier is set for + applier as well as rollbacker threads. */ - DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5);); - mysql_mutex_unlock(&LOCK_thread_count); + if (IF_WSREP(!thd->wsrep_applier, 1)) + dec_connection_count(thd->scheduler); + thd->cleanup(); + thd->add_status_to_global(); + unlink_not_visible_thd(thd); delete thd; - thread_safe_decrement32(&thread_count); + dec_thread_count(); DBUG_VOID_RETURN; } @@ -2989,11 +3019,21 @@ static bool cache_thread() mysql_cond_signal(&COND_flush_thread_cache); if (wake_thread) { + CONNECT *connect; THD *thd; + wake_thread--; - thd= thread_cache.get(); + connect= thread_cache.get(); mysql_mutex_unlock(&LOCK_thread_cache); + if (!(thd= connect->create_thd())) + { + /* Out of resources. Free thread to get more resources */ + connect->close_and_delete(); + DBUG_RETURN(0); + } + delete connect; + thd->thread_stack= (char*) &thd; // For store_globals (void) thd->store_globals(); @@ -3016,10 +3056,7 @@ static bool cache_thread() thd->thr_create_utime= microsecond_interval_timer(); thd->start_utime= thd->thr_create_utime; - /* Link thd into list of all active threads (THD's) */ - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); DBUG_RETURN(1); } } @@ -3033,7 +3070,7 @@ static bool cache_thread() SYNOPSIS one_thread_per_connection_end() - thd Thread handler + thd Thread handler. This may be null if we run out of resources. put_in_cache Store thread in cache, if there is room in it Normally this is true in all cases except when we got out of resources initializing the current thread @@ -3052,12 +3089,13 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) DBUG_ENTER("one_thread_per_connection_end"); const bool wsrep_applier= IF_WSREP(thd->wsrep_applier, false); - unlink_thd(thd); + if (thd) + unlink_thd(thd); if (!wsrep_applier && put_in_cache && cache_thread()) DBUG_RETURN(0); // Thread is reused - signal_thd_deleted(); + DBUG_PRINT("info", ("killing thread")); DBUG_LEAVE; // Must match DBUG_ENTER() #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) ERR_remove_state(0); @@ -3425,7 +3463,7 @@ static void start_signal_handler(void) (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); (void) my_setstacksize(&thr_attr,my_thread_stack_size); - mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_start_thread); if ((error= mysql_thread_create(key_thread_signal_hand, &signal_thread, &thr_attr, signal_hand, 0))) { @@ -3433,8 +3471,8 @@ static void start_signal_handler(void) error,errno); exit(1); } - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_start_thread, &LOCK_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); (void) pthread_attr_destroy(&thr_attr); DBUG_VOID_RETURN; @@ -3484,12 +3522,12 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) signal to start_signal_handler that we are ready This works by waiting for start_signal_handler to free mutex, after which we signal it that we are ready. - At this pointer there is no other threads running, so there + At this point there is no other threads running, so there should not be any other mysql_cond_signal() calls. */ - mysql_mutex_lock(&LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_lock(&LOCK_start_thread); + mysql_cond_broadcast(&COND_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); (void) pthread_sigmask(SIG_BLOCK,&set,NULL); for (;;) @@ -4124,7 +4162,7 @@ static int init_common_variables() sf_malloc_dbug_id= mariadb_dbug_id; #endif - max_system_variables.pseudo_thread_id= (ulong)~0; + max_system_variables.pseudo_thread_id= ~(my_thread_id) 0; server_start_time= flush_status_time= my_time(0); global_rpl_filter= new Rpl_filter; @@ -4637,6 +4675,7 @@ 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_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_start_thread, &LOCK_start_thread, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_show_status, &LOCK_show_status, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_LOCK_delayed_insert, @@ -4699,6 +4738,7 @@ static int init_thread_environment() mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant); mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL); mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL); + mysql_cond_init(key_COND_start_thread, &COND_start_thread, NULL); mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL); #ifdef HAVE_REPLICATION mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST); @@ -5465,7 +5505,7 @@ static void handle_connections_methods() unireg_abort(1); // Will not return } - mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_start); mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL); handler_count=0; if (hPipe != INVALID_HANDLE_VALUE) @@ -5508,17 +5548,17 @@ static void handle_connections_methods() #endif while (handler_count > 0) - mysql_cond_wait(&COND_handler_count, &LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_handler_count, &LOCK_thread_start); + mysql_mutex_unlock(&LOCK_thread_start); DBUG_VOID_RETURN; } void decrement_handler_count() { - mysql_mutex_lock(&LOCK_thread_count); - handler_count--; - mysql_cond_signal(&COND_handler_count); - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_start); + if (--handler_count == 0) + mysql_cond_signal(&COND_handler_count); + mysql_mutex_unlock(&LOCK_thread_start); my_thread_end(); } #else @@ -5985,18 +6025,10 @@ int mysqld_main(int argc, char **argv) DBUG_PRINT("quit",("Exiting main thread")); #ifndef __WIN__ -#ifdef EXTRA_DEBUG2 - sql_print_error("Before Lock_thread_count"); -#endif - WSREP_DEBUG("Before Lock_thread_count"); - mysql_mutex_lock(&LOCK_thread_count); - DBUG_PRINT("quit", ("Got thread_count mutex")); + mysql_mutex_lock(&LOCK_start_thread); select_thread_in_use=0; // For close_connections - mysql_mutex_unlock(&LOCK_thread_count); - mysql_cond_broadcast(&COND_thread_count); -#ifdef EXTRA_DEBUG2 - sql_print_error("After lock_thread_count"); -#endif + mysql_cond_broadcast(&COND_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); #endif /* __WIN__ */ #ifdef HAVE_PSI_THREAD_INTERFACE @@ -6261,7 +6293,7 @@ static void bootstrap(MYSQL_FILE *file) my_net_init(&thd->net,(st_vio*) 0, (void*) 0, MYF(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++; + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); thread_count++; // Safe as only one thread running in_bootstrap= TRUE; @@ -6281,10 +6313,7 @@ static void bootstrap(MYSQL_FILE *file) /* Wait for thread to die */ mysql_mutex_lock(&LOCK_thread_count); while (in_bootstrap) - { mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); - } mysql_mutex_unlock(&LOCK_thread_count); #else thd->mysql= 0; @@ -6314,7 +6343,7 @@ static bool read_init_file(char *file_name) */ void inc_thread_created(void) { - thread_created++; + statistic_increment(thread_created, &LOCK_status); } #ifndef EMBEDDED_LIBRARY @@ -6325,18 +6354,12 @@ void inc_thread_created(void) NOTES This is only used for debugging, when starting mysqld with --thread-handling=no-threads or --one-thread - - When we enter this function, LOCK_thread_count is hold! */ -void handle_connection_in_main_thread(THD *thd) +void handle_connection_in_main_thread(CONNECT *connect) { - mysql_mutex_assert_owner(&LOCK_thread_count); - thread_cache_size=0; // Safety - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); - thd->start_utime= microsecond_interval_timer(); - do_handle_one_connection(thd); + thread_cache_size= 0; // Safety + do_handle_one_connection(connect); } @@ -6344,10 +6367,11 @@ void handle_connection_in_main_thread(THD *thd) Scheduler that uses one thread per connection */ -void create_thread_to_handle_connection(THD *thd) +void create_thread_to_handle_connection(CONNECT *connect) { + char error_message_buff[MYSQL_ERRMSG_SIZE]; + int error; DBUG_ENTER("create_thread_to_handle_connection"); - mysql_mutex_assert_owner(&LOCK_thread_count); /* Check if we can get thread from the cache */ if (cached_thread_count > wake_thread) @@ -6356,9 +6380,8 @@ void create_thread_to_handle_connection(THD *thd) /* Recheck condition when we have the lock */ if (cached_thread_count > wake_thread) { - mysql_mutex_unlock(&LOCK_thread_count); /* Get thread from cache */ - thread_cache.push_back(thd); + thread_cache.push_back(connect); wake_thread++; mysql_cond_signal(&COND_thread_cache); mysql_mutex_unlock(&LOCK_thread_cache); @@ -6368,46 +6391,33 @@ void create_thread_to_handle_connection(THD *thd) mysql_mutex_unlock(&LOCK_thread_cache); } - char error_message_buff[MYSQL_ERRMSG_SIZE]; /* Create new thread to handle connection */ - int error; - thread_created++; - threads.append(thd); - DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id)); - thd->prior_thr_create_utime= microsecond_interval_timer(); + inc_thread_created(); + DBUG_PRINT("info",(("creating thread %lu"), (ulong) connect->thread_id)); + connect->prior_thr_create_utime= microsecond_interval_timer(); + if ((error= mysql_thread_create(key_thread_one_connection, - &thd->real_id, &connection_attrib, + &connect->real_id, &connection_attrib, handle_one_connection, - (void*) thd))) + (void*) connect))) { /* purecov: begin inspected */ DBUG_PRINT("error", ("Can't create thread to handle request (error %d)", error)); - thd->killed= KILL_CONNECTION; // Safety - mysql_mutex_unlock(&LOCK_thread_count); - - mysql_mutex_lock(&LOCK_connection_count); - (*thd->scheduler->connection_count)--; - mysql_mutex_unlock(&LOCK_connection_count); - + dec_connection_count(connect->scheduler); statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); - /* Can't use my_error() since store_globals has not been called. */ my_snprintf(error_message_buff, sizeof(error_message_buff), - ER_THD(thd, ER_CANT_CREATE_THREAD), error); - net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); - close_connection(thd, ER_OUT_OF_RESOURCES); - - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); - mysql_mutex_unlock(&LOCK_thread_count); - delete thd; - thread_safe_decrement32(&thread_count); - return; + ER_DEFAULT(ER_CANT_CREATE_THREAD), error); + connect->close_with_error(ER_CANT_CREATE_THREAD, + error_message_buff, + ER_OUT_OF_RESOURCES); + /* thread_count was incremented in create_new_thread() */ + dec_thread_count(); + DBUG_VOID_RETURN; /* purecov: end */ } - mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("Thread created")); DBUG_VOID_RETURN; } @@ -6426,7 +6436,7 @@ void create_thread_to_handle_connection(THD *thd) @param[in,out] thd Thread handle of future thread. */ -static void create_new_thread(THD *thd) +static void create_new_thread(CONNECT *connect) { DBUG_ENTER("create_new_thread"); @@ -6437,20 +6447,19 @@ static void create_new_thread(THD *thd) mysql_mutex_lock(&LOCK_connection_count); - if (*thd->scheduler->connection_count >= - *thd->scheduler->max_connections + 1|| abort_loop) + if (*connect->scheduler->connection_count >= + *connect->scheduler->max_connections + 1|| abort_loop) { - mysql_mutex_unlock(&LOCK_connection_count); - DBUG_PRINT("error",("Too many connections")); - close_connection(thd, ER_CON_COUNT_ERROR); + + mysql_mutex_unlock(&LOCK_connection_count); statistic_increment(denied_connections, &LOCK_status); - delete thd; statistic_increment(connection_errors_max_connection, &LOCK_status); + connect->close_with_error(0, NullS, ER_CON_COUNT_ERROR); DBUG_VOID_RETURN; } - ++*thd->scheduler->connection_count; + ++*connect->scheduler->connection_count; if (connection_count + extra_connection_count > max_used_connections) max_used_connections= connection_count + extra_connection_count; @@ -6458,17 +6467,15 @@ static void create_new_thread(THD *thd) mysql_mutex_unlock(&LOCK_connection_count); thread_safe_increment32(&thread_count); + connect->thread_count_incremented= 1; - /* Start a new thread to handle connection. */ - mysql_mutex_lock(&LOCK_thread_count); /* The initialization of thread_id is done in create_embedded_thd() for the embedded library. TODO: refactor this to avoid code duplication there */ - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - - MYSQL_CALLBACK(thd->scheduler, add_connection, (thd)); + connect->thread_id= next_thread_id(); + connect->scheduler->add_connection(connect); DBUG_VOID_RETURN; } @@ -6503,13 +6510,12 @@ void handle_connections_sockets() MYSQL_SOCKET sock= mysql_socket_invalid(); MYSQL_SOCKET new_sock= mysql_socket_invalid(); uint error_count=0; - THD *thd; + CONNECT *connect; struct sockaddr_storage cAddr; int ip_flags __attribute__((unused))=0; int socket_flags __attribute__((unused))= 0; int extra_ip_flags __attribute__((unused))=0; int flags=0,retval; - st_vio *vio_tmp; bool is_unix_sock; #ifdef HAVE_POLL int socket_count= 0; @@ -6708,58 +6714,43 @@ void handle_connections_sockets() } #endif /* HAVE_LIBWRAP */ - /* - ** Don't allow too many connections - */ + DBUG_PRINT("info", ("Creating CONNECT for new connection")); - DBUG_PRINT("info", ("Creating THD for new connection")); - if (!(thd= new THD)) + if ((connect= new CONNECT())) { - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); - statistic_increment(connection_errors_internal, &LOCK_status); - continue; - } - /* Set to get io buffers to be part of THD */ - set_current_thd(thd); - - is_unix_sock= (mysql_socket_getfd(sock) == - mysql_socket_getfd(unix_sock)); + is_unix_sock= (mysql_socket_getfd(sock) == + mysql_socket_getfd(unix_sock)); - if (!(vio_tmp= - mysql_socket_vio_new(new_sock, - is_unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, - is_unix_sock ? VIO_LOCALHOST: 0)) || - my_net_init(&thd->net, vio_tmp, thd, MYF(MY_THREAD_SPECIFIC))) - { - /* - Only delete the temporary vio if we didn't already attach it to the - NET object. The destructor in THD will delete any initialized net - structure. - */ - if (vio_tmp && thd->net.vio != vio_tmp) - vio_delete(vio_tmp); - else + if (!(connect->vio= + mysql_socket_vio_new(new_sock, + is_unix_sock ? VIO_TYPE_SOCKET : + VIO_TYPE_TCPIP, + is_unix_sock ? VIO_LOCALHOST: 0))) { - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); + delete connect; + connect= 0; // Error handling below } - delete thd; + } + + if (!connect) + { + /* Connect failure */ + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_close(new_sock); + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); continue; } - init_net_server_extension(thd); if (is_unix_sock) - thd->security_ctx->host=(char*) my_localhost; + connect->host= my_localhost; if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) { - thd->extra_port= 1; - thd->scheduler= extra_thread_scheduler; + connect->extra_port= 1; + connect->scheduler= extra_thread_scheduler; } - create_new_thread(thd); - set_current_thd(0); + create_new_thread(connect); } sd_notify(0, "STOPPING=1\n" "STATUS=Shutdown in progress"); @@ -6780,7 +6771,6 @@ pthread_handler_t handle_connections_namedpipes(void *arg) { HANDLE hConnectedPipe; OVERLAPPED connectOverlapped= {0}; - THD *thd; my_thread_init(); DBUG_ENTER("handle_connections_namedpipes"); connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); @@ -6849,24 +6839,18 @@ pthread_handler_t handle_connections_namedpipes(void *arg) continue; // We have to try again } - if (!(thd = new THD)) + if (!(connect= new CONNECT) || + !(connect->vio= vio_new_win32pipe(hConnectedPipe))) { DisconnectNamedPipe(hConnectedPipe); CloseHandle(hConnectedPipe); + delete connect; + statistic_increment(aborted_connects,&LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); continue; } - set_current_thd(thd); - if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || - my_net_init(&thd->net, thd->net.vio, thd, MYF(MY_THREAD_SPECIFIC))) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - delete thd; - continue; - } - /* Host is unknown */ - thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); - create_new_thread(thd); - set_current_thd(0); + connect->host= my_localhost; + create_new_thread(connect); } CloseHandle(connectOverlapped.hEvent); DBUG_LEAVE; @@ -6903,7 +6887,8 @@ pthread_handler_t handle_connections_shared_memory(void *arg) /* get enough space base-name + '_' + longest suffix we might ever send */ - if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE)))) + if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, + MYF(MY_FAE)))) goto error; if (my_security_attr_create(&sa_event, &errmsg, @@ -6969,7 +6954,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) HANDLE event_server_wrote= 0; HANDLE event_server_read= 0; HANDLE event_conn_closed= 0; - THD *thd= 0; + CONNECT *connect= 0; p= int10_to_str(connect_number, connect_number_char, 10); /* @@ -7031,8 +7016,13 @@ pthread_handler_t handle_connections_shared_memory(void *arg) } if (abort_loop) goto errorconn; - if (!(thd= new THD)) + + if (!(connect= new CONNECT)) + { + errmsg= "Could not create CONNECT object"; goto errorconn; + } + /* Send number of connection to client */ int4store(handle_connect_map, connect_number); if (!SetEvent(event_connect_answer)) @@ -7046,24 +7036,20 @@ 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, + if (!(connect->vio= vio_new_win32shared_memory(handle_client_file_map, handle_client_map, event_client_wrote, event_client_read, event_server_wrote, event_server_read, - event_conn_closed)) || - my_net_init(&thd->net, thd->net.vio, thd, MYF(MY_THREAD_SPECIFIC))) + event_conn_closed))) { - close_connection(thd, ER_OUT_OF_RESOURCES); - errmsg= 0; + errmsg= "Could not create VIO object"; goto errorconn; } - thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ - create_new_thread(thd); + connect->host= my_localhost; /* Host is unknown */ + create_new_thread(connect); connect_number++; - set_current_thd(thd); continue; errorconn: @@ -7089,9 +7075,11 @@ errorconn: CloseHandle(event_client_read); if (event_conn_closed) CloseHandle(event_conn_closed); - delete thd; + + delete connect; + statistic_increment(aborted_connects,&LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); } - set_current_thd(0); /* End shared memory handling */ error: @@ -8383,7 +8371,7 @@ SHOW_VAR status_vars[]= { {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, {"Com", (char*) com_status_vars, SHOW_ARRAY}, {"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC}, - {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, + {"Connections", (char*) &global_thread_id, SHOW_LONG_NOFLUSH}, {"Connection_errors_accept", (char*) &connection_errors_accept, SHOW_LONG}, {"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG}, {"Connection_errors_max_connections", (char*) &connection_errors_max_connection, SHOW_LONG}, @@ -8763,7 +8751,8 @@ static int mysql_init_variables(void) what_to_log= ~ (1L << (uint) COM_TIME); denied_connections= 0; executed_events= 0; - global_query_id= thread_id= 1L; + global_query_id= 1; + global_thread_id= 0; strmov(server_version, MYSQL_SERVER_VERSION); threads.empty(); thread_cache.empty(); diff --git a/sql/mysqld.h b/sql/mysqld.h index 4e6f2fcd29d..84920df7095 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -30,6 +30,7 @@ #include "my_rdtsc.h" class THD; +class CONNECT; struct handlerton; class Time_zone; @@ -81,8 +82,8 @@ enum enum_slave_parallel_mode { /* Function prototypes */ void kill_mysql(THD *thd= 0); void close_connection(THD *thd, uint sql_errno= 0); -void handle_connection_in_main_thread(THD *thd); -void create_thread_to_handle_connection(THD *thd); +void handle_connection_in_main_thread(CONNECT *thd); +void create_thread_to_handle_connection(CONNECT *connect); void delete_running_thd(THD *thd); void signal_thd_deleted(); void unlink_thd(THD *thd); @@ -90,6 +91,8 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache); void flush_thread_cache(); void refresh_status(THD *thd); bool is_secure_file_path(char *path); +void dec_connection_count(scheduler_functions *scheduler); +extern void init_net_server_extension(THD *thd); extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ; @@ -117,7 +120,7 @@ extern bool opt_skip_name_resolve; extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop; -extern bool in_bootstrap; +extern bool volatile in_bootstrap; extern uint connection_count; extern my_bool opt_safe_user_create; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; @@ -177,7 +180,7 @@ extern char log_error_file[FN_REFLEN], *opt_tc_log_file; extern const double log_10[309]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; -extern ulong thread_id; +extern my_thread_id global_thread_id; extern ulong binlog_cache_use, binlog_cache_disk_use; extern ulong binlog_stmt_cache_use, binlog_stmt_cache_disk_use; extern ulong aborted_threads,aborted_connects; @@ -292,6 +295,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, key_rpl_group_info_sleep_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, + key_LOCK_start_thread, key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc; extern PSI_mutex_key key_RELAYLOG_LOCK_index; extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, @@ -323,6 +327,7 @@ extern PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_relay_log_info_start_cond, key_relay_log_info_stop_cond, key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, + key_COND_start_thread, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache; extern PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, key_COND_wait_commit; @@ -558,6 +563,7 @@ extern mysql_mutex_t LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count, LOCK_slave_init; extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thread_count; +extern mysql_mutex_t LOCK_start_thread; #ifdef HAVE_OPENSSL extern char* des_key_file; extern mysql_mutex_t LOCK_des_key_file; @@ -566,7 +572,7 @@ extern mysql_mutex_t LOCK_server_started; extern mysql_cond_t COND_server_started; extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern mysql_rwlock_t LOCK_system_variables_hash; -extern mysql_cond_t COND_thread_count; +extern mysql_cond_t COND_thread_count, COND_start_thread; extern mysql_cond_t COND_manager; extern mysql_cond_t COND_slave_init; extern int32 thread_running; @@ -698,6 +704,16 @@ inline query_id_t get_query_id() return my_atomic_load64_explicit(&global_query_id, MY_MEMORY_ORDER_RELAXED); } +/* increment global_thread_id and return it. */ +inline __attribute__((warn_unused_result)) my_thread_id next_thread_id() +{ + return my_atomic_add32_explicit(&global_thread_id, 1, MY_MEMORY_ORDER_RELAXED); +} + +#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32) +extern my_thread_id next_thread_id_noinline(); +#define next_thread_id() next_thread_id_noinline() +#endif /* TODO: Replace this with an inline function. @@ -746,7 +762,8 @@ inline void dec_thread_running() thread_safe_decrement32(&thread_running); } -void set_server_version(void); +extern void set_server_version(void); +extern void dec_thread_count(void); #if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32) extern "C" THD *_current_thd_noinline(); @@ -768,6 +785,7 @@ inline int set_current_thd(THD *thd) return my_pthread_setspecific_ptr(THR_THD, thd); } + /* @todo remove, make it static in ha_maria.cc currently it's needed for sql_select.cc diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 4b21ffebe1f..fa04f6d2637 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3944,7 +3944,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) { /* if we run out of slots or we are not using tempool */ sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid, - thd->thread_id, thd->tmp_table++); + (ulong) thd->thread_id, thd->tmp_table++); } fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME); diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index b4e7b1a89dd..286162efcb8 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -969,10 +969,8 @@ handle_rpl_parallel_thread(void *arg) my_thread_init(); thd = new THD; thd->thread_stack = (char*)&thd; - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); + add_to_active_threads(thd); set_current_thd(thd); pthread_detach_this_thread(); thd->init_for_queries(); @@ -1372,10 +1370,10 @@ handle_rpl_parallel_thread(void *arg) thd->reset_db(NULL, 0); thd_proc_info(thd, "Slave worker thread exiting"); thd->temporary_tables= 0; - mysql_mutex_lock(&LOCK_thread_count); + THD_CHECK_SENTRY(thd); + unlink_not_visible_thd(thd); delete thd; - mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_lock(&rpt->LOCK_rpl_thread); rpt->running= false; diff --git a/sql/scheduler.cc b/sql/scheduler.cc index bc3166210b5..2a0138d06a8 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -22,9 +22,9 @@ #pragma implementation #endif +#include "mysqld.h" #include "sql_connect.h" // init_new_connection_handler_thread #include "scheduler.h" -#include "mysqld.h" #include "sql_class.h" #include "sql_callback.h" #include <violite.h> @@ -35,7 +35,8 @@ static bool no_threads_end(THD *thd, bool put_in_cache) { - unlink_thd(thd); + if (thd) + unlink_thd(thd); return 1; // Abort handle_one_connection } @@ -81,7 +82,9 @@ static void scheduler_wait_net_end(void) { one_thread_scheduler() or one_thread_per_connection_scheduler() in mysqld.cc, so this init function will always be called. */ -void scheduler_init() { + +void scheduler_init() +{ thr_set_lock_wait_callback(scheduler_wait_lock_begin, scheduler_wait_lock_end); thr_set_sync_wait_callback(scheduler_wait_sync_begin, @@ -118,7 +121,6 @@ void post_kill_notification(THD *thd) #ifndef EMBEDDED_LIBRARY - void one_thread_per_connection_scheduler(scheduler_functions *func, ulong *arg_max_connections, uint *arg_connection_count) @@ -132,6 +134,14 @@ void one_thread_per_connection_scheduler(scheduler_functions *func, func->end_thread= one_thread_per_connection_end; func->post_kill_notification= post_kill_notification; } +#else +bool init_new_connection_handler_thread() +{ + return 0; +} +void handle_connection_in_main_thread(CONNECT *connect) +{ +} #endif /* @@ -144,10 +154,7 @@ void one_thread_scheduler(scheduler_functions *func) func->max_threads= 1; func->max_connections= &max_connections; func->connection_count= &connection_count; -#ifndef EMBEDDED_LIBRARY func->init_new_connection_thread= init_new_connection_handler_thread; func->add_connection= handle_connection_in_main_thread; -#endif func->end_thread= no_threads_end; } - diff --git a/sql/scheduler.h b/sql/scheduler.h index f7aff377eac..71553372999 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -37,7 +37,7 @@ struct scheduler_functions ulong *max_connections; bool (*init)(void); bool (*init_new_connection_thread)(void); - void (*add_connection)(THD *thd); + void (*add_connection)(CONNECT *connect); void (*thd_wait_begin)(THD *thd, int wait_type); void (*thd_wait_end)(THD *thd); void (*post_kill_notification)(THD *thd); diff --git a/sql/slave.cc b/sql/slave.cc index 72bed45d245..12eac9c1082 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -294,9 +294,7 @@ handle_slave_init(void *arg __attribute__((unused))) my_thread_init(); thd= new THD; thd->thread_stack= (char*) &thd; /* Set approximate stack start */ - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= next_thread_id(); thd->system_thread = SYSTEM_THREAD_SLAVE_INIT; thread_safe_increment32(&service_thread_count); thd->store_globals(); @@ -310,19 +308,17 @@ handle_slave_init(void *arg __attribute__((unused))) rpl_gtid_slave_state_table_name.str, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); - - mysql_mutex_lock(&LOCK_thread_count); delete thd; - mysql_mutex_unlock(&LOCK_thread_count); thread_safe_decrement32(&service_thread_count); - signal_thd_deleted(); - my_thread_end(); - mysql_mutex_lock(&LOCK_slave_init); + /* Signal run_slave_init_thread() that we are done */ + + mysql_mutex_lock(&LOCK_start_thread); slave_init_thread_running= false; - mysql_cond_broadcast(&COND_slave_init); - mysql_mutex_unlock(&LOCK_slave_init); + mysql_cond_broadcast(&COND_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); + my_thread_end(); return 0; } @@ -347,11 +343,10 @@ run_slave_init_thread() return 1; } - mysql_mutex_lock(&LOCK_slave_init); + mysql_mutex_lock(&LOCK_start_thread); while (slave_init_thread_running) - mysql_cond_wait(&COND_slave_init, &LOCK_slave_init); - mysql_mutex_unlock(&LOCK_slave_init); - + mysql_cond_wait(&COND_start_thread, &LOCK_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); return 0; } @@ -3076,9 +3071,7 @@ static int init_slave_thread(THD* thd, Master_info *mi, thd->variables.log_slow_filter= global_system_variables.log_slow_filter; set_slave_thread_options(thd); thd->client_capabilities = CLIENT_LOCAL_FILES; - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); if (thd_type == SLAVE_THD_SQL) THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log); @@ -3970,9 +3963,7 @@ pthread_handler_t handle_slave_io(void *arg) goto err_during_init; } thd->system_thread_info.rpl_io_info= &io_info; - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); mi->slave_running = MYSQL_SLAVE_RUN_NOT_CONNECT; mi->abort_slave = 0; mysql_mutex_unlock(&mi->run_lock); @@ -4295,6 +4286,7 @@ err: flush_master_info(mi, TRUE, TRUE); THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit); thd->add_status_to_global(); + unlink_not_visible_thd(thd); mysql_mutex_lock(&mi->run_lock); err_during_init: @@ -4354,7 +4346,8 @@ int check_temp_dir(char* tmp_file) size_t tmp_dir_size; DBUG_ENTER("check_temp_dir"); - mysql_mutex_lock(&LOCK_thread_count); + /* This look is safe to use as this function is only called once */ + mysql_mutex_lock(&LOCK_start_thread); if (check_temp_dir_run) { result= check_temp_dir_result; @@ -4393,7 +4386,7 @@ int check_temp_dir(char* tmp_file) end: check_temp_dir_result= result; - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_start_thread); DBUG_RETURN(result); } @@ -4571,9 +4564,7 @@ pthread_handler_t handle_slave_sql(void *arg) applied. In all other cases it must be FALSE. */ thd->variables.binlog_annotate_row_events= 0; - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); /* We are going to set slave_running to 1. Assuming slave I/O thread is alive and connected, this is going to make Seconds_Behind_Master be 0 @@ -4882,7 +4873,9 @@ pthread_handler_t handle_slave_sql(void *arg) } THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit); thd->add_status_to_global(); + unlink_not_visible_thd(thd); mysql_mutex_lock(&rli->run_lock); + err_during_init: /* We need data_lock, at least to wake up any waiting master_pos_wait() */ mysql_mutex_lock(&rli->data_lock); @@ -4906,12 +4899,8 @@ err_during_init: to avoid unneeded position re-init */ thd->temporary_tables = 0; // remove tempation from destructor to close them - THD_CHECK_SENTRY(thd); rli->sql_driver_thd= 0; - mysql_mutex_lock(&LOCK_thread_count); thd->rgi_fake= thd->rgi_slave= NULL; - delete serial_rgi; - mysql_mutex_unlock(&LOCK_thread_count); #ifdef WITH_WSREP /* @@ -4940,10 +4929,11 @@ err_during_init: #endif /* WITH_WSREP */ /* - Note: the order of the broadcast and unlock calls below (first broadcast, then unlock) - is important. Otherwise a killer_thread can execute between the calls and - delete the mi structure leading to a crash! (see BUG#25306 for details) - */ + Note: the order of the broadcast and unlock calls below (first + broadcast, then unlock) is important. Otherwise a killer_thread can + execute between the calls and delete the mi structure leading to a + crash! (see BUG#25306 for details) + */ mysql_cond_broadcast(&rli->stop_cond); DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); mysql_mutex_unlock(&rli->run_lock); // tell the world we are done @@ -4959,9 +4949,13 @@ err_during_init: rpl_parallel_inactivate_pool(&global_rpl_thread_pool); mysql_mutex_unlock(&LOCK_active_mi); + /* TODO: Check if this lock is needed */ mysql_mutex_lock(&LOCK_thread_count); - delete thd; + delete serial_rgi; mysql_mutex_unlock(&LOCK_thread_count); + + THD_CHECK_SENTRY(thd); + delete thd; thread_safe_decrement32(&service_thread_count); signal_thd_deleted(); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c8b0092d246..34a618aba98 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1233,7 +1233,8 @@ bool close_temporary_tables(THD *thd) */ for (; table && is_user_table(table) && - tmpkeyval(thd, table) == thd->variables.pseudo_thread_id && + (ulong) tmpkeyval(thd, table) == + (ulong) thd->variables.pseudo_thread_id && table->s->db.length == db.length() && memcmp(table->s->db.str, db.ptr(), db.length()) == 0; table= next) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 345feb6094a..c1f64c89e1b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -702,12 +702,6 @@ extern "C" @param length length of buffer @param max_query_len how many chars of query to copy (0 for all) - @req LOCK_thread_count - - @note LOCK_thread_count mutex is not necessary when the function is invoked on - the currently running thread (current_thd) or if the caller in some other - way guarantees that access to thd->query is serialized. - @return Pointer to string */ @@ -953,7 +947,7 @@ THD::THD(bool is_wsrep_applier) // Must be reset to handle error with THD's created for init of mysqld lex->current_select= 0; user_time.val= start_time= start_time_sec_part= 0; - start_utime= utime_after_query= prior_thr_create_utime= 0L; + start_utime= utime_after_query= 0; utime_after_lock= 0L; progress.arena= 0; progress.report_to_client= 0; @@ -1378,6 +1372,12 @@ extern "C" THD *_current_thd_noinline(void) { return my_pthread_getspecific_ptr(THD*,THR_THD); } + +extern "C" my_thread_id next_thread_id_noinline() +{ +#undef next_thread_id + return next_thread_id(); +} #endif /* @@ -1628,6 +1628,10 @@ THD::~THD() THD *orig_thd= current_thd; THD_CHECK_SENTRY(this); DBUG_ENTER("~THD()"); + /* Check that we have already called thd->unlink() */ + DBUG_ASSERT(prev == 0 && next == 0); + /* This takes a long time so we should not do this under LOCK_thread_count */ + mysql_mutex_assert_not_owner(&LOCK_thread_count); /* In error cases, thd may not be current thd. We have to fix this so @@ -4073,7 +4077,7 @@ void Security_context::destroy() // If not pointer to constant if (host != my_localhost) { - my_free(host); + my_free((char*) host); host= NULL; } if (user != delayed_user) diff --git a/sql/sql_class.h b/sql/sql_class.h index a15a738b1bf..2c8270055db 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1185,7 +1185,8 @@ public: priv_user - The user privilege we are using. May be "" for anonymous user. ip - client IP */ - char *host, *user, *ip; + const char *host; + char *user, *ip; char priv_user[USERNAME_LENGTH]; char proxy_user[USERNAME_LENGTH + MAX_HOSTNAME + 5]; /* The host privilege we are using */ @@ -4027,8 +4028,41 @@ public: { main_lex.restore_set_statement_var(); } + + /* + Reset current_linfo + Setting current_linfo to 0 needs to be done with LOCK_thread_count to + ensure that adjust_linfo_offsets doesn't use a structure that may + be deleted. + */ + inline void reset_current_linfo() + { + mysql_mutex_lock(&LOCK_thread_count); + current_linfo= 0; + mysql_mutex_unlock(&LOCK_thread_count); + } }; +inline void add_to_active_threads(THD *thd) +{ + mysql_mutex_lock(&LOCK_thread_count); + threads.append(thd); + mysql_mutex_unlock(&LOCK_thread_count); +} + +/* + This should be called when you want to delete a thd that was not + running any queries. + This function will assert if the THD was not linked. +*/ + +inline void unlink_not_visible_thd(THD *thd) +{ + thd->assert_if_linked(); + mysql_mutex_lock(&LOCK_thread_count); + thd->unlink(); + mysql_mutex_unlock(&LOCK_thread_count); +} /** A short cut for thd->get_stmt_da()->set_ok_status(). */ diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 7821b96b9bb..c02db1b3947 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -827,14 +827,17 @@ bool thd_init_client_charset(THD *thd, uint cs_number) Initialize connection threads */ +#ifndef EMBEDDED_LIBRARY bool init_new_connection_handler_thread() { pthread_detach_this_thread(); if (my_thread_init()) { + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); return 1; } + DBUG_EXECUTE_IF("simulate_failed_connection_1", return(1); ); return 0; } @@ -850,7 +853,6 @@ bool init_new_connection_handler_thread() 1 error */ -#ifndef EMBEDDED_LIBRARY static int check_connection(THD *thd) { uint connect_errors= 0; @@ -951,6 +953,7 @@ static int check_connection(THD *thd) this is treated as a global server OOM error. TODO: remove the need for my_strdup. */ + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); return 1; /* The error is set by my_strdup(). */ } @@ -968,7 +971,7 @@ static int check_connection(THD *thd) if (thd->main_security_ctx.host) { if (thd->main_security_ctx.host != my_localhost) - thd->main_security_ctx.host[MY_MIN(strlen(thd->main_security_ctx.host), + ((char*) thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host), HOSTNAME_LENGTH)]= 0; thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; } @@ -1016,6 +1019,7 @@ static int check_connection(THD *thd) Hence, there is no reason to account on OOM conditions per client IP, we count failures in the global server status instead. */ + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); return 1; /* The error is set by alloc(). */ } @@ -1054,7 +1058,8 @@ bool setup_connection_thread_globals(THD *thd) { close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); + statistic_increment(connection_errors_internal, &LOCK_status); + thd->scheduler->end_thread(thd, 0); return 1; // Error } return 0; @@ -1082,7 +1087,7 @@ bool login_connection(THD *thd) int error= 0; DBUG_ENTER("login_connection"); DBUG_PRINT("info", ("login_connection called by thread %lu", - thd->thread_id)); + (ulong) thd->thread_id)); /* Use "connect_timeout" value during connection phase */ my_net_set_read_timeout(net, connect_timeout); @@ -1254,11 +1259,11 @@ void prepare_new_connection_state(THD* thd) pthread_handler_t handle_one_connection(void *arg) { - THD *thd= (THD*) arg; + CONNECT *connect= (CONNECT*) arg; - mysql_thread_set_psi_id(thd->thread_id); + mysql_thread_set_psi_id(connect->thread_id); - do_handle_one_connection(thd); + do_handle_one_connection(connect); return 0; } @@ -1290,19 +1295,17 @@ bool thd_is_connection_alive(THD *thd) return FALSE; } -void do_handle_one_connection(THD *thd_arg) -{ - THD *thd= thd_arg; - - thd->thr_create_utime= microsecond_interval_timer(); - /* We need to set this because of time_out_user_resource_limits */ - thd->start_utime= thd->thr_create_utime; - if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0)) +void do_handle_one_connection(CONNECT *connect) +{ + ulonglong thr_create_utime= microsecond_interval_timer(); + THD *thd; + if (connect->scheduler->init_new_connection_thread() || + !(thd= connect->create_thd())) { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); + scheduler_functions *scheduler= connect->scheduler; + connect->close_with_error(0, 0, ER_OUT_OF_RESOURCES); + scheduler->end_thread(0, 0); return; } @@ -1311,14 +1314,22 @@ void do_handle_one_connection(THD *thd_arg) increment slow_launch_threads counter if it took more than slow_launch_time seconds to create the thread. */ - if (thd->prior_thr_create_utime) + + if (connect->prior_thr_create_utime) { - ulong launch_time= (ulong) (thd->thr_create_utime - - thd->prior_thr_create_utime); + ulong launch_time= (ulong) (thr_create_utime - + connect->prior_thr_create_utime); if (launch_time >= slow_launch_time*1000000L) statistic_increment(slow_launch_threads, &LOCK_status); - thd->prior_thr_create_utime= 0; } + delete connect; + + /* Make THD visible in show processlist */ + add_to_active_threads(thd); + + thd->thr_create_utime= thr_create_utime; + /* We need to set this because of time_out_user_resource_limits */ + thd->start_utime= thr_create_utime; /* handle_one_connection() is normally the only way a thread would @@ -1365,7 +1376,7 @@ end_thread: if (thd->userstat_running) update_global_user_stats(thd, create_user, time(NULL)); - if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0)) + if (thd->scheduler->end_thread(thd, 1)) return; // Probably no-threads /* @@ -1377,3 +1388,110 @@ end_thread: } } #endif /* EMBEDDED_LIBRARY */ + + +/* Handling of CONNECT objects */ + +/* + Close connection without error and delete the connect object + This and close_with_error are only called if we didn't manage to + create a new thd object. +*/ + +void CONNECT::close_and_delete() +{ + DBUG_ENTER("close_and_delete"); + + if (vio) + vio_close(vio); + if (thread_count_incremented) + { + /* + Normally this is handled by THD::unlink. As we haven't yet created + a THD and put it in the thread list, we have to manage counting here. + */ + dec_thread_count(); + dec_connection_count(scheduler); + } + statistic_increment(connection_errors_internal, &LOCK_status); + statistic_increment(aborted_connects,&LOCK_status); + + delete this; + DBUG_VOID_RETURN; +} + +/* + Close a connection with a possible error to the end user + Alse deletes the connection object, like close_and_delete() +*/ + +void CONNECT::close_with_error(uint sql_errno, + const char *message, uint close_error) +{ + THD *thd= create_thd(); + if (thd) + { + if (sql_errno) + net_send_error(thd, sql_errno, message, NULL); + close_connection(thd, close_error); + delete thd; + set_current_thd(0); + if (thread_count_incremented) + { + dec_thread_count(); + dec_connection_count(scheduler); + } + delete this; + statistic_increment(connection_errors_internal, &LOCK_status); + statistic_increment(aborted_connects,&LOCK_status); + } + else + { + /* + Out of memory; We can't generate an error, just close the connection + close_and_delete() will increment statistics. + */ + close_and_delete(); + } +} + + +CONNECT::~CONNECT() +{ + if (vio) + vio_delete(vio); +} + +/* Create a THD based on a CONNECT object */ + +THD *CONNECT::create_thd() +{ + my_bool res; + THD *thd; + DBUG_ENTER("create_thd"); + + DBUG_EXECUTE_IF("simulate_failed_connection_2", DBUG_RETURN(0); ); + + if (!(thd= new THD)) + DBUG_RETURN(0); + + set_current_thd(thd); + res= my_net_init(&thd->net, vio, thd, MYF(MY_THREAD_SPECIFIC)); + vio= 0; // Vio now handled by thd + + if (res) + { + delete thd; + set_current_thd(0); + DBUG_RETURN(0); + } + + init_net_server_extension(thd); + + thd->security_ctx->host= host; + thd->extra_port= extra_port; + thd->scheduler= scheduler; + thd->thread_id= thd->variables.pseudo_thread_id= thread_id; + thd->real_id= real_id; + DBUG_RETURN(thd); +} diff --git a/sql/sql_connect.h b/sql/sql_connect.h index bab171606ba..902ebfa41c9 100644 --- a/sql/sql_connect.h +++ b/sql/sql_connect.h @@ -19,8 +19,43 @@ #include "my_sys.h" /* pthread_handler_t */ #include "mysql_com.h" /* enum_server_command */ #include "structs.h" +#include <mysql/psi/mysql_socket.h> #include <hash.h> +/* + Object to hold connect information to be given to the newly created thread +*/ + +class scheduler_functions; + +class CONNECT : public ilink { +public: + /* To be copied to THD */ + Vio *vio; /* Copied to THD with my_net_init() */ + const char *host; + scheduler_functions *scheduler; + my_thread_id thread_id; + pthread_t real_id; + bool extra_port; + + /* Own variables */ + bool thread_count_incremented; + ulonglong prior_thr_create_utime; + + CONNECT() + :vio(0), host(0), scheduler(thread_scheduler), thread_id(0), real_id(0), + extra_port(0), + thread_count_incremented(0), prior_thr_create_utime(0) + { + }; + ~CONNECT(); + void close_and_delete(); + void close_with_error(uint sql_errno, + const char *message, uint close_error); + THD *create_thd(); +}; + + class THD; typedef struct st_lex_user LEX_USER; typedef struct user_conn USER_CONN; @@ -37,7 +72,7 @@ void free_global_index_stats(void); void free_global_client_stats(void); pthread_handler_t handle_one_connection(void *arg); -void do_handle_one_connection(THD *thd_arg); +void do_handle_one_connection(CONNECT *connect); bool init_new_connection_handler_thread(); void reset_mqh(LEX_USER *lu, bool get_them); bool check_mqh(THD *thd, uint check_command); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e27cc6de073..fb020a9a302 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2068,6 +2068,7 @@ public: delayed_lock= global_system_variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; mysql_mutex_unlock(&LOCK_thread_count); + thread_safe_increment32(&thread_count); DBUG_VOID_RETURN; } ~Delayed_insert() @@ -2081,17 +2082,24 @@ public: close_thread_tables(&thd); thd.mdl_context.release_transactional_locks(); } - mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_destroy(&mutex); mysql_cond_destroy(&cond); mysql_cond_destroy(&cond_client); + + /* + We could use unlink_not_visible_threads() here, but as + delayed_insert_threads also needs to be protected by + the LOCK_thread_count mutex, we open code this. + */ + mysql_mutex_lock(&LOCK_thread_count); thd.unlink(); // Must be unlinked under lock - my_free(thd.query()); - thd.security_ctx->user= thd.security_ctx->host=0; delayed_insert_threads--; mysql_mutex_unlock(&LOCK_thread_count); - thread_safe_decrement32(&thread_count); - mysql_cond_broadcast(&COND_thread_count); /* Tell main we are ready */ + + my_free(thd.query()); + thd.security_ctx->user= 0; + thd.security_ctx->host= 0; + dec_thread_count(); } /* The following is for checking when we can delete ourselves */ @@ -2226,8 +2234,6 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, if (!(di= new Delayed_insert(thd->lex->current_select))) goto end_create; - thread_safe_increment32(&thread_count); - /* Annotating delayed inserts is not supported. */ @@ -2803,15 +2809,13 @@ pthread_handler_t handle_delayed_insert(void *arg) pthread_detach_this_thread(); /* Add thread to THD list so that's it's visible in 'show processlist' */ - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); thd->set_current_time(); - threads.append(thd); + add_to_active_threads(thd); if (abort_loop) thd->killed= KILL_CONNECTION; else thd->reset_killed(); - mysql_mutex_unlock(&LOCK_thread_count); mysql_thread_set_psi_id(thd->thread_id); diff --git a/sql/sql_list.h b/sql/sql_list.h index 718306c2193..113af35bad7 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -650,6 +650,10 @@ struct ilink if (next) next->prev=prev; prev=0 ; next=0; } + inline void assert_if_linked() + { + DBUG_ASSERT(prev != 0 && next != 0); + } virtual ~ilink() { unlink(); } /*lint -e1740 */ }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 84f0c6369fd..355f62d55b7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -844,12 +844,13 @@ end: delete thd; #ifndef EMBEDDED_LIBRARY - thread_safe_decrement32(&thread_count); + DBUG_ASSERT(thread_count == 1); in_bootstrap= FALSE; - - mysql_mutex_lock(&LOCK_thread_count); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + /* + dec_thread_count will signal bootstrap() function that we have ended as + thread_count will become 0. + */ + dec_thread_count(); my_thread_end(); pthread_exit(0); #endif @@ -954,7 +955,6 @@ bool do_command(THD *thd) if(!thd->skip_wait_timeout) my_net_set_read_timeout(net, thd->variables.net_wait_timeout); - /* XXX: this code is here only to clear possible errors of init_connect. Consider moving to init_connect() instead. @@ -7279,7 +7279,6 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, and Query_log_event::print() would give ';;' output). This also helps display only the current query in SHOW PROCESSLIST. - Note that we don't need LOCK_thread_count to modify query_length. */ if (found_semicolon && (ulong) (found_semicolon - thd->query())) thd->set_query_inner(thd->query(), diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 19f7e5ab4e6..cc22377b117 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2181,9 +2181,7 @@ static int init_binlog_sender(binlog_send_info *info, linfo->pos= *pos; // note: publish that we use file, before we open it - mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo= linfo; - mysql_mutex_unlock(&LOCK_thread_count); if (check_start_offset(info, linfo->log_file_name, *pos)) return 1; @@ -2922,9 +2920,7 @@ err: mysql_file_close(file, MYF(MY_WME)); } - mysql_mutex_lock(&LOCK_thread_count); - thd->current_linfo = 0; - mysql_mutex_unlock(&LOCK_thread_count); + thd->reset_current_linfo(); thd->variables.max_allowed_packet= old_max_allowed_packet; delete info->fdev; @@ -3379,10 +3375,8 @@ err: SYNOPSIS kill_zombie_dump_threads() slave_server_id the slave's server id - */ - void kill_zombie_dump_threads(uint32 slave_server_id) { mysql_mutex_lock(&LOCK_thread_count); @@ -3946,9 +3940,7 @@ bool mysql_show_binlog_events(THD* thd) goto err; } - mysql_mutex_lock(&LOCK_thread_count); - thd->current_linfo = &linfo; - mysql_mutex_unlock(&LOCK_thread_count); + thd->current_linfo= &linfo; if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0) goto err; @@ -4080,9 +4072,7 @@ err: else my_eof(thd); - mysql_mutex_lock(&LOCK_thread_count); - thd->current_linfo = 0; - mysql_mutex_unlock(&LOCK_thread_count); + thd->reset_current_linfo(); thd->variables.max_allowed_packet= old_max_allowed_packet; DBUG_RETURN(ret); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cb0f9e594ff..8c4e8812d72 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16137,7 +16137,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, { /* if we run out of slots or we are not using tempool */ sprintf(path, "%s%lx_%lx_%x", tmp_file_prefix,current_pid, - thd->thread_id, thd->tmp_table++); + (ulong) thd->thread_id, thd->tmp_table++); } /* diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 8e7525893eb..642cf208908 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -88,7 +88,7 @@ static my_bool print_cached_tables_callback(TDC_element *element, THD *in_use= entry->in_use; printf("%-14.14s %-32s%6ld%8ld%6d %s\n", entry->s->db.str, entry->s->table_name.str, element->version, - in_use ? in_use->thread_id : 0, + in_use ? (long) in_use->thread_id : (long) 0, entry->db_stat ? 1 : 0, in_use ? lock_descriptions[(int)entry->reginfo.lock_type] : "Not in use"); diff --git a/sql/threadpool.h b/sql/threadpool.h index 7b62d2cb70a..3bbcf3f67f6 100644 --- a/sql/threadpool.h +++ b/sql/threadpool.h @@ -38,10 +38,12 @@ extern int threadpool_add_connection(THD *thd); threadpool_unix.cc or threadpool_win.cc */ extern bool tp_init(); -extern void tp_add_connection(THD*); +extern bool tp_init_new_connection_thread(); +extern void tp_add_connection(CONNECT *); extern void tp_wait_begin(THD *, int); extern void tp_wait_end(THD*); extern void tp_post_kill_notification(THD *thd); +extern bool tp_end_thread(THD *thd, bool cache_thread); extern void tp_end(void); /* Used in SHOW for threadpool_idle_thread_count */ diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 9fb38319096..c1a092dafb9 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -221,7 +221,8 @@ int threadpool_process_request(THD *thd) /* - In the loop below, the flow is essentially the copy of thead-per-connections + In the loop below, the flow is essentially the copy of + thead-per-connections logic, see do_handle_one_connection() in sql_connect.c The goal is to execute a single query, thus the loop is normally executed @@ -266,12 +267,12 @@ static scheduler_functions tp_scheduler_functions= NULL, NULL, tp_init, // init - NULL, // init_new_connection_thread + tp_init_new_connection_thread, // init_new_connection_thread tp_add_connection, // add_connection tp_wait_begin, // thd_wait_begin tp_wait_end, // thd_wait_end post_kill_notification, // post_kill_notification - NULL, // end_thread + tp_end_thread, // Dummy function tp_end // end }; diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index 89a2036cb10..684b074f9f0 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -809,7 +809,7 @@ static int create_worker(thread_group_t *thread_group) if (!err) { thread_group->last_thread_creation_time=microsecond_interval_timer(); - thread_created++; + statistic_increment(thread_created,&LOCK_status); add_thread_count(thread_group, 1); } else @@ -1203,14 +1203,14 @@ void wait_end(thread_group_t *thread_group) Allocate/initialize a new connection structure. */ -connection_t *alloc_connection(THD *thd) +connection_t *alloc_connection() { + connection_t* connection; DBUG_ENTER("alloc_connection"); + DBUG_EXECUTE_IF("simulate_failed_connection_1", DBUG_RETURN(0); ); - connection_t* connection = (connection_t *)my_malloc(sizeof(connection_t),0); - if (connection) + if ((connection = (connection_t *)my_malloc(sizeof(connection_t),0))) { - connection->thd = thd; connection->waiting= false; connection->logged_in= false; connection->bound_to_poll_descriptor= false; @@ -1225,38 +1225,40 @@ connection_t *alloc_connection(THD *thd) Add a new connection to thread pool.. */ -void tp_add_connection(THD *thd) +void tp_add_connection(CONNECT *connect) { + connection_t *connection; + THD *thd; DBUG_ENTER("tp_add_connection"); - - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); - connection_t *connection= alloc_connection(thd); - if (connection) + + if (!(connection= alloc_connection()) || !(thd= connect->create_thd())) { - thd->event_scheduler.data= connection; + my_free(connection); + connect->close_and_delete(); + DBUG_VOID_RETURN; + } + connection->thd= thd; + delete connect; + + add_to_active_threads(thd); + + thd->event_scheduler.data= connection; - /* Assign connection to a group. */ - thread_group_t *group= - &all_groups[thd->thread_id%group_count]; + /* Assign connection to a group. */ + thread_group_t *group= + &all_groups[thd->thread_id%group_count]; - connection->thread_group=group; + connection->thread_group=group; - mysql_mutex_lock(&group->mutex); - group->connection_count++; - mysql_mutex_unlock(&group->mutex); + mysql_mutex_lock(&group->mutex); + group->connection_count++; + mysql_mutex_unlock(&group->mutex); - /* - Add connection to the work queue.Actual logon - will be done by a worker thread. - */ - queue_put(group, connection); - } - else - { - /* Allocation failed */ - threadpool_cleanup_connection(thd); - } + /* + Add connection to the work queue.Actual logon + will be done by a worker thread. + */ + queue_put(group, connection); DBUG_VOID_RETURN; } @@ -1549,6 +1551,18 @@ bool tp_init() } +/* Dummy functions, do nothing */ + +bool tp_init_new_connection_thread() +{ + return 0; +} + +bool tp_end_thread(THD *thd, bool cache_thread) +{ + return 0; +} + void tp_end() { DBUG_ENTER("tp_end"); diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index 4be51f3d6e9..e036bd614fd 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -230,7 +230,7 @@ struct connection_t }; -void init_connection(connection_t *connection) +void init_connection(connection_t *connection, THD *thd) { connection->logged_in = false; connection->handle= 0; @@ -243,7 +243,8 @@ void init_connection(connection_t *connection) memset(&connection->overlapped, 0, sizeof(OVERLAPPED)); InitializeThreadpoolEnvironment(&connection->callback_environ); SetThreadpoolCallbackPool(&connection->callback_environ, pool); - connection->thd = 0; + connection->thd = thd; + thd->event_scheduler.data= connection; } @@ -465,7 +466,7 @@ static void check_thread_init() if (FlsGetValue(fls) == NULL) { FlsSetValue(fls, (void *)1); - thread_created++; + statistic_increment(thread_created, &LOCK_status); InterlockedIncrement((volatile long *)&tp_stats.num_worker_threads); } } @@ -532,6 +533,16 @@ bool tp_init(void) } +/* Dummy functions, do nothing */ + +bool tp_init_new_connection_thread() +{ + return 0; +} + +bool tp_end_thread(THD *thd, bool cache_thread) +{} + /** Scheduler callback : Destroy the scheduler. */ @@ -544,7 +555,6 @@ void tp_end(void) } } - /* Handle read completion/notification. */ @@ -656,24 +666,26 @@ static void CALLBACK shm_read_callback(PTP_CALLBACK_INSTANCE instance, /* Notify the thread pool about a new connection. - NOTE: LOCK_thread_count is locked on entry. This function must unlock it. */ -void tp_add_connection(THD *thd) + +void tp_add_connection(CONNECT *connect) { - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + THD *thd; + connection_t *con; - connection_t *con = (connection_t *)malloc(sizeof(connection_t)); - if(!con) + if (!(con = (connection_t *) malloc(sizeof(connection_t))) || + !(thd= connect->create_thd())) { tp_log_warning("Allocation failed", "tp_add_connection"); - threadpool_cleanup_connection(thd); + free(con) + connect->close_and_delete(); return; } + delete connect; + + add_to_active_threads(thd); - init_connection(con); - con->thd= thd; - thd->event_scheduler.data= con; + init_connection(con, thd); /* Try to login asynchronously, using threads in the pool */ PTP_WORK wrk = CreateThreadpoolWork(login_callback,con, &con->callback_environ); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 03524c8ad5c..0c527bf3708 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1744,8 +1744,9 @@ pthread_handler_t start_wsrep_THD(void *arg) goto error; } + thd->thread_id= next_thread_id(); + mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id=thread_id++; if (wsrep_gtid_mode) { diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index bba99703119..ade91a159ca 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -1077,7 +1077,7 @@ static inline void dec_counter_for_resize_op(PAGECACHE *pagecache) { DBUG_PRINT("signal", ("thread %s %ld", last_thread->next->name, - last_thread->next->id)); + (ulong) last_thread->next->id)); pagecache_pthread_cond_signal(&last_thread->next->suspend); } } @@ -1341,7 +1341,8 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, */ if ((PAGECACHE_HASH_LINK *) thread->keycache_link == hash_link) { - DBUG_PRINT("signal", ("thread: %s %ld", thread->name, thread->id)); + DBUG_PRINT("signal", ("thread: %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_signal(&thread->suspend); wqueue_unlink_from_queue(&pagecache->waiting_for_block, thread); block->requests++; @@ -1579,7 +1580,7 @@ static inline void wait_for_readers(PAGECACHE *pagecache DBUG_ENTER("wait_for_readers"); DBUG_PRINT("wait", ("suspend thread: %s %ld block: %u", - thread->name, thread->id, + thread->name, (ulong) thread->id, PCBLOCK_NUMBER(pagecache, block))); block->condvar= &thread->suspend; pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); @@ -1604,7 +1605,7 @@ static void wait_for_flush(PAGECACHE *pagecache do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -1671,7 +1672,8 @@ static void unlink_hash(PAGECACHE *pagecache, PAGECACHE_HASH_LINK *hash_link) if (page->file.file == hash_link->file.file && page->pageno == hash_link->pageno) { - DBUG_PRINT("signal", ("thread %s %ld", thread->name, thread->id)); + DBUG_PRINT("signal", ("thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_signal(&thread->suspend); wqueue_unlink_from_queue(&pagecache->waiting_for_hash_link, thread); } @@ -1811,7 +1813,7 @@ restart: thread->keycache_link= (void *) &page; wqueue_link_into_queue(&pagecache->waiting_for_hash_link, thread); DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); thread->keycache_link= NULL; @@ -1991,7 +1993,8 @@ restart: do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -2082,7 +2085,8 @@ restart: do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -2355,7 +2359,7 @@ static my_bool pagecache_wait_lock(PAGECACHE *pagecache, do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -2755,7 +2759,8 @@ static void read_block(PAGECACHE *pagecache, do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -4549,7 +4554,7 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache, { DBUG_PRINT("wait", ("(1) suspend thread %s %ld", - thread->name, thread->id)); + thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -4710,7 +4715,7 @@ restart: { DBUG_PRINT("wait", ("(2) suspend thread %s %ld", - thread->name, thread->id)); + thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -4914,7 +4919,8 @@ my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -5057,7 +5063,8 @@ static void pagecache_dump(PAGECACHE *pagecache) PAGECACHE_PAGE *page; uint i; - fprintf(pagecache_dump_file, "thread: %s %ld\n", thread->name, thread->id); + fprintf(pagecache_dump_file, "thread: %s %ld\n", thread->name, + (ulong) thread->id); i=0; thread=last=waiting_for_hash_link.last_thread; @@ -5069,7 +5076,7 @@ static void pagecache_dump(PAGECACHE *pagecache) page= (PAGECACHE_PAGE *) thread->keycache_link; fprintf(pagecache_dump_file, "thread: %s %ld, (file,pageno)=(%u,%lu)\n", - thread->name, thread->id, + thread->name, (ulong) thread->id, (uint) page->file.file,(ulong) page->pageno); if (++i == MAX_QUEUE_LEN) break; @@ -5086,7 +5093,7 @@ static void pagecache_dump(PAGECACHE *pagecache) hash_link= (PAGECACHE_HASH_LINK *) thread->keycache_link; fprintf(pagecache_dump_file, "thread: %s %u hash_link:%u (file,pageno)=(%u,%lu)\n", - thread->name, thread->id, + thread->name, (ulong) thread->id, (uint) PAGECACHE_HASH_LINK_NUMBER(pagecache, hash_link), (uint) hash_link->file.file,(ulong) hash_link->pageno); if (++i == MAX_QUEUE_LEN) @@ -5116,7 +5123,7 @@ static void pagecache_dump(PAGECACHE *pagecache) { thread=thread->next; fprintf(pagecache_dump_file, - "thread: %s %ld\n", thread->name, thread->id); + "thread: %s %ld\n", thread->name, (ulong) thread->id); if (++i == MAX_QUEUE_LEN) break; } diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index c5c47064403..681a3fb144c 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -37,8 +37,6 @@ #include "spd_ping_table.h" #include "spd_malloc.h" -extern ulong *spd_db_att_thread_id; - extern handlerton *spider_hton_ptr; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; pthread_mutex_t spider_conn_id_mutex; @@ -2269,9 +2267,7 @@ void *spider_bg_conn_action( my_thread_end(); DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif @@ -2782,9 +2778,7 @@ void *spider_bg_sts_action( #endif DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif @@ -3164,9 +3158,7 @@ void *spider_bg_crd_action( #endif DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif @@ -3653,9 +3645,7 @@ void *spider_bg_mon_action( my_thread_end(); DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 9f46e55ca09..69a05dc94fb 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -737,7 +737,8 @@ int spider_db_errorno( "to %ld: %d %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - current_thd->thread_id, error_num, conn->db_conn->get_error()); + (ulong) current_thd->thread_id, error_num, + conn->db_conn->get_error()); } if (!conn->mta_conn_mutex_unlock_later) { @@ -757,7 +758,8 @@ int spider_db_errorno( "to %ld: %d %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - current_thd->thread_id, error_num, conn->db_conn->get_error()); + (ulong) current_thd->thread_id, error_num, + conn->db_conn->get_error()); } if (!conn->mta_conn_mutex_unlock_later) { diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 3f56d9a9d89..6215a5584d0 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1717,7 +1717,7 @@ int spider_db_mysql::exec_query( l_time->tm_hour, l_time->tm_min, l_time->tm_sec, security_ctx->user ? security_ctx->user : "system user", security_ctx->host_or_ip, - thd->thread_id, + (ulong) thd->thread_id, tmp_query_str.c_ptr_safe()); } if (log_result_error_with_sql & 1) @@ -1731,7 +1731,7 @@ int spider_db_mysql::exec_query( "sql: %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - thd->thread_id, conn->tgt_host, db_conn->thread_id, + (ulong) thd->thread_id, conn->tgt_host, (ulong) db_conn->thread_id, tmp_query_str.c_ptr_safe()); } } @@ -1745,7 +1745,7 @@ int spider_db_mysql::exec_query( "affected_rows: %llu id: %llu status: %u warning_count: %u\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, db_conn->thread_id, thd->thread_id, + conn->tgt_host, (ulong) db_conn->thread_id, (ulong) thd->thread_id, db_conn->affected_rows, db_conn->insert_id, db_conn->server_status, db_conn->warning_count); if (spider_param_log_result_errors() >= 3) @@ -1760,7 +1760,7 @@ int spider_db_mysql::exec_query( "affected_rows: %llu id: %llu status: %u warning_count: %u\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, db_conn->thread_id, thd->thread_id, + conn->tgt_host, (ulong) db_conn->thread_id, (ulong) thd->thread_id, db_conn->affected_rows, db_conn->insert_id, db_conn->server_status, db_conn->warning_count); } @@ -1889,8 +1889,8 @@ void spider_db_mysql::print_warnings( "from [%s] %ld to %ld: %s %s %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, db_conn->thread_id, - current_thd->thread_id, row[0], row[1], row[2]); + conn->tgt_host, (ulong) db_conn->thread_id, + (ulong) current_thd->thread_id, row[0], row[1], row[2]); row = mysql_fetch_row(res); } if (res) diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index a9aea90dcdd..64579bcee6c 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -41,7 +41,6 @@ #include "spd_direct_sql.h" #include "spd_malloc.h" -ulong *spd_db_att_thread_id; #ifdef SPIDER_XID_USES_xid_cache_iterate #else #ifdef XID_CACHE_IS_SPLITTED @@ -6327,8 +6326,6 @@ int spider_db_init( #ifdef _WIN32 HMODULE current_module = GetModuleHandle(NULL); - spd_db_att_thread_id = (ulong *) - GetProcAddress(current_module, "?thread_id@@3KA"); #ifdef SPIDER_XID_USES_xid_cache_iterate #else #ifdef XID_CACHE_IS_SPLITTED @@ -6362,7 +6359,6 @@ int spider_db_init( spd_abort_loop = (bool volatile *) GetProcAddress(current_module, "?abort_loop@@3_NC"); #else - spd_db_att_thread_id = &thread_id; #ifdef SPIDER_XID_USES_xid_cache_iterate #else #ifdef XID_CACHE_IS_SPLITTED |