summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2016-02-01 12:45:39 +0200
committerMonty <monty@mariadb.org>2016-02-07 10:34:03 +0200
commit3d4a7390c1a94ef6e07b04b52ea94a95878cda1b (patch)
treea53179de37b318e27e48546ed3bc8a723148104a
parent076aa182c2d2ee67c233d0e79c900dfba6f593c1 (diff)
downloadmariadb-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)
-rw-r--r--include/my_atomic.h6
-rw-r--r--include/mysql/psi/mysql_socket.h2
-rw-r--r--include/thread_pool_priv.h2
-rw-r--r--libmysqld/lib_sql.cc2
-rw-r--r--mysql-test/r/connect2.result45
-rw-r--r--mysql-test/r/log_tables.result6
-rw-r--r--mysql-test/r/mdev375.result3
-rw-r--r--mysql-test/r/mysqlbinlog_row_minimal.result22
-rw-r--r--mysql-test/suite/binlog/r/binlog_reset_master.result1
-rw-r--r--mysql-test/suite/binlog/t/binlog_reset_master.test26
-rw-r--r--mysql-test/t/connect2.cnf9
-rw-r--r--mysql-test/t/connect2.test81
-rw-r--r--mysql-test/t/mdev375.test1
-rw-r--r--mysys/mf_keycache.c32
-rw-r--r--mysys/thr_lock.c26
-rw-r--r--mysys/thr_mutex.c4
-rw-r--r--plugin/feedback/sender_thread.cc4
-rw-r--r--plugin/handler_socket/handlersocket/database.cpp8
-rw-r--r--sql/event_scheduler.cc17
-rw-r--r--sql/hostname.cc4
-rw-r--r--sql/hostname.h2
-rw-r--r--sql/log.cc8
-rw-r--r--sql/mysqld.cc445
-rw-r--r--sql/mysqld.h30
-rw-r--r--sql/opt_subselect.cc2
-rw-r--r--sql/rpl_parallel.cc10
-rw-r--r--sql/scheduler.cc21
-rw-r--r--sql/scheduler.h2
-rw-r--r--sql/slave.cc64
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.cc20
-rw-r--r--sql/sql_class.h36
-rw-r--r--sql/sql_connect.cc164
-rw-r--r--sql/sql_connect.h37
-rw-r--r--sql/sql_insert.cc26
-rw-r--r--sql/sql_list.h4
-rw-r--r--sql/sql_parse.cc13
-rw-r--r--sql/sql_repl.cc16
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_test.cc2
-rw-r--r--sql/threadpool.h4
-rw-r--r--sql/threadpool_common.cc7
-rw-r--r--sql/threadpool_unix.cc74
-rw-r--r--sql/threadpool_win.cc40
-rw-r--r--sql/wsrep_mysqld.cc3
-rw-r--r--storage/maria/ma_pagecache.c41
-rw-r--r--storage/spider/spd_conn.cc18
-rw-r--r--storage/spider/spd_db_conn.cc6
-rw-r--r--storage/spider/spd_db_mysql.cc12
-rw-r--r--storage/spider/spd_table.cc4
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