mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -38,7 +38,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \
|
|||||||
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
|
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
|
||||||
my_handler.h my_time.h \
|
my_handler.h my_time.h \
|
||||||
my_vle.h my_user.h my_atomic.h atomic/nolock.h \
|
my_vle.h my_user.h my_atomic.h atomic/nolock.h \
|
||||||
atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \
|
atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \
|
||||||
atomic/solaris.h \
|
atomic/solaris.h \
|
||||||
atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h
|
atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#ifndef ATOMIC_RWLOCK_INCLUDED
|
||||||
|
#define ATOMIC_RWLOCK_INCLUDED
|
||||||
|
|
||||||
/* Copyright (C) 2006 MySQL AB
|
/* Copyright (C) 2006 MySQL AB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -13,7 +16,8 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t;
|
typedef struct {pthread_mutex_t rw;} my_atomic_rwlock_t;
|
||||||
|
#define MY_ATOMIC_MODE_RWLOCKS 1
|
||||||
|
|
||||||
#ifdef MY_ATOMIC_MODE_DUMMY
|
#ifdef MY_ATOMIC_MODE_DUMMY
|
||||||
/*
|
/*
|
||||||
@ -31,18 +35,27 @@ typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t;
|
|||||||
#define my_atomic_rwlock_wrunlock(name)
|
#define my_atomic_rwlock_wrunlock(name)
|
||||||
#define MY_ATOMIC_MODE "dummy (non-atomic)"
|
#define MY_ATOMIC_MODE "dummy (non-atomic)"
|
||||||
#else
|
#else
|
||||||
#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw)
|
/*
|
||||||
#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0)
|
we're using read-write lock macros but map them to mutex locks, and they're
|
||||||
#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw)
|
faster. Still, having semantically rich API we can change the
|
||||||
#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw)
|
underlying implementation, if necessary.
|
||||||
#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw)
|
*/
|
||||||
#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw)
|
#define my_atomic_rwlock_destroy(name) pthread_mutex_destroy(& (name)->rw)
|
||||||
#define MY_ATOMIC_MODE "rwlocks"
|
#define my_atomic_rwlock_init(name) pthread_mutex_init(& (name)->rw, 0)
|
||||||
|
#define my_atomic_rwlock_rdlock(name) pthread_mutex_lock(& (name)->rw)
|
||||||
|
#define my_atomic_rwlock_wrlock(name) pthread_mutex_lock(& (name)->rw)
|
||||||
|
#define my_atomic_rwlock_rdunlock(name) pthread_mutex_unlock(& (name)->rw)
|
||||||
|
#define my_atomic_rwlock_wrunlock(name) pthread_mutex_unlock(& (name)->rw)
|
||||||
|
#define MY_ATOMIC_MODE "mutex"
|
||||||
|
#ifndef MY_ATOMIC_MODE_RWLOCKS
|
||||||
|
#define MY_ATOMIC_MODE_RWLOCKS 1
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define make_atomic_add_body(S) int ## S sav; sav= *a; *a+= v; v=sav;
|
#define make_atomic_add_body(S) int ## S sav; sav= *a; *a+= v; v=sav;
|
||||||
#define make_atomic_swap_body(S) int ## S sav; sav= *a; *a= v; v=sav;
|
#define make_atomic_fas_body(S) int ## S sav; sav= *a; *a= v; v=sav;
|
||||||
#define make_atomic_cas_body(S) if ((ret= (*a == *cmp))) *a= set; else *cmp=*a;
|
#define make_atomic_cas_body(S) if ((ret= (*a == *cmp))) *a= set; else *cmp=*a;
|
||||||
#define make_atomic_load_body(S) ret= *a;
|
#define make_atomic_load_body(S) ret= *a;
|
||||||
#define make_atomic_store_body(S) *a= v;
|
#define make_atomic_store_body(S) *a= v;
|
||||||
|
|
||||||
|
#endif /* ATOMIC_RWLOCK_INCLUDED */
|
||||||
|
@ -42,15 +42,37 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MY_ATOMIC_NO_XADD
|
#ifndef MY_ATOMIC_NO_XADD
|
||||||
#define make_atomic_add_body(S) \
|
#define make_atomic_add_body(S) make_atomic_add_body ## S
|
||||||
asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a))
|
#define make_atomic_cas_body(S) make_atomic_cas_body ## S
|
||||||
#endif
|
#endif
|
||||||
#define make_atomic_fas_body(S) \
|
|
||||||
asm volatile ("xchg %0, %1;" : "+q" (v) , "+m" (*a))
|
#define make_atomic_add_body32 \
|
||||||
#define make_atomic_cas_body(S) \
|
asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a))
|
||||||
|
|
||||||
|
#define make_atomic_cas_body32 \
|
||||||
asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \
|
asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \
|
||||||
: "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set))
|
: "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set))
|
||||||
|
|
||||||
|
#define make_atomic_cas_bodyptr make_atomic_cas_body32
|
||||||
|
|
||||||
|
#ifndef __x86_64__
|
||||||
|
#define make_atomic_add_body64 make_atomic_add_body32
|
||||||
|
#define make_atomic_cas_body64 make_atomic_cas_body32
|
||||||
|
#else
|
||||||
|
#define make_atomic_add_body64 \
|
||||||
|
int64 tmp=*a; \
|
||||||
|
while (!my_atomic_cas64(a, &tmp, tmp+v)); \
|
||||||
|
v=tmp;
|
||||||
|
#define make_atomic_cas_body64 \
|
||||||
|
int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \
|
||||||
|
asm volatile (LOCK_prefix "; cmpxchg8b %0; setz %2;" \
|
||||||
|
: "+m" (*a), "+A" (*cmp), "=q" (ret) \
|
||||||
|
:"b" (ebx), "c" (ecx))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define make_atomic_fas_body(S) \
|
||||||
|
asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a))
|
||||||
|
|
||||||
#ifdef MY_ATOMIC_MODE_DUMMY
|
#ifdef MY_ATOMIC_MODE_DUMMY
|
||||||
#define make_atomic_load_body(S) ret=*a
|
#define make_atomic_load_body(S) ret=*a
|
||||||
#define make_atomic_store_body(S) *a=v
|
#define make_atomic_store_body(S) *a=v
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
my_atomic_store#(&var, what)
|
my_atomic_store#(&var, what)
|
||||||
store 'what' in *var
|
store 'what' in *var
|
||||||
|
|
||||||
'#' is substituted by a size suffix - 8, 16, 32, or ptr
|
'#' is substituted by a size suffix - 8, 16, 32, 64, or ptr
|
||||||
(e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr).
|
(e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr).
|
||||||
|
|
||||||
NOTE This operations are not always atomic, so they always must be
|
NOTE This operations are not always atomic, so they always must be
|
||||||
@ -129,6 +129,7 @@
|
|||||||
make_transparent_unions(8)
|
make_transparent_unions(8)
|
||||||
make_transparent_unions(16)
|
make_transparent_unions(16)
|
||||||
make_transparent_unions(32)
|
make_transparent_unions(32)
|
||||||
|
make_transparent_unions(64)
|
||||||
make_transparent_unions(ptr)
|
make_transparent_unions(ptr)
|
||||||
#undef uintptr
|
#undef uintptr
|
||||||
#undef make_transparent_unions
|
#undef make_transparent_unions
|
||||||
@ -140,10 +141,12 @@ make_transparent_unions(ptr)
|
|||||||
#define U_8 int8
|
#define U_8 int8
|
||||||
#define U_16 int16
|
#define U_16 int16
|
||||||
#define U_32 int32
|
#define U_32 int32
|
||||||
|
#define U_64 int64
|
||||||
#define U_ptr intptr
|
#define U_ptr intptr
|
||||||
#define Uv_8 int8
|
#define Uv_8 int8
|
||||||
#define Uv_16 int16
|
#define Uv_16 int16
|
||||||
#define Uv_32 int32
|
#define Uv_32 int32
|
||||||
|
#define Uv_64 int64
|
||||||
#define Uv_ptr intptr
|
#define Uv_ptr intptr
|
||||||
#define U_a volatile *a
|
#define U_a volatile *a
|
||||||
#define U_cmp *cmp
|
#define U_cmp *cmp
|
||||||
@ -217,6 +220,7 @@ make_atomic_cas(8)
|
|||||||
make_atomic_cas(16)
|
make_atomic_cas(16)
|
||||||
#endif
|
#endif
|
||||||
make_atomic_cas(32)
|
make_atomic_cas(32)
|
||||||
|
make_atomic_cas(64)
|
||||||
make_atomic_cas(ptr)
|
make_atomic_cas(ptr)
|
||||||
|
|
||||||
#ifdef MY_ATOMIC_HAS_8_16
|
#ifdef MY_ATOMIC_HAS_8_16
|
||||||
@ -224,12 +228,14 @@ make_atomic_add(8)
|
|||||||
make_atomic_add(16)
|
make_atomic_add(16)
|
||||||
#endif
|
#endif
|
||||||
make_atomic_add(32)
|
make_atomic_add(32)
|
||||||
|
make_atomic_add(64)
|
||||||
|
|
||||||
#ifdef MY_ATOMIC_HAS_8_16
|
#ifdef MY_ATOMIC_HAS_8_16
|
||||||
make_atomic_load(8)
|
make_atomic_load(8)
|
||||||
make_atomic_load(16)
|
make_atomic_load(16)
|
||||||
#endif
|
#endif
|
||||||
make_atomic_load(32)
|
make_atomic_load(32)
|
||||||
|
make_atomic_load(64)
|
||||||
make_atomic_load(ptr)
|
make_atomic_load(ptr)
|
||||||
|
|
||||||
#ifdef MY_ATOMIC_HAS_8_16
|
#ifdef MY_ATOMIC_HAS_8_16
|
||||||
@ -237,6 +243,7 @@ make_atomic_fas(8)
|
|||||||
make_atomic_fas(16)
|
make_atomic_fas(16)
|
||||||
#endif
|
#endif
|
||||||
make_atomic_fas(32)
|
make_atomic_fas(32)
|
||||||
|
make_atomic_fas(64)
|
||||||
make_atomic_fas(ptr)
|
make_atomic_fas(ptr)
|
||||||
|
|
||||||
#ifdef MY_ATOMIC_HAS_8_16
|
#ifdef MY_ATOMIC_HAS_8_16
|
||||||
@ -244,6 +251,7 @@ make_atomic_store(8)
|
|||||||
make_atomic_store(16)
|
make_atomic_store(16)
|
||||||
#endif
|
#endif
|
||||||
make_atomic_store(32)
|
make_atomic_store(32)
|
||||||
|
make_atomic_store(64)
|
||||||
make_atomic_store(ptr)
|
make_atomic_store(ptr)
|
||||||
|
|
||||||
#ifdef _atomic_h_cleanup_
|
#ifdef _atomic_h_cleanup_
|
||||||
@ -254,10 +262,12 @@ make_atomic_store(ptr)
|
|||||||
#undef U_8
|
#undef U_8
|
||||||
#undef U_16
|
#undef U_16
|
||||||
#undef U_32
|
#undef U_32
|
||||||
|
#undef U_64
|
||||||
#undef U_ptr
|
#undef U_ptr
|
||||||
#undef Uv_8
|
#undef Uv_8
|
||||||
#undef Uv_16
|
#undef Uv_16
|
||||||
#undef Uv_32
|
#undef Uv_32
|
||||||
|
#undef Uv_64
|
||||||
#undef Uv_ptr
|
#undef Uv_ptr
|
||||||
#undef a
|
#undef a
|
||||||
#undef cmp
|
#undef cmp
|
||||||
|
@ -832,6 +832,8 @@ typedef SOCKET_SIZE_TYPE size_socket;
|
|||||||
#endif
|
#endif
|
||||||
#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
|
#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
|
||||||
|
|
||||||
|
#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL)
|
||||||
|
#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL
|
||||||
#define INT_MIN32 (~0x7FFFFFFFL)
|
#define INT_MIN32 (~0x7FFFFFFFL)
|
||||||
#define INT_MAX32 0x7FFFFFFFL
|
#define INT_MAX32 0x7FFFFFFFL
|
||||||
#define UINT_MAX32 0xFFFFFFFFL
|
#define UINT_MAX32 0xFFFFFFFFL
|
||||||
|
@ -132,9 +132,10 @@ post_init_event_thread(THD *thd)
|
|||||||
pthread_mutex_lock(&LOCK_thread_count);
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
thread_count++;
|
thread_count++;
|
||||||
thread_running++;
|
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
|
inc_thread_running();
|
||||||
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,10 +157,12 @@ deinit_event_thread(THD *thd)
|
|||||||
DBUG_PRINT("exit", ("Event thread finishing"));
|
DBUG_PRINT("exit", ("Event thread finishing"));
|
||||||
pthread_mutex_lock(&LOCK_thread_count);
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
thread_count--;
|
thread_count--;
|
||||||
thread_running--;
|
|
||||||
delete thd;
|
delete thd;
|
||||||
pthread_cond_broadcast(&COND_thread_count);
|
pthread_cond_broadcast(&COND_thread_count);
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
|
dec_thread_running();
|
||||||
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -417,10 +420,12 @@ Event_scheduler::start()
|
|||||||
net_end(&new_thd->net);
|
net_end(&new_thd->net);
|
||||||
pthread_mutex_lock(&LOCK_thread_count);
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
thread_count--;
|
thread_count--;
|
||||||
thread_running--;
|
|
||||||
delete new_thd;
|
delete new_thd;
|
||||||
pthread_cond_broadcast(&COND_thread_count);
|
pthread_cond_broadcast(&COND_thread_count);
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
|
dec_thread_running();
|
||||||
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
UNLOCK_DATA();
|
UNLOCK_DATA();
|
||||||
@ -550,10 +555,12 @@ error:
|
|||||||
net_end(&new_thd->net);
|
net_end(&new_thd->net);
|
||||||
pthread_mutex_lock(&LOCK_thread_count);
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
thread_count--;
|
thread_count--;
|
||||||
thread_running--;
|
|
||||||
delete new_thd;
|
delete new_thd;
|
||||||
pthread_cond_broadcast(&COND_thread_count);
|
pthread_cond_broadcast(&COND_thread_count);
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
|
dec_thread_running();
|
||||||
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
}
|
}
|
||||||
delete event_name;
|
delete event_name;
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
@ -3026,9 +3026,9 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
|
|||||||
{
|
{
|
||||||
thd->set_time((time_t)when);
|
thd->set_time((time_t)when);
|
||||||
thd->set_query((char*)query_arg, q_len_arg);
|
thd->set_query((char*)query_arg, q_len_arg);
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id = next_query_id();
|
thd->query_id = next_query_id();
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
thd->variables.pseudo_thread_id= thread_id; // for temp tables
|
thd->variables.pseudo_thread_id= thread_id; // for temp tables
|
||||||
DBUG_PRINT("query",("%s",thd->query));
|
DBUG_PRINT("query",("%s",thd->query));
|
||||||
|
|
||||||
@ -4504,9 +4504,9 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
|
|||||||
if (rpl_filter->db_ok(thd->db))
|
if (rpl_filter->db_ok(thd->db))
|
||||||
{
|
{
|
||||||
thd->set_time((time_t)when);
|
thd->set_time((time_t)when);
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id = next_query_id();
|
thd->query_id = next_query_id();
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
/*
|
/*
|
||||||
Initing thd->row_count is not necessary in theory as this variable has no
|
Initing thd->row_count is not necessary in theory as this variable has no
|
||||||
influence in the case of the slave SQL thread (it is used to generate a
|
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)
|
|||||||
DBUG_ASSERT(rli->sql_thd == thd);
|
DBUG_ASSERT(rli->sql_thd == thd);
|
||||||
|
|
||||||
/* Step the query id to mark what columns that are actually used. */
|
/* Step the query id to mark what columns that are actually used. */
|
||||||
pthread_mutex_lock(&LOCK_thread_count);
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id= next_query_id();
|
thd->query_id= next_query_id();
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
|
|
||||||
if (!(memory= my_multi_malloc(MYF(MY_WME),
|
if (!(memory= my_multi_malloc(MYF(MY_WME),
|
||||||
&table_list, (uint) sizeof(RPL_TABLE_LIST),
|
&table_list, (uint) sizeof(RPL_TABLE_LIST),
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "sql_array.h"
|
#include "sql_array.h"
|
||||||
#include "sql_plugin.h"
|
#include "sql_plugin.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
#include <my_atomic.h>
|
||||||
|
|
||||||
class Parser_state;
|
class Parser_state;
|
||||||
|
|
||||||
@ -75,11 +76,49 @@ typedef ulong nesting_map; /* Used for flags of nesting constructs */
|
|||||||
typedef ulonglong nested_join_map;
|
typedef ulonglong nested_join_map;
|
||||||
|
|
||||||
/* query_id */
|
/* query_id */
|
||||||
typedef ulonglong query_id_t;
|
typedef int64 query_id_t;
|
||||||
extern query_id_t global_query_id;
|
extern query_id_t global_query_id;
|
||||||
|
extern int32 thread_running;
|
||||||
|
extern my_atomic_rwlock_t global_query_id_lock;
|
||||||
|
|
||||||
/* increment query_id and return it. */
|
/* increment query_id and return it. */
|
||||||
inline query_id_t next_query_id() { return global_query_id++; }
|
inline query_id_t next_query_id()
|
||||||
|
{
|
||||||
|
query_id_t id;
|
||||||
|
id= my_atomic_add64(&global_query_id, 1);
|
||||||
|
return (id+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline query_id_t get_query_id()
|
||||||
|
{
|
||||||
|
query_id_t id;
|
||||||
|
id= my_atomic_load64(&global_query_id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32
|
||||||
|
inc_thread_running()
|
||||||
|
{
|
||||||
|
int32 num_thread_running;
|
||||||
|
num_thread_running= my_atomic_add32(&thread_running, 1);
|
||||||
|
return (num_thread_running+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32
|
||||||
|
dec_thread_running()
|
||||||
|
{
|
||||||
|
int32 num_thread_running;
|
||||||
|
num_thread_running= my_atomic_add32(&thread_running, -1);
|
||||||
|
return (num_thread_running-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32
|
||||||
|
get_thread_running()
|
||||||
|
{
|
||||||
|
int32 num_thread_running;
|
||||||
|
num_thread_running= my_atomic_load32(&thread_running);
|
||||||
|
return num_thread_running;
|
||||||
|
}
|
||||||
|
|
||||||
/* useful constants */
|
/* useful constants */
|
||||||
extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty;
|
extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty;
|
||||||
@ -1994,7 +2033,7 @@ extern bool opt_ignore_builtin_innodb;
|
|||||||
extern my_bool opt_character_set_client_handshake;
|
extern my_bool opt_character_set_client_handshake;
|
||||||
extern bool volatile abort_loop, shutdown_in_progress;
|
extern bool volatile abort_loop, shutdown_in_progress;
|
||||||
extern bool in_bootstrap;
|
extern bool in_bootstrap;
|
||||||
extern uint volatile thread_count, thread_running, global_read_lock;
|
extern uint volatile thread_count, global_read_lock;
|
||||||
extern uint connection_count;
|
extern uint connection_count;
|
||||||
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
|
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
|
||||||
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
|
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
|
||||||
|
@ -523,7 +523,8 @@ uint mysqld_port_timeout;
|
|||||||
uint delay_key_write_options, protocol_version;
|
uint delay_key_write_options, protocol_version;
|
||||||
uint lower_case_table_names;
|
uint lower_case_table_names;
|
||||||
uint tc_heuristic_recover= 0;
|
uint tc_heuristic_recover= 0;
|
||||||
uint volatile thread_count, thread_running;
|
uint volatile thread_count;
|
||||||
|
int32 thread_running;
|
||||||
ulonglong thd_startup_options;
|
ulonglong thd_startup_options;
|
||||||
ulong back_log, connect_timeout, concurrency, server_id;
|
ulong back_log, connect_timeout, concurrency, server_id;
|
||||||
ulong table_cache_size, table_def_size;
|
ulong table_cache_size, table_def_size;
|
||||||
@ -539,6 +540,7 @@ ulonglong max_binlog_cache_size=0;
|
|||||||
ulong query_cache_size=0;
|
ulong query_cache_size=0;
|
||||||
ulong refresh_version; /* Increments on each reload */
|
ulong refresh_version; /* Increments on each reload */
|
||||||
query_id_t global_query_id;
|
query_id_t global_query_id;
|
||||||
|
my_atomic_rwlock_t global_query_id_lock;
|
||||||
ulong aborted_threads, aborted_connects;
|
ulong aborted_threads, aborted_connects;
|
||||||
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
|
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
|
||||||
ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
|
ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
|
||||||
@ -1349,6 +1351,7 @@ void clean_up(bool print_message)
|
|||||||
DBUG_PRINT("quit", ("Error messages freed"));
|
DBUG_PRINT("quit", ("Error messages freed"));
|
||||||
/* Tell main we are ready */
|
/* Tell main we are ready */
|
||||||
logger.cleanup_end();
|
logger.cleanup_end();
|
||||||
|
my_atomic_rwlock_destroy(&global_query_id_lock);
|
||||||
(void) pthread_mutex_lock(&LOCK_thread_count);
|
(void) pthread_mutex_lock(&LOCK_thread_count);
|
||||||
DBUG_PRINT("quit", ("got thread count lock"));
|
DBUG_PRINT("quit", ("got thread count lock"));
|
||||||
ready_to_exit=1;
|
ready_to_exit=1;
|
||||||
@ -7730,6 +7733,7 @@ static int mysql_init_variables(void)
|
|||||||
what_to_log= ~ (1L << (uint) COM_TIME);
|
what_to_log= ~ (1L << (uint) COM_TIME);
|
||||||
refresh_version= 1L; /* Increments on each reload */
|
refresh_version= 1L; /* Increments on each reload */
|
||||||
global_query_id= thread_id= 1L;
|
global_query_id= thread_id= 1L;
|
||||||
|
my_atomic_rwlock_init(&global_query_id_lock);
|
||||||
strmov(server_version, MYSQL_SERVER_VERSION);
|
strmov(server_version, MYSQL_SERVER_VERSION);
|
||||||
myisam_recover_options_str= sql_mode_str= "OFF";
|
myisam_recover_options_str= sql_mode_str= "OFF";
|
||||||
myisam_stats_method_str= "nulls_unequal";
|
myisam_stats_method_str= "nulls_unequal";
|
||||||
|
@ -2702,9 +2702,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
*/
|
*/
|
||||||
thd->lex= m_lex;
|
thd->lex= m_lex;
|
||||||
|
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id= next_query_id();
|
thd->query_id= next_query_id();
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
|
|
||||||
if (thd->prelocked_mode == NON_PRELOCKED)
|
if (thd->prelocked_mode == NON_PRELOCKED)
|
||||||
{
|
{
|
||||||
|
@ -505,7 +505,9 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||||||
We don't need to obtain LOCK_thread_count here because in bootstrap
|
We don't need to obtain LOCK_thread_count here because in bootstrap
|
||||||
mode we have only one thread.
|
mode we have only one thread.
|
||||||
*/
|
*/
|
||||||
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id=next_query_id();
|
thd->query_id=next_query_id();
|
||||||
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
thd->set_time();
|
thd->set_time();
|
||||||
mysql_parse(thd, thd->query, length, & found_semicolon);
|
mysql_parse(thd, thd->query, length, & found_semicolon);
|
||||||
close_thread_tables(thd); // Free tables
|
close_thread_tables(thd); // Free tables
|
||||||
@ -971,29 +973,30 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
thd->enable_slow_log= TRUE;
|
thd->enable_slow_log= TRUE;
|
||||||
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
|
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
|
||||||
thd->set_time();
|
thd->set_time();
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id= global_query_id;
|
{
|
||||||
|
query_id_t query_id;
|
||||||
switch( command ) {
|
switch( command ) {
|
||||||
/* Ignore these statements. */
|
/* Ignore these statements. */
|
||||||
case COM_STATISTICS:
|
case COM_STATISTICS:
|
||||||
case COM_PING:
|
case COM_PING:
|
||||||
break;
|
query_id= get_query_id();
|
||||||
/* Only increase id on these statements but don't count them. */
|
break;
|
||||||
case COM_STMT_PREPARE:
|
/* Only increase id on these statements but don't count them. */
|
||||||
case COM_STMT_CLOSE:
|
case COM_STMT_PREPARE:
|
||||||
case COM_STMT_RESET:
|
case COM_STMT_CLOSE:
|
||||||
next_query_id();
|
case COM_STMT_RESET:
|
||||||
break;
|
query_id= next_query_id() - 1;
|
||||||
/* Increase id and count all other statements. */
|
break;
|
||||||
default:
|
/* Increase id and count all other statements. */
|
||||||
statistic_increment(thd->status_var.questions, &LOCK_status);
|
default:
|
||||||
next_query_id();
|
statistic_increment(thd->status_var.questions, &LOCK_status);
|
||||||
|
query_id= next_query_id() - 1;
|
||||||
|
}
|
||||||
|
thd->query_id= query_id;
|
||||||
}
|
}
|
||||||
|
inc_thread_running();
|
||||||
thread_running++;
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clear the set of flags that are expected to be cleared at the
|
Clear the set of flags that are expected to be cleared at the
|
||||||
@ -1259,15 +1262,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
(char *) thd->security_ctx->host_or_ip);
|
(char *) thd->security_ctx->host_or_ip);
|
||||||
|
|
||||||
thd->set_query(beginning_of_next_stmt, length);
|
thd->set_query(beginning_of_next_stmt, length);
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
||||||
/*
|
/*
|
||||||
Count each statement from the client.
|
Count each statement from the client.
|
||||||
*/
|
*/
|
||||||
statistic_increment(thd->status_var.questions, &LOCK_status);
|
statistic_increment(thd->status_var.questions, &LOCK_status);
|
||||||
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thd->query_id= next_query_id();
|
thd->query_id= next_query_id();
|
||||||
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
thd->set_time(); /* Reset the query start time. */
|
thd->set_time(); /* Reset the query start time. */
|
||||||
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
||||||
mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt);
|
mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1610,9 +1613,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
thd_proc_info(thd, "cleaning up");
|
thd_proc_info(thd, "cleaning up");
|
||||||
thd->set_query(NULL, 0);
|
thd->set_query(NULL, 0);
|
||||||
thd->command=COM_SLEEP;
|
thd->command=COM_SLEEP;
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
thread_running--;
|
dec_thread_running();
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
thd_proc_info(thd, 0);
|
thd_proc_info(thd, 0);
|
||||||
thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
|
thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
|
||||||
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
|
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2006 MySQL AB
|
/* Copyright (C) 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -13,10 +13,7 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#include <my_global.h>
|
#include "thr_template.c"
|
||||||
#include <my_sys.h>
|
|
||||||
#include <my_atomic.h>
|
|
||||||
#include <tap.h>
|
|
||||||
|
|
||||||
/* at least gcc 3.4.5 and 3.4.6 (but not 3.2.3) on RHEL */
|
/* at least gcc 3.4.5 and 3.4.6 (but not 3.2.3) on RHEL */
|
||||||
#if __GNUC__ == 3 && __GNUC_MINOR__ == 4
|
#if __GNUC__ == 3 && __GNUC_MINOR__ == 4
|
||||||
@ -25,181 +22,162 @@
|
|||||||
#define GCC_BUG_WORKAROUND
|
#define GCC_BUG_WORKAROUND
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32 a32,b32,c32;
|
volatile uint32 b32;
|
||||||
|
volatile int32 c32;
|
||||||
my_atomic_rwlock_t rwl;
|
my_atomic_rwlock_t rwl;
|
||||||
|
|
||||||
pthread_attr_t thr_attr;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t cond;
|
|
||||||
int N;
|
|
||||||
|
|
||||||
/* add and sub a random number in a loop. Must get 0 at the end */
|
/* add and sub a random number in a loop. Must get 0 at the end */
|
||||||
pthread_handler_t test_atomic_add_handler(void *arg)
|
pthread_handler_t test_atomic_add(void *arg)
|
||||||
{
|
{
|
||||||
int m=*(int *)arg;
|
int m= (*(int *)arg)/2;
|
||||||
GCC_BUG_WORKAROUND int32 x;
|
GCC_BUG_WORKAROUND int32 x;
|
||||||
for (x=((int)((long)(&m))); m ; m--)
|
for (x= ((int)(intptr)(&m)); m ; m--)
|
||||||
{
|
{
|
||||||
x=x*m+0x87654321;
|
x= (x*m+0x87654321) & INT_MAX32;
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
my_atomic_add32(&a32, x);
|
my_atomic_add32(&bad, x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
my_atomic_add32(&a32, -x);
|
my_atomic_add32(&bad, -x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
N--;
|
if (!--running_threads) pthread_cond_signal(&cond);
|
||||||
if (!N) pthread_cond_signal(&cond);
|
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile int64 a64;
|
||||||
|
/* add and sub a random number in a loop. Must get 0 at the end */
|
||||||
|
pthread_handler_t test_atomic_add64(void *arg)
|
||||||
|
{
|
||||||
|
int m= (*(int *)arg)/2;
|
||||||
|
GCC_BUG_WORKAROUND int64 x;
|
||||||
|
for (x= ((int64)(intptr)(&m)); m ; m--)
|
||||||
|
{
|
||||||
|
x= (x*m+0xfdecba987654321LL) & INT_MAX64;
|
||||||
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
|
my_atomic_add64(&a64, x);
|
||||||
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
|
||||||
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
|
my_atomic_add64(&a64, -x);
|
||||||
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
if (!--running_threads)
|
||||||
|
{
|
||||||
|
bad= (a64 != 0);
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1. generate thread number 0..N-1 from b32
|
1. generate thread number 0..N-1 from b32
|
||||||
2. add it to a32
|
2. add it to bad
|
||||||
3. swap thread numbers in c32
|
3. swap thread numbers in c32
|
||||||
4. (optionally) one more swap to avoid 0 as a result
|
4. (optionally) one more swap to avoid 0 as a result
|
||||||
5. subtract result from a32
|
5. subtract result from bad
|
||||||
must get 0 in a32 at the end
|
must get 0 in bad at the end
|
||||||
*/
|
*/
|
||||||
pthread_handler_t test_atomic_swap_handler(void *arg)
|
pthread_handler_t test_atomic_fas(void *arg)
|
||||||
{
|
{
|
||||||
int m=*(int *)arg;
|
int m= *(int *)arg;
|
||||||
int32 x;
|
int32 x;
|
||||||
|
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
x=my_atomic_add32(&b32, 1);
|
x= my_atomic_add32(&b32, 1);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
my_atomic_add32(&a32, x);
|
my_atomic_add32(&bad, x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
|
||||||
for (; m ; m--)
|
for (; m ; m--)
|
||||||
{
|
{
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
x=my_atomic_swap32(&c32, x);
|
x= my_atomic_fas32(&c32, x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!x)
|
if (!x)
|
||||||
{
|
{
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
x=my_atomic_swap32(&c32, x);
|
x= my_atomic_fas32(&c32, x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
}
|
}
|
||||||
|
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
my_atomic_add32(&a32, -x);
|
my_atomic_add32(&bad, -x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
N--;
|
if (!--running_threads) pthread_cond_signal(&cond);
|
||||||
if (!N) pthread_cond_signal(&cond);
|
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
same as test_atomic_add_handler, but my_atomic_add32 is emulated with
|
same as test_atomic_add, but my_atomic_add32 is emulated with
|
||||||
(slower) my_atomic_cas32
|
my_atomic_cas32 - notice that the slowdown is proportional to the
|
||||||
|
number of CPUs
|
||||||
*/
|
*/
|
||||||
pthread_handler_t test_atomic_cas_handler(void *arg)
|
pthread_handler_t test_atomic_cas(void *arg)
|
||||||
{
|
{
|
||||||
int m=*(int *)arg, ok;
|
int m= (*(int *)arg)/2, ok= 0;
|
||||||
GCC_BUG_WORKAROUND int32 x,y;
|
GCC_BUG_WORKAROUND int32 x, y;
|
||||||
for (x=((int)((long)(&m))); m ; m--)
|
for (x= ((int)(intptr)(&m)); m ; m--)
|
||||||
{
|
{
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
y=my_atomic_load32(&a32);
|
y= my_atomic_load32(&bad);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
|
x= (x*m+0x87654321) & INT_MAX32;
|
||||||
x=x*m+0x87654321;
|
|
||||||
do {
|
do {
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
ok=my_atomic_cas32(&a32, &y, y+x);
|
ok= my_atomic_cas32(&bad, &y, (uint32)y+x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
} while (!ok);
|
} while (!ok) ;
|
||||||
do {
|
do {
|
||||||
my_atomic_rwlock_wrlock(&rwl);
|
my_atomic_rwlock_wrlock(&rwl);
|
||||||
ok=my_atomic_cas32(&a32, &y, y-x);
|
ok= my_atomic_cas32(&bad, &y, y-x);
|
||||||
my_atomic_rwlock_wrunlock(&rwl);
|
my_atomic_rwlock_wrunlock(&rwl);
|
||||||
} while (!ok);
|
} while (!ok) ;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
N--;
|
if (!--running_threads) pthread_cond_signal(&cond);
|
||||||
if (!N) pthread_cond_signal(&cond);
|
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_atomic(const char *test, pthread_handler handler, int n, int m)
|
|
||||||
|
void do_tests()
|
||||||
{
|
{
|
||||||
pthread_t t;
|
plan(6);
|
||||||
ulonglong now=my_getsystime();
|
|
||||||
|
|
||||||
a32= 0;
|
bad= my_atomic_initialize();
|
||||||
b32= 0;
|
ok(!bad, "my_atomic_initialize() returned %d", bad);
|
||||||
c32= 0;
|
|
||||||
|
|
||||||
diag("Testing %s with %d threads, %d iterations... ", test, n, m);
|
|
||||||
for (N=n ; n ; n--)
|
|
||||||
{
|
|
||||||
if (pthread_create(&t, &thr_attr, handler, &m) != 0)
|
|
||||||
{
|
|
||||||
diag("Could not create thread");
|
|
||||||
a32= 1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
while (N)
|
|
||||||
pthread_cond_wait(&cond, &mutex);
|
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
now=my_getsystime()-now;
|
|
||||||
err:
|
|
||||||
ok(a32 == 0, "tested %s in %g secs", test, ((double)now)/1e7);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
MY_INIT("my_atomic-t.c");
|
|
||||||
|
|
||||||
diag("N CPUs: %d", my_getncpus());
|
|
||||||
err= my_atomic_initialize();
|
|
||||||
|
|
||||||
plan(4);
|
|
||||||
ok(err == 0, "my_atomic_initialize() returned %d", err);
|
|
||||||
|
|
||||||
pthread_attr_init(&thr_attr);
|
|
||||||
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
|
||||||
pthread_mutex_init(&mutex, 0);
|
|
||||||
pthread_cond_init(&cond, 0);
|
|
||||||
my_atomic_rwlock_init(&rwl);
|
my_atomic_rwlock_init(&rwl);
|
||||||
|
|
||||||
#ifdef HPUX11
|
b32= c32= 0;
|
||||||
#define CYCLES 1000
|
test_concurrently("my_atomic_add32", test_atomic_add, THREADS, CYCLES);
|
||||||
#else
|
b32= c32= 0;
|
||||||
#define CYCLES 10000
|
test_concurrently("my_atomic_fas32", test_atomic_fas, THREADS, CYCLES);
|
||||||
#endif
|
b32= c32= 0;
|
||||||
#define THREADS 100
|
test_concurrently("my_atomic_cas32", test_atomic_cas, THREADS, CYCLES);
|
||||||
test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS, CYCLES);
|
|
||||||
test_atomic("my_atomic_swap32", test_atomic_swap_handler, THREADS, CYCLES);
|
{
|
||||||
test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS, CYCLES);
|
int64 b=0x1000200030004000LL;
|
||||||
/*
|
a64=0;
|
||||||
workaround until we know why it crashes randomly on some machine
|
my_atomic_add64(&a64, b);
|
||||||
(BUG#22320).
|
ok(a64==b, "add64");
|
||||||
*/
|
}
|
||||||
sleep(2);
|
a64=0;
|
||||||
|
test_concurrently("my_atomic_add64", test_atomic_add64, THREADS, CYCLES);
|
||||||
|
|
||||||
pthread_mutex_destroy(&mutex);
|
|
||||||
pthread_cond_destroy(&cond);
|
|
||||||
pthread_attr_destroy(&thr_attr);
|
|
||||||
my_atomic_rwlock_destroy(&rwl);
|
my_atomic_rwlock_destroy(&rwl);
|
||||||
return exit_status();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
92
unittest/mysys/thr_template.c
Normal file
92
unittest/mysys/thr_template.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/* Copyright (C) 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#include <my_global.h>
|
||||||
|
#include <my_sys.h>
|
||||||
|
#include <my_atomic.h>
|
||||||
|
#include <tap.h>
|
||||||
|
|
||||||
|
volatile uint32 bad;
|
||||||
|
pthread_attr_t thr_attr;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
uint running_threads;
|
||||||
|
|
||||||
|
void do_tests();
|
||||||
|
|
||||||
|
void test_concurrently(const char *test, pthread_handler handler, int n, int m)
|
||||||
|
{
|
||||||
|
pthread_t t;
|
||||||
|
ulonglong now= my_getsystime();
|
||||||
|
|
||||||
|
bad= 0;
|
||||||
|
|
||||||
|
diag("Testing %s with %d threads, %d iterations... ", test, n, m);
|
||||||
|
for (running_threads= n ; n ; n--)
|
||||||
|
{
|
||||||
|
if (pthread_create(&t, &thr_attr, handler, &m) != 0)
|
||||||
|
{
|
||||||
|
diag("Could not create thread");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
while (running_threads)
|
||||||
|
pthread_cond_wait(&cond, &mutex);
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
now= my_getsystime()-now;
|
||||||
|
ok(!bad, "tested %s in %g secs (%d)", test, ((double)now)/1e7, bad);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc __attribute__((unused)), char **argv)
|
||||||
|
{
|
||||||
|
MY_INIT("thd_template");
|
||||||
|
|
||||||
|
if (argv[1] && *argv[1])
|
||||||
|
DBUG_SET_INITIAL(argv[1]);
|
||||||
|
|
||||||
|
pthread_mutex_init(&mutex, 0);
|
||||||
|
pthread_cond_init(&cond, 0);
|
||||||
|
pthread_attr_init(&thr_attr);
|
||||||
|
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
|
#ifdef MY_ATOMIC_MODE_RWLOCKS
|
||||||
|
#if defined(HPUX11) || defined(__POWERPC__) /* showed to be very slow (scheduler-related) */
|
||||||
|
#define CYCLES 300
|
||||||
|
#else
|
||||||
|
#define CYCLES 3000
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define CYCLES 3000
|
||||||
|
#endif
|
||||||
|
#define THREADS 30
|
||||||
|
|
||||||
|
diag("N CPUs: %d, atomic ops: %s", my_getncpus(), MY_ATOMIC_MODE);
|
||||||
|
|
||||||
|
do_tests();
|
||||||
|
|
||||||
|
/*
|
||||||
|
workaround until we know why it crashes randomly on some machine
|
||||||
|
(BUG#22320).
|
||||||
|
*/
|
||||||
|
sleep(2);
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
|
pthread_attr_destroy(&thr_attr);
|
||||||
|
my_end(0);
|
||||||
|
return exit_status();
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user