~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-05-11 17:50:22 UTC
  • Revision ID: brian@gaz-20090511175022-y35q9ky6uh9ldcjt
Replacing Sun employee copyright headers (aka... anything done by a Sun
employee is copyright by Sun).

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