00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "thr0loc.h"
00027 #ifdef UNIV_NONINL
00028 #include "thr0loc.ic"
00029 #endif
00030
00031 #include "sync0sync.h"
00032 #include "hash0hash.h"
00033 #include "mem0mem.h"
00034 #include "srv0srv.h"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00048 static mutex_t thr_local_mutex;
00049
00051 static hash_table_t* thr_local_hash = NULL;
00052
00054 typedef struct thr_local_struct thr_local_t;
00055
00056 #ifdef UNIV_PFS_MUTEX
00057
00058 UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
00059 #endif
00060
00065 struct thr_local_struct{
00066 os_thread_id_t id;
00067 os_thread_t handle;
00068 ulint slot_no;
00070 ibool in_ibuf;
00072 hash_node_t hash;
00073 ulint magic_n;
00074 };
00075
00077 #define THR_LOCAL_MAGIC_N 1231234
00078
00079 #ifdef UNIV_DEBUG
00080
00083 static
00084 ibool
00085 thr_local_validate(
00086
00087 const thr_local_t* local)
00088 {
00089 ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
00090 ut_ad(local->slot_no == ULINT_UNDEFINED
00091 || local->slot_no < OS_THREAD_MAX_N);
00092 ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
00093 return(TRUE);
00094 }
00095 #endif
00096
00097
00100 static
00101 thr_local_t*
00102 thr_local_get(
00103
00104 os_thread_id_t id)
00105 {
00106 thr_local_t* local;
00107
00108 try_again:
00109 ut_ad(thr_local_hash);
00110 ut_ad(mutex_own(&thr_local_mutex));
00111
00112
00113
00114 local = NULL;
00115
00116 HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
00117 thr_local_t*, local, ut_ad(thr_local_validate(local)),
00118 os_thread_eq(local->id, id));
00119 if (local == NULL) {
00120 mutex_exit(&thr_local_mutex);
00121
00122 thr_local_create();
00123
00124 mutex_enter(&thr_local_mutex);
00125
00126 goto try_again;
00127 }
00128
00129 ut_ad(thr_local_validate(local));
00130
00131 return(local);
00132 }
00133
00134
00137 UNIV_INTERN
00138 ulint
00139 thr_local_get_slot_no(
00140
00141 os_thread_id_t id)
00142 {
00143 ulint slot_no;
00144 thr_local_t* local;
00145
00146 mutex_enter(&thr_local_mutex);
00147
00148 local = thr_local_get(id);
00149
00150 slot_no = local->slot_no;
00151
00152 mutex_exit(&thr_local_mutex);
00153
00154 return(slot_no);
00155 }
00156
00157
00159 UNIV_INTERN
00160 void
00161 thr_local_set_slot_no(
00162
00163 os_thread_id_t id,
00164 ulint slot_no)
00165 {
00166 thr_local_t* local;
00167
00168 mutex_enter(&thr_local_mutex);
00169
00170 local = thr_local_get(id);
00171
00172 local->slot_no = slot_no;
00173
00174 mutex_exit(&thr_local_mutex);
00175 }
00176
00177
00181 UNIV_INTERN
00182 ibool*
00183 thr_local_get_in_ibuf_field(void)
00184
00185 {
00186 thr_local_t* local;
00187
00188 mutex_enter(&thr_local_mutex);
00189
00190 local = thr_local_get(os_thread_get_curr_id());
00191
00192 mutex_exit(&thr_local_mutex);
00193
00194 return(&(local->in_ibuf));
00195 }
00196
00197
00199 UNIV_INTERN
00200 void
00201 thr_local_create(void)
00202
00203 {
00204 thr_local_t* local;
00205
00206 if (thr_local_hash == NULL) {
00207 thr_local_init();
00208 }
00209
00210 local = static_cast<thr_local_t *>(mem_alloc(sizeof(thr_local_t)));
00211
00212 local->id = os_thread_get_curr_id();
00213 local->handle = os_thread_get_curr();
00214 local->magic_n = THR_LOCAL_MAGIC_N;
00215 local->slot_no = ULINT_UNDEFINED;
00216 local->in_ibuf = FALSE;
00217
00218 mutex_enter(&thr_local_mutex);
00219
00220 HASH_INSERT(thr_local_t, hash, thr_local_hash,
00221 os_thread_pf(os_thread_get_curr_id()),
00222 local);
00223
00224 mutex_exit(&thr_local_mutex);
00225 }
00226
00227
00229 UNIV_INTERN
00230 void
00231 thr_local_free(
00232
00233 os_thread_id_t id)
00234 {
00235 thr_local_t* local;
00236
00237 mutex_enter(&thr_local_mutex);
00238
00239
00240
00241 HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
00242 thr_local_t*, local, ut_ad(thr_local_validate(local)),
00243 os_thread_eq(local->id, id));
00244 if (local == NULL) {
00245 mutex_exit(&thr_local_mutex);
00246
00247 return;
00248 }
00249
00250 HASH_DELETE(thr_local_t, hash, thr_local_hash,
00251 os_thread_pf(id), local);
00252
00253 mutex_exit(&thr_local_mutex);
00254
00255 ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
00256 ut_ad(thr_local_validate(local));
00257
00258 mem_free(local);
00259 }
00260
00261
00263 UNIV_INTERN
00264 void
00265 thr_local_init(void)
00266
00267 {
00268
00269 ut_a(thr_local_hash == NULL);
00270
00271 thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
00272
00273 mutex_create(thr_local_mutex_key,
00274 &thr_local_mutex, SYNC_THR_LOCAL);
00275 }
00276
00277
00278
00279 UNIV_INTERN
00280 void
00281 thr_local_close(void)
00282
00283 {
00284 ulint i;
00285
00286 ut_a(thr_local_hash != NULL);
00287
00288
00289
00290 for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
00291 thr_local_t* local;
00292
00293 local = static_cast<thr_local_t *>(HASH_GET_FIRST(thr_local_hash, i));
00294
00295 while (local) {
00296 thr_local_t* prev_local = local;
00297
00298 local = static_cast<thr_local_t *>(HASH_GET_NEXT(hash, prev_local));
00299 ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
00300 ut_ad(thr_local_validate(prev_local));
00301 mem_free(prev_local);
00302 }
00303 }
00304
00305 hash_table_free(thr_local_hash);
00306 thr_local_hash = NULL;
00307 }