~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Renamed more stuff to drizzle.

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