mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-33748 get rid of pthread_(get_/set_)specific, use thread_local
Apart from better performance when accessing thread local variables, we'll get rid of things that depend on initialization/cleanup of pthread_key_t variables. Where appropriate, use compiler-dependent pre-C++11 thread-local equivalents, where it makes sense, to avoid initialization check overhead that non-static thread_local can suffer from.
This commit is contained in:
parent
68fed7e785
commit
7c5fdc9b6a
26 changed files with 93 additions and 234 deletions
|
@ -379,7 +379,6 @@ CHECK_FUNCTION_EXISTS (pthread_attr_getguardsize HAVE_PTHREAD_ATTR_GETGUARDSIZE)
|
|||
CHECK_FUNCTION_EXISTS (pthread_attr_setstacksize HAVE_PTHREAD_ATTR_SETSTACKSIZE)
|
||||
CHECK_FUNCTION_EXISTS (pthread_condattr_create HAVE_PTHREAD_CONDATTR_CREATE)
|
||||
CHECK_FUNCTION_EXISTS (pthread_getaffinity_np HAVE_PTHREAD_GETAFFINITY_NP)
|
||||
CHECK_FUNCTION_EXISTS (pthread_key_delete HAVE_PTHREAD_KEY_DELETE)
|
||||
CHECK_FUNCTION_EXISTS (pthread_rwlock_rdlock HAVE_PTHREAD_RWLOCK_RDLOCK)
|
||||
CHECK_FUNCTION_EXISTS (pthread_sigmask HAVE_PTHREAD_SIGMASK)
|
||||
CHECK_FUNCTION_EXISTS (pthread_yield_np HAVE_PTHREAD_YIELD_NP)
|
||||
|
|
|
@ -183,4 +183,16 @@ rarely invoked function for size instead for speed. */
|
|||
|
||||
#include <my_attribute.h>
|
||||
|
||||
/*
|
||||
C++11 thread_local incurs a performance penalty on some platforms
|
||||
accessing "extern thread_local" variable (not static).
|
||||
To workaround, we use the platform specific thread local
|
||||
storage mechanism, which also available in plain C.
|
||||
*/
|
||||
#if defined (_MSC_VER)
|
||||
# define MY_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
# define MY_THREAD_LOCAL __thread
|
||||
#endif
|
||||
|
||||
#endif /* MY_COMPILER_INCLUDED */
|
||||
|
|
|
@ -109,14 +109,6 @@ int pthread_cancel(pthread_t thread);
|
|||
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
|
||||
|
||||
#undef SAFE_MUTEX /* This will cause conflicts */
|
||||
#define pthread_key(T,V) DWORD V
|
||||
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
|
||||
#define pthread_key_delete(A) TlsFree(A)
|
||||
#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
|
||||
#define pthread_setspecific(A,B) (!TlsSetValue((A),(LPVOID)(B)))
|
||||
#define pthread_getspecific(A) (TlsGetValue(A))
|
||||
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
|
||||
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
|
||||
|
||||
#define pthread_equal(A,B) ((A) == (B))
|
||||
#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0)
|
||||
|
@ -154,9 +146,6 @@ int pthread_cancel(pthread_t thread);
|
|||
#include <synch.h>
|
||||
#endif
|
||||
|
||||
#define pthread_key(T,V) pthread_key_t V
|
||||
#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V))
|
||||
#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V))
|
||||
#define pthread_detach_this_thread()
|
||||
#define pthread_handler_t EXTERNC void *
|
||||
typedef void *(* pthread_handler)(void *);
|
||||
|
@ -232,8 +221,6 @@ int sigwait(sigset_t *setp, int *sigp); /* Use our implementation */
|
|||
#undef HAVE_GETHOSTBYADDR_R /* No definition */
|
||||
#endif
|
||||
|
||||
#define my_pthread_getspecific(A,B) ((A) pthread_getspecific(B))
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
struct tm *localtime_r(const time_t *clock, struct tm *res);
|
||||
#endif
|
||||
|
@ -248,17 +235,7 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res);
|
|||
#define pthread_condattr_destroy pthread_condattr_delete
|
||||
#endif
|
||||
|
||||
/* FSU THREADS */
|
||||
#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete)
|
||||
#define pthread_key_delete(A) pthread_dummy(0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)
|
||||
/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */
|
||||
#define pthread_key_create(A,B) \
|
||||
pthread_keycreate(A,(B) ?\
|
||||
(pthread_destructor_t) (B) :\
|
||||
(pthread_destructor_t) pthread_dummy)
|
||||
#define pthread_attr_init(A) pthread_attr_create(A)
|
||||
#define pthread_attr_destroy(A) pthread_attr_delete(A)
|
||||
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
|
||||
|
@ -723,7 +700,7 @@ extern uint my_thread_end_wait_time;
|
|||
extern my_bool safe_mutex_deadlock_detector;
|
||||
#define my_thread_var (_my_thread_var())
|
||||
#define my_errno my_thread_var->thr_errno
|
||||
int set_mysys_var(struct st_my_thread_var *mysys_var);
|
||||
void set_mysys_var(struct st_my_thread_var *mysys_var);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -260,7 +260,7 @@ extern ulong my_file_total_opened;
|
|||
extern ulong my_sync_count;
|
||||
extern uint mysys_usage_id;
|
||||
extern int32 my_file_opened;
|
||||
extern my_bool my_init_done, my_thr_key_mysys_exists;
|
||||
extern my_bool my_init_done;
|
||||
extern my_bool my_assert;
|
||||
extern my_bool my_assert_on_error;
|
||||
extern myf my_global_flags; /* Set to MY_WME for more error messages */
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
#ifdef _WIN32
|
||||
typedef struct thread_attr pthread_attr_t;
|
||||
typedef DWORD pthread_t;
|
||||
typedef DWORD pthread_key_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -50,7 +50,6 @@ static void setup_codepages();
|
|||
#define EXE_LINKPATH "/proc/curproc/file"
|
||||
#endif
|
||||
|
||||
extern pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
|
||||
|
||||
#define SCALE_SEC 100
|
||||
#define SCALE_USEC 10000
|
||||
|
@ -350,8 +349,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
|
|||
#endif
|
||||
|
||||
/* At very last, delete mysys key, it is used everywhere including DBUG */
|
||||
pthread_key_delete(THR_KEY_mysys);
|
||||
my_init_done= my_thr_key_mysys_exists= 0;
|
||||
my_init_done= 0;
|
||||
} /* my_end */
|
||||
|
||||
#ifdef DBUG_ASSERT_EXISTS
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <m_string.h>
|
||||
#include <signal.h>
|
||||
|
||||
pthread_key(struct st_my_thread_var*, THR_KEY_mysys=-1);
|
||||
mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open,
|
||||
THR_LOCK_lock, THR_LOCK_myisam, THR_LOCK_heap,
|
||||
THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads,
|
||||
|
@ -41,8 +40,6 @@ static void install_sigabrt_handler();
|
|||
|
||||
/** True if @c my_thread_global_init() has been called. */
|
||||
static my_bool my_thread_global_init_done= 0;
|
||||
/* True if THR_KEY_mysys is created */
|
||||
my_bool my_thr_key_mysys_exists= 0;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -152,12 +149,10 @@ void my_thread_global_reinit(void)
|
|||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error (Couldn't create THR_KEY_mysys)
|
||||
*/
|
||||
|
||||
my_bool my_thread_global_init(void)
|
||||
{
|
||||
int pth_ret;
|
||||
|
||||
/* Normally this should never be called twice */
|
||||
DBUG_ASSERT(my_thread_global_init_done == 0);
|
||||
|
@ -165,21 +160,6 @@ my_bool my_thread_global_init(void)
|
|||
return 0;
|
||||
my_thread_global_init_done= 1;
|
||||
|
||||
/*
|
||||
THR_KEY_mysys is deleted in my_end() as DBUG libraries are using it even
|
||||
after my_thread_global_end() is called.
|
||||
my_thr_key_mysys_exist is used to protect against application like QT
|
||||
that calls my_thread_global_init() + my_thread_global_end() multiple times
|
||||
without calling my_init() + my_end().
|
||||
*/
|
||||
if (!my_thr_key_mysys_exists &&
|
||||
(pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
|
||||
{
|
||||
fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret);
|
||||
return 1;
|
||||
}
|
||||
my_thr_key_mysys_exists= 1;
|
||||
|
||||
/* Mutex used by my_thread_init() and after my_thread_destroy_mutex() */
|
||||
my_thread_init_internal_mutex();
|
||||
|
||||
|
@ -384,16 +364,18 @@ void my_thread_end(void)
|
|||
}
|
||||
}
|
||||
|
||||
static MY_THREAD_LOCAL struct st_my_thread_var *my_thread_var_;
|
||||
struct st_my_thread_var *_my_thread_var(void)
|
||||
{
|
||||
return my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
|
||||
return my_thread_var_;
|
||||
}
|
||||
|
||||
int set_mysys_var(struct st_my_thread_var *mysys_var)
|
||||
void set_mysys_var(struct st_my_thread_var *mysys_var)
|
||||
{
|
||||
return my_pthread_setspecific_ptr(THR_KEY_mysys, mysys_var);
|
||||
my_thread_var_= mysys_var;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Get name of current thread.
|
||||
****************************************************************************/
|
||||
|
|
|
@ -101,7 +101,6 @@ LEX_CSTRING default_master_connection_name= { (char*) "", 0 };
|
|||
|
||||
int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
|
||||
|
||||
static pthread_key(Master_info*, RPL_MASTER_INFO);
|
||||
|
||||
enum enum_slave_reconnect_actions
|
||||
{
|
||||
|
@ -582,9 +581,6 @@ int init_slave()
|
|||
So it's safer to take the lock.
|
||||
*/
|
||||
|
||||
if (pthread_key_create(&RPL_MASTER_INFO, NULL))
|
||||
goto err;
|
||||
|
||||
master_info_index= new Master_info_index;
|
||||
if (!master_info_index || master_info_index->init_all_master_info())
|
||||
{
|
||||
|
@ -4831,9 +4827,6 @@ pthread_handler_t handle_slave_io(void *arg)
|
|||
DBUG_PRINT("master_info",("log_file_name: '%s' position: %llu",
|
||||
mi->master_log_name, mi->master_log_pos));
|
||||
|
||||
/* This must be called before run any binlog_relay_io hooks */
|
||||
my_pthread_setspecific_ptr(RPL_MASTER_INFO, mi);
|
||||
|
||||
/* Load the set of seen GTIDs, if we did not already. */
|
||||
if (rpl_load_gtid_slave_state(thd))
|
||||
{
|
||||
|
|
|
@ -5151,23 +5151,22 @@ void destroy_thd(MYSQL_THD thd)
|
|||
like for example, evaluation of virtual function in innodb
|
||||
purge.
|
||||
*/
|
||||
extern "C" pthread_key(struct st_my_thread_var *, THR_KEY_mysys);
|
||||
MYSQL_THD create_background_thd()
|
||||
{
|
||||
auto save_thd = current_thd;
|
||||
set_current_thd(nullptr);
|
||||
|
||||
auto save_mysysvar= pthread_getspecific(THR_KEY_mysys);
|
||||
auto save_mysysvar= my_thread_var;
|
||||
|
||||
/*
|
||||
Allocate new mysys_var specifically new THD,
|
||||
so that e.g safemalloc, DBUG etc are happy.
|
||||
*/
|
||||
pthread_setspecific(THR_KEY_mysys, 0);
|
||||
set_mysys_var(nullptr);
|
||||
my_thread_init();
|
||||
auto thd_mysysvar= pthread_getspecific(THR_KEY_mysys);
|
||||
auto thd_mysysvar= my_thread_var;
|
||||
auto thd= new THD(0);
|
||||
pthread_setspecific(THR_KEY_mysys, save_mysysvar);
|
||||
set_mysys_var(save_mysysvar);
|
||||
thd->set_psi(nullptr);
|
||||
set_current_thd(save_thd);
|
||||
|
||||
|
@ -5200,8 +5199,8 @@ void *thd_attach_thd(MYSQL_THD thd)
|
|||
DBUG_ASSERT(!current_thd);
|
||||
DBUG_ASSERT(thd && thd->mysys_var);
|
||||
|
||||
auto save_mysysvar= pthread_getspecific(THR_KEY_mysys);
|
||||
pthread_setspecific(THR_KEY_mysys, thd->mysys_var);
|
||||
auto save_mysysvar= my_thread_var;
|
||||
set_mysys_var(thd->mysys_var);
|
||||
thd->thread_stack= (char *) &thd;
|
||||
thd->store_globals();
|
||||
return save_mysysvar;
|
||||
|
@ -5214,7 +5213,7 @@ void *thd_attach_thd(MYSQL_THD thd)
|
|||
void thd_detach_thd(void *mysysvar)
|
||||
{
|
||||
/* Restore mysys_var that is changed when THD was attached.*/
|
||||
pthread_setspecific(THR_KEY_mysys, mysysvar);
|
||||
set_mysys_var((st_my_thread_var *)mysysvar);
|
||||
/* Restore the THD (we assume it was NULL during attach).*/
|
||||
set_current_thd(0);
|
||||
}
|
||||
|
@ -5227,7 +5226,7 @@ void destroy_background_thd(MYSQL_THD thd)
|
|||
{
|
||||
DBUG_ASSERT(!current_thd);
|
||||
auto thd_mysys_var= thd->mysys_var;
|
||||
auto save_mysys_var= thd_attach_thd(thd);
|
||||
auto save_mysys_var= (st_my_thread_var *)thd_attach_thd(thd);
|
||||
DBUG_ASSERT(thd_mysys_var != save_mysys_var);
|
||||
/*
|
||||
Workaround the adverse effect decrementing thread_count on THD()
|
||||
|
@ -5249,9 +5248,9 @@ void destroy_background_thd(MYSQL_THD thd)
|
|||
auto save_psi_thread= PSI_CALL_get_thread();
|
||||
#endif
|
||||
PSI_CALL_set_thread(0);
|
||||
pthread_setspecific(THR_KEY_mysys, thd_mysys_var);
|
||||
set_mysys_var(thd_mysys_var);
|
||||
my_thread_end();
|
||||
pthread_setspecific(THR_KEY_mysys, save_mysys_var);
|
||||
set_mysys_var(save_mysys_var);
|
||||
PSI_CALL_set_thread(save_psi_thread);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "rpl_rli.h"
|
||||
#include "rpl_mi.h"
|
||||
|
||||
extern "C" pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
|
||||
|
||||
static Wsrep_thd_queue* wsrep_rollback_queue= 0;
|
||||
static Atomic_counter<uint64_t> wsrep_bf_aborts_counter;
|
||||
|
@ -513,8 +512,8 @@ int wsrep_create_threadvars()
|
|||
{
|
||||
/* Caller should have called wsrep_reset_threadvars() before this
|
||||
method. */
|
||||
DBUG_ASSERT(!pthread_getspecific(THR_KEY_mysys));
|
||||
pthread_setspecific(THR_KEY_mysys, 0);
|
||||
DBUG_ASSERT(!my_thread_var);
|
||||
set_mysys_var(0);
|
||||
ret= my_thread_init();
|
||||
}
|
||||
return ret;
|
||||
|
@ -526,7 +525,7 @@ void wsrep_delete_threadvars()
|
|||
{
|
||||
/* The caller should have called wsrep_store_threadvars() before
|
||||
this method. */
|
||||
DBUG_ASSERT(pthread_getspecific(THR_KEY_mysys));
|
||||
DBUG_ASSERT(my_thread_var);
|
||||
/* Reset psi state to avoid deallocating applier thread
|
||||
psi_thread. */
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
|
@ -538,7 +537,7 @@ void wsrep_delete_threadvars()
|
|||
#endif /* HAVE_PSI_INTERFACE */
|
||||
my_thread_end();
|
||||
PSI_CALL_set_thread(psi_thread);
|
||||
pthread_setspecific(THR_KEY_mysys, 0);
|
||||
set_mysys_var(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,9 +545,7 @@ void wsrep_assign_from_threadvars(THD *thd)
|
|||
{
|
||||
if (thread_handling == SCHEDULER_TYPES_COUNT)
|
||||
{
|
||||
st_my_thread_var *mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
|
||||
DBUG_ASSERT(mysys_var);
|
||||
thd->set_mysys_var(mysys_var);
|
||||
thd->set_mysys_var(my_thread_var);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,21 +553,21 @@ Wsrep_threadvars wsrep_save_threadvars()
|
|||
{
|
||||
return Wsrep_threadvars{
|
||||
current_thd,
|
||||
(st_my_thread_var*) pthread_getspecific(THR_KEY_mysys)
|
||||
my_thread_var
|
||||
};
|
||||
}
|
||||
|
||||
void wsrep_restore_threadvars(const Wsrep_threadvars& globals)
|
||||
{
|
||||
set_current_thd(globals.cur_thd);
|
||||
pthread_setspecific(THR_KEY_mysys, globals.mysys_var);
|
||||
set_mysys_var(globals.mysys_var);
|
||||
}
|
||||
|
||||
void wsrep_store_threadvars(THD *thd)
|
||||
{
|
||||
if (thread_handling == SCHEDULER_TYPES_COUNT)
|
||||
{
|
||||
pthread_setspecific(THR_KEY_mysys, thd->mysys_var);
|
||||
set_mysys_var(thd->mysys_var);
|
||||
}
|
||||
thd->store_globals();
|
||||
}
|
||||
|
@ -579,7 +576,7 @@ void wsrep_reset_threadvars(THD *thd)
|
|||
{
|
||||
if (thread_handling == SCHEDULER_TYPES_COUNT)
|
||||
{
|
||||
pthread_setspecific(THR_KEY_mysys, 0);
|
||||
set_mysys_var(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
typedef pthread_key_t thread_local_key_t;
|
||||
typedef pthread_t my_thread_handle;
|
||||
typedef pthread_attr_t my_thread_attr_t;
|
||||
#if defined(HAVE_PTHREAD_THREADID_NP) || defined(HAVE_GETTID) || defined(HAVE_SYS_GETTID) || defined(HAVE_GETTHRID)
|
||||
|
@ -34,19 +33,6 @@ typedef unsigned long long my_thread_os_id_t;
|
|||
#endif
|
||||
|
||||
#define LOCK_plugin_delete LOCK_plugin
|
||||
|
||||
static inline int my_create_thread_local_key(thread_local_key_t *key, void (*destructor)(void*))
|
||||
{ return pthread_key_create(key, destructor); }
|
||||
|
||||
static inline int my_delete_thread_local_key(thread_local_key_t key)
|
||||
{ return pthread_key_delete(key); }
|
||||
|
||||
static inline void *my_get_thread_local(thread_local_key_t key)
|
||||
{ return pthread_getspecific(key); }
|
||||
|
||||
static inline int my_set_thread_local(thread_local_key_t key, const void *ptr)
|
||||
{ return pthread_setspecific(key, ptr); }
|
||||
|
||||
static inline int my_thread_create(my_thread_handle *thread,
|
||||
const my_thread_attr_t *attr, void *(*start_routine)(void *), void *arg)
|
||||
{ return pthread_create(thread, attr, start_routine, arg); }
|
||||
|
|
|
@ -1351,24 +1351,22 @@ static inline int mysql_mutex_lock(...)
|
|||
@ingroup Performance_schema_implementation
|
||||
*/
|
||||
|
||||
thread_local_key_t THR_PFS;
|
||||
thread_local_key_t THR_PFS_VG; // global_variables
|
||||
thread_local_key_t THR_PFS_SV; // session_variables
|
||||
thread_local_key_t THR_PFS_VBT; // variables_by_thread
|
||||
thread_local_key_t THR_PFS_SG; // global_status
|
||||
thread_local_key_t THR_PFS_SS; // session_status
|
||||
thread_local_key_t THR_PFS_SBT; // status_by_thread
|
||||
thread_local_key_t THR_PFS_SBU; // status_by_user
|
||||
thread_local_key_t THR_PFS_SBH; // status_by_host
|
||||
thread_local_key_t THR_PFS_SBA; // status_by_account
|
||||
MY_THREAD_LOCAL void* THR_PFS_VG; // global_variables
|
||||
MY_THREAD_LOCAL void* THR_PFS_SV; // session_variables
|
||||
MY_THREAD_LOCAL void* THR_PFS_VBT; // variables_by_thread
|
||||
MY_THREAD_LOCAL void* THR_PFS_SG; // global_status
|
||||
MY_THREAD_LOCAL void* THR_PFS_SS; // session_status
|
||||
MY_THREAD_LOCAL void* THR_PFS_SBT; // status_by_thread
|
||||
MY_THREAD_LOCAL void* THR_PFS_SBU; // status_by_user
|
||||
MY_THREAD_LOCAL void* THR_PFS_SBH; // status_by_host
|
||||
MY_THREAD_LOCAL void* THR_PFS_SBA; // status_by_account
|
||||
|
||||
bool THR_PFS_initialized= false;
|
||||
MY_THREAD_LOCAL PFS_thread* THR_PFS;
|
||||
|
||||
static inline PFS_thread*
|
||||
my_thread_get_THR_PFS()
|
||||
{
|
||||
assert(THR_PFS_initialized);
|
||||
PFS_thread *thread= static_cast<PFS_thread*>(my_get_thread_local(THR_PFS));
|
||||
PFS_thread *thread= THR_PFS;
|
||||
assert(thread == NULL || sanitize_thread(thread) != NULL);
|
||||
return thread;
|
||||
}
|
||||
|
@ -1376,8 +1374,7 @@ my_thread_get_THR_PFS()
|
|||
static inline void
|
||||
my_thread_set_THR_PFS(PFS_thread *pfs)
|
||||
{
|
||||
assert(THR_PFS_initialized);
|
||||
my_set_thread_local(THR_PFS, pfs);
|
||||
THR_PFS= pfs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,19 +40,18 @@
|
|||
*/
|
||||
extern struct PSI_bootstrap PFS_bootstrap;
|
||||
/** Performance schema Thread Local Storage key. */
|
||||
extern pthread_key_t THR_PFS;
|
||||
extern pthread_key_t THR_PFS_VG; // global_variables
|
||||
extern pthread_key_t THR_PFS_SV; // session_variables
|
||||
extern pthread_key_t THR_PFS_VBT; // variables_by_thread
|
||||
extern pthread_key_t THR_PFS_SG; // global_status
|
||||
extern pthread_key_t THR_PFS_SS; // session_status
|
||||
extern pthread_key_t THR_PFS_SBT; // status_by_thread
|
||||
extern pthread_key_t THR_PFS_SBU; // status_by_user
|
||||
extern pthread_key_t THR_PFS_SBA; // status_by_host
|
||||
extern pthread_key_t THR_PFS_SBH; // status_by_account
|
||||
struct PFS_thread;
|
||||
|
||||
/** True when @c THR_PFS and all other Performance Schema TLS keys are initialized. */
|
||||
extern bool THR_PFS_initialized;
|
||||
extern MY_THREAD_LOCAL PFS_thread* THR_PFS;
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_VG; // global_variables
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SV; // session_variables
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_VBT; // variables_by_thread
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SG; // global_status
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SS; // session_status
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SBT; // status_by_thread
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SBU; // status_by_user
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SBA; // status_by_host
|
||||
extern MY_THREAD_LOCAL void* THR_PFS_SBH; // status_by_account
|
||||
|
||||
#define PSI_VOLATILITY_UNKNOWN 0
|
||||
#define PSI_VOLATILITY_SESSION 1
|
||||
|
|
|
@ -146,7 +146,7 @@ bool PFS_table_context::initialize(void)
|
|||
if (m_restore)
|
||||
{
|
||||
/* Restore context from TLS. */
|
||||
PFS_table_context *context= static_cast<PFS_table_context *>(my_get_thread_local(m_thr_key));
|
||||
PFS_table_context *context= static_cast<PFS_table_context *>(*m_thr_varptr);
|
||||
assert(context != NULL);
|
||||
|
||||
if(context)
|
||||
|
@ -160,7 +160,7 @@ bool PFS_table_context::initialize(void)
|
|||
else
|
||||
{
|
||||
/* Check that TLS is not in use. */
|
||||
PFS_table_context *context= static_cast<PFS_table_context *>(my_get_thread_local(m_thr_key));
|
||||
PFS_table_context *context= static_cast<PFS_table_context *>(*m_thr_varptr);
|
||||
//assert(context == NULL);
|
||||
|
||||
context= this;
|
||||
|
@ -178,7 +178,7 @@ bool PFS_table_context::initialize(void)
|
|||
}
|
||||
|
||||
/* Write to TLS. */
|
||||
my_set_thread_local(m_thr_key, static_cast<void *>(context));
|
||||
*m_thr_varptr=static_cast<void *>(context);
|
||||
}
|
||||
|
||||
m_initialized= (m_map_size > 0) ? (m_map != NULL) : true;
|
||||
|
@ -187,8 +187,8 @@ bool PFS_table_context::initialize(void)
|
|||
}
|
||||
|
||||
/* Constructor for global or single thread tables, map size = 0. */
|
||||
PFS_table_context::PFS_table_context(ulonglong current_version, bool restore, thread_local_key_t key) :
|
||||
m_thr_key(key), m_current_version(current_version), m_last_version(0),
|
||||
PFS_table_context::PFS_table_context(ulonglong current_version, bool restore, void** thr_var_ptr) :
|
||||
m_thr_varptr(thr_var_ptr), m_current_version(current_version), m_last_version(0),
|
||||
m_map(NULL), m_map_size(0),
|
||||
m_restore(restore), m_initialized(false), m_last_item(0)
|
||||
{
|
||||
|
@ -196,8 +196,8 @@ PFS_table_context::PFS_table_context(ulonglong current_version, bool restore, th
|
|||
}
|
||||
|
||||
/* Constructor for by-thread or aggregate tables, map size = max thread/user/host/account. */
|
||||
PFS_table_context::PFS_table_context(ulonglong current_version, ulong map_size, bool restore, thread_local_key_t key) :
|
||||
m_thr_key(key), m_current_version(current_version), m_last_version(0),
|
||||
PFS_table_context::PFS_table_context(ulonglong current_version, ulong map_size, bool restore, void** thr_var_ptr) :
|
||||
m_thr_varptr(thr_var_ptr), m_current_version(current_version), m_last_version(0),
|
||||
m_map(NULL), m_map_size(map_size),
|
||||
m_restore(restore), m_initialized(false), m_last_item(0)
|
||||
{
|
||||
|
|
|
@ -47,15 +47,7 @@ using PFS_ident_table = Lex_ident_i_s_table;
|
|||
*/
|
||||
|
||||
#include "pfs_instr_class.h"
|
||||
extern pthread_key_t THR_PFS_VG; // global_variables
|
||||
extern pthread_key_t THR_PFS_SV; // session_variables
|
||||
extern pthread_key_t THR_PFS_VBT; // variables_by_thread
|
||||
extern pthread_key_t THR_PFS_SG; // global_status
|
||||
extern pthread_key_t THR_PFS_SS; // session_status
|
||||
extern pthread_key_t THR_PFS_SBT; // status_by_thread
|
||||
extern pthread_key_t THR_PFS_SBU; // status_by_user
|
||||
extern pthread_key_t THR_PFS_SBH; // status_by_host
|
||||
extern pthread_key_t THR_PFS_SBA; // status_by_account
|
||||
#include "pfs.h"
|
||||
|
||||
class Field;
|
||||
struct PFS_engine_table_share;
|
||||
|
@ -72,8 +64,8 @@ struct time_normalizer;
|
|||
class PFS_table_context
|
||||
{
|
||||
public:
|
||||
PFS_table_context(ulonglong current_version, bool restore, pthread_key_t key);
|
||||
PFS_table_context(ulonglong current_version, ulong map_size, bool restore, pthread_key_t key);
|
||||
PFS_table_context(ulonglong current_version, bool restore, void** thr_var_ptr);
|
||||
PFS_table_context(ulonglong current_version, ulong map_size, bool restore, void** thr_var_ptr);
|
||||
~PFS_table_context(void);
|
||||
|
||||
bool initialize(void);
|
||||
|
@ -83,7 +75,7 @@ public:
|
|||
bool versions_match(void) { return m_last_version == m_current_version; }
|
||||
void set_item(ulong n);
|
||||
bool is_item_set(ulong n);
|
||||
pthread_key_t m_thr_key;
|
||||
void** m_thr_varptr;
|
||||
|
||||
private:
|
||||
ulonglong m_current_version;
|
||||
|
|
|
@ -434,7 +434,7 @@ void destroy_cond(PFS_cond *pfs)
|
|||
|
||||
PFS_thread* PFS_thread::get_current_thread()
|
||||
{
|
||||
return static_cast<PFS_thread*>(my_get_thread_local(THR_PFS));
|
||||
return THR_PFS;
|
||||
}
|
||||
|
||||
void PFS_thread::reset_session_connect_attrs()
|
||||
|
|
|
@ -54,10 +54,6 @@ PFS_global_param pfs_param;
|
|||
|
||||
PFS_table_stat PFS_table_stat::g_reset_template;
|
||||
|
||||
C_MODE_START
|
||||
static void destroy_pfs_thread(void *key);
|
||||
C_MODE_END
|
||||
|
||||
static void cleanup_performance_schema(void);
|
||||
void cleanup_instrument_config(void);
|
||||
|
||||
|
@ -71,40 +67,11 @@ void pre_initialize_performance_schema()
|
|||
global_idle_stat.reset();
|
||||
global_table_io_stat.reset();
|
||||
global_table_lock_stat.reset();
|
||||
|
||||
if (my_create_thread_local_key(&THR_PFS, destroy_pfs_thread))
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_VG, NULL)) // global_variables
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SV, NULL)) // session_variables
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_VBT, NULL)) // variables_by_thread
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SG, NULL)) // global_status
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SS, NULL)) // session_status
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SBT, NULL)) // status_by_thread
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SBU, NULL)) // status_by_user
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SBH, NULL)) // status_by_host
|
||||
return;
|
||||
if (my_create_thread_local_key(&THR_PFS_SBA, NULL)) // status_by_account
|
||||
return;
|
||||
|
||||
THR_PFS_initialized= true;
|
||||
}
|
||||
|
||||
struct PSI_bootstrap*
|
||||
initialize_performance_schema(PFS_global_param *param)
|
||||
{
|
||||
if (!THR_PFS_initialized)
|
||||
{
|
||||
/* Pre-initialization failed. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pfs_enabled= param->m_enabled;
|
||||
|
||||
pfs_automated_sizing(param);
|
||||
|
@ -208,24 +175,6 @@ initialize_performance_schema(PFS_global_param *param)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_pfs_thread(void *key)
|
||||
{
|
||||
PFS_thread* pfs= reinterpret_cast<PFS_thread*> (key);
|
||||
assert(pfs);
|
||||
/*
|
||||
This automatic cleanup is a last resort and best effort to avoid leaks,
|
||||
and may not work on windows due to the implementation of pthread_key_create().
|
||||
Please either use:
|
||||
- my_thread_end()
|
||||
- or PSI_server->delete_current_thread()
|
||||
in the instrumented code, to explicitly cleanup the instrumentation.
|
||||
|
||||
Avoid invalid writes when the main() thread completes after shutdown:
|
||||
the memory pointed by pfs is already released.
|
||||
*/
|
||||
if (pfs_initialized)
|
||||
destroy_thread(pfs);
|
||||
}
|
||||
|
||||
static void cleanup_performance_schema(void)
|
||||
{
|
||||
|
@ -324,36 +273,16 @@ void shutdown_performance_schema(void)
|
|||
global_transaction_class.m_enabled= false;
|
||||
|
||||
cleanup_performance_schema();
|
||||
/*
|
||||
Be careful to not delete un-initialized keys,
|
||||
this would affect key 0, which is THR_KEY_mysys,
|
||||
*/
|
||||
if (THR_PFS_initialized)
|
||||
{
|
||||
my_set_thread_local(THR_PFS, NULL);
|
||||
my_set_thread_local(THR_PFS_VG, NULL); // global_variables
|
||||
my_set_thread_local(THR_PFS_SV, NULL); // session_variables
|
||||
my_set_thread_local(THR_PFS_VBT, NULL); // variables_by_thread
|
||||
my_set_thread_local(THR_PFS_SG, NULL); // global_status
|
||||
my_set_thread_local(THR_PFS_SS, NULL); // session_status
|
||||
my_set_thread_local(THR_PFS_SBT, NULL); // status_by_thread
|
||||
my_set_thread_local(THR_PFS_SBU, NULL); // status_by_user
|
||||
my_set_thread_local(THR_PFS_SBH, NULL); // status_by_host
|
||||
my_set_thread_local(THR_PFS_SBA, NULL); // status_by_account
|
||||
|
||||
my_delete_thread_local_key(THR_PFS);
|
||||
my_delete_thread_local_key(THR_PFS_VG);
|
||||
my_delete_thread_local_key(THR_PFS_SV);
|
||||
my_delete_thread_local_key(THR_PFS_VBT);
|
||||
my_delete_thread_local_key(THR_PFS_SG);
|
||||
my_delete_thread_local_key(THR_PFS_SS);
|
||||
my_delete_thread_local_key(THR_PFS_SBT);
|
||||
my_delete_thread_local_key(THR_PFS_SBU);
|
||||
my_delete_thread_local_key(THR_PFS_SBH);
|
||||
my_delete_thread_local_key(THR_PFS_SBA);
|
||||
|
||||
THR_PFS_initialized= false;
|
||||
}
|
||||
THR_PFS= NULL;
|
||||
THR_PFS_VG= NULL; // global_variables
|
||||
THR_PFS_SV= NULL; // session_variables
|
||||
THR_PFS_VBT= NULL; // variables_by_thread
|
||||
THR_PFS_SG= NULL; // global_status
|
||||
THR_PFS_SS= NULL; // session_status
|
||||
THR_PFS_SBT= NULL; // status_by_thread
|
||||
THR_PFS_SBU= NULL; // status_by_user
|
||||
THR_PFS_SBH= NULL; // status_by_host
|
||||
THR_PFS_SBA= NULL; // status_by_account
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,7 +59,7 @@ class table_global_status_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_global_status_context(ulonglong current_version, bool restore) :
|
||||
PFS_table_context(current_version, restore, THR_PFS_SG) { }
|
||||
PFS_table_context(current_version, restore, &THR_PFS_SG) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.GLOBAL_STATUS. */
|
||||
|
|
|
@ -47,7 +47,7 @@ class table_global_variables_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_global_variables_context(ulonglong hash_version, bool restore) :
|
||||
PFS_table_context(hash_version, restore, THR_PFS_VG) {}
|
||||
PFS_table_context(hash_version, restore, &THR_PFS_VG) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -61,7 +61,7 @@ class table_session_status_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_session_status_context(ulonglong current_version, bool restore) :
|
||||
PFS_table_context(current_version, restore, THR_PFS_SS) { }
|
||||
PFS_table_context(current_version, restore, &THR_PFS_SS) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.SESSION_STATUS. */
|
||||
|
|
|
@ -47,7 +47,7 @@ class table_session_variables_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_session_variables_context(ulonglong hash_version, bool restore) :
|
||||
PFS_table_context(hash_version, restore, THR_PFS_SV) {}
|
||||
PFS_table_context(hash_version, restore, &THR_PFS_SV) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,7 +95,7 @@ class table_status_by_account_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_status_by_account_context(ulonglong current_version, bool restore) :
|
||||
PFS_table_context(current_version, global_account_container.get_row_count(), restore, THR_PFS_SBH) { }
|
||||
PFS_table_context(current_version, global_account_container.get_row_count(), restore, &THR_PFS_SBH) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.STATUS_BY_ACCOUNT. */
|
||||
|
|
|
@ -93,7 +93,7 @@ class table_status_by_host_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_status_by_host_context(ulonglong current_version, bool restore) :
|
||||
PFS_table_context(current_version, global_host_container.get_row_count(), restore, THR_PFS_SBH) { }
|
||||
PFS_table_context(current_version, global_host_container.get_row_count(), restore, &THR_PFS_SBH) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.STATUS_BY_HOST. */
|
||||
|
|
|
@ -91,7 +91,7 @@ class table_status_by_thread_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_status_by_thread_context(ulonglong current_version, bool restore) :
|
||||
PFS_table_context(current_version, global_thread_container.get_row_count(), restore, THR_PFS_SBT) { }
|
||||
PFS_table_context(current_version, global_thread_container.get_row_count(), restore, &THR_PFS_SBT) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.STATUS_BY_THREAD. */
|
||||
|
|
|
@ -93,7 +93,7 @@ class table_status_by_user_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_status_by_user_context(ulonglong current_version, bool restore) :
|
||||
PFS_table_context(current_version, global_user_container.get_row_count(), restore, THR_PFS_SBU) { }
|
||||
PFS_table_context(current_version, global_user_container.get_row_count(), restore, &THR_PFS_SBU) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.STATUS_BY_USER. */
|
||||
|
|
|
@ -92,7 +92,7 @@ class table_variables_by_thread_context : public PFS_table_context
|
|||
{
|
||||
public:
|
||||
table_variables_by_thread_context(ulonglong hash_version, bool restore) :
|
||||
PFS_table_context(hash_version, global_thread_container.get_row_count(), restore, THR_PFS_VBT) { }
|
||||
PFS_table_context(hash_version, global_thread_container.get_row_count(), restore, &THR_PFS_VBT) { }
|
||||
};
|
||||
|
||||
/** Table PERFORMANCE_SCHEMA.VARIABLES_BY_THREAD. */
|
||||
|
|
Loading…
Reference in a new issue