~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/os/os0thread.c

MergedĀ inĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************************
2
 
The interface to the operating system thread control primitives
3
 
 
4
 
(c) 1995 Innobase Oy
5
 
 
6
 
Created 9/8/1995 Heikki Tuuri
7
 
*******************************************************/
8
 
 
9
 
#include "os0thread.h"
10
 
#ifdef UNIV_NONINL
11
 
#include "os0thread.ic"
12
 
#endif
13
 
 
14
 
#ifdef __WIN__
15
 
#include <windows.h>
16
 
#endif
17
 
 
18
 
#include "srv0srv.h"
19
 
#include "os0sync.h"
20
 
 
21
 
/*******************************************************************
22
 
Compares two thread ids for equality. */
23
 
 
24
 
ibool
25
 
os_thread_eq(
26
 
/*=========*/
27
 
                                /* out: TRUE if equal */
28
 
        os_thread_id_t  a,      /* in: OS thread or thread id */
29
 
        os_thread_id_t  b)      /* in: OS thread or thread id */
30
 
{
31
 
#ifdef __WIN__
32
 
        if (a == b) {
33
 
                return(TRUE);
34
 
        }
35
 
 
36
 
        return(FALSE);
37
 
#else
38
 
        if (pthread_equal(a, b)) {
39
 
                return(TRUE);
40
 
        }
41
 
 
42
 
        return(FALSE);
43
 
#endif
44
 
}
45
 
 
46
 
/********************************************************************
47
 
Converts an OS thread id to a ulint. It is NOT guaranteed that the ulint is
48
 
unique for the thread though! */
49
 
 
50
 
ulint
51
 
os_thread_pf(
52
 
/*=========*/
53
 
        os_thread_id_t  a)
54
 
{
55
 
#ifdef UNIV_HPUX10
56
 
        /* In HP-UX-10.20 a pthread_t is a struct of 3 fields: field1, field2,
57
 
        field3. We do not know if field1 determines the thread uniquely. */
58
 
 
59
 
        return((ulint)(a.field1));
60
 
#else
61
 
        return((ulint)a);
62
 
#endif
63
 
}
64
 
 
65
 
/*********************************************************************
66
 
Returns the thread identifier of current thread. Currently the thread
67
 
identifier in Unix is the thread handle itself. Note that in HP-UX
68
 
pthread_t is a struct of 3 fields. */
69
 
 
70
 
os_thread_id_t
71
 
os_thread_get_curr_id(void)
72
 
/*=======================*/
73
 
{
74
 
#ifdef __WIN__
75
 
        return(GetCurrentThreadId());
76
 
#else
77
 
        return(pthread_self());
78
 
#endif
79
 
}
80
 
 
81
 
/********************************************************************
82
 
Creates a new thread of execution. The execution starts from
83
 
the function given. The start function takes a void* parameter
84
 
and returns an ulint. */
85
 
 
86
 
os_thread_t
87
 
os_thread_create(
88
 
/*=============*/
89
 
                                                /* out: handle to the thread */
90
 
#ifndef __WIN__
91
 
        os_posix_f_t            start_f,
92
 
#else
93
 
        ulint (*start_f)(void*),                /* in: pointer to function
94
 
                                                from which to start */
95
 
#endif
96
 
        void*                   arg,            /* in: argument to start
97
 
                                                function */
98
 
        os_thread_id_t*         thread_id)      /* out: id of the created
99
 
                                                thread, or NULL */
100
 
{
101
 
#ifdef __WIN__
102
 
        os_thread_t     thread;
103
 
        DWORD           win_thread_id;
104
 
 
105
 
        os_mutex_enter(os_sync_mutex);
106
 
        os_thread_count++;
107
 
        os_mutex_exit(os_sync_mutex);
108
 
 
109
 
        thread = CreateThread(NULL,     /* no security attributes */
110
 
                              0,        /* default size stack */
111
 
                              (LPTHREAD_START_ROUTINE)start_f,
112
 
                              arg,
113
 
                              0,        /* thread runs immediately */
114
 
                              &win_thread_id);
115
 
 
116
 
        if (srv_set_thread_priorities) {
117
 
 
118
 
                /* Set created thread priority the same as a normal query
119
 
                in MYSQL: we try to prevent starvation of threads by
120
 
                assigning same priority QUERY_PRIOR to all */
121
 
 
122
 
                ut_a(SetThreadPriority(thread, srv_query_thread_priority));
123
 
        }
124
 
 
125
 
        if (thread_id) {
126
 
                *thread_id = win_thread_id;
127
 
        }
128
 
 
129
 
        return(thread);
130
 
#else
131
 
        int             ret;
132
 
        os_thread_t     pthread;
133
 
        pthread_attr_t  attr;
134
 
 
135
 
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
136
 
        pthread_attr_init(&attr);
137
 
#endif
138
 
 
139
 
#ifdef UNIV_AIX
140
 
        /* We must make sure a thread stack is at least 32 kB, otherwise
141
 
        InnoDB might crash; we do not know if the default stack size on
142
 
        AIX is always big enough. An empirical test on AIX-4.3 suggested
143
 
        the size was 96 kB, though. */
144
 
 
145
 
        ret = pthread_attr_setstacksize(&attr,
146
 
                                        (size_t)(PTHREAD_STACK_MIN
147
 
                                                 + 32 * 1024));
148
 
        if (ret) {
149
 
                fprintf(stderr,
150
 
                        "InnoDB: Error: pthread_attr_setstacksize"
151
 
                        " returned %d\n", ret);
152
 
                exit(1);
153
 
        }
154
 
#endif
155
 
        os_mutex_enter(os_sync_mutex);
156
 
        os_thread_count++;
157
 
        os_mutex_exit(os_sync_mutex);
158
 
 
159
 
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
160
 
        ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
161
 
#else
162
 
        ret = pthread_create(&pthread, &attr, start_f, arg);
163
 
#endif
164
 
        if (ret) {
165
 
                fprintf(stderr,
166
 
                        "InnoDB: Error: pthread_create returned %d\n", ret);
167
 
                exit(1);
168
 
        }
169
 
 
170
 
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
171
 
        pthread_attr_destroy(&attr);
172
 
#endif
173
 
        if (srv_set_thread_priorities) {
174
 
                  struct sched_param tmp_sched_param;
175
 
 
176
 
                  memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
177
 
                  tmp_sched_param.sched_priority= srv_query_thread_priority;
178
 
                  (void)pthread_setschedparam(pthread, SCHED_OTHER, &tmp_sched_param);
179
 
        }
180
 
 
181
 
        if (thread_id) {
182
 
                *thread_id = pthread;
183
 
        }
184
 
 
185
 
        return(pthread);
186
 
#endif
187
 
}
188
 
 
189
 
/*********************************************************************
190
 
Exits the current thread. */
191
 
 
192
 
void
193
 
os_thread_exit(
194
 
/*===========*/
195
 
        void*   exit_value)     /* in: exit value; in Windows this void*
196
 
                                is cast as a DWORD */
197
 
{
198
 
#ifdef UNIV_DEBUG_THREAD_CREATION
199
 
        fprintf(stderr, "Thread exits, id %lu\n",
200
 
                os_thread_pf(os_thread_get_curr_id()));
201
 
#endif
202
 
        os_mutex_enter(os_sync_mutex);
203
 
        os_thread_count--;
204
 
        os_mutex_exit(os_sync_mutex);
205
 
 
206
 
#ifdef __WIN__
207
 
        ExitThread((DWORD)exit_value);
208
 
#else
209
 
        pthread_exit(exit_value);
210
 
#endif
211
 
}
212
 
 
213
 
#ifdef HAVE_PTHREAD_JOIN
214
 
int
215
 
os_thread_join(
216
 
/*===========*/
217
 
  os_thread_id_t  thread_id)    /* in: id of the thread to join */
218
 
{
219
 
        return(pthread_join(thread_id, NULL));
220
 
}
221
 
#endif
222
 
/*********************************************************************
223
 
Returns handle to the current thread. */
224
 
 
225
 
os_thread_t
226
 
os_thread_get_curr(void)
227
 
/*====================*/
228
 
{
229
 
#ifdef __WIN__
230
 
        return(GetCurrentThread());
231
 
#else
232
 
        return(pthread_self());
233
 
#endif
234
 
}
235
 
 
236
 
/*********************************************************************
237
 
Advises the os to give up remainder of the thread's time slice. */
238
 
 
239
 
void
240
 
os_thread_yield(void)
241
 
/*=================*/
242
 
{
243
 
#if defined(__WIN__)
244
 
        Sleep(0);
245
 
#elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
246
 
        sched_yield();
247
 
#elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
248
 
        pthread_yield();
249
 
#elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
250
 
        pthread_yield(0);
251
 
#else
252
 
        os_thread_sleep(0);
253
 
#endif
254
 
}
255
 
 
256
 
/*********************************************************************
257
 
The thread sleeps at least the time given in microseconds. */
258
 
 
259
 
void
260
 
os_thread_sleep(
261
 
/*============*/
262
 
        ulint   tm)     /* in: time in microseconds */
263
 
{
264
 
#ifdef __WIN__
265
 
        Sleep((DWORD) tm / 1000);
266
 
#else
267
 
        struct timeval  t;
268
 
 
269
 
        t.tv_sec = tm / 1000000;
270
 
        t.tv_usec = tm % 1000000;
271
 
 
272
 
        select(0, NULL, NULL, NULL, &t);
273
 
#endif
274
 
}
275
 
 
276
 
/**********************************************************************
277
 
Sets a thread priority. */
278
 
 
279
 
void
280
 
os_thread_set_priority(
281
 
/*===================*/
282
 
        os_thread_t     handle, /* in: OS handle to the thread */
283
 
        ulint           pri)    /* in: priority */
284
 
{
285
 
#ifdef __WIN__
286
 
        int     os_pri;
287
 
 
288
 
        if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
289
 
                os_pri = THREAD_PRIORITY_BELOW_NORMAL;
290
 
        } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
291
 
                os_pri = THREAD_PRIORITY_NORMAL;
292
 
        } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
293
 
                os_pri = THREAD_PRIORITY_HIGHEST;
294
 
        } else {
295
 
                ut_error;
296
 
        }
297
 
 
298
 
        ut_a(SetThreadPriority(handle, os_pri));
299
 
#else
300
 
        UT_NOT_USED(handle);
301
 
        UT_NOT_USED(pri);
302
 
#endif
303
 
}
304
 
 
305
 
/**********************************************************************
306
 
Gets a thread priority. */
307
 
 
308
 
ulint
309
 
os_thread_get_priority(
310
 
/*===================*/
311
 
                                /* out: priority */
312
 
        os_thread_t     handle __attribute__((unused)))
313
 
                                /* in: OS handle to the thread */
314
 
{
315
 
#ifdef __WIN__
316
 
        int     os_pri;
317
 
        ulint   pri;
318
 
 
319
 
        os_pri = GetThreadPriority(handle);
320
 
 
321
 
        if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
322
 
                pri = OS_THREAD_PRIORITY_BACKGROUND;
323
 
        } else if (os_pri == THREAD_PRIORITY_NORMAL) {
324
 
                pri = OS_THREAD_PRIORITY_NORMAL;
325
 
        } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
326
 
                pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
327
 
        } else {
328
 
                ut_error;
329
 
        }
330
 
 
331
 
        return(pri);
332
 
#else
333
 
        return(0);
334
 
#endif
335
 
}
336
 
 
337
 
/**********************************************************************
338
 
Gets the last operating system error code for the calling thread. */
339
 
 
340
 
ulint
341
 
os_thread_get_last_error(void)
342
 
/*==========================*/
343
 
{
344
 
#ifdef __WIN__
345
 
        return(GetLastError());
346
 
#else
347
 
        return(0);
348
 
#endif
349
 
}