~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Cleanup around SAFEMALLOC

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 (srv_set_thread_priorities) {
139
 
 
140
 
                /* Set created thread priority the same as a normal query
141
 
                in MYSQL: we try to prevent starvation of threads by
142
 
                assigning same priority QUERY_PRIOR to all */
143
 
 
144
 
                ut_a(SetThreadPriority(thread, srv_query_thread_priority));
145
 
        }
146
 
 
147
 
        if (thread_id) {
148
 
                *thread_id = win_thread_id;
149
 
        }
150
 
 
151
 
        return(thread);
152
 
#else
153
 
        int             ret;
154
 
        os_thread_t     pthread;
155
 
        pthread_attr_t  attr;
156
 
 
157
 
#ifndef UNIV_HPUX10
158
 
        pthread_attr_init(&attr);
159
 
#endif
160
 
 
161
 
#ifdef UNIV_AIX
162
 
        /* We must make sure a thread stack is at least 32 kB, otherwise
163
 
        InnoDB might crash; we do not know if the default stack size on
164
 
        AIX is always big enough. An empirical test on AIX-4.3 suggested
165
 
        the size was 96 kB, though. */
166
 
 
167
 
        ret = pthread_attr_setstacksize(&attr,
168
 
                                        (size_t)(PTHREAD_STACK_MIN
169
 
                                                 + 32 * 1024));
170
 
        if (ret) {
171
 
                fprintf(stderr,
172
 
                        "InnoDB: Error: pthread_attr_setstacksize"
173
 
                        " returned %d\n", ret);
174
 
                exit(1);
175
 
        }
176
 
#endif
177
 
#ifdef __NETWARE__
178
 
        ret = pthread_attr_setstacksize(&attr,
179
 
                                        (size_t) NW_THD_STACKSIZE);
180
 
        if (ret) {
181
 
                fprintf(stderr,
182
 
                        "InnoDB: Error: pthread_attr_setstacksize"
183
 
                        " returned %d\n", ret);
184
 
                exit(1);
185
 
        }
186
 
#endif
187
 
        os_mutex_enter(os_sync_mutex);
188
 
        os_thread_count++;
189
 
        os_mutex_exit(os_sync_mutex);
190
 
 
191
 
#ifdef UNIV_HPUX10
192
 
        ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
193
 
#else
194
 
        ret = pthread_create(&pthread, &attr, start_f, arg);
195
 
#endif
196
 
        if (ret) {
197
 
                fprintf(stderr,
198
 
                        "InnoDB: Error: pthread_create returned %d\n", ret);
199
 
                exit(1);
200
 
        }
201
 
 
202
 
#ifndef UNIV_HPUX10
203
 
        pthread_attr_destroy(&attr);
204
 
#endif
205
 
        if (srv_set_thread_priorities) {
206
 
 
207
 
                  struct sched_param tmp_sched_param;
208
 
 
209
 
                  memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
210
 
                  tmp_sched_param.sched_priority= srv_query_thread_priority;
211
 
                  (void)pthread_setschedparam(pthread, SCHED_OTHER, &tmp_sched_param);
212
 
        }
213
 
 
214
 
        if (thread_id) {
215
 
                *thread_id = pthread;
216
 
        }
217
 
 
218
 
        return(pthread);
219
 
#endif
220
 
}
221
 
 
222
 
/*****************************************************************//**
223
 
Exits the current thread. */
224
 
UNIV_INTERN
225
 
void
226
 
os_thread_exit(
227
 
/*===========*/
228
 
        void*   exit_value)     /*!< in: exit value; in Windows this void*
229
 
                                is cast as a DWORD */
230
 
{
231
 
#ifdef UNIV_DEBUG_THREAD_CREATION
232
 
        fprintf(stderr, "Thread exits, id %lu\n",
233
 
                os_thread_pf(os_thread_get_curr_id()));
234
 
#endif
235
 
        os_mutex_enter(os_sync_mutex);
236
 
        os_thread_count--;
237
 
        os_mutex_exit(os_sync_mutex);
238
 
 
239
 
#ifdef __WIN__
240
 
        ExitThread((DWORD)exit_value);
241
 
#else
242
 
        pthread_exit(exit_value);
243
 
#endif
244
 
}
245
 
 
246
 
/*****************************************************************//**
247
 
Returns handle to the current thread.
248
 
@return current thread handle */
249
 
UNIV_INTERN
250
 
os_thread_t
251
 
os_thread_get_curr(void)
252
 
/*====================*/
253
 
{
254
 
#ifdef __WIN__
255
 
        return(GetCurrentThread());
256
 
#else
257
 
        return(pthread_self());
258
 
#endif
259
 
}
260
 
 
261
 
/*****************************************************************//**
262
 
Advises the os to give up remainder of the thread's time slice. */
263
 
UNIV_INTERN
264
 
void
265
 
os_thread_yield(void)
266
 
/*=================*/
267
 
{
268
 
#if defined(__WIN__)
269
 
        Sleep(0);
270
 
#elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
271
 
        sched_yield();
272
 
#elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
273
 
        pthread_yield();
274
 
#elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
275
 
        pthread_yield(0);
276
 
#else
277
 
        os_thread_sleep(0);
278
 
#endif
279
 
}
280
 
#endif /* !UNIV_HOTBACKUP */
281
 
 
282
 
/*****************************************************************//**
283
 
The thread sleeps at least the time given in microseconds. */
284
 
UNIV_INTERN
285
 
void
286
 
os_thread_sleep(
287
 
/*============*/
288
 
        ulint   tm)     /*!< in: time in microseconds */
289
 
{
290
 
#ifdef __WIN__
291
 
        Sleep((DWORD) tm / 1000);
292
 
#elif defined(__NETWARE__)
293
 
        delay(tm / 1000);
294
 
#else
295
 
        struct timeval  t;
296
 
 
297
 
        t.tv_sec = tm / 1000000;
298
 
        t.tv_usec = tm % 1000000;
299
 
 
300
 
        select(0, NULL, NULL, NULL, &t);
301
 
#endif
302
 
}
303
 
 
304
 
#ifndef UNIV_HOTBACKUP
305
 
/******************************************************************//**
306
 
Sets a thread priority. */
307
 
UNIV_INTERN
308
 
void
309
 
os_thread_set_priority(
310
 
/*===================*/
311
 
        os_thread_t     handle, /*!< in: OS handle to the thread */
312
 
        ulint           pri)    /*!< in: priority */
313
 
{
314
 
#ifdef __WIN__
315
 
        int     os_pri;
316
 
 
317
 
        if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
318
 
                os_pri = THREAD_PRIORITY_BELOW_NORMAL;
319
 
        } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
320
 
                os_pri = THREAD_PRIORITY_NORMAL;
321
 
        } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
322
 
                os_pri = THREAD_PRIORITY_HIGHEST;
323
 
        } else {
324
 
                ut_error;
325
 
        }
326
 
 
327
 
        ut_a(SetThreadPriority(handle, os_pri));
328
 
#else
329
 
        UT_NOT_USED(handle);
330
 
        UT_NOT_USED(pri);
331
 
#endif
332
 
}
333
 
 
334
 
/******************************************************************//**
335
 
Gets a thread priority.
336
 
@return priority */
337
 
UNIV_INTERN
338
 
ulint
339
 
os_thread_get_priority(
340
 
/*===================*/
341
 
        os_thread_t     handle __attribute__((unused)))
342
 
                                /*!< in: OS handle to the thread */
343
 
{
344
 
#ifdef __WIN__
345
 
        int     os_pri;
346
 
        ulint   pri;
347
 
 
348
 
        os_pri = GetThreadPriority(handle);
349
 
 
350
 
        if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
351
 
                pri = OS_THREAD_PRIORITY_BACKGROUND;
352
 
        } else if (os_pri == THREAD_PRIORITY_NORMAL) {
353
 
                pri = OS_THREAD_PRIORITY_NORMAL;
354
 
        } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
355
 
                pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
356
 
        } else {
357
 
                ut_error;
358
 
        }
359
 
 
360
 
        return(pri);
361
 
#else
362
 
        return(0);
363
 
#endif
364
 
}
365
 
 
366
 
/******************************************************************//**
367
 
Gets the last operating system error code for the calling thread.
368
 
@return last error on Windows, 0 otherwise */
369
 
UNIV_INTERN
370
 
ulint
371
 
os_thread_get_last_error(void)
372
 
/*==========================*/
373
 
{
374
 
#ifdef __WIN__
375
 
        return(GetLastError());
376
 
#else
377
 
        return(0);
378
 
#endif
379
 
}
380
 
#endif /* !UNIV_HOTBACKUP */