~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-10-10 23:04:21 UTC
  • mto: (509.1.1 codestyle)
  • mto: This revision was merged to the branch mainline in revision 511.
  • Revision ID: monty@inaugust.com-20081010230421-zohe1eppxievpw8d
Removed O_NOFOLLOW

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 os/os0thread.c
21
 
The interface to the operating system thread control primitives
22
 
 
23
 
Created 9/8/1995 Heikki Tuuri
24
 
*******************************************************/
25
 
 
26
 
#include "os0thread.h"
27
 
#ifdef UNIV_NONINL
28
 
#include "os0thread.ic"
29
 
#endif
30
 
 
31
 
#ifdef __WIN__
32
 
#include <windows.h>
33
 
#else
34
 
#include <sys/select.h>
35
 
#endif
36
 
 
37
 
#ifndef UNIV_HOTBACKUP
38
 
#include "srv0srv.h"
39
 
#include "os0sync.h"
40
 
 
41
 
/***************************************************************//**
42
 
Compares two thread ids for equality.
43
 
@return TRUE if equal */
44
 
UNIV_INTERN
45
 
ibool
46
 
os_thread_eq(
47
 
/*=========*/
48
 
        os_thread_id_t  a,      /*!< in: OS thread or thread id */
49
 
        os_thread_id_t  b)      /*!< in: OS thread or thread id */
50
 
{
51
 
#ifdef __WIN__
52
 
        if (a == b) {
53
 
                return(TRUE);
54
 
        }
55
 
 
56
 
        return(FALSE);
57
 
#else
58
 
        if (pthread_equal(a, b)) {
59
 
                return(TRUE);
60
 
        }
61
 
 
62
 
        return(FALSE);
63
 
#endif
64
 
}
65
 
 
66
 
/****************************************************************//**
67
 
Converts an OS thread id to a ulint. It is NOT guaranteed that the ulint is
68
 
unique for the thread though!
69
 
@return thread identifier as a number */
70
 
UNIV_INTERN
71
 
ulint
72
 
os_thread_pf(
73
 
/*=========*/
74
 
        os_thread_id_t  a)      /*!< in: OS thread identifier */
75
 
{
76
 
#ifdef UNIV_HPUX10
77
 
        /* In HP-UX-10.20 a pthread_t is a struct of 3 fields: field1, field2,
78
 
        field3. We do not know if field1 determines the thread uniquely. */
79
 
 
80
 
        return((ulint)(a.field1));
81
 
#else
82
 
        return((ulint)a);
83
 
#endif
84
 
}
85
 
 
86
 
/*****************************************************************//**
87
 
Returns the thread identifier of current thread. Currently the thread
88
 
identifier in Unix is the thread handle itself. Note that in HP-UX
89
 
pthread_t is a struct of 3 fields.
90
 
@return current thread identifier */
91
 
UNIV_INTERN
92
 
os_thread_id_t
93
 
os_thread_get_curr_id(void)
94
 
/*=======================*/
95
 
{
96
 
#ifdef __WIN__
97
 
        return(GetCurrentThreadId());
98
 
#else
99
 
        return(pthread_self());
100
 
#endif
101
 
}
102
 
 
103
 
/****************************************************************//**
104
 
Creates a new thread of execution. The execution starts from
105
 
the function given. The start function takes a void* parameter
106
 
and returns an ulint.
107
 
@return handle to the thread */
108
 
UNIV_INTERN
109
 
os_thread_t
110
 
os_thread_create(
111
 
/*=============*/
112
 
#ifndef __WIN__
113
 
        os_posix_f_t            start_f,
114
 
#else
115
 
        ulint (*start_f)(void*),                /*!< in: pointer to function
116
 
                                                from which to start */
117
 
#endif
118
 
        void*                   arg,            /*!< in: argument to start
119
 
                                                function */
120
 
        os_thread_id_t*         thread_id)      /*!< out: id of the created
121
 
                                                thread, or NULL */
122
 
{
123
 
#ifdef __WIN__
124
 
        os_thread_t     thread;
125
 
        DWORD           win_thread_id;
126
 
 
127
 
        os_mutex_enter(os_sync_mutex);
128
 
        os_thread_count++;
129
 
        os_mutex_exit(os_sync_mutex);
130
 
 
131
 
        thread = CreateThread(NULL,     /* no security attributes */
132
 
                              0,        /* default size stack */
133
 
                              (LPTHREAD_START_ROUTINE)start_f,
134
 
                              arg,
135
 
                              0,        /* thread runs immediately */
136
 
                              &win_thread_id);
137
 
 
138
 
        if (thread_id) {
139
 
                *thread_id = win_thread_id;
140
 
        }
141
 
 
142
 
        return(thread);
143
 
#else
144
 
        int             ret;
145
 
        os_thread_t     pthread;
146
 
        pthread_attr_t  attr;
147
 
 
148
 
#ifndef UNIV_HPUX10
149
 
        pthread_attr_init(&attr);
150
 
#endif
151
 
 
152
 
#ifdef UNIV_AIX
153
 
        /* We must make sure a thread stack is at least 32 kB, otherwise
154
 
        InnoDB might crash; we do not know if the default stack size on
155
 
        AIX is always big enough. An empirical test on AIX-4.3 suggested
156
 
        the size was 96 kB, though. */
157
 
 
158
 
        ret = pthread_attr_setstacksize(&attr,
159
 
                                        (size_t)(PTHREAD_STACK_MIN
160
 
                                                 + 32 * 1024));
161
 
        if (ret) {
162
 
                fprintf(stderr,
163
 
                        "InnoDB: Error: pthread_attr_setstacksize"
164
 
                        " returned %d\n", ret);
165
 
                exit(1);
166
 
        }
167
 
#endif
168
 
#ifdef __NETWARE__
169
 
        ret = pthread_attr_setstacksize(&attr,
170
 
                                        (size_t) NW_THD_STACKSIZE);
171
 
        if (ret) {
172
 
                fprintf(stderr,
173
 
                        "InnoDB: Error: pthread_attr_setstacksize"
174
 
                        " returned %d\n", ret);
175
 
                exit(1);
176
 
        }
177
 
#endif
178
 
        os_mutex_enter(os_sync_mutex);
179
 
        os_thread_count++;
180
 
        os_mutex_exit(os_sync_mutex);
181
 
 
182
 
#ifdef UNIV_HPUX10
183
 
        ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
184
 
#else
185
 
        ret = pthread_create(&pthread, &attr, start_f, arg);
186
 
#endif
187
 
        if (ret) {
188
 
                fprintf(stderr,
189
 
                        "InnoDB: Error: pthread_create returned %d\n", ret);
190
 
                exit(1);
191
 
        }
192
 
 
193
 
#ifndef UNIV_HPUX10
194
 
        pthread_attr_destroy(&attr);
195
 
#endif
196
 
 
197
 
        if (thread_id) {
198
 
                *thread_id = pthread;
199
 
        }
200
 
 
201
 
        return(pthread);
202
 
#endif
203
 
}
204
 
 
205
 
/*****************************************************************//**
206
 
Exits the current thread. */
207
 
UNIV_INTERN
208
 
void
209
 
os_thread_exit(
210
 
/*===========*/
211
 
        void*   exit_value)     /*!< in: exit value; in Windows this void*
212
 
                                is cast as a DWORD */
213
 
{
214
 
#ifdef UNIV_DEBUG_THREAD_CREATION
215
 
        fprintf(stderr, "Thread exits, id %lu\n",
216
 
                os_thread_pf(os_thread_get_curr_id()));
217
 
#endif
218
 
        os_mutex_enter(os_sync_mutex);
219
 
        os_thread_count--;
220
 
        os_mutex_exit(os_sync_mutex);
221
 
 
222
 
#ifdef __WIN__
223
 
        ExitThread((DWORD)exit_value);
224
 
#else
225
 
        pthread_exit(exit_value);
226
 
#endif
227
 
}
228
 
 
229
 
/*****************************************************************//**
230
 
Returns handle to the current thread.
231
 
@return current thread handle */
232
 
UNIV_INTERN
233
 
os_thread_t
234
 
os_thread_get_curr(void)
235
 
/*====================*/
236
 
{
237
 
#ifdef __WIN__
238
 
        return(GetCurrentThread());
239
 
#else
240
 
        return(pthread_self());
241
 
#endif
242
 
}
243
 
 
244
 
/*****************************************************************//**
245
 
Advises the os to give up remainder of the thread's time slice. */
246
 
UNIV_INTERN
247
 
void
248
 
os_thread_yield(void)
249
 
/*=================*/
250
 
{
251
 
#if defined(__WIN__)
252
 
        Sleep(0);
253
 
#elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
254
 
        sched_yield();
255
 
#elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
256
 
        pthread_yield();
257
 
#elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
258
 
        pthread_yield(0);
259
 
#else
260
 
        os_thread_sleep(0);
261
 
#endif
262
 
}
263
 
#endif /* !UNIV_HOTBACKUP */
264
 
 
265
 
/*****************************************************************//**
266
 
The thread sleeps at least the time given in microseconds. */
267
 
UNIV_INTERN
268
 
void
269
 
os_thread_sleep(
270
 
/*============*/
271
 
        ulint   tm)     /*!< in: time in microseconds */
272
 
{
273
 
#ifdef __WIN__
274
 
        Sleep((DWORD) tm / 1000);
275
 
#elif defined(__NETWARE__)
276
 
        delay(tm / 1000);
277
 
#else
278
 
        struct timeval  t;
279
 
 
280
 
        t.tv_sec = tm / 1000000;
281
 
        t.tv_usec = tm % 1000000;
282
 
 
283
 
        select(0, NULL, NULL, NULL, &t);
284
 
#endif
285
 
}
286
 
 
287
 
#ifndef UNIV_HOTBACKUP
288
 
/******************************************************************//**
289
 
Sets a thread priority. */
290
 
UNIV_INTERN
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
 
@return priority */
320
 
UNIV_INTERN
321
 
ulint
322
 
os_thread_get_priority(
323
 
/*===================*/
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
 
@return last error on Windows, 0 otherwise */
352
 
UNIV_INTERN
353
 
ulint
354
 
os_thread_get_last_error(void)
355
 
/*==========================*/
356
 
{
357
 
#ifdef __WIN__
358
 
        return(GetLastError());
359
 
#else
360
 
        return(0);
361
 
#endif
362
 
}
363
 
#endif /* !UNIV_HOTBACKUP */