~jaypipes/drizzle/new-test-runner

« back to all changes in this revision

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

  • Committer: Jay Pipes
  • Date: 2008-12-11 17:52:34 UTC
  • mfrom: (482.16.152 testable)
  • Revision ID: jpipes@serialcoder-20081211175234-uqsfvmgxejvmellq
merge with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
The interface to the operating system
 
3
synchronization primitives.
 
4
 
 
5
(c) 1995 Innobase Oy
 
6
 
 
7
Created 9/6/1995 Heikki Tuuri
 
8
*******************************************************/
 
9
 
 
10
#include "os0sync.h"
 
11
#ifdef UNIV_NONINL
 
12
#include "os0sync.ic"
 
13
#endif
 
14
 
 
15
#ifdef __WIN__
 
16
#include <windows.h>
 
17
#endif
 
18
 
 
19
#include "ut0mem.h"
 
20
#include "srv0start.h"
 
21
 
 
22
/* Type definition for an operating system mutex struct */
 
23
struct os_mutex_struct{
 
24
        os_event_t      event;  /* Used by sync0arr.c for queing threads */
 
25
        void*           handle; /* OS handle to mutex */
 
26
        ulint           count;  /* we use this counter to check
 
27
                                that the same thread does not
 
28
                                recursively lock the mutex: we
 
29
                                do not assume that the OS mutex
 
30
                                supports recursive locking, though
 
31
                                NT seems to do that */
 
32
        UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
 
33
                                /* list of all 'slow' OS mutexes created */
 
34
};
 
35
 
 
36
/* Mutex protecting counts and the lists of OS mutexes and events */
 
37
UNIV_INTERN os_mutex_t  os_sync_mutex;
 
38
static ibool            os_sync_mutex_inited    = FALSE;
 
39
static ibool            os_sync_free_called     = FALSE;
 
40
 
 
41
/* This is incremented by 1 in os_thread_create and decremented by 1 in
 
42
os_thread_exit */
 
43
UNIV_INTERN ulint       os_thread_count         = 0;
 
44
 
 
45
/* The list of all events created */
 
46
static UT_LIST_BASE_NODE_T(os_event_struct_t)   os_event_list;
 
47
 
 
48
/* The list of all OS 'slow' mutexes */
 
49
static UT_LIST_BASE_NODE_T(os_mutex_str_t)      os_mutex_list;
 
50
 
 
51
UNIV_INTERN ulint       os_event_count          = 0;
 
52
UNIV_INTERN ulint       os_mutex_count          = 0;
 
53
UNIV_INTERN ulint       os_fast_mutex_count     = 0;
 
54
 
 
55
/* Because a mutex is embedded inside an event and there is an
 
56
event embedded inside a mutex, on free, this generates a recursive call.
 
57
This version of the free event function doesn't acquire the global lock */
 
58
static void os_event_free_internal(os_event_t   event);
 
59
 
 
60
/*************************************************************
 
61
Initializes global event and OS 'slow' mutex lists. */
 
62
UNIV_INTERN
 
63
void
 
64
os_sync_init(void)
 
65
/*==============*/
 
66
{
 
67
        UT_LIST_INIT(os_event_list);
 
68
        UT_LIST_INIT(os_mutex_list);
 
69
 
 
70
        os_sync_mutex = os_mutex_create(NULL);
 
71
 
 
72
        os_sync_mutex_inited = TRUE;
 
73
}
 
74
 
 
75
/*************************************************************
 
76
Frees created events and OS 'slow' mutexes. */
 
77
UNIV_INTERN
 
78
void
 
79
os_sync_free(void)
 
80
/*==============*/
 
81
{
 
82
        os_event_t      event;
 
83
        os_mutex_t      mutex;
 
84
 
 
85
        os_sync_free_called = TRUE;
 
86
        event = UT_LIST_GET_FIRST(os_event_list);
 
87
 
 
88
        while (event) {
 
89
 
 
90
                os_event_free(event);
 
91
 
 
92
                event = UT_LIST_GET_FIRST(os_event_list);
 
93
        }
 
94
 
 
95
        mutex = UT_LIST_GET_FIRST(os_mutex_list);
 
96
 
 
97
        while (mutex) {
 
98
                if (mutex == os_sync_mutex) {
 
99
                        /* Set the flag to FALSE so that we do not try to
 
100
                        reserve os_sync_mutex any more in remaining freeing
 
101
                        operations in shutdown */
 
102
                        os_sync_mutex_inited = FALSE;
 
103
                }
 
104
 
 
105
                os_mutex_free(mutex);
 
106
 
 
107
                mutex = UT_LIST_GET_FIRST(os_mutex_list);
 
108
        }
 
109
        os_sync_free_called = FALSE;
 
110
}
 
111
 
 
112
/*************************************************************
 
113
Creates an event semaphore, i.e., a semaphore which may just have two
 
114
states: signaled and nonsignaled. The created event is manual reset: it
 
115
must be reset explicitly by calling sync_os_reset_event. */
 
116
UNIV_INTERN
 
117
os_event_t
 
118
os_event_create(
 
119
/*============*/
 
120
                                /* out: the event handle */
 
121
        const char*     name)   /* in: the name of the event, if NULL
 
122
                                the event is created without a name */
 
123
{
 
124
#ifdef __WIN__
 
125
        os_event_t event;
 
126
 
 
127
        event = ut_malloc(sizeof(struct os_event_struct));
 
128
 
 
129
        event->handle = CreateEvent(NULL, /* No security attributes */
 
130
                                    TRUE, /* Manual reset */
 
131
                                    FALSE, /* Initial state nonsignaled */
 
132
                                    (LPCTSTR) name);
 
133
        if (!event->handle) {
 
134
                fprintf(stderr,
 
135
                        "InnoDB: Could not create a Windows event semaphore;"
 
136
                        " Windows error %lu\n",
 
137
                        (ulong) GetLastError());
 
138
        }
 
139
#else /* Unix */
 
140
        os_event_t      event;
 
141
 
 
142
        UT_NOT_USED(name);
 
143
 
 
144
        event = ut_malloc(sizeof(struct os_event_struct));
 
145
 
 
146
        os_fast_mutex_init(&(event->os_mutex));
 
147
 
 
148
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
 
149
        ut_a(0 == pthread_cond_init(&(event->cond_var),
 
150
                                    pthread_condattr_default));
 
151
#else
 
152
        ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
 
153
#endif
 
154
        event->is_set = FALSE;
 
155
 
 
156
        /* We return this value in os_event_reset(), which can then be
 
157
        be used to pass to the os_event_wait_low(). The value of zero
 
158
        is reserved in os_event_wait_low() for the case when the
 
159
        caller does not want to pass any signal_count value. To
 
160
        distinguish between the two cases we initialize signal_count
 
161
        to 1 here. */
 
162
        event->signal_count = 1;
 
163
#endif /* __WIN__ */
 
164
 
 
165
        /* The os_sync_mutex can be NULL because during startup an event
 
166
        can be created [ because it's embedded in the mutex/rwlock ] before
 
167
        this module has been initialized */
 
168
        if (os_sync_mutex != NULL) {
 
169
                os_mutex_enter(os_sync_mutex);
 
170
        }
 
171
 
 
172
        /* Put to the list of events */
 
173
        UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
 
174
 
 
175
        os_event_count++;
 
176
 
 
177
        if (os_sync_mutex != NULL) {
 
178
                os_mutex_exit(os_sync_mutex);
 
179
        }
 
180
 
 
181
        return(event);
 
182
}
 
183
 
 
184
#ifdef __WIN__
 
185
/*************************************************************
 
186
Creates an auto-reset event semaphore, i.e., an event which is automatically
 
187
reset when a single thread is released. Works only in Windows. */
 
188
UNIV_INTERN
 
189
os_event_t
 
190
os_event_create_auto(
 
191
/*=================*/
 
192
                                /* out: the event handle */
 
193
        const char*     name)   /* in: the name of the event, if NULL
 
194
                                the event is created without a name */
 
195
{
 
196
        os_event_t event;
 
197
 
 
198
        event = ut_malloc(sizeof(struct os_event_struct));
 
199
 
 
200
        event->handle = CreateEvent(NULL, /* No security attributes */
 
201
                                    FALSE, /* Auto-reset */
 
202
                                    FALSE, /* Initial state nonsignaled */
 
203
                                    (LPCTSTR) name);
 
204
 
 
205
        if (!event->handle) {
 
206
                fprintf(stderr,
 
207
                        "InnoDB: Could not create a Windows auto"
 
208
                        " event semaphore; Windows error %lu\n",
 
209
                        (ulong) GetLastError());
 
210
        }
 
211
 
 
212
        /* Put to the list of events */
 
213
        os_mutex_enter(os_sync_mutex);
 
214
 
 
215
        UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
 
216
 
 
217
        os_event_count++;
 
218
 
 
219
        os_mutex_exit(os_sync_mutex);
 
220
 
 
221
        return(event);
 
222
}
 
223
#endif
 
224
 
 
225
/**************************************************************
 
226
Sets an event semaphore to the signaled state: lets waiting threads
 
227
proceed. */
 
228
UNIV_INTERN
 
229
void
 
230
os_event_set(
 
231
/*=========*/
 
232
        os_event_t      event)  /* in: event to set */
 
233
{
 
234
#ifdef __WIN__
 
235
        ut_a(event);
 
236
        ut_a(SetEvent(event->handle));
 
237
#else
 
238
        ut_a(event);
 
239
 
 
240
        os_fast_mutex_lock(&(event->os_mutex));
 
241
 
 
242
        if (event->is_set) {
 
243
                /* Do nothing */
 
244
        } else {
 
245
                event->is_set = TRUE;
 
246
                event->signal_count += 1;
 
247
                ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
 
248
        }
 
249
 
 
250
        os_fast_mutex_unlock(&(event->os_mutex));
 
251
#endif
 
252
}
 
253
 
 
254
/**************************************************************
 
255
Resets an event semaphore to the nonsignaled state. Waiting threads will
 
256
stop to wait for the event.
 
257
The return value should be passed to os_even_wait_low() if it is desired
 
258
that this thread should not wait in case of an intervening call to
 
259
os_event_set() between this os_event_reset() and the
 
260
os_event_wait_low() call. See comments for os_event_wait_low(). */
 
261
UNIV_INTERN
 
262
ib_int64_t
 
263
os_event_reset(
 
264
/*===========*/
 
265
                                /* out: current signal_count. */
 
266
        os_event_t      event)  /* in: event to reset */
 
267
{
 
268
        ib_int64_t      ret = 0;
 
269
 
 
270
#ifdef __WIN__
 
271
        ut_a(event);
 
272
 
 
273
        ut_a(ResetEvent(event->handle));
 
274
#else
 
275
        ut_a(event);
 
276
 
 
277
        os_fast_mutex_lock(&(event->os_mutex));
 
278
 
 
279
        if (!event->is_set) {
 
280
                /* Do nothing */
 
281
        } else {
 
282
                event->is_set = FALSE;
 
283
        }
 
284
        ret = event->signal_count;
 
285
 
 
286
        os_fast_mutex_unlock(&(event->os_mutex));
 
287
#endif
 
288
        return(ret);
 
289
}
 
290
 
 
291
/**************************************************************
 
292
Frees an event object, without acquiring the global lock. */
 
293
static
 
294
void
 
295
os_event_free_internal(
 
296
/*===================*/
 
297
        os_event_t      event)  /* in: event to free */
 
298
{
 
299
#ifdef __WIN__
 
300
        ut_a(event);
 
301
 
 
302
        ut_a(CloseHandle(event->handle));
 
303
#else
 
304
        ut_a(event);
 
305
 
 
306
        /* This is to avoid freeing the mutex twice */
 
307
        os_fast_mutex_free(&(event->os_mutex));
 
308
 
 
309
        ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
 
310
#endif
 
311
        /* Remove from the list of events */
 
312
 
 
313
        UT_LIST_REMOVE(os_event_list, os_event_list, event);
 
314
 
 
315
        os_event_count--;
 
316
 
 
317
        ut_free(event);
 
318
}
 
319
 
 
320
/**************************************************************
 
321
Frees an event object. */
 
322
UNIV_INTERN
 
323
void
 
324
os_event_free(
 
325
/*==========*/
 
326
        os_event_t      event)  /* in: event to free */
 
327
 
 
328
{
 
329
#ifdef __WIN__
 
330
        ut_a(event);
 
331
 
 
332
        ut_a(CloseHandle(event->handle));
 
333
#else
 
334
        ut_a(event);
 
335
 
 
336
        os_fast_mutex_free(&(event->os_mutex));
 
337
        ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
 
338
#endif
 
339
        /* Remove from the list of events */
 
340
 
 
341
        os_mutex_enter(os_sync_mutex);
 
342
 
 
343
        UT_LIST_REMOVE(os_event_list, os_event_list, event);
 
344
 
 
345
        os_event_count--;
 
346
 
 
347
        os_mutex_exit(os_sync_mutex);
 
348
 
 
349
        ut_free(event);
 
350
}
 
351
 
 
352
/**************************************************************
 
353
Waits for an event object until it is in the signaled state. If
 
354
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
 
355
waiting thread when the event becomes signaled (or immediately if the
 
356
event is already in the signaled state).
 
357
 
 
358
Typically, if the event has been signalled after the os_event_reset()
 
359
we'll return immediately because event->is_set == TRUE.
 
360
There are, however, situations (e.g.: sync_array code) where we may
 
361
lose this information. For example:
 
362
 
 
363
thread A calls os_event_reset()
 
364
thread B calls os_event_set()   [event->is_set == TRUE]
 
365
thread C calls os_event_reset() [event->is_set == FALSE]
 
366
thread A calls os_event_wait()  [infinite wait!]
 
367
thread C calls os_event_wait()  [infinite wait!]
 
368
 
 
369
Where such a scenario is possible, to avoid infinite wait, the
 
370
value returned by os_event_reset() should be passed in as
 
371
reset_sig_count. */
 
372
UNIV_INTERN
 
373
void
 
374
os_event_wait_low(
 
375
/*==============*/
 
376
        os_event_t      event,          /* in: event to wait */
 
377
        ib_int64_t      reset_sig_count)/* in: zero or the value
 
378
                                        returned by previous call of
 
379
                                        os_event_reset(). */
 
380
{
 
381
#ifdef __WIN__
 
382
        DWORD   err;
 
383
 
 
384
        ut_a(event);
 
385
 
 
386
        UT_NOT_USED(reset_sig_count);
 
387
 
 
388
        /* Specify an infinite time limit for waiting */
 
389
        err = WaitForSingleObject(event->handle, INFINITE);
 
390
 
 
391
        ut_a(err == WAIT_OBJECT_0);
 
392
 
 
393
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
 
394
                os_thread_exit(NULL);
 
395
        }
 
396
#else
 
397
        ib_int64_t      old_signal_count;
 
398
 
 
399
        os_fast_mutex_lock(&(event->os_mutex));
 
400
 
 
401
        if (reset_sig_count) {
 
402
                old_signal_count = reset_sig_count;
 
403
        } else {
 
404
                old_signal_count = event->signal_count;
 
405
        }
 
406
 
 
407
        for (;;) {
 
408
                if (event->is_set == TRUE
 
409
                    || event->signal_count != old_signal_count) {
 
410
 
 
411
                        os_fast_mutex_unlock(&(event->os_mutex));
 
412
 
 
413
                        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
 
414
 
 
415
                                os_thread_exit(NULL);
 
416
                        }
 
417
                        /* Ok, we may return */
 
418
 
 
419
                        return;
 
420
                }
 
421
 
 
422
                pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
 
423
 
 
424
                /* Solaris manual said that spurious wakeups may occur: we
 
425
                have to check if the event really has been signaled after
 
426
                we came here to wait */
 
427
        }
 
428
#endif
 
429
}
 
430
 
 
431
/**************************************************************
 
432
Waits for an event object until it is in the signaled state or
 
433
a timeout is exceeded. In Unix the timeout is always infinite. */
 
434
UNIV_INTERN
 
435
ulint
 
436
os_event_wait_time(
 
437
/*===============*/
 
438
                                /* out: 0 if success, OS_SYNC_TIME_EXCEEDED if
 
439
                                timeout was exceeded */
 
440
        os_event_t      event,  /* in: event to wait */
 
441
        ulint           time)   /* in: timeout in microseconds, or
 
442
                                OS_SYNC_INFINITE_TIME */
 
443
{
 
444
#ifdef __WIN__
 
445
        DWORD   err;
 
446
 
 
447
        ut_a(event);
 
448
 
 
449
        if (time != OS_SYNC_INFINITE_TIME) {
 
450
                err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
 
451
        } else {
 
452
                err = WaitForSingleObject(event->handle, INFINITE);
 
453
        }
 
454
 
 
455
        if (err == WAIT_OBJECT_0) {
 
456
 
 
457
                return(0);
 
458
        } else if (err == WAIT_TIMEOUT) {
 
459
 
 
460
                return(OS_SYNC_TIME_EXCEEDED);
 
461
        } else {
 
462
                ut_error;
 
463
                return(1000000); /* dummy value to eliminate compiler warn. */
 
464
        }
 
465
#else
 
466
        UT_NOT_USED(time);
 
467
 
 
468
        /* In Posix this is just an ordinary, infinite wait */
 
469
 
 
470
        os_event_wait(event);
 
471
 
 
472
        return(0);
 
473
#endif
 
474
}
 
475
 
 
476
#ifdef __WIN__
 
477
/**************************************************************
 
478
Waits for any event in an OS native event array. Returns if even a single
 
479
one is signaled or becomes signaled. */
 
480
UNIV_INTERN
 
481
ulint
 
482
os_event_wait_multiple(
 
483
/*===================*/
 
484
                                        /* out: index of the event
 
485
                                        which was signaled */
 
486
        ulint                   n,      /* in: number of events in the
 
487
                                        array */
 
488
        os_native_event_t*      native_event_array)
 
489
                                        /* in: pointer to an array of event
 
490
                                        handles */
 
491
{
 
492
        DWORD   index;
 
493
 
 
494
        ut_a(native_event_array);
 
495
        ut_a(n > 0);
 
496
 
 
497
        index = WaitForMultipleObjects((DWORD) n, native_event_array,
 
498
                                       FALSE,      /* Wait for any 1 event */
 
499
                                       INFINITE); /* Infinite wait time
 
500
                                                  limit */
 
501
        ut_a(index >= WAIT_OBJECT_0);   /* NOTE: Pointless comparision */
 
502
        ut_a(index < WAIT_OBJECT_0 + n);
 
503
 
 
504
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
 
505
                os_thread_exit(NULL);
 
506
        }
 
507
 
 
508
        return(index - WAIT_OBJECT_0);
 
509
}
 
510
#endif
 
511
 
 
512
/*************************************************************
 
513
Creates an operating system mutex semaphore. Because these are slow, the
 
514
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
 
515
UNIV_INTERN
 
516
os_mutex_t
 
517
os_mutex_create(
 
518
/*============*/
 
519
                                /* out: the mutex handle */
 
520
        const char*     name)   /* in: the name of the mutex, if NULL
 
521
                                the mutex is created without a name */
 
522
{
 
523
#ifdef __WIN__
 
524
        HANDLE          mutex;
 
525
        os_mutex_t      mutex_str;
 
526
 
 
527
        mutex = CreateMutex(NULL,       /* No security attributes */
 
528
                            FALSE,              /* Initial state: no owner */
 
529
                            (LPCTSTR) name);
 
530
        ut_a(mutex);
 
531
#else
 
532
        os_fast_mutex_t*        mutex;
 
533
        os_mutex_t              mutex_str;
 
534
 
 
535
        UT_NOT_USED(name);
 
536
 
 
537
        mutex = ut_malloc(sizeof(os_fast_mutex_t));
 
538
 
 
539
        os_fast_mutex_init(mutex);
 
540
#endif
 
541
        mutex_str = ut_malloc(sizeof(os_mutex_str_t));
 
542
 
 
543
        mutex_str->handle = mutex;
 
544
        mutex_str->count = 0;
 
545
        mutex_str->event = os_event_create(NULL);
 
546
 
 
547
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
548
                /* When creating os_sync_mutex itself we cannot reserve it */
 
549
                os_mutex_enter(os_sync_mutex);
 
550
        }
 
551
 
 
552
        UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
 
553
 
 
554
        os_mutex_count++;
 
555
 
 
556
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
557
                os_mutex_exit(os_sync_mutex);
 
558
        }
 
559
 
 
560
        return(mutex_str);
 
561
}
 
562
 
 
563
/**************************************************************
 
564
Acquires ownership of a mutex semaphore. */
 
565
UNIV_INTERN
 
566
void
 
567
os_mutex_enter(
 
568
/*===========*/
 
569
        os_mutex_t      mutex)  /* in: mutex to acquire */
 
570
{
 
571
#ifdef __WIN__
 
572
        DWORD   err;
 
573
 
 
574
        ut_a(mutex);
 
575
 
 
576
        /* Specify infinite time limit for waiting */
 
577
        err = WaitForSingleObject(mutex->handle, INFINITE);
 
578
 
 
579
        ut_a(err == WAIT_OBJECT_0);
 
580
 
 
581
        (mutex->count)++;
 
582
        ut_a(mutex->count == 1);
 
583
#else
 
584
        os_fast_mutex_lock(mutex->handle);
 
585
 
 
586
        (mutex->count)++;
 
587
 
 
588
        ut_a(mutex->count == 1);
 
589
#endif
 
590
}
 
591
 
 
592
/**************************************************************
 
593
Releases ownership of a mutex. */
 
594
UNIV_INTERN
 
595
void
 
596
os_mutex_exit(
 
597
/*==========*/
 
598
        os_mutex_t      mutex)  /* in: mutex to release */
 
599
{
 
600
        ut_a(mutex);
 
601
 
 
602
        ut_a(mutex->count == 1);
 
603
 
 
604
        (mutex->count)--;
 
605
#ifdef __WIN__
 
606
        ut_a(ReleaseMutex(mutex->handle));
 
607
#else
 
608
        os_fast_mutex_unlock(mutex->handle);
 
609
#endif
 
610
}
 
611
 
 
612
/**************************************************************
 
613
Frees a mutex object. */
 
614
UNIV_INTERN
 
615
void
 
616
os_mutex_free(
 
617
/*==========*/
 
618
        os_mutex_t      mutex)  /* in: mutex to free */
 
619
{
 
620
        ut_a(mutex);
 
621
 
 
622
        if (UNIV_LIKELY(!os_sync_free_called)) {
 
623
                os_event_free_internal(mutex->event);
 
624
        }
 
625
 
 
626
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
627
                os_mutex_enter(os_sync_mutex);
 
628
        }
 
629
 
 
630
        UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
 
631
 
 
632
        os_mutex_count--;
 
633
 
 
634
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
635
                os_mutex_exit(os_sync_mutex);
 
636
        }
 
637
 
 
638
#ifdef __WIN__
 
639
        ut_a(CloseHandle(mutex->handle));
 
640
 
 
641
        ut_free(mutex);
 
642
#else
 
643
        os_fast_mutex_free(mutex->handle);
 
644
        ut_free(mutex->handle);
 
645
        ut_free(mutex);
 
646
#endif
 
647
}
 
648
 
 
649
/*************************************************************
 
650
Initializes an operating system fast mutex semaphore. */
 
651
UNIV_INTERN
 
652
void
 
653
os_fast_mutex_init(
 
654
/*===============*/
 
655
        os_fast_mutex_t*        fast_mutex)     /* in: fast mutex */
 
656
{
 
657
#ifdef __WIN__
 
658
        ut_a(fast_mutex);
 
659
 
 
660
        InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
 
661
#else
 
662
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
 
663
        ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
 
664
#else
 
665
        ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
 
666
#endif
 
667
#endif
 
668
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
669
                /* When creating os_sync_mutex itself (in Unix) we cannot
 
670
                reserve it */
 
671
 
 
672
                os_mutex_enter(os_sync_mutex);
 
673
        }
 
674
 
 
675
        os_fast_mutex_count++;
 
676
 
 
677
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
678
                os_mutex_exit(os_sync_mutex);
 
679
        }
 
680
}
 
681
 
 
682
/**************************************************************
 
683
Acquires ownership of a fast mutex. */
 
684
UNIV_INTERN
 
685
void
 
686
os_fast_mutex_lock(
 
687
/*===============*/
 
688
        os_fast_mutex_t*        fast_mutex)     /* in: mutex to acquire */
 
689
{
 
690
#ifdef __WIN__
 
691
        EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex);
 
692
#else
 
693
        pthread_mutex_lock(fast_mutex);
 
694
#endif
 
695
}
 
696
 
 
697
/**************************************************************
 
698
Releases ownership of a fast mutex. */
 
699
UNIV_INTERN
 
700
void
 
701
os_fast_mutex_unlock(
 
702
/*=================*/
 
703
        os_fast_mutex_t*        fast_mutex)     /* in: mutex to release */
 
704
{
 
705
#ifdef __WIN__
 
706
        LeaveCriticalSection(fast_mutex);
 
707
#else
 
708
        pthread_mutex_unlock(fast_mutex);
 
709
#endif
 
710
}
 
711
 
 
712
/**************************************************************
 
713
Frees a mutex object. */
 
714
UNIV_INTERN
 
715
void
 
716
os_fast_mutex_free(
 
717
/*===============*/
 
718
        os_fast_mutex_t*        fast_mutex)     /* in: mutex to free */
 
719
{
 
720
#ifdef __WIN__
 
721
        ut_a(fast_mutex);
 
722
 
 
723
        DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
 
724
#else
 
725
        int     ret;
 
726
 
 
727
        ret = pthread_mutex_destroy(fast_mutex);
 
728
 
 
729
        if (UNIV_UNLIKELY(ret != 0)) {
 
730
                ut_print_timestamp(stderr);
 
731
                fprintf(stderr,
 
732
                        "  InnoDB: error: return value %lu when calling\n"
 
733
                        "InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
 
734
                fprintf(stderr,
 
735
                        "InnoDB: Byte contents of the pthread mutex at %p:\n",
 
736
                        (void*) fast_mutex);
 
737
                ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
 
738
                putc('\n', stderr);
 
739
        }
 
740
#endif
 
741
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
742
                /* When freeing the last mutexes, we have
 
743
                already freed os_sync_mutex */
 
744
 
 
745
                os_mutex_enter(os_sync_mutex);
 
746
        }
 
747
 
 
748
        os_fast_mutex_count--;
 
749
 
 
750
        if (UNIV_LIKELY(os_sync_mutex_inited)) {
 
751
                os_mutex_exit(os_sync_mutex);
 
752
        }
 
753
}