~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Renamed more stuff to drizzle.

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