Skip to content

Commit 8c457e8

Browse files
committed
Bug#20333037: MOVE CURRENT MUTEX/COND FROM THREAD LOCAL STORAGE TO THD
Move current_mutex, current_cond and mutex fields from TLS to THD. This reduces thread local storage usage and is a step towards removing the requirement of calling my_thread_init() and my_thread_end().
1 parent d88a6b0 commit 8c457e8

31 files changed

+190
-160
lines changed

include/my_sys.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,25 @@ extern void (*local_message_hook)(enum loglevel ll,
220220
extern uint my_file_limit;
221221
extern ulong my_thread_stack_size;
222222

223-
extern void (*proc_info_hook)(void *, const PSI_stage_info *, PSI_stage_info *,
224-
const char *, const char *, const unsigned int);
223+
/*
224+
Hooks for reporting execution stage information. The server implementation
225+
of these will also set THD::current_cond/current_mutex.
226+
By having hooks, we avoid direct dependencies on server code.
227+
*/
228+
extern void (*enter_cond_hook)(void *opaque_thd,
229+
mysql_cond_t *cond,
230+
mysql_mutex_t *mutex,
231+
const PSI_stage_info *stage,
232+
PSI_stage_info *old_stage,
233+
const char *src_function,
234+
const char *src_file,
235+
int src_line);
236+
237+
extern void (*exit_cond_hook)(void *opaque_thd,
238+
const PSI_stage_info *stage,
239+
const char *src_function,
240+
const char *src_file,
241+
int src_line);
225242

226243
/* charsets */
227244
#define MY_ALL_CHARSETS_SIZE 2048

include/my_thread_local.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ struct st_my_thread_var
7979
int thr_winerr;
8080
#endif
8181
mysql_cond_t suspend;
82-
mysql_mutex_t mutex;
83-
mysql_mutex_t * volatile current_mutex;
84-
mysql_cond_t * volatile current_cond;
8582
my_thread_id id;
8683
int volatile abort;
8784
struct st_my_thread_var *next,**prev;

mysys/my_init.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ PSI_stage_info stage_waiting_for_table_level_lock=
444444

445445
PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
446446
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock,
447-
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
447+
key_THR_LOCK_charset, key_THR_LOCK_heap,
448448
key_THR_LOCK_lock, key_THR_LOCK_malloc,
449449
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
450450
key_THR_LOCK_open, key_THR_LOCK_threads,
@@ -456,7 +456,6 @@ static PSI_mutex_info all_mysys_mutexes[]=
456456
{ &key_IO_CACHE_append_buffer_lock, "IO_CACHE::append_buffer_lock", 0},
457457
{ &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0},
458458
{ &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0},
459-
{ &key_my_thread_var_mutex, "my_thread_var::mutex", 0},
460459
{ &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL},
461460
{ &key_THR_LOCK_heap, "THR_LOCK_heap", PSI_FLAG_GLOBAL},
462461
{ &key_THR_LOCK_lock, "THR_LOCK_lock", PSI_FLAG_GLOBAL},

mysys/my_static.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -89,19 +89,34 @@ void (*fatal_error_handler_hook)(uint error, const char *str, myf MyFlags)=
8989
void (*local_message_hook)(enum loglevel ll, const char *format, va_list args)=
9090
my_message_local_stderr;
9191

92-
static void proc_info_dummy(void *a __attribute__((unused)),
92+
static void enter_cond_dummy(void *a __attribute__((unused)),
93+
mysql_cond_t *b __attribute__((unused)),
94+
mysql_mutex_t *c __attribute__((unused)),
95+
const PSI_stage_info *d __attribute__((unused)),
96+
PSI_stage_info *e __attribute__((unused)),
97+
const char *f __attribute__((unused)),
98+
const char *g __attribute__((unused)),
99+
int h __attribute__((unused)))
100+
{ };
101+
102+
static void exid_cond_dummy(void *a __attribute__((unused)),
93103
const PSI_stage_info *b __attribute__((unused)),
94-
PSI_stage_info *c __attribute__((unused)),
104+
const char *c __attribute__((unused)),
95105
const char *d __attribute__((unused)),
96-
const char *e __attribute__((unused)),
97-
const unsigned int f __attribute__((unused)))
98-
{
99-
return;
100-
}
101-
102-
/* this is to be able to call set_thd_proc_info from the C code */
103-
void (*proc_info_hook)(void *, const PSI_stage_info *, PSI_stage_info *,
104-
const char *, const char *, const unsigned int)= proc_info_dummy;
106+
int e __attribute__((unused)))
107+
{ };
108+
109+
/*
110+
Initialize these hooks to dummy implementations. The real server
111+
implementations will be set during server startup by
112+
init_server_components().
113+
*/
114+
void (*enter_cond_hook)(void *, mysql_cond_t *, mysql_mutex_t *,
115+
const PSI_stage_info *, PSI_stage_info *,
116+
const char *, const char *, int)= enter_cond_dummy;
117+
118+
void (*exit_cond_hook)(void *, const PSI_stage_info *,
119+
const char *, const char *, int)= exid_cond_dummy;
105120

106121
#if defined(ENABLED_DEBUG_SYNC)
107122
/**

mysys/my_thr_init.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ void my_thread_global_reinit()
9494
tmp= mysys_thread_var();
9595
DBUG_ASSERT(tmp);
9696

97-
mysql_mutex_destroy(&tmp->mutex);
98-
mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST);
99-
10097
mysql_cond_destroy(&tmp->suspend);
10198
mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend);
10299
}
@@ -257,7 +254,6 @@ my_bool my_thread_init()
257254
if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
258255
return TRUE;
259256

260-
mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST);
261257
mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend);
262258

263259
tmp->stack_ends_here= (char*)&tmp +
@@ -306,7 +302,6 @@ void my_thread_end()
306302
}
307303
#endif
308304
mysql_cond_destroy(&tmp->suspend);
309-
mysql_mutex_destroy(&tmp->mutex);
310305
free(tmp);
311306

312307
/*

mysys/mysys_priv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ C_MODE_START
2828

2929
extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
3030
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock,
31-
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
31+
key_THR_LOCK_charset, key_THR_LOCK_heap,
3232
key_THR_LOCK_lock, key_THR_LOCK_malloc,
3333
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
3434
key_THR_LOCK_open, key_THR_LOCK_threads,

mysys/thr_lock.c

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,6 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
356356
my_bool in_wait_list, ulong lock_wait_timeout,
357357
struct st_my_thread_var *thread_var)
358358
{
359-
mysql_cond_t *cond= &thread_var->suspend;
360359
struct timespec wait_timeout;
361360
enum enum_thr_lock_result result= THR_LOCK_ABORTED;
362361
PSI_stage_info old_stage;
@@ -394,13 +393,11 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
394393
locks_waited++;
395394

396395
/* Set up control struct to allow others to abort locks */
397-
thread_var->current_mutex= &data->lock->mutex;
398-
thread_var->current_cond= cond;
399-
data->cond= cond;
396+
data->cond= &thread_var->suspend;
400397

401-
proc_info_hook(NULL, &stage_waiting_for_table_level_lock,
402-
&old_stage,
403-
__func__, __FILE__, __LINE__);
398+
enter_cond_hook(NULL, data->cond, &data->lock->mutex,
399+
&stage_waiting_for_table_level_lock, &old_stage,
400+
__func__, __FILE__, __LINE__);
404401

405402
/*
406403
Since before_lock_wait potentially can create more threads to
@@ -418,7 +415,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
418415
set_timespec(&wait_timeout, lock_wait_timeout);
419416
while (!thread_var->abort || in_wait_list)
420417
{
421-
int rc= mysql_cond_timedwait(cond, &data->lock->mutex, &wait_timeout);
418+
int rc= mysql_cond_timedwait(data->cond, &data->lock->mutex, &wait_timeout);
422419
/*
423420
We must break the wait if one of the following occurs:
424421
- the connection has been aborted (!thread_var->abort),
@@ -481,13 +478,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
481478
}
482479
mysql_mutex_unlock(&data->lock->mutex);
483480

484-
/* The following must be done after unlock of lock->mutex */
485-
mysql_mutex_lock(&thread_var->mutex);
486-
thread_var->current_mutex= 0;
487-
thread_var->current_cond= 0;
488-
mysql_mutex_unlock(&thread_var->mutex);
489-
490-
proc_info_hook(NULL, &old_stage, NULL, __func__, __FILE__, __LINE__);
481+
exit_cond_hook(NULL, &old_stage, __func__, __FILE__, __LINE__);
491482

492483
DBUG_RETURN(result);
493484
}
@@ -1385,7 +1376,6 @@ static void *test_thread(void *arg)
13851376
struct st_my_thread_var my_thread_var;
13861377
memset(&my_thread_var, 0, sizeof(my_thread_var));
13871378
my_thread_var.id= param + 1; /* Main thread uses value 0. */
1388-
mysql_mutex_init(0, &my_thread_var.mutex, MY_MUTEX_INIT_FAST);
13891379
mysql_cond_init(0, &my_thread_var.suspend);
13901380

13911381
printf("Thread T@%u (%d) started\n", my_thread_var.id, param);

plugin/semisync/semisync_master.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Copyright (C) 2007 Google Inc.
2-
Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -854,8 +854,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
854854
else
855855
rpl_semi_sync_master_no_transactions++;
856856

857-
/* The lock held will be released by thd_exit_cond, so no need to
858-
call unlock() here */
857+
unlock();
859858
THD_EXIT_COND(NULL, & old_stage);
860859
}
861860

sql/binlog.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7068,6 +7068,7 @@ int MYSQL_BIN_LOG::wait_for_update_relay_log(THD* thd, const struct timespec *ti
70687068
else
70697069
ret= mysql_cond_timedwait(&update_cond, &LOCK_log,
70707070
const_cast<struct timespec *>(timeout));
7071+
mysql_mutex_unlock(&LOCK_log);
70717072
thd->EXIT_COND(&old_stage);
70727073

70737074
DBUG_RETURN(ret);

sql/debug_sync.cc

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -238,20 +238,21 @@
238238
#endif
239239
while (!thd->killed && !end_of_wait_condition)
240240
mysql_cond_wait(&condition_variable, &mutex);
241+
mysql_mutex_unlock(&mutex);
241242
thd->exit_cond(old_message);
242243
243244
Here some explanations:
244245
245246
thd->enter_cond() is used to register the condition variable and the
246-
mutex in thd->mysys_var. This is done to allow the thread to be
247-
interrupted (killed) from its sleep. Another thread can find the
248-
condition variable to signal and mutex to use for synchronization in
249-
this thread's THD::mysys_var.
247+
mutex in THD::current_cond/current_mutex. This is done to allow the
248+
thread to be interrupted (killed) from its sleep. Another thread can
249+
find the condition variable to signal and mutex to use for synchronization
250+
in this thread's THD.
250251
251252
thd->enter_cond() requires the mutex to be acquired in advance.
252253
253-
thd->exit_cond() unregisters the condition variable and mutex and
254-
releases the mutex.
254+
thd->exit_cond() unregisters the condition variable and mutex. Requires
255+
the mutex to be released in advance.
255256
256257
If you want to have a Debug Sync point with the wait, please place it
257258
behind enter_cond(). Only then you can safely decide, if the wait will
@@ -280,6 +281,7 @@
280281
[DEBUG_SYNC(thd, "sync_point_name");]
281282
mysql_cond_wait(&condition_variable, &mutex);
282283
}
284+
mysql_mutex_unlock(&mutex);
283285
thd->exit_cond(old_message);
284286
}
285287
@@ -291,7 +293,7 @@
291293
condition variable. It would just set THD::killed. But if we would not
292294
test it again, we would go asleep though we are killed. If the killing
293295
thread would kill us when we are after the second test, but still
294-
before sleeping, we hold the mutex, which is registered in mysys_var.
296+
before sleeping, we hold the mutex, which is registered in THD.
295297
The killing thread would try to acquire the mutex before signaling
296298
the condition variable. Since the mutex is only released implicitly in
297299
mysql_cond_wait(), the signaling happens at the right place. We
@@ -1903,19 +1905,13 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
19031905
mutex and cond. This would prohibit the use of DEBUG_SYNC
19041906
between other places of enter_cond() and exit_cond().
19051907
1906-
We need to check for existence of thd->mysys_var to also make
1907-
it possible to use DEBUG_SYNC framework in scheduler when this
1908-
variable has been set to NULL.
1908+
Note that we cannot lock LOCK_current_cond here. See comment
1909+
in THD::enter_cond().
19091910
*/
1910-
if (thd->mysys_var)
1911-
{
1912-
old_mutex= thd->mysys_var->current_mutex;
1913-
old_cond= thd->mysys_var->current_cond;
1914-
thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex;
1915-
thd->mysys_var->current_cond= &debug_sync_global.ds_cond;
1916-
}
1917-
else
1918-
old_mutex= NULL;
1911+
old_mutex= thd->current_mutex;
1912+
old_cond= thd->current_cond;
1913+
thd->current_mutex= &debug_sync_global.ds_mutex;
1914+
thd->current_cond= &debug_sync_global.ds_cond;
19191915

19201916
set_timespec(&abstime, action->timeout);
19211917
DBUG_EXECUTE("debug_sync_exec", {
@@ -1974,11 +1970,11 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
19741970
mysql_mutex_unlock(&debug_sync_global.ds_mutex);
19751971
if (old_mutex)
19761972
{
1977-
mysql_mutex_lock(&thd->mysys_var->mutex);
1978-
thd->mysys_var->current_mutex= old_mutex;
1979-
thd->mysys_var->current_cond= old_cond;
1973+
mysql_mutex_lock(&thd->LOCK_current_cond);
1974+
thd->current_mutex= old_mutex;
1975+
thd->current_cond= old_cond;
1976+
mysql_mutex_unlock(&thd->LOCK_current_cond);
19801977
debug_sync_thd_proc_info(thd, old_proc_info);
1981-
mysql_mutex_unlock(&thd->mysys_var->mutex);
19821978
}
19831979
else
19841980
debug_sync_thd_proc_info(thd, old_proc_info);

0 commit comments

Comments
 (0)