diff options
Diffstat (limited to 'storage/xtradb/thr/thr0loc.c')
-rw-r--r-- | storage/xtradb/thr/thr0loc.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/storage/xtradb/thr/thr0loc.c b/storage/xtradb/thr/thr0loc.c new file mode 100644 index 00000000000..aea1992a921 --- /dev/null +++ b/storage/xtradb/thr/thr0loc.c @@ -0,0 +1,273 @@ +/***************************************************************************** + +Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. + +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 + +*****************************************************************************/ + +/****************************************************** +The thread local storage + +Created 10/5/1995 Heikki Tuuri +*******************************************************/ + +#include "thr0loc.h" +#ifdef UNIV_NONINL +#include "thr0loc.ic" +#endif + +#include "sync0sync.h" +#include "hash0hash.h" +#include "mem0mem.h" +#include "srv0srv.h" + +/* + IMPLEMENTATION OF THREAD LOCAL STORAGE + ====================================== + +The threads sometimes need private data which depends on the thread id. +This is implemented as a hash table, where the hash value is calculated +from the thread id, to prepare for a large number of threads. The hash table +is protected by a mutex. If you need modify the program and put new data to +the thread local storage, just add it to struct thr_local_struct in the +header file. */ + +/* Mutex protecting the local storage hash table */ +static mutex_t thr_local_mutex; + +/* The hash table. The module is not yet initialized when it is NULL. */ +static hash_table_t* thr_local_hash = NULL; +ulint thr_local_hash_n_nodes = 0; + +/* The private data for each thread should be put to +the structure below and the accessor functions written +for the field. */ +typedef struct thr_local_struct thr_local_t; + +struct thr_local_struct{ + os_thread_id_t id; /* id of the thread which owns this struct */ + os_thread_t handle; /* operating system handle to the thread */ + ulint slot_no;/* the index of the slot in the thread table + for this thread */ + ibool in_ibuf;/* TRUE if the the thread is doing an ibuf + operation */ + hash_node_t hash; /* hash chain node */ + ulint magic_n; +}; + +#define THR_LOCAL_MAGIC_N 1231234 + +/*********************************************************************** +Returns the local storage struct for a thread. */ +static +thr_local_t* +thr_local_get( +/*==========*/ + /* out: local storage */ + os_thread_id_t id) /* in: thread id of the thread */ +{ + thr_local_t* local; + +try_again: + ut_ad(thr_local_hash); + ut_ad(mutex_own(&thr_local_mutex)); + + /* Look for the local struct in the hash table */ + + local = NULL; + + HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), + thr_local_t*, local,, os_thread_eq(local->id, id)); + if (local == NULL) { + mutex_exit(&thr_local_mutex); + + thr_local_create(); + + mutex_enter(&thr_local_mutex); + + goto try_again; + } + + ut_ad(local->magic_n == THR_LOCAL_MAGIC_N); + + return(local); +} + +/*********************************************************************** +Gets the slot number in the thread table of a thread. */ +UNIV_INTERN +ulint +thr_local_get_slot_no( +/*==================*/ + /* out: slot number */ + os_thread_id_t id) /* in: thread id of the thread */ +{ + ulint slot_no; + thr_local_t* local; + + mutex_enter(&thr_local_mutex); + + local = thr_local_get(id); + + slot_no = local->slot_no; + + mutex_exit(&thr_local_mutex); + + return(slot_no); +} + +/*********************************************************************** +Sets the slot number in the thread table of a thread. */ +UNIV_INTERN +void +thr_local_set_slot_no( +/*==================*/ + os_thread_id_t id, /* in: thread id of the thread */ + ulint slot_no)/* in: slot number */ +{ + thr_local_t* local; + + mutex_enter(&thr_local_mutex); + + local = thr_local_get(id); + + local->slot_no = slot_no; + + mutex_exit(&thr_local_mutex); +} + +/*********************************************************************** +Returns pointer to the 'in_ibuf' field within the current thread local +storage. */ +UNIV_INTERN +ibool* +thr_local_get_in_ibuf_field(void) +/*=============================*/ + /* out: pointer to the in_ibuf field */ +{ + thr_local_t* local; + + mutex_enter(&thr_local_mutex); + + local = thr_local_get(os_thread_get_curr_id()); + + mutex_exit(&thr_local_mutex); + + return(&(local->in_ibuf)); +} + +/*********************************************************************** +Creates a local storage struct for the calling new thread. */ +UNIV_INTERN +void +thr_local_create(void) +/*==================*/ +{ + thr_local_t* local; + + if (thr_local_hash == NULL) { + thr_local_init(); + } + + local = mem_alloc(sizeof(thr_local_t)); + + local->id = os_thread_get_curr_id(); + local->handle = os_thread_get_curr(); + local->magic_n = THR_LOCAL_MAGIC_N; + + local->in_ibuf = FALSE; + + mutex_enter(&thr_local_mutex); + + HASH_INSERT(thr_local_t, hash, thr_local_hash, + os_thread_pf(os_thread_get_curr_id()), + local); + + thr_local_hash_n_nodes++; + mutex_exit(&thr_local_mutex); +} + +/*********************************************************************** +Frees the local storage struct for the specified thread. */ +UNIV_INTERN +void +thr_local_free( +/*===========*/ + os_thread_id_t id) /* in: thread id */ +{ + thr_local_t* local; + + mutex_enter(&thr_local_mutex); + + /* Look for the local struct in the hash table */ + + HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), + thr_local_t*, local,, os_thread_eq(local->id, id)); + if (local == NULL) { + mutex_exit(&thr_local_mutex); + + return; + } + + HASH_DELETE(thr_local_t, hash, thr_local_hash, + os_thread_pf(id), local); + thr_local_hash_n_nodes--; + + mutex_exit(&thr_local_mutex); + + ut_a(local->magic_n == THR_LOCAL_MAGIC_N); + + mem_free(local); +} + +/******************************************************************** +Initializes the thread local storage module. */ +UNIV_INTERN +void +thr_local_init(void) +/*================*/ +{ + + ut_a(thr_local_hash == NULL); + + thr_local_hash = hash_create(OS_THREAD_MAX_N + 100); + + mutex_create(&thr_local_mutex, SYNC_THR_LOCAL); +} + +/************************************************************************* +Return local hash table informations. */ + +ulint +thr_local_hash_cells(void) +/*======================*/ +{ + if (thr_local_hash) { + return (thr_local_hash->n_cells); + } else { + return 0; + } +} + +ulint +thr_local_hash_nodes(void) +/*======================*/ +{ + if (thr_local_hash) { + return (thr_local_hash_n_nodes + * (sizeof(thr_local_t) + MEM_BLOCK_HEADER_SIZE)); + } else { + return 0; + } +} |