Commit 7c5fdc9b authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

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.
parent 68fed7e7
......@@ -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
bool THR_PFS_initialized= false;
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
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
/** True when @c THR_PFS and all other Performance Schema TLS keys are initialized. */
extern bool THR_PFS_initialized;
struct PFS_thread;
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 @@ class PFS_table_context
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. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment