~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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