Drizzled Public API Documentation

thr0loc.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
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   IMPLEMENTATION OF THREAD LOCAL STORAGE
00038   ======================================
00039 
00040 The threads sometimes need private data which depends on the thread id.
00041 This is implemented as a hash table, where the hash value is calculated
00042 from the thread id, to prepare for a large number of threads. The hash table
00043 is protected by a mutex. If you need modify the program and put new data to
00044 the thread local storage, just add it to struct thr_local_struct in the
00045 header file. */
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 /* Key to register the mutex with performance schema */
00058 UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
00059 #endif /* UNIV_PFS_MUTEX */
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 /* UNIV_DEBUG */
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   /* Look for the local struct in the hash table */
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   /* Look for the local struct in the hash table */
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 Close the thread local storage module. */
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   /* Free the hash elements. We don't remove them from the table
00289   because we are going to destroy the table anyway. */
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 }