~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/thr/thr0loc.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
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.
 
8
 
 
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.
 
12
 
 
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., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
/**************************************************//**
 
20
@file thr/thr0loc.c
 
21
The thread local storage
 
22
 
 
23
Created 10/5/1995 Heikki Tuuri
 
24
*******************************************************/
 
25
 
 
26
#include "thr0loc.h"
 
27
#ifdef UNIV_NONINL
 
28
#include "thr0loc.ic"
 
29
#endif
 
30
 
 
31
#include "sync0sync.h"
 
32
#include "hash0hash.h"
 
33
#include "mem0mem.h"
 
34
#include "srv0srv.h"
 
35
 
 
36
/*
 
37
        IMPLEMENTATION OF THREAD LOCAL STORAGE
 
38
        ======================================
 
39
 
 
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
 
45
header file. */
 
46
 
 
47
/** Mutex protecting thr_local_hash */
 
48
static mutex_t          thr_local_mutex;
 
49
 
 
50
/** The hash table. The module is not yet initialized when it is NULL. */
 
51
static hash_table_t*    thr_local_hash  = NULL;
 
52
 
 
53
/** Thread local data */
 
54
typedef struct thr_local_struct thr_local_t;
 
55
 
 
56
/** @brief Thread local data.
 
57
The private data for each thread should be put to
 
58
the structure below and the accessor functions written
 
59
for the field. */
 
60
struct thr_local_struct{
 
61
        os_thread_id_t  id;     /*!< id of the thread which owns this struct */
 
62
        os_thread_t     handle; /*!< operating system handle to the thread */
 
63
        ulint           slot_no;/*!< the index of the slot in the thread table
 
64
                                for this thread */
 
65
        ibool           in_ibuf;/*!< TRUE if the thread is doing an ibuf
 
66
                                operation */
 
67
        hash_node_t     hash;   /*!< hash chain node */
 
68
        ulint           magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
 
69
};
 
70
 
 
71
/** The value of thr_local_struct::magic_n */
 
72
#define THR_LOCAL_MAGIC_N       1231234
 
73
 
 
74
/*******************************************************************//**
 
75
Returns the local storage struct for a thread.
 
76
@return local storage */
 
77
static
 
78
thr_local_t*
 
79
thr_local_get(
 
80
/*==========*/
 
81
        os_thread_id_t  id)     /*!< in: thread id of the thread */
 
82
{
 
83
        thr_local_t*    local;
 
84
 
 
85
try_again:
 
86
        ut_ad(thr_local_hash);
 
87
        ut_ad(mutex_own(&thr_local_mutex));
 
88
 
 
89
        /* Look for the local struct in the hash table */
 
90
 
 
91
        local = NULL;
 
92
 
 
93
        HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
 
94
                    thr_local_t*, local,, os_thread_eq(local->id, id));
 
95
        if (local == NULL) {
 
96
                mutex_exit(&thr_local_mutex);
 
97
 
 
98
                thr_local_create();
 
99
 
 
100
                mutex_enter(&thr_local_mutex);
 
101
 
 
102
                goto try_again;
 
103
        }
 
104
 
 
105
        ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
 
106
 
 
107
        return(local);
 
108
}
 
109
 
 
110
/*******************************************************************//**
 
111
Gets the slot number in the thread table of a thread.
 
112
@return slot number */
 
113
UNIV_INTERN
 
114
ulint
 
115
thr_local_get_slot_no(
 
116
/*==================*/
 
117
        os_thread_id_t  id)     /*!< in: thread id of the thread */
 
118
{
 
119
        ulint           slot_no;
 
120
        thr_local_t*    local;
 
121
 
 
122
        mutex_enter(&thr_local_mutex);
 
123
 
 
124
        local = thr_local_get(id);
 
125
 
 
126
        slot_no = local->slot_no;
 
127
 
 
128
        mutex_exit(&thr_local_mutex);
 
129
 
 
130
        return(slot_no);
 
131
}
 
132
 
 
133
/*******************************************************************//**
 
134
Sets the slot number in the thread table of a thread. */
 
135
UNIV_INTERN
 
136
void
 
137
thr_local_set_slot_no(
 
138
/*==================*/
 
139
        os_thread_id_t  id,     /*!< in: thread id of the thread */
 
140
        ulint           slot_no)/*!< in: slot number */
 
141
{
 
142
        thr_local_t*    local;
 
143
 
 
144
        mutex_enter(&thr_local_mutex);
 
145
 
 
146
        local = thr_local_get(id);
 
147
 
 
148
        local->slot_no = slot_no;
 
149
 
 
150
        mutex_exit(&thr_local_mutex);
 
151
}
 
152
 
 
153
/*******************************************************************//**
 
154
Returns pointer to the 'in_ibuf' field within the current thread local
 
155
storage.
 
156
@return pointer to the in_ibuf field */
 
157
UNIV_INTERN
 
158
ibool*
 
159
thr_local_get_in_ibuf_field(void)
 
160
/*=============================*/
 
161
{
 
162
        thr_local_t*    local;
 
163
 
 
164
        mutex_enter(&thr_local_mutex);
 
165
 
 
166
        local = thr_local_get(os_thread_get_curr_id());
 
167
 
 
168
        mutex_exit(&thr_local_mutex);
 
169
 
 
170
        return(&(local->in_ibuf));
 
171
}
 
172
 
 
173
/*******************************************************************//**
 
174
Creates a local storage struct for the calling new thread. */
 
175
UNIV_INTERN
 
176
void
 
177
thr_local_create(void)
 
178
/*==================*/
 
179
{
 
180
        thr_local_t*    local;
 
181
 
 
182
        if (thr_local_hash == NULL) {
 
183
                thr_local_init();
 
184
        }
 
185
 
 
186
        local = mem_alloc(sizeof(thr_local_t));
 
187
 
 
188
        local->id = os_thread_get_curr_id();
 
189
        local->handle = os_thread_get_curr();
 
190
        local->magic_n = THR_LOCAL_MAGIC_N;
 
191
 
 
192
        local->in_ibuf = FALSE;
 
193
 
 
194
        mutex_enter(&thr_local_mutex);
 
195
 
 
196
        HASH_INSERT(thr_local_t, hash, thr_local_hash,
 
197
                    os_thread_pf(os_thread_get_curr_id()),
 
198
                    local);
 
199
 
 
200
        mutex_exit(&thr_local_mutex);
 
201
}
 
202
 
 
203
/*******************************************************************//**
 
204
Frees the local storage struct for the specified thread. */
 
205
UNIV_INTERN
 
206
void
 
207
thr_local_free(
 
208
/*===========*/
 
209
        os_thread_id_t  id)     /*!< in: thread id */
 
210
{
 
211
        thr_local_t*    local;
 
212
 
 
213
        mutex_enter(&thr_local_mutex);
 
214
 
 
215
        /* Look for the local struct in the hash table */
 
216
 
 
217
        HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
 
218
                    thr_local_t*, local,, os_thread_eq(local->id, id));
 
219
        if (local == NULL) {
 
220
                mutex_exit(&thr_local_mutex);
 
221
 
 
222
                return;
 
223
        }
 
224
 
 
225
        HASH_DELETE(thr_local_t, hash, thr_local_hash,
 
226
                    os_thread_pf(id), local);
 
227
 
 
228
        mutex_exit(&thr_local_mutex);
 
229
 
 
230
        ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
 
231
 
 
232
        mem_free(local);
 
233
}
 
234
 
 
235
/****************************************************************//**
 
236
Initializes the thread local storage module. */
 
237
UNIV_INTERN
 
238
void
 
239
thr_local_init(void)
 
240
/*================*/
 
241
{
 
242
 
 
243
        ut_a(thr_local_hash == NULL);
 
244
 
 
245
        thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
 
246
 
 
247
        mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
 
248
}
 
249
 
 
250
/********************************************************************
 
251
Close the thread local storage module. */
 
252
UNIV_INTERN
 
253
void
 
254
thr_local_close(void)
 
255
/*=================*/
 
256
{
 
257
        ulint           i;
 
258
 
 
259
        ut_a(thr_local_hash != NULL);
 
260
 
 
261
        /* Free the hash elements. We don't remove them from the table
 
262
        because we are going to destroy the table anyway. */
 
263
        for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
 
264
                thr_local_t*    local;
 
265
 
 
266
                local = HASH_GET_FIRST(thr_local_hash, i);
 
267
 
 
268
                while (local) {
 
269
                        thr_local_t*    prev_local = local;
 
270
 
 
271
                        local = HASH_GET_NEXT(hash, prev_local);
 
272
                        ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
 
273
                        mem_free(prev_local);
 
274
                }
 
275
        }
 
276
 
 
277
        hash_table_free(thr_local_hash);
 
278
        thr_local_hash = NULL;
 
279
}