~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to storage/innobase/os/os0thread.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 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
#ifdef __NETWARE__
 
156
        ret = pthread_attr_setstacksize(&attr,
 
157
                                        (size_t) NW_THD_STACKSIZE);
 
158
        if (ret) {
 
159
                fprintf(stderr,
 
160
                        "InnoDB: Error: pthread_attr_setstacksize"
 
161
                        " returned %d\n", ret);
 
162
                exit(1);
 
163
        }
 
164
#endif
 
165
        os_mutex_enter(os_sync_mutex);
 
166
        os_thread_count++;
 
167
        os_mutex_exit(os_sync_mutex);
 
168
 
 
169
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
 
170
        ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
 
171
#else
 
172
        ret = pthread_create(&pthread, &attr, start_f, arg);
 
173
#endif
 
174
        if (ret) {
 
175
                fprintf(stderr,
 
176
                        "InnoDB: Error: pthread_create returned %d\n", ret);
 
177
                exit(1);
 
178
        }
 
179
 
 
180
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
 
181
        pthread_attr_destroy(&attr);
 
182
#endif
 
183
        if (srv_set_thread_priorities) {
 
184
 
 
185
                my_pthread_setprio(pthread, srv_query_thread_priority);
 
186
        }
 
187
 
 
188
        if (thread_id) {
 
189
                *thread_id = pthread;
 
190
        }
 
191
 
 
192
        return(pthread);
 
193
#endif
 
194
}
 
195
 
 
196
/*********************************************************************
 
197
Exits the current thread. */
 
198
 
 
199
void
 
200
os_thread_exit(
 
201
/*===========*/
 
202
        void*   exit_value)     /* in: exit value; in Windows this void*
 
203
                                is cast as a DWORD */
 
204
{
 
205
#ifdef UNIV_DEBUG_THREAD_CREATION
 
206
        fprintf(stderr, "Thread exits, id %lu\n",
 
207
                os_thread_pf(os_thread_get_curr_id()));
 
208
#endif
 
209
        os_mutex_enter(os_sync_mutex);
 
210
        os_thread_count--;
 
211
        os_mutex_exit(os_sync_mutex);
 
212
 
 
213
#ifdef __WIN__
 
214
        ExitThread((DWORD)exit_value);
 
215
#else
 
216
        pthread_exit(exit_value);
 
217
#endif
 
218
}
 
219
 
 
220
#ifdef HAVE_PTHREAD_JOIN
 
221
int
 
222
os_thread_join(
 
223
/*===========*/
 
224
  os_thread_id_t  thread_id)    /* in: id of the thread to join */
 
225
{
 
226
        return(pthread_join(thread_id, NULL));
 
227
}
 
228
#endif
 
229
/*********************************************************************
 
230
Returns handle to the current thread. */
 
231
 
 
232
os_thread_t
 
233
os_thread_get_curr(void)
 
234
/*====================*/
 
235
{
 
236
#ifdef __WIN__
 
237
        return(GetCurrentThread());
 
238
#else
 
239
        return(pthread_self());
 
240
#endif
 
241
}
 
242
 
 
243
/*********************************************************************
 
244
Advises the os to give up remainder of the thread's time slice. */
 
245
 
 
246
void
 
247
os_thread_yield(void)
 
248
/*=================*/
 
249
{
 
250
#if defined(__WIN__)
 
251
        Sleep(0);
 
252
#elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
 
253
        sched_yield();
 
254
#elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
 
255
        pthread_yield();
 
256
#elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
 
257
        pthread_yield(0);
 
258
#else
 
259
        os_thread_sleep(0);
 
260
#endif
 
261
}
 
262
 
 
263
/*********************************************************************
 
264
The thread sleeps at least the time given in microseconds. */
 
265
 
 
266
void
 
267
os_thread_sleep(
 
268
/*============*/
 
269
        ulint   tm)     /* in: time in microseconds */
 
270
{
 
271
#ifdef __WIN__
 
272
        Sleep((DWORD) tm / 1000);
 
273
#elif defined(__NETWARE__)
 
274
        delay(tm / 1000);
 
275
#else
 
276
        struct timeval  t;
 
277
 
 
278
        t.tv_sec = tm / 1000000;
 
279
        t.tv_usec = tm % 1000000;
 
280
 
 
281
        select(0, NULL, NULL, NULL, &t);
 
282
#endif
 
283
}
 
284
 
 
285
/**********************************************************************
 
286
Sets a thread priority. */
 
287
 
 
288
void
 
289
os_thread_set_priority(
 
290
/*===================*/
 
291
        os_thread_t     handle, /* in: OS handle to the thread */
 
292
        ulint           pri)    /* in: priority */
 
293
{
 
294
#ifdef __WIN__
 
295
        int     os_pri;
 
296
 
 
297
        if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
 
298
                os_pri = THREAD_PRIORITY_BELOW_NORMAL;
 
299
        } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
 
300
                os_pri = THREAD_PRIORITY_NORMAL;
 
301
        } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
 
302
                os_pri = THREAD_PRIORITY_HIGHEST;
 
303
        } else {
 
304
                ut_error;
 
305
        }
 
306
 
 
307
        ut_a(SetThreadPriority(handle, os_pri));
 
308
#else
 
309
        UT_NOT_USED(handle);
 
310
        UT_NOT_USED(pri);
 
311
#endif
 
312
}
 
313
 
 
314
/**********************************************************************
 
315
Gets a thread priority. */
 
316
 
 
317
ulint
 
318
os_thread_get_priority(
 
319
/*===================*/
 
320
                                /* out: priority */
 
321
        os_thread_t     handle __attribute__((unused)))
 
322
                                /* in: OS handle to the thread */
 
323
{
 
324
#ifdef __WIN__
 
325
        int     os_pri;
 
326
        ulint   pri;
 
327
 
 
328
        os_pri = GetThreadPriority(handle);
 
329
 
 
330
        if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
 
331
                pri = OS_THREAD_PRIORITY_BACKGROUND;
 
332
        } else if (os_pri == THREAD_PRIORITY_NORMAL) {
 
333
                pri = OS_THREAD_PRIORITY_NORMAL;
 
334
        } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
 
335
                pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
 
336
        } else {
 
337
                ut_error;
 
338
        }
 
339
 
 
340
        return(pri);
 
341
#else
 
342
        return(0);
 
343
#endif
 
344
}
 
345
 
 
346
/**********************************************************************
 
347
Gets the last operating system error code for the calling thread. */
 
348
 
 
349
ulint
 
350
os_thread_get_last_error(void)
 
351
/*==========================*/
 
352
{
 
353
#ifdef __WIN__
 
354
        return(GetLastError());
 
355
#else
 
356
        return(0);
 
357
#endif
 
358
}