1
/*****************************************************************************
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
21
The thread local storage
23
Created 10/5/1995 Heikki Tuuri
24
*******************************************************/
31
#include "sync0sync.h"
32
#include "hash0hash.h"
37
IMPLEMENTATION OF THREAD LOCAL STORAGE
38
======================================
40
The threads sometimes need private data which depends on the thread id.
41
This is implemented as a hash table, where the hash value is calculated
42
from the thread id, to prepare for a large number of threads. The hash table
43
is protected by a mutex. If you need modify the program and put new data to
44
the thread local storage, just add it to struct thr_local_struct in the
47
/** Mutex protecting thr_local_hash */
48
static mutex_t thr_local_mutex;
50
/** The hash table. The module is not yet initialized when it is NULL. */
51
static hash_table_t* thr_local_hash = NULL;
53
/** Thread local data */
54
typedef struct thr_local_struct thr_local_t;
57
/* Key to register the mutex with performance schema */
58
UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
59
#endif /* UNIV_PFS_MUTEX */
61
/** @brief Thread local data.
62
The private data for each thread should be put to
63
the structure below and the accessor functions written
65
struct thr_local_struct{
66
os_thread_id_t id; /*!< id of the thread which owns this struct */
67
os_thread_t handle; /*!< operating system handle to the thread */
68
ulint slot_no;/*!< the index of the slot in the thread table
70
ibool in_ibuf;/*!< TRUE if the the thread is doing an ibuf
72
hash_node_t hash; /*!< hash chain node */
73
ulint magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
76
/** The value of thr_local_struct::magic_n */
77
#define THR_LOCAL_MAGIC_N 1231234
79
/*******************************************************************//**
80
Returns the local storage struct for a thread.
81
@return local storage */
86
os_thread_id_t id) /*!< in: thread id of the thread */
91
ut_ad(thr_local_hash);
92
ut_ad(mutex_own(&thr_local_mutex));
94
/* Look for the local struct in the hash table */
98
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
99
thr_local_t*, local,, os_thread_eq(local->id, id));
101
mutex_exit(&thr_local_mutex);
105
mutex_enter(&thr_local_mutex);
110
ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
115
/*******************************************************************//**
116
Gets the slot number in the thread table of a thread.
117
@return slot number */
120
thr_local_get_slot_no(
121
/*==================*/
122
os_thread_id_t id) /*!< in: thread id of the thread */
127
mutex_enter(&thr_local_mutex);
129
local = thr_local_get(id);
131
slot_no = local->slot_no;
133
mutex_exit(&thr_local_mutex);
138
/*******************************************************************//**
139
Sets the slot number in the thread table of a thread. */
142
thr_local_set_slot_no(
143
/*==================*/
144
os_thread_id_t id, /*!< in: thread id of the thread */
145
ulint slot_no)/*!< in: slot number */
149
mutex_enter(&thr_local_mutex);
151
local = thr_local_get(id);
153
local->slot_no = slot_no;
155
mutex_exit(&thr_local_mutex);
158
/*******************************************************************//**
159
Returns pointer to the 'in_ibuf' field within the current thread local
161
@return pointer to the in_ibuf field */
164
thr_local_get_in_ibuf_field(void)
165
/*=============================*/
169
mutex_enter(&thr_local_mutex);
171
local = thr_local_get(os_thread_get_curr_id());
173
mutex_exit(&thr_local_mutex);
175
return(&(local->in_ibuf));
178
/*******************************************************************//**
179
Creates a local storage struct for the calling new thread. */
182
thr_local_create(void)
183
/*==================*/
187
if (thr_local_hash == NULL) {
191
local = mem_alloc(sizeof(thr_local_t));
193
local->id = os_thread_get_curr_id();
194
local->handle = os_thread_get_curr();
195
local->magic_n = THR_LOCAL_MAGIC_N;
197
local->in_ibuf = FALSE;
199
mutex_enter(&thr_local_mutex);
201
HASH_INSERT(thr_local_t, hash, thr_local_hash,
202
os_thread_pf(os_thread_get_curr_id()),
205
mutex_exit(&thr_local_mutex);
208
/*******************************************************************//**
209
Frees the local storage struct for the specified thread. */
214
os_thread_id_t id) /*!< in: thread id */
218
mutex_enter(&thr_local_mutex);
220
/* Look for the local struct in the hash table */
222
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
223
thr_local_t*, local,, os_thread_eq(local->id, id));
225
mutex_exit(&thr_local_mutex);
230
HASH_DELETE(thr_local_t, hash, thr_local_hash,
231
os_thread_pf(id), local);
233
mutex_exit(&thr_local_mutex);
235
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
240
/****************************************************************//**
241
Initializes the thread local storage module. */
248
ut_a(thr_local_hash == NULL);
250
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
252
mutex_create(thr_local_mutex_key,
253
&thr_local_mutex, SYNC_THR_LOCAL);
256
/********************************************************************
257
Close the thread local storage module. */
260
thr_local_close(void)
261
/*=================*/
265
ut_a(thr_local_hash != NULL);
267
/* Free the hash elements. We don't remove them from the table
268
because we are going to destroy the table anyway. */
269
for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
272
local = HASH_GET_FIRST(thr_local_hash, i);
275
thr_local_t* prev_local = local;
277
local = HASH_GET_NEXT(hash, prev_local);
278
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
279
mem_free(prev_local);
283
hash_table_free(thr_local_hash);
284
thr_local_hash = NULL;