~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2011-01-04 09:31:58 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110104093158-smhgvkfdi2y9au3i
Tags: 2011.01.07-0ubuntu1
New upstream release.

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