~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Mark Atwood
  • Date: 2008-10-16 11:33:16 UTC
  • mto: (520.1.13 drizzle)
  • mto: This revision was merged to the branch mainline in revision 530.
  • Revision ID: mark@fallenpegasus.com-20081016113316-ff6jdt31ck90sjdh
an implemention of the errmsg plugin

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., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 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_detach(pthread_self());
226
 
        pthread_exit(exit_value);
227
 
#endif
228
 
}
229
 
 
230
 
/*****************************************************************//**
231
 
Returns handle to the current thread.
232
 
@return current thread handle */
233
 
UNIV_INTERN
234
 
os_thread_t
235
 
os_thread_get_curr(void)
236
 
/*====================*/
237
 
{
238
 
#ifdef __WIN__
239
 
        return(GetCurrentThread());
240
 
#else
241
 
        return(pthread_self());
242
 
#endif
243
 
}
244
 
 
245
 
/*****************************************************************//**
246
 
Advises the os to give up remainder of the thread's time slice. */
247
 
UNIV_INTERN
248
 
void
249
 
os_thread_yield(void)
250
 
/*=================*/
251
 
{
252
 
#if defined(__WIN__)
253
 
        Sleep(0);
254
 
#elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
255
 
        sched_yield();
256
 
#elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
257
 
        pthread_yield();
258
 
#elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
259
 
        pthread_yield(0);
260
 
#else
261
 
        os_thread_sleep(0);
262
 
#endif
263
 
}
264
 
#endif /* !UNIV_HOTBACKUP */
265
 
 
266
 
/*****************************************************************//**
267
 
The thread sleeps at least the time given in microseconds. */
268
 
UNIV_INTERN
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
 
#ifndef UNIV_HOTBACKUP
289
 
/******************************************************************//**
290
 
Sets a thread priority. */
291
 
UNIV_INTERN
292
 
void
293
 
os_thread_set_priority(
294
 
/*===================*/
295
 
        os_thread_t     handle, /*!< in: OS handle to the thread */
296
 
        ulint           pri)    /*!< in: priority */
297
 
{
298
 
#ifdef __WIN__
299
 
        int     os_pri;
300
 
 
301
 
        if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
302
 
                os_pri = THREAD_PRIORITY_BELOW_NORMAL;
303
 
        } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
304
 
                os_pri = THREAD_PRIORITY_NORMAL;
305
 
        } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
306
 
                os_pri = THREAD_PRIORITY_HIGHEST;
307
 
        } else {
308
 
                ut_error;
309
 
        }
310
 
 
311
 
        ut_a(SetThreadPriority(handle, os_pri));
312
 
#else
313
 
        UT_NOT_USED(handle);
314
 
        UT_NOT_USED(pri);
315
 
#endif
316
 
}
317
 
 
318
 
/******************************************************************//**
319
 
Gets a thread priority.
320
 
@return priority */
321
 
UNIV_INTERN
322
 
ulint
323
 
os_thread_get_priority(
324
 
/*===================*/
325
 
        os_thread_t     handle __attribute__((unused)))
326
 
                                /*!< in: OS handle to the thread */
327
 
{
328
 
#ifdef __WIN__
329
 
        int     os_pri;
330
 
        ulint   pri;
331
 
 
332
 
        os_pri = GetThreadPriority(handle);
333
 
 
334
 
        if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
335
 
                pri = OS_THREAD_PRIORITY_BACKGROUND;
336
 
        } else if (os_pri == THREAD_PRIORITY_NORMAL) {
337
 
                pri = OS_THREAD_PRIORITY_NORMAL;
338
 
        } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
339
 
                pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
340
 
        } else {
341
 
                ut_error;
342
 
        }
343
 
 
344
 
        return(pri);
345
 
#else
346
 
        return(0);
347
 
#endif
348
 
}
349
 
 
350
 
/******************************************************************//**
351
 
Gets the last operating system error code for the calling thread.
352
 
@return last error on Windows, 0 otherwise */
353
 
UNIV_INTERN
354
 
ulint
355
 
os_thread_get_last_error(void)
356
 
/*==========================*/
357
 
{
358
 
#ifdef __WIN__
359
 
        return(GetLastError());
360
 
#else
361
 
        return(0);
362
 
#endif
363
 
}
364
 
#endif /* !UNIV_HOTBACKUP */