~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2013-12-22 10:27:05 UTC
  • Revision ID: package-import@ubuntu.com-20131222102705-mndw7s12mz0szrcn
Tags: upstream-5.5.32
Import upstream version 5.5.32

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