~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
The thread local storage
 
3
 
 
4
(c) 1995 Innobase Oy
 
5
 
 
6
Created 10/5/1995 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "thr0loc.h"
 
10
#ifdef UNIV_NONINL
 
11
#include "thr0loc.ic"
 
12
#endif
 
13
 
 
14
#include "sync0sync.h"
 
15
#include "hash0hash.h"
 
16
#include "mem0mem.h"
 
17
#include "srv0srv.h"
 
18
 
 
19
/*
 
20
        IMPLEMENTATION OF THREAD LOCAL STORAGE
 
21
        ======================================
 
22
 
 
23
The threads sometimes need private data which depends on the thread id.
 
24
This is implemented as a hash table, where the hash value is calculated
 
25
from the thread id, to prepare for a large number of threads. The hash table
 
26
is protected by a mutex. If you need modify the program and put new data to
 
27
the thread local storage, just add it to struct thr_local_struct in the
 
28
header file. */
 
29
 
 
30
/* Mutex protecting the local storage hash table */
 
31
mutex_t thr_local_mutex;
 
32
 
 
33
/* The hash table. The module is not yet initialized when it is NULL. */
 
34
hash_table_t*   thr_local_hash  = NULL;
 
35
 
 
36
/* The private data for each thread should be put to
 
37
the structure below and the accessor functions written
 
38
for the field. */
 
39
typedef struct thr_local_struct thr_local_t;
 
40
 
 
41
struct thr_local_struct{
 
42
        os_thread_id_t  id;     /* id of the thread which owns this struct */
 
43
        os_thread_t     handle; /* operating system handle to the thread */
 
44
        ulint           slot_no;/* the index of the slot in the thread table
 
45
                                for this thread */
 
46
        ibool           in_ibuf;/* TRUE if the the thread is doing an ibuf
 
47
                                operation */
 
48
        hash_node_t     hash;   /* hash chain node */
 
49
        ulint           magic_n;
 
50
};
 
51
 
 
52
#define THR_LOCAL_MAGIC_N       1231234
 
53
 
 
54
/***********************************************************************
 
55
Returns the local storage struct for a thread. */
 
56
static
 
57
thr_local_t*
 
58
thr_local_get(
 
59
/*==========*/
 
60
                                /* out: local storage */
 
61
        os_thread_id_t  id)     /* in: thread id of the thread */
 
62
{
 
63
        thr_local_t*    local;
 
64
 
 
65
try_again:
 
66
        ut_ad(thr_local_hash);
 
67
        ut_ad(mutex_own(&thr_local_mutex));
 
68
 
 
69
        /* Look for the local struct in the hash table */
 
70
 
 
71
        local = NULL;
 
72
 
 
73
        HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
 
74
                    local, os_thread_eq(local->id, id));
 
75
        if (local == NULL) {
 
76
                mutex_exit(&thr_local_mutex);
 
77
 
 
78
                thr_local_create();
 
79
 
 
80
                mutex_enter(&thr_local_mutex);
 
81
 
 
82
                goto try_again;
 
83
        }
 
84
 
 
85
        ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
 
86
 
 
87
        return(local);
 
88
}
 
89
 
 
90
/***********************************************************************
 
91
Gets the slot number in the thread table of a thread. */
 
92
 
 
93
ulint
 
94
thr_local_get_slot_no(
 
95
/*==================*/
 
96
                                /* out: slot number */
 
97
        os_thread_id_t  id)     /* in: thread id of the thread */
 
98
{
 
99
        ulint           slot_no;
 
100
        thr_local_t*    local;
 
101
 
 
102
        mutex_enter(&thr_local_mutex);
 
103
 
 
104
        local = thr_local_get(id);
 
105
 
 
106
        slot_no = local->slot_no;
 
107
 
 
108
        mutex_exit(&thr_local_mutex);
 
109
 
 
110
        return(slot_no);
 
111
}
 
112
 
 
113
/***********************************************************************
 
114
Sets the slot number in the thread table of a thread. */
 
115
 
 
116
void
 
117
thr_local_set_slot_no(
 
118
/*==================*/
 
119
        os_thread_id_t  id,     /* in: thread id of the thread */
 
120
        ulint           slot_no)/* in: slot number */
 
121
{
 
122
        thr_local_t*    local;
 
123
 
 
124
        mutex_enter(&thr_local_mutex);
 
125
 
 
126
        local = thr_local_get(id);
 
127
 
 
128
        local->slot_no = slot_no;
 
129
 
 
130
        mutex_exit(&thr_local_mutex);
 
131
}
 
132
 
 
133
/***********************************************************************
 
134
Returns pointer to the 'in_ibuf' field within the current thread local
 
135
storage. */
 
136
 
 
137
ibool*
 
138
thr_local_get_in_ibuf_field(void)
 
139
/*=============================*/
 
140
                        /* out: pointer to the in_ibuf field */
 
141
{
 
142
        thr_local_t*    local;
 
143
 
 
144
        mutex_enter(&thr_local_mutex);
 
145
 
 
146
        local = thr_local_get(os_thread_get_curr_id());
 
147
 
 
148
        mutex_exit(&thr_local_mutex);
 
149
 
 
150
        return(&(local->in_ibuf));
 
151
}
 
152
 
 
153
/***********************************************************************
 
154
Creates a local storage struct for the calling new thread. */
 
155
 
 
156
void
 
157
thr_local_create(void)
 
158
/*==================*/
 
159
{
 
160
        thr_local_t*    local;
 
161
 
 
162
        if (thr_local_hash == NULL) {
 
163
                thr_local_init();
 
164
        }
 
165
 
 
166
        local = mem_alloc(sizeof(thr_local_t));
 
167
 
 
168
        local->id = os_thread_get_curr_id();
 
169
        local->handle = os_thread_get_curr();
 
170
        local->magic_n = THR_LOCAL_MAGIC_N;
 
171
 
 
172
        local->in_ibuf = FALSE;
 
173
 
 
174
        mutex_enter(&thr_local_mutex);
 
175
 
 
176
        HASH_INSERT(thr_local_t, hash, thr_local_hash,
 
177
                    os_thread_pf(os_thread_get_curr_id()),
 
178
                    local);
 
179
 
 
180
        mutex_exit(&thr_local_mutex);
 
181
}
 
182
 
 
183
/***********************************************************************
 
184
Frees the local storage struct for the specified thread. */
 
185
 
 
186
void
 
187
thr_local_free(
 
188
/*===========*/
 
189
        os_thread_id_t  id)     /* in: thread id */
 
190
{
 
191
        thr_local_t*    local;
 
192
 
 
193
        mutex_enter(&thr_local_mutex);
 
194
 
 
195
        /* Look for the local struct in the hash table */
 
196
 
 
197
        HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
 
198
                    local, os_thread_eq(local->id, id));
 
199
        if (local == NULL) {
 
200
                mutex_exit(&thr_local_mutex);
 
201
 
 
202
                return;
 
203
        }
 
204
 
 
205
        HASH_DELETE(thr_local_t, hash, thr_local_hash,
 
206
                    os_thread_pf(id), local);
 
207
 
 
208
        mutex_exit(&thr_local_mutex);
 
209
 
 
210
        ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
 
211
 
 
212
        mem_free(local);
 
213
}
 
214
 
 
215
/********************************************************************
 
216
Initializes the thread local storage module. */
 
217
 
 
218
void
 
219
thr_local_init(void)
 
220
/*================*/
 
221
{
 
222
 
 
223
        ut_a(thr_local_hash == NULL);
 
224
 
 
225
        thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
 
226
 
 
227
        mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
 
228
}