~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/os/os0sync.cc

  • Committer: Monty Taylor
  • Date: 2008-09-16 00:00:48 UTC
  • mto: This revision was merged to the branch mainline in revision 391.
  • Revision ID: monty@inaugust.com-20080916000048-3rvrv3gv9l0ad3gs
Fixed copyright headers in drizzled/

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/os0sync.c
21
 
The interface to the operating system
22
 
synchronization primitives.
23
 
 
24
 
Created 9/6/1995 Heikki Tuuri
25
 
*******************************************************/
26
 
#include "univ.i"
27
 
 
28
 
#include <errno.h>
29
 
 
30
 
#include "os0sync.h"
31
 
#ifdef UNIV_NONINL
32
 
#include "os0sync.ic"
33
 
#endif
34
 
 
35
 
#ifdef __WIN__
36
 
#include <windows.h>
37
 
#endif
38
 
 
39
 
#include "ut0mem.h"
40
 
#include "srv0start.h"
41
 
#include "srv0srv.h"
42
 
#include "ha_prototypes.h"
43
 
 
44
 
/* Type definition for an operating system mutex struct */
45
 
struct os_mutex_struct{
46
 
        os_event_t      event;  /*!< Used by sync0arr.c for queing threads */
47
 
        void*           handle; /*!< OS handle to mutex */
48
 
        ulint           count;  /*!< we use this counter to check
49
 
                                that the same thread does not
50
 
                                recursively lock the mutex: we
51
 
                                do not assume that the OS mutex
52
 
                                supports recursive locking, though
53
 
                                NT seems to do that */
54
 
        UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
55
 
                                /* list of all 'slow' OS mutexes created */
56
 
};
57
 
 
58
 
/** Mutex protecting counts and the lists of OS mutexes and events */
59
 
UNIV_INTERN os_mutex_t  os_sync_mutex;
60
 
/** TRUE if os_sync_mutex has been initialized */
61
 
static ibool            os_sync_mutex_inited    = FALSE;
62
 
/** TRUE when os_sync_free() is being executed */
63
 
static ibool            os_sync_free_called     = FALSE;
64
 
 
65
 
/** This is incremented by 1 in os_thread_create and decremented by 1 in
66
 
os_thread_exit */
67
 
UNIV_INTERN ulint       os_thread_count         = 0;
68
 
 
69
 
/** The list of all events created */
70
 
static UT_LIST_BASE_NODE_T(os_event_struct_t)   os_event_list;
71
 
 
72
 
/** The list of all OS 'slow' mutexes */
73
 
static UT_LIST_BASE_NODE_T(os_mutex_str_t)      os_mutex_list;
74
 
 
75
 
UNIV_INTERN ulint       os_event_count          = 0;
76
 
UNIV_INTERN ulint       os_mutex_count          = 0;
77
 
UNIV_INTERN ulint       os_fast_mutex_count     = 0;
78
 
 
79
 
/* The number of microsecnds in a second. */
80
 
static const ulint MICROSECS_IN_A_SECOND = 1000000;
81
 
 
82
 
/* Because a mutex is embedded inside an event and there is an
83
 
event embedded inside a mutex, on free, this generates a recursive call.
84
 
This version of the free event function doesn't acquire the global lock */
85
 
static void os_event_free_internal(os_event_t   event);
86
 
 
87
 
/* On Windows (Vista and later), load function pointers for condition
88
 
variable handling. Those functions are not available in prior versions,
89
 
so we have to use them via runtime loading, as long as we support XP. */
90
 
static void os_cond_module_init(void);
91
 
 
92
 
#ifdef __WIN__
93
 
/* Prototypes and function pointers for condition variable functions */
94
 
typedef VOID (WINAPI* InitializeConditionVariableProc)
95
 
             (PCONDITION_VARIABLE ConditionVariable);
96
 
static InitializeConditionVariableProc initialize_condition_variable;
97
 
 
98
 
typedef BOOL (WINAPI* SleepConditionVariableCSProc)
99
 
             (PCONDITION_VARIABLE ConditionVariable,
100
 
              PCRITICAL_SECTION CriticalSection,
101
 
              DWORD dwMilliseconds);
102
 
static SleepConditionVariableCSProc sleep_condition_variable;
103
 
 
104
 
typedef VOID (WINAPI* WakeAllConditionVariableProc)
105
 
             (PCONDITION_VARIABLE ConditionVariable);
106
 
static WakeAllConditionVariableProc wake_all_condition_variable;
107
 
 
108
 
typedef VOID (WINAPI* WakeConditionVariableProc)
109
 
             (PCONDITION_VARIABLE ConditionVariable);
110
 
static WakeConditionVariableProc wake_condition_variable;
111
 
#endif
112
 
 
113
 
/*********************************************************//**
114
 
Initialitze condition variable */
115
 
UNIV_INLINE
116
 
void
117
 
os_cond_init(
118
 
/*=========*/
119
 
        os_cond_t*      cond)   /*!< in: condition variable. */
120
 
{
121
 
        ut_a(cond);
122
 
 
123
 
#ifdef __WIN__
124
 
        ut_a(initialize_condition_variable != NULL);
125
 
        initialize_condition_variable(cond);
126
 
#else
127
 
        ut_a(pthread_cond_init(cond, NULL) == 0);
128
 
#endif
129
 
}
130
 
 
131
 
/*********************************************************//**
132
 
Do a timed wait on condition variable.
133
 
@return TRUE if timed out, FALSE otherwise */
134
 
UNIV_INLINE
135
 
ibool
136
 
os_cond_wait_timed(
137
 
/*===============*/
138
 
        os_cond_t*              cond,           /*!< in: condition variable. */
139
 
        os_fast_mutex_t*        mutex,          /*!< in: fast mutex */
140
 
#ifndef __WIN__
141
 
        const struct timespec*  abstime         /*!< in: timeout */
142
 
#else
143
 
        DWORD                   time_in_ms      /*!< in: timeout in
144
 
                                                milliseconds*/
145
 
#endif /* !__WIN__ */
146
 
)
147
 
{
148
 
#ifdef __WIN__
149
 
        BOOL    ret;
150
 
        DWORD   err;
151
 
 
152
 
        ut_a(sleep_condition_variable != NULL);
153
 
 
154
 
        ret = sleep_condition_variable(cond, mutex, time_in_ms);
155
 
 
156
 
        if (!ret) {
157
 
                err = GetLastError();
158
 
                /* From http://msdn.microsoft.com/en-us/library/ms686301%28VS.85%29.aspx,
159
 
                "Condition variables are subject to spurious wakeups
160
 
                (those not associated with an explicit wake) and stolen wakeups
161
 
                (another thread manages to run before the woken thread)."
162
 
                Check for both types of timeouts.
163
 
                Conditions are checked by the caller.*/
164
 
                if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
165
 
                        return(TRUE);
166
 
                }
167
 
        }
168
 
 
169
 
        ut_a(ret);
170
 
 
171
 
        return(FALSE);
172
 
#else
173
 
        int     ret;
174
 
 
175
 
        ret = pthread_cond_timedwait(cond, mutex, abstime);
176
 
 
177
 
        switch (ret) {
178
 
        case 0:
179
 
        case ETIMEDOUT:
180
 
        /* We play it safe by checking for EINTR even though
181
 
        according to the POSIX documentation it can't return EINTR. */
182
 
        case EINTR:
183
 
                break;
184
 
 
185
 
        default:
186
 
                fprintf(stderr, "  InnoDB: pthread_cond_timedwait() returned: "
187
 
                                "%d: abstime={%lu,%lu}\n",
188
 
                                ret, (ulong) abstime->tv_sec, (ulong) abstime->tv_nsec);
189
 
                ut_error;
190
 
        }
191
 
 
192
 
        return(ret == ETIMEDOUT);
193
 
#endif
194
 
}
195
 
/*********************************************************//**
196
 
Wait on condition variable */
197
 
UNIV_INLINE
198
 
void
199
 
os_cond_wait(
200
 
/*=========*/
201
 
        os_cond_t*              cond,   /*!< in: condition variable. */
202
 
        os_fast_mutex_t*        mutex)  /*!< in: fast mutex */
203
 
{
204
 
        ut_a(cond);
205
 
        ut_a(mutex);
206
 
 
207
 
#ifdef __WIN__
208
 
        ut_a(sleep_condition_variable != NULL);
209
 
        ut_a(sleep_condition_variable(cond, mutex, INFINITE));
210
 
#else
211
 
        ut_a(pthread_cond_wait(cond, mutex) == 0);
212
 
#endif
213
 
}
214
 
 
215
 
/*********************************************************//**
216
 
Wakes all threads  waiting for condition variable */
217
 
UNIV_INLINE
218
 
void
219
 
os_cond_broadcast(
220
 
/*==============*/
221
 
        os_cond_t*      cond)   /*!< in: condition variable. */
222
 
{
223
 
        ut_a(cond);
224
 
 
225
 
#ifdef __WIN__
226
 
        ut_a(wake_all_condition_variable != NULL);
227
 
        wake_all_condition_variable(cond);
228
 
#else
229
 
        ut_a(pthread_cond_broadcast(cond) == 0);
230
 
#endif
231
 
}
232
 
 
233
 
/*********************************************************//**
234
 
Wakes one thread waiting for condition variable */
235
 
UNIV_INLINE
236
 
void
237
 
os_cond_signal(
238
 
/*==========*/
239
 
        os_cond_t*      cond)   /*!< in: condition variable. */
240
 
{
241
 
        ut_a(cond);
242
 
 
243
 
#ifdef __WIN__
244
 
        ut_a(wake_condition_variable != NULL);
245
 
        wake_condition_variable(cond);
246
 
#else
247
 
        ut_a(pthread_cond_signal(cond) == 0);
248
 
#endif
249
 
}
250
 
 
251
 
/*********************************************************//**
252
 
Destroys condition variable */
253
 
UNIV_INLINE
254
 
void
255
 
os_cond_destroy(
256
 
/*============*/
257
 
        os_cond_t*      cond)   /*!< in: condition variable. */
258
 
{
259
 
#ifdef __WIN__
260
 
        /* Do nothing */
261
 
#else
262
 
        ut_a(pthread_cond_destroy(cond) == 0);
263
 
#endif
264
 
}
265
 
 
266
 
/*********************************************************//**
267
 
On Windows (Vista and later), load function pointers for condition variable
268
 
handling. Those functions are not available in prior versions, so we have to
269
 
use them via runtime loading, as long as we support XP. */
270
 
static
271
 
void
272
 
os_cond_module_init(void)
273
 
/*=====================*/
274
 
{
275
 
#ifdef __WIN__
276
 
        HMODULE         h_dll;
277
 
 
278
 
        if (!srv_use_native_conditions)
279
 
                return;
280
 
 
281
 
        h_dll = GetModuleHandle("kernel32");
282
 
 
283
 
        initialize_condition_variable = (InitializeConditionVariableProc)
284
 
                         GetProcAddress(h_dll, "InitializeConditionVariable");
285
 
        sleep_condition_variable = (SleepConditionVariableCSProc)
286
 
                          GetProcAddress(h_dll, "SleepConditionVariableCS");
287
 
        wake_all_condition_variable = (WakeAllConditionVariableProc)
288
 
                             GetProcAddress(h_dll, "WakeAllConditionVariable");
289
 
        wake_condition_variable = (WakeConditionVariableProc)
290
 
                         GetProcAddress(h_dll, "WakeConditionVariable");
291
 
 
292
 
        /* When using native condition variables, check function pointers */
293
 
        ut_a(initialize_condition_variable);
294
 
        ut_a(sleep_condition_variable);
295
 
        ut_a(wake_all_condition_variable);
296
 
        ut_a(wake_condition_variable);
297
 
#endif
298
 
}
299
 
 
300
 
/*********************************************************//**
301
 
Initializes global event and OS 'slow' mutex lists. */
302
 
UNIV_INTERN
303
 
void
304
 
os_sync_init(void)
305
 
/*==============*/
306
 
{
307
 
        UT_LIST_INIT(os_event_list);
308
 
        UT_LIST_INIT(os_mutex_list);
309
 
 
310
 
        os_sync_mutex = NULL;
311
 
        os_sync_mutex_inited = FALSE;
312
 
 
313
 
        /* Now for Windows only */
314
 
        os_cond_module_init();
315
 
 
316
 
        os_sync_mutex = os_mutex_create();
317
 
 
318
 
        os_sync_mutex_inited = TRUE;
319
 
}
320
 
 
321
 
/*********************************************************//**
322
 
Frees created events and OS 'slow' mutexes. */
323
 
UNIV_INTERN
324
 
void
325
 
os_sync_free(void)
326
 
/*==============*/
327
 
{
328
 
        os_event_t      event;
329
 
        os_mutex_t      mutex;
330
 
 
331
 
        os_sync_free_called = TRUE;
332
 
        event = UT_LIST_GET_FIRST(os_event_list);
333
 
 
334
 
        while (event) {
335
 
 
336
 
                os_event_free(event);
337
 
 
338
 
                event = UT_LIST_GET_FIRST(os_event_list);
339
 
        }
340
 
 
341
 
        mutex = UT_LIST_GET_FIRST(os_mutex_list);
342
 
 
343
 
        while (mutex) {
344
 
                if (mutex == os_sync_mutex) {
345
 
                        /* Set the flag to FALSE so that we do not try to
346
 
                        reserve os_sync_mutex any more in remaining freeing
347
 
                        operations in shutdown */
348
 
                        os_sync_mutex_inited = FALSE;
349
 
                }
350
 
 
351
 
                os_mutex_free(mutex);
352
 
 
353
 
                mutex = UT_LIST_GET_FIRST(os_mutex_list);
354
 
        }
355
 
        os_sync_free_called = FALSE;
356
 
}
357
 
 
358
 
/*********************************************************//**
359
 
Creates an event semaphore, i.e., a semaphore which may just have two
360
 
states: signaled and nonsignaled. The created event is manual reset: it
361
 
must be reset explicitly by calling sync_os_reset_event.
362
 
@return the event handle */
363
 
UNIV_INTERN
364
 
os_event_t
365
 
os_event_create(
366
 
/*============*/
367
 
        const char*     name)   /*!< in: the name of the event, if NULL
368
 
                                the event is created without a name */
369
 
{
370
 
        os_event_t      event;
371
 
 
372
 
#ifdef __WIN__
373
 
        if(!srv_use_native_conditions) {
374
 
 
375
 
                event = ut_malloc(sizeof(struct os_event_struct));
376
 
 
377
 
                event->handle = CreateEvent(NULL,
378
 
                                            TRUE,
379
 
                                            FALSE,
380
 
                                            (LPCTSTR) name);
381
 
                if (!event->handle) {
382
 
                        fprintf(stderr,
383
 
                                "InnoDB: Could not create a Windows event"
384
 
                                " semaphore; Windows error %lu\n",
385
 
                                (ulong) GetLastError());
386
 
                }
387
 
        } else /* Windows with condition variables */
388
 
#endif
389
 
 
390
 
        {
391
 
                UT_NOT_USED(name);
392
 
 
393
 
                event = static_cast<os_event_struct*>(ut_malloc(sizeof(struct os_event_struct)));
394
 
 
395
 
                os_fast_mutex_init(&(event->os_mutex));
396
 
 
397
 
                os_cond_init(&(event->cond_var));
398
 
 
399
 
                event->is_set = FALSE;
400
 
 
401
 
                /* We return this value in os_event_reset(), which can then be
402
 
                be used to pass to the os_event_wait_low(). The value of zero
403
 
                is reserved in os_event_wait_low() for the case when the
404
 
                caller does not want to pass any signal_count value. To
405
 
                distinguish between the two cases we initialize signal_count
406
 
                to 1 here. */
407
 
                event->signal_count = 1;
408
 
        }
409
 
 
410
 
        /* The os_sync_mutex can be NULL because during startup an event
411
 
        can be created [ because it's embedded in the mutex/rwlock ] before
412
 
        this module has been initialized */
413
 
        if (os_sync_mutex != NULL) {
414
 
                os_mutex_enter(os_sync_mutex);
415
 
        }
416
 
 
417
 
        /* Put to the list of events */
418
 
        UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
419
 
 
420
 
        os_event_count++;
421
 
 
422
 
        if (os_sync_mutex != NULL) {
423
 
                os_mutex_exit(os_sync_mutex);
424
 
        }
425
 
 
426
 
        return(event);
427
 
}
428
 
 
429
 
/**********************************************************//**
430
 
Sets an event semaphore to the signaled state: lets waiting threads
431
 
proceed. */
432
 
UNIV_INTERN
433
 
void
434
 
os_event_set(
435
 
/*=========*/
436
 
        os_event_t      event)  /*!< in: event to set */
437
 
{
438
 
        ut_a(event);
439
 
 
440
 
#ifdef __WIN__
441
 
        if (!srv_use_native_conditions) {
442
 
                ut_a(SetEvent(event->handle));
443
 
                return;
444
 
        }
445
 
#endif
446
 
 
447
 
        ut_a(event);
448
 
 
449
 
        os_fast_mutex_lock(&(event->os_mutex));
450
 
 
451
 
        if (event->is_set) {
452
 
                /* Do nothing */
453
 
        } else {
454
 
                event->is_set = TRUE;
455
 
                event->signal_count += 1;
456
 
                os_cond_broadcast(&(event->cond_var));
457
 
        }
458
 
 
459
 
        os_fast_mutex_unlock(&(event->os_mutex));
460
 
}
461
 
 
462
 
/**********************************************************//**
463
 
Resets an event semaphore to the nonsignaled state. Waiting threads will
464
 
stop to wait for the event.
465
 
The return value should be passed to os_even_wait_low() if it is desired
466
 
that this thread should not wait in case of an intervening call to
467
 
os_event_set() between this os_event_reset() and the
468
 
os_event_wait_low() call. See comments for os_event_wait_low().
469
 
@return current signal_count. */
470
 
UNIV_INTERN
471
 
ib_int64_t
472
 
os_event_reset(
473
 
/*===========*/
474
 
        os_event_t      event)  /*!< in: event to reset */
475
 
{
476
 
        ib_int64_t      ret = 0;
477
 
 
478
 
        ut_a(event);
479
 
 
480
 
#ifdef __WIN__
481
 
        if(!srv_use_native_conditions) {
482
 
                ut_a(ResetEvent(event->handle));
483
 
                return(0);
484
 
        }
485
 
#endif
486
 
 
487
 
        os_fast_mutex_lock(&(event->os_mutex));
488
 
 
489
 
        if (!event->is_set) {
490
 
                /* Do nothing */
491
 
        } else {
492
 
                event->is_set = FALSE;
493
 
        }
494
 
        ret = event->signal_count;
495
 
 
496
 
        os_fast_mutex_unlock(&(event->os_mutex));
497
 
        return(ret);
498
 
}
499
 
 
500
 
/**********************************************************//**
501
 
Frees an event object, without acquiring the global lock. */
502
 
static
503
 
void
504
 
os_event_free_internal(
505
 
/*===================*/
506
 
        os_event_t      event)  /*!< in: event to free */
507
 
{
508
 
#ifdef __WIN__
509
 
        if(!srv_use_native_conditions) {
510
 
                ut_a(event);
511
 
                ut_a(CloseHandle(event->handle));
512
 
        } else
513
 
#endif
514
 
        {
515
 
                ut_a(event);
516
 
 
517
 
                /* This is to avoid freeing the mutex twice */
518
 
                os_fast_mutex_free(&(event->os_mutex));
519
 
 
520
 
                os_cond_destroy(&(event->cond_var));
521
 
        }
522
 
 
523
 
        /* Remove from the list of events */
524
 
        UT_LIST_REMOVE(os_event_list, os_event_list, event);
525
 
 
526
 
        os_event_count--;
527
 
 
528
 
        ut_free(event);
529
 
}
530
 
 
531
 
/**********************************************************//**
532
 
Frees an event object. */
533
 
UNIV_INTERN
534
 
void
535
 
os_event_free(
536
 
/*==========*/
537
 
        os_event_t      event)  /*!< in: event to free */
538
 
 
539
 
{
540
 
        ut_a(event);
541
 
#ifdef __WIN__
542
 
        if(!srv_use_native_conditions){
543
 
                ut_a(CloseHandle(event->handle));
544
 
        } else /*Windows with condition variables */
545
 
#endif
546
 
        {
547
 
                os_fast_mutex_free(&(event->os_mutex));
548
 
 
549
 
                os_cond_destroy(&(event->cond_var));
550
 
        }
551
 
 
552
 
        /* Remove from the list of events */
553
 
        os_mutex_enter(os_sync_mutex);
554
 
 
555
 
        UT_LIST_REMOVE(os_event_list, os_event_list, event);
556
 
 
557
 
        os_event_count--;
558
 
 
559
 
        os_mutex_exit(os_sync_mutex);
560
 
 
561
 
        ut_free(event);
562
 
}
563
 
 
564
 
/**********************************************************//**
565
 
Waits for an event object until it is in the signaled state. If
566
 
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
567
 
waiting thread when the event becomes signaled (or immediately if the
568
 
event is already in the signaled state).
569
 
 
570
 
Typically, if the event has been signalled after the os_event_reset()
571
 
we'll return immediately because event->is_set == TRUE.
572
 
There are, however, situations (e.g.: sync_array code) where we may
573
 
lose this information. For example:
574
 
 
575
 
thread A calls os_event_reset()
576
 
thread B calls os_event_set()   [event->is_set == TRUE]
577
 
thread C calls os_event_reset() [event->is_set == FALSE]
578
 
thread A calls os_event_wait()  [infinite wait!]
579
 
thread C calls os_event_wait()  [infinite wait!]
580
 
 
581
 
Where such a scenario is possible, to avoid infinite wait, the
582
 
value returned by os_event_reset() should be passed in as
583
 
reset_sig_count. */
584
 
UNIV_INTERN
585
 
void
586
 
os_event_wait_low(
587
 
/*==============*/
588
 
        os_event_t      event,          /*!< in: event to wait */
589
 
        ib_int64_t      reset_sig_count)/*!< in: zero or the value
590
 
                                        returned by previous call of
591
 
                                        os_event_reset(). */
592
 
{
593
 
        ib_int64_t      old_signal_count;
594
 
 
595
 
#ifdef __WIN__
596
 
        if(!srv_use_native_conditions) {
597
 
                DWORD   err;
598
 
 
599
 
                ut_a(event);
600
 
 
601
 
                UT_NOT_USED(reset_sig_count);
602
 
 
603
 
                /* Specify an infinite wait */
604
 
                err = WaitForSingleObject(event->handle, INFINITE);
605
 
 
606
 
                ut_a(err == WAIT_OBJECT_0);
607
 
 
608
 
                if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
609
 
                        os_thread_exit(NULL);
610
 
                }
611
 
                return;
612
 
        }
613
 
#endif
614
 
 
615
 
        os_fast_mutex_lock(&(event->os_mutex));
616
 
 
617
 
        if (reset_sig_count) {
618
 
                old_signal_count = reset_sig_count;
619
 
        } else {
620
 
                old_signal_count = event->signal_count;
621
 
        }
622
 
 
623
 
        for (;;) {
624
 
                if (event->is_set == TRUE
625
 
                    || event->signal_count != old_signal_count) {
626
 
 
627
 
                        os_fast_mutex_unlock(&(event->os_mutex));
628
 
 
629
 
                        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
630
 
 
631
 
                                os_thread_exit(NULL);
632
 
                        }
633
 
                        /* Ok, we may return */
634
 
 
635
 
                        return;
636
 
                }
637
 
 
638
 
                os_cond_wait(&(event->cond_var), &(event->os_mutex));
639
 
 
640
 
                /* Solaris manual said that spurious wakeups may occur: we
641
 
                have to check if the event really has been signaled after
642
 
                we came here to wait */
643
 
        }
644
 
}
645
 
 
646
 
/**********************************************************//**
647
 
Waits for an event object until it is in the signaled state or
648
 
a timeout is exceeded.
649
 
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
650
 
UNIV_INTERN
651
 
ulint
652
 
os_event_wait_time_low(
653
 
/*===================*/
654
 
        os_event_t      event,                  /*!< in: event to wait */
655
 
        ulint           time_in_usec,           /*!< in: timeout in
656
 
                                                microseconds, or
657
 
                                                OS_SYNC_INFINITE_TIME */
658
 
        ib_int64_t      reset_sig_count)        /*!< in: zero or the value
659
 
                                                returned by previous call of
660
 
                                                os_event_reset(). */
661
 
 
662
 
{
663
 
        ibool           timed_out = FALSE;
664
 
        ib_int64_t      old_signal_count;
665
 
 
666
 
#ifdef __WIN__
667
 
        DWORD           time_in_ms;
668
 
 
669
 
        if (!srv_use_native_conditions) {
670
 
                DWORD   err;
671
 
 
672
 
                ut_a(event);
673
 
 
674
 
                if (time_in_usec != OS_SYNC_INFINITE_TIME) {
675
 
                        time_in_ms = time_in_usec / 1000;
676
 
                        err = WaitForSingleObject(event->handle, time_in_ms);
677
 
                } else {
678
 
                        err = WaitForSingleObject(event->handle, INFINITE);
679
 
                }
680
 
 
681
 
                if (err == WAIT_OBJECT_0) {
682
 
                        return(0);
683
 
                } else if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
684
 
                        return(OS_SYNC_TIME_EXCEEDED);
685
 
                }
686
 
 
687
 
                ut_error;
688
 
                /* Dummy value to eliminate compiler warning. */
689
 
                return(42);
690
 
        } else {
691
 
                ut_a(sleep_condition_variable != NULL);
692
 
 
693
 
                if (time_in_usec != OS_SYNC_INFINITE_TIME) {
694
 
                        time_in_ms = time_in_usec / 1000;
695
 
                } else {
696
 
                        time_in_ms = INFINITE;
697
 
                }
698
 
        }
699
 
#else
700
 
        struct timespec abstime;
701
 
 
702
 
        if (time_in_usec != OS_SYNC_INFINITE_TIME) {
703
 
                struct timeval  tv;
704
 
                int             ret;
705
 
                ulint           sec;
706
 
                ulint           usec;
707
 
 
708
 
                ret = ut_usectime(&sec, &usec);
709
 
                ut_a(ret == 0);
710
 
 
711
 
                tv.tv_sec = sec;
712
 
                tv.tv_usec = usec;
713
 
 
714
 
                tv.tv_usec += time_in_usec;
715
 
 
716
 
                if ((ulint) tv.tv_usec >= MICROSECS_IN_A_SECOND) {
717
 
                        tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
718
 
                        tv.tv_usec %= MICROSECS_IN_A_SECOND;
719
 
                }
720
 
 
721
 
                abstime.tv_sec  = tv.tv_sec;
722
 
                abstime.tv_nsec = tv.tv_usec * 1000;
723
 
        } else {
724
 
                abstime.tv_nsec = 999999999;
725
 
                abstime.tv_sec = (time_t) ULINT_MAX;
726
 
        }
727
 
 
728
 
        ut_a(abstime.tv_nsec <= 999999999);
729
 
 
730
 
#endif /* __WIN__ */
731
 
 
732
 
        os_fast_mutex_lock(&event->os_mutex);
733
 
 
734
 
        if (reset_sig_count) {
735
 
                old_signal_count = reset_sig_count;
736
 
        } else {
737
 
                old_signal_count = event->signal_count;
738
 
        }
739
 
 
740
 
        do {
741
 
                if (event->is_set == TRUE
742
 
                    || event->signal_count != old_signal_count) {
743
 
 
744
 
                        break;
745
 
                }
746
 
 
747
 
                timed_out = os_cond_wait_timed(
748
 
                        &event->cond_var, &event->os_mutex,
749
 
#ifndef __WIN__
750
 
                        &abstime
751
 
#else
752
 
                        time_in_ms
753
 
#endif /* !__WIN__ */
754
 
                );
755
 
 
756
 
        } while (!timed_out);
757
 
 
758
 
        os_fast_mutex_unlock(&event->os_mutex);
759
 
 
760
 
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
761
 
 
762
 
                os_thread_exit(NULL);
763
 
        }
764
 
 
765
 
        return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
766
 
}
767
 
 
768
 
/*********************************************************//**
769
 
Creates an operating system mutex semaphore. Because these are slow, the
770
 
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
771
 
@return the mutex handle */
772
 
UNIV_INTERN
773
 
os_mutex_t
774
 
os_mutex_create(void)
775
 
/*=================*/
776
 
{
777
 
        os_fast_mutex_t*        mutex;
778
 
        os_mutex_t              mutex_str;
779
 
 
780
 
        mutex = static_cast<os_fast_mutex_t*>(ut_malloc(sizeof(os_fast_mutex_t)));
781
 
 
782
 
        os_fast_mutex_init(mutex);
783
 
        mutex_str = static_cast<os_mutex_t>(ut_malloc(sizeof(os_mutex_str_t)));
784
 
 
785
 
        mutex_str->handle = mutex;
786
 
        mutex_str->count = 0;
787
 
        mutex_str->event = os_event_create(NULL);
788
 
 
789
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
790
 
                /* When creating os_sync_mutex itself we cannot reserve it */
791
 
                os_mutex_enter(os_sync_mutex);
792
 
        }
793
 
 
794
 
        UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
795
 
 
796
 
        os_mutex_count++;
797
 
 
798
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
799
 
                os_mutex_exit(os_sync_mutex);
800
 
        }
801
 
 
802
 
        return(mutex_str);
803
 
}
804
 
 
805
 
/**********************************************************//**
806
 
Acquires ownership of a mutex semaphore. */
807
 
UNIV_INTERN
808
 
void
809
 
os_mutex_enter(
810
 
/*===========*/
811
 
        os_mutex_t      mutex)  /*!< in: mutex to acquire */
812
 
{
813
 
        os_fast_mutex_lock(static_cast<os_fast_mutex_t *>(mutex->handle));
814
 
 
815
 
        (mutex->count)++;
816
 
 
817
 
        ut_a(mutex->count == 1);
818
 
}
819
 
 
820
 
/**********************************************************//**
821
 
Releases ownership of a mutex. */
822
 
UNIV_INTERN
823
 
void
824
 
os_mutex_exit(
825
 
/*==========*/
826
 
        os_mutex_t      mutex)  /*!< in: mutex to release */
827
 
{
828
 
        ut_a(mutex);
829
 
 
830
 
        ut_a(mutex->count == 1);
831
 
 
832
 
        (mutex->count)--;
833
 
        os_fast_mutex_unlock(static_cast<os_fast_mutex_t *>(mutex->handle));
834
 
}
835
 
 
836
 
/**********************************************************//**
837
 
Frees a mutex object. */
838
 
UNIV_INTERN
839
 
void
840
 
os_mutex_free(
841
 
/*==========*/
842
 
        os_mutex_t      mutex)  /*!< in: mutex to free */
843
 
{
844
 
        ut_a(mutex);
845
 
 
846
 
        if (UNIV_LIKELY(!os_sync_free_called)) {
847
 
                os_event_free_internal(mutex->event);
848
 
        }
849
 
 
850
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
851
 
                os_mutex_enter(os_sync_mutex);
852
 
        }
853
 
 
854
 
        UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
855
 
 
856
 
        os_mutex_count--;
857
 
 
858
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
859
 
                os_mutex_exit(os_sync_mutex);
860
 
        }
861
 
 
862
 
        os_fast_mutex_free(static_cast<os_fast_mutex_t *>(mutex->handle));
863
 
        ut_free(mutex->handle);
864
 
        ut_free(mutex);
865
 
}
866
 
 
867
 
/*********************************************************//**
868
 
Initializes an operating system fast mutex semaphore. */
869
 
UNIV_INTERN
870
 
void
871
 
os_fast_mutex_init(
872
 
/*===============*/
873
 
        os_fast_mutex_t*        fast_mutex)     /*!< in: fast mutex */
874
 
{
875
 
#ifdef __WIN__
876
 
        ut_a(fast_mutex);
877
 
 
878
 
        InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
879
 
#else
880
 
        ut_a(0 == pthread_mutex_init(fast_mutex, NULL));
881
 
#endif
882
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
883
 
                /* When creating os_sync_mutex itself (in Unix) we cannot
884
 
                reserve it */
885
 
 
886
 
                os_mutex_enter(os_sync_mutex);
887
 
        }
888
 
 
889
 
        os_fast_mutex_count++;
890
 
 
891
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
892
 
                os_mutex_exit(os_sync_mutex);
893
 
        }
894
 
}
895
 
 
896
 
/**********************************************************//**
897
 
Acquires ownership of a fast mutex. */
898
 
UNIV_INTERN
899
 
void
900
 
os_fast_mutex_lock(
901
 
/*===============*/
902
 
        os_fast_mutex_t*        fast_mutex)     /*!< in: mutex to acquire */
903
 
{
904
 
#ifdef __WIN__
905
 
        EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex);
906
 
#else
907
 
        pthread_mutex_lock(fast_mutex);
908
 
#endif
909
 
}
910
 
 
911
 
/**********************************************************//**
912
 
Releases ownership of a fast mutex. */
913
 
UNIV_INTERN
914
 
void
915
 
os_fast_mutex_unlock(
916
 
/*=================*/
917
 
        os_fast_mutex_t*        fast_mutex)     /*!< in: mutex to release */
918
 
{
919
 
#ifdef __WIN__
920
 
        LeaveCriticalSection(fast_mutex);
921
 
#else
922
 
        pthread_mutex_unlock(fast_mutex);
923
 
#endif
924
 
}
925
 
 
926
 
/**********************************************************//**
927
 
Frees a mutex object. */
928
 
UNIV_INTERN
929
 
void
930
 
os_fast_mutex_free(
931
 
/*===============*/
932
 
        os_fast_mutex_t*        fast_mutex)     /*!< in: mutex to free */
933
 
{
934
 
#ifdef __WIN__
935
 
        ut_a(fast_mutex);
936
 
 
937
 
        DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
938
 
#else
939
 
        int     ret;
940
 
 
941
 
        ret = pthread_mutex_destroy(fast_mutex);
942
 
 
943
 
        if (UNIV_UNLIKELY(ret != 0)) {
944
 
                ut_print_timestamp(stderr);
945
 
                fprintf(stderr,
946
 
                        "  InnoDB: error: return value %lu when calling\n"
947
 
                        "InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
948
 
                fprintf(stderr,
949
 
                        "InnoDB: Byte contents of the pthread mutex at %p:\n",
950
 
                        (void*) fast_mutex);
951
 
                ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
952
 
                putc('\n', stderr);
953
 
        }
954
 
#endif
955
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
956
 
                /* When freeing the last mutexes, we have
957
 
                already freed os_sync_mutex */
958
 
 
959
 
                os_mutex_enter(os_sync_mutex);
960
 
        }
961
 
 
962
 
        ut_ad(os_fast_mutex_count > 0);
963
 
        os_fast_mutex_count--;
964
 
 
965
 
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
966
 
                os_mutex_exit(os_sync_mutex);
967
 
        }
968
 
}