Skip to content

Commit c4ce446

Browse files
author
Mikael Ronstrom
committed
Backported my_atomic from 6.0-codebase and added support for 64-bit atomics to enable removal of LOCK_thread_count from every query, removed LOCK_thread_count from use in dispatch_command and close of query which is used in every query, now uses atomic increments/decrements instead
1 parent 6e4f01f commit c4ce446

File tree

13 files changed

+337
-167
lines changed

13 files changed

+337
-167
lines changed

include/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \
3838
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
3939
my_handler.h my_time.h \
4040
my_vle.h my_user.h my_atomic.h atomic/nolock.h \
41-
atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \
41+
atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \
4242
atomic/solaris.h \
4343
atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h
4444

include/atomic/rwlock.h

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#ifndef ATOMIC_RWLOCK_INCLUDED
2+
#define ATOMIC_RWLOCK_INCLUDED
3+
14
/* Copyright (C) 2006 MySQL AB
25
36
This program is free software; you can redistribute it and/or modify
@@ -13,7 +16,8 @@
1316
along with this program; if not, write to the Free Software
1417
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1518

16-
typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t;
19+
typedef struct {pthread_mutex_t rw;} my_atomic_rwlock_t;
20+
#define MY_ATOMIC_MODE_RWLOCKS 1
1721

1822
#ifdef MY_ATOMIC_MODE_DUMMY
1923
/*
@@ -31,18 +35,27 @@ typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t;
3135
#define my_atomic_rwlock_wrunlock(name)
3236
#define MY_ATOMIC_MODE "dummy (non-atomic)"
3337
#else
34-
#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw)
35-
#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0)
36-
#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw)
37-
#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw)
38-
#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw)
39-
#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw)
40-
#define MY_ATOMIC_MODE "rwlocks"
38+
/*
39+
we're using read-write lock macros but map them to mutex locks, and they're
40+
faster. Still, having semantically rich API we can change the
41+
underlying implementation, if necessary.
42+
*/
43+
#define my_atomic_rwlock_destroy(name) pthread_mutex_destroy(& (name)->rw)
44+
#define my_atomic_rwlock_init(name) pthread_mutex_init(& (name)->rw, 0)
45+
#define my_atomic_rwlock_rdlock(name) pthread_mutex_lock(& (name)->rw)
46+
#define my_atomic_rwlock_wrlock(name) pthread_mutex_lock(& (name)->rw)
47+
#define my_atomic_rwlock_rdunlock(name) pthread_mutex_unlock(& (name)->rw)
48+
#define my_atomic_rwlock_wrunlock(name) pthread_mutex_unlock(& (name)->rw)
49+
#define MY_ATOMIC_MODE "mutex"
50+
#ifndef MY_ATOMIC_MODE_RWLOCKS
51+
#define MY_ATOMIC_MODE_RWLOCKS 1
52+
#endif
4153
#endif
4254

4355
#define make_atomic_add_body(S) int ## S sav; sav= *a; *a+= v; v=sav;
44-
#define make_atomic_swap_body(S) int ## S sav; sav= *a; *a= v; v=sav;
56+
#define make_atomic_fas_body(S) int ## S sav; sav= *a; *a= v; v=sav;
4557
#define make_atomic_cas_body(S) if ((ret= (*a == *cmp))) *a= set; else *cmp=*a;
4658
#define make_atomic_load_body(S) ret= *a;
4759
#define make_atomic_store_body(S) *a= v;
4860

61+
#endif /* ATOMIC_RWLOCK_INCLUDED */

include/atomic/x86-gcc.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,37 @@
4242
#endif
4343

4444
#ifndef MY_ATOMIC_NO_XADD
45-
#define make_atomic_add_body(S) \
46-
asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a))
45+
#define make_atomic_add_body(S) make_atomic_add_body ## S
46+
#define make_atomic_cas_body(S) make_atomic_cas_body ## S
4747
#endif
48-
#define make_atomic_fas_body(S) \
49-
asm volatile ("xchg %0, %1;" : "+q" (v) , "+m" (*a))
50-
#define make_atomic_cas_body(S) \
48+
49+
#define make_atomic_add_body32 \
50+
asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a))
51+
52+
#define make_atomic_cas_body32 \
5153
asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \
5254
: "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set))
5355

56+
#define make_atomic_cas_bodyptr make_atomic_cas_body32
57+
58+
#ifndef __x86_64__
59+
#define make_atomic_add_body64 make_atomic_add_body32
60+
#define make_atomic_cas_body64 make_atomic_cas_body32
61+
#else
62+
#define make_atomic_add_body64 \
63+
int64 tmp=*a; \
64+
while (!my_atomic_cas64(a, &tmp, tmp+v)); \
65+
v=tmp;
66+
#define make_atomic_cas_body64 \
67+
int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \
68+
asm volatile (LOCK_prefix "; cmpxchg8b %0; setz %2;" \
69+
: "+m" (*a), "+A" (*cmp), "=q" (ret) \
70+
:"b" (ebx), "c" (ecx))
71+
#endif
72+
73+
#define make_atomic_fas_body(S) \
74+
asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a))
75+
5476
#ifdef MY_ATOMIC_MODE_DUMMY
5577
#define make_atomic_load_body(S) ret=*a
5678
#define make_atomic_store_body(S) *a=v

include/my_atomic.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
my_atomic_store#(&var, what)
3838
store 'what' in *var
3939
40-
'#' is substituted by a size suffix - 8, 16, 32, or ptr
40+
'#' is substituted by a size suffix - 8, 16, 32, 64, or ptr
4141
(e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr).
4242
4343
NOTE This operations are not always atomic, so they always must be
@@ -129,6 +129,7 @@
129129
make_transparent_unions(8)
130130
make_transparent_unions(16)
131131
make_transparent_unions(32)
132+
make_transparent_unions(64)
132133
make_transparent_unions(ptr)
133134
#undef uintptr
134135
#undef make_transparent_unions
@@ -140,10 +141,12 @@ make_transparent_unions(ptr)
140141
#define U_8 int8
141142
#define U_16 int16
142143
#define U_32 int32
144+
#define U_64 int64
143145
#define U_ptr intptr
144146
#define Uv_8 int8
145147
#define Uv_16 int16
146148
#define Uv_32 int32
149+
#define Uv_64 int64
147150
#define Uv_ptr intptr
148151
#define U_a volatile *a
149152
#define U_cmp *cmp
@@ -217,33 +220,38 @@ make_atomic_cas(8)
217220
make_atomic_cas(16)
218221
#endif
219222
make_atomic_cas(32)
223+
make_atomic_cas(64)
220224
make_atomic_cas(ptr)
221225

222226
#ifdef MY_ATOMIC_HAS_8_16
223227
make_atomic_add(8)
224228
make_atomic_add(16)
225229
#endif
226230
make_atomic_add(32)
231+
make_atomic_add(64)
227232

228233
#ifdef MY_ATOMIC_HAS_8_16
229234
make_atomic_load(8)
230235
make_atomic_load(16)
231236
#endif
232237
make_atomic_load(32)
238+
make_atomic_load(64)
233239
make_atomic_load(ptr)
234240

235241
#ifdef MY_ATOMIC_HAS_8_16
236242
make_atomic_fas(8)
237243
make_atomic_fas(16)
238244
#endif
239245
make_atomic_fas(32)
246+
make_atomic_fas(64)
240247
make_atomic_fas(ptr)
241248

242249
#ifdef MY_ATOMIC_HAS_8_16
243250
make_atomic_store(8)
244251
make_atomic_store(16)
245252
#endif
246253
make_atomic_store(32)
254+
make_atomic_store(64)
247255
make_atomic_store(ptr)
248256

249257
#ifdef _atomic_h_cleanup_
@@ -254,10 +262,12 @@ make_atomic_store(ptr)
254262
#undef U_8
255263
#undef U_16
256264
#undef U_32
265+
#undef U_64
257266
#undef U_ptr
258267
#undef Uv_8
259268
#undef Uv_16
260269
#undef Uv_32
270+
#undef Uv_64
261271
#undef Uv_ptr
262272
#undef a
263273
#undef cmp

include/my_global.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,8 @@ typedef SOCKET_SIZE_TYPE size_socket;
832832
#endif
833833
#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
834834

835+
#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL)
836+
#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL
835837
#define INT_MIN32 (~0x7FFFFFFFL)
836838
#define INT_MAX32 0x7FFFFFFFL
837839
#define UINT_MAX32 0xFFFFFFFFL

sql/event_scheduler.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,10 @@ post_init_event_thread(THD *thd)
132132
pthread_mutex_lock(&LOCK_thread_count);
133133
threads.append(thd);
134134
thread_count++;
135-
thread_running++;
136135
pthread_mutex_unlock(&LOCK_thread_count);
137-
136+
my_atomic_rwlock_wrlock(&global_query_id_lock);
137+
inc_thread_running();
138+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
138139
return FALSE;
139140
}
140141

@@ -156,10 +157,12 @@ deinit_event_thread(THD *thd)
156157
DBUG_PRINT("exit", ("Event thread finishing"));
157158
pthread_mutex_lock(&LOCK_thread_count);
158159
thread_count--;
159-
thread_running--;
160160
delete thd;
161161
pthread_cond_broadcast(&COND_thread_count);
162162
pthread_mutex_unlock(&LOCK_thread_count);
163+
my_atomic_rwlock_wrlock(&global_query_id_lock);
164+
dec_thread_running();
165+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
163166
}
164167

165168

@@ -417,10 +420,12 @@ Event_scheduler::start()
417420
net_end(&new_thd->net);
418421
pthread_mutex_lock(&LOCK_thread_count);
419422
thread_count--;
420-
thread_running--;
421423
delete new_thd;
422424
pthread_cond_broadcast(&COND_thread_count);
423425
pthread_mutex_unlock(&LOCK_thread_count);
426+
my_atomic_rwlock_wrlock(&global_query_id_lock);
427+
dec_thread_running();
428+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
424429
}
425430
end:
426431
UNLOCK_DATA();
@@ -550,10 +555,12 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name)
550555
net_end(&new_thd->net);
551556
pthread_mutex_lock(&LOCK_thread_count);
552557
thread_count--;
553-
thread_running--;
554558
delete new_thd;
555559
pthread_cond_broadcast(&COND_thread_count);
556560
pthread_mutex_unlock(&LOCK_thread_count);
561+
my_atomic_rwlock_wrlock(&global_query_id_lock);
562+
dec_thread_running();
563+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
557564
}
558565
delete event_name;
559566
DBUG_RETURN(TRUE);

sql/log_event.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,9 +3026,9 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
30263026
{
30273027
thd->set_time((time_t)when);
30283028
thd->set_query((char*)query_arg, q_len_arg);
3029-
VOID(pthread_mutex_lock(&LOCK_thread_count));
3029+
my_atomic_rwlock_wrlock(&global_query_id_lock);
30303030
thd->query_id = next_query_id();
3031-
VOID(pthread_mutex_unlock(&LOCK_thread_count));
3031+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
30323032
thd->variables.pseudo_thread_id= thread_id; // for temp tables
30333033
DBUG_PRINT("query",("%s",thd->query));
30343034

@@ -4504,9 +4504,9 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
45044504
if (rpl_filter->db_ok(thd->db))
45054505
{
45064506
thd->set_time((time_t)when);
4507-
VOID(pthread_mutex_lock(&LOCK_thread_count));
4507+
my_atomic_rwlock_wrlock(&global_query_id_lock);
45084508
thd->query_id = next_query_id();
4509-
VOID(pthread_mutex_unlock(&LOCK_thread_count));
4509+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
45104510
/*
45114511
Initing thd->row_count is not necessary in theory as this variable has no
45124512
influence in the case of the slave SQL thread (it is used to generate a
@@ -8025,9 +8025,9 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
80258025
DBUG_ASSERT(rli->sql_thd == thd);
80268026

80278027
/* Step the query id to mark what columns that are actually used. */
8028-
pthread_mutex_lock(&LOCK_thread_count);
8028+
my_atomic_rwlock_wrlock(&global_query_id_lock);
80298029
thd->query_id= next_query_id();
8030-
pthread_mutex_unlock(&LOCK_thread_count);
8030+
my_atomic_rwlock_wrunlock(&global_query_id_lock);
80318031

80328032
if (!(memory= my_multi_malloc(MYF(MY_WME),
80338033
&table_list, (uint) sizeof(RPL_TABLE_LIST),

sql/mysql_priv.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "sql_array.h"
4444
#include "sql_plugin.h"
4545
#include "scheduler.h"
46+
#include <my_atomic.h>
4647

4748
class Parser_state;
4849

@@ -75,11 +76,49 @@ typedef ulong nesting_map; /* Used for flags of nesting constructs */
7576
typedef ulonglong nested_join_map;
7677

7778
/* query_id */
78-
typedef ulonglong query_id_t;
79+
typedef int64 query_id_t;
7980
extern query_id_t global_query_id;
81+
extern int32 thread_running;
82+
extern my_atomic_rwlock_t global_query_id_lock;
8083

8184
/* increment query_id and return it. */
82-
inline query_id_t next_query_id() { return global_query_id++; }
85+
inline query_id_t next_query_id()
86+
{
87+
query_id_t id;
88+
id= my_atomic_add64(&global_query_id, 1);
89+
return (id+1);
90+
}
91+
92+
inline query_id_t get_query_id()
93+
{
94+
query_id_t id;
95+
id= my_atomic_load64(&global_query_id);
96+
return id;
97+
}
98+
99+
inline int32
100+
inc_thread_running()
101+
{
102+
int32 num_thread_running;
103+
num_thread_running= my_atomic_add32(&thread_running, 1);
104+
return (num_thread_running+1);
105+
}
106+
107+
inline int32
108+
dec_thread_running()
109+
{
110+
int32 num_thread_running;
111+
num_thread_running= my_atomic_add32(&thread_running, -1);
112+
return (num_thread_running-1);
113+
}
114+
115+
inline int32
116+
get_thread_running()
117+
{
118+
int32 num_thread_running;
119+
num_thread_running= my_atomic_load32(&thread_running);
120+
return num_thread_running;
121+
}
83122

84123
/* useful constants */
85124
extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty;
@@ -1994,7 +2033,7 @@ extern bool opt_ignore_builtin_innodb;
19942033
extern my_bool opt_character_set_client_handshake;
19952034
extern bool volatile abort_loop, shutdown_in_progress;
19962035
extern bool in_bootstrap;
1997-
extern uint volatile thread_count, thread_running, global_read_lock;
2036+
extern uint volatile thread_count, global_read_lock;
19982037
extern uint connection_count;
19992038
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
20002039
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;

sql/mysqld.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,8 @@ uint mysqld_port_timeout;
523523
uint delay_key_write_options, protocol_version;
524524
uint lower_case_table_names;
525525
uint tc_heuristic_recover= 0;
526-
uint volatile thread_count, thread_running;
526+
uint volatile thread_count;
527+
int32 thread_running;
527528
ulonglong thd_startup_options;
528529
ulong back_log, connect_timeout, concurrency, server_id;
529530
ulong table_cache_size, table_def_size;
@@ -539,6 +540,7 @@ ulonglong max_binlog_cache_size=0;
539540
ulong query_cache_size=0;
540541
ulong refresh_version; /* Increments on each reload */
541542
query_id_t global_query_id;
543+
my_atomic_rwlock_t global_query_id_lock;
542544
ulong aborted_threads, aborted_connects;
543545
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
544546
ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
@@ -1349,6 +1351,7 @@ void clean_up(bool print_message)
13491351
DBUG_PRINT("quit", ("Error messages freed"));
13501352
/* Tell main we are ready */
13511353
logger.cleanup_end();
1354+
my_atomic_rwlock_destroy(&global_query_id_lock);
13521355
(void) pthread_mutex_lock(&LOCK_thread_count);
13531356
DBUG_PRINT("quit", ("got thread count lock"));
13541357
ready_to_exit=1;
@@ -7730,6 +7733,7 @@ static int mysql_init_variables(void)
77307733
what_to_log= ~ (1L << (uint) COM_TIME);
77317734
refresh_version= 1L; /* Increments on each reload */
77327735
global_query_id= thread_id= 1L;
7736+
my_atomic_rwlock_init(&global_query_id_lock);
77337737
strmov(server_version, MYSQL_SERVER_VERSION);
77347738
myisam_recover_options_str= sql_mode_str= "OFF";
77357739
myisam_stats_method_str= "nulls_unequal";

0 commit comments

Comments
 (0)