~jlukas79/+junk/mysql-server

« back to all changes in this revision

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

manual merge 6.0-main --> 6.0-bka-review

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
/* Type definition for an operating system mutex struct */
23
23
struct os_mutex_struct{
 
24
        os_event_t      event;  /* Used by sync0arr.c for queing threads */
24
25
        void*           handle; /* OS handle to mutex */
25
26
        ulint           count;  /* we use this counter to check
26
27
                                that the same thread does not
35
36
/* Mutex protecting counts and the lists of OS mutexes and events */
36
37
os_mutex_t      os_sync_mutex;
37
38
ibool           os_sync_mutex_inited    = FALSE;
 
39
ibool           os_sync_free_called     = FALSE;
38
40
 
39
41
/* This is incremented by 1 in os_thread_create and decremented by 1 in
40
42
os_thread_exit */
50
52
ulint   os_mutex_count          = 0;
51
53
ulint   os_fast_mutex_count     = 0;
52
54
 
 
55
/* Because a mutex is embedded inside an event and there is an
 
56
event embedded inside a mutex, on free, this generates a recursive call.
 
57
This version of the free event function doesn't acquire the global lock */
 
58
static void os_event_free_internal(os_event_t   event);
53
59
 
54
60
/*************************************************************
55
61
Initializes global event and OS 'slow' mutex lists. */
76
82
        os_event_t      event;
77
83
        os_mutex_t      mutex;
78
84
 
 
85
        os_sync_free_called = TRUE;
79
86
        event = UT_LIST_GET_FIRST(os_event_list);
80
87
 
81
88
        while (event) {
99
106
 
100
107
                mutex = UT_LIST_GET_FIRST(os_mutex_list);
101
108
        }
 
109
        os_sync_free_called = FALSE;
102
110
}
103
111
 
104
112
/*************************************************************
144
152
        ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
145
153
#endif
146
154
        event->is_set = FALSE;
147
 
        event->signal_count = 0;
 
155
 
 
156
        /* We return this value in os_event_reset(), which can then be
 
157
        be used to pass to the os_event_wait_low(). The value of zero
 
158
        is reserved in os_event_wait_low() for the case when the
 
159
        caller does not want to pass any signal_count value. To
 
160
        distinguish between the two cases we initialize signal_count
 
161
        to 1 here. */
 
162
        event->signal_count = 1;
148
163
#endif /* __WIN__ */
149
164
 
 
165
        /* The os_sync_mutex can be NULL because during startup an event
 
166
        can be created [ because it's embedded in the mutex/rwlock ] before
 
167
        this module has been initialized */
 
168
        if (os_sync_mutex != NULL) {
 
169
                os_mutex_enter(os_sync_mutex);
 
170
        }
 
171
 
150
172
        /* Put to the list of events */
151
 
        os_mutex_enter(os_sync_mutex);
152
 
 
153
173
        UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
154
174
 
155
175
        os_event_count++;
156
176
 
157
 
        os_mutex_exit(os_sync_mutex);
 
177
        if (os_sync_mutex != NULL) {
 
178
                os_mutex_exit(os_sync_mutex);
 
179
        }
158
180
 
159
181
        return(event);
160
182
}
231
253
 
232
254
/**************************************************************
233
255
Resets an event semaphore to the nonsignaled state. Waiting threads will
234
 
stop to wait for the event. */
 
256
stop to wait for the event.
 
257
The return value should be passed to os_even_wait_low() if it is desired
 
258
that this thread should not wait in case of an intervening call to
 
259
os_event_set() between this os_event_reset() and the
 
260
os_event_wait_low() call. See comments for os_event_wait_low(). */
235
261
 
236
 
void
 
262
ib_longlong
237
263
os_event_reset(
238
264
/*===========*/
 
265
                                /* out: current signal_count. */
239
266
        os_event_t      event)  /* in: event to reset */
240
267
{
 
268
        ib_longlong     ret = 0;
 
269
 
241
270
#ifdef __WIN__
242
271
        ut_a(event);
243
272
 
252
281
        } else {
253
282
                event->is_set = FALSE;
254
283
        }
 
284
        ret = event->signal_count;
255
285
 
256
286
        os_fast_mutex_unlock(&(event->os_mutex));
257
287
#endif
 
288
        return(ret);
 
289
}
 
290
 
 
291
/**************************************************************
 
292
Frees an event object, without acquiring the global lock. */
 
293
static
 
294
void
 
295
os_event_free_internal(
 
296
/*===================*/
 
297
        os_event_t      event)  /* in: event to free */
 
298
{
 
299
#ifdef __WIN__
 
300
        ut_a(event);
 
301
 
 
302
        ut_a(CloseHandle(event->handle));
 
303
#else
 
304
        ut_a(event);
 
305
 
 
306
        /* This is to avoid freeing the mutex twice */
 
307
        os_fast_mutex_free(&(event->os_mutex));
 
308
 
 
309
        ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
 
310
#endif
 
311
        /* Remove from the list of events */
 
312
 
 
313
        UT_LIST_REMOVE(os_event_list, os_event_list, event);
 
314
 
 
315
        os_event_count--;
 
316
 
 
317
        ut_free(event);
258
318
}
259
319
 
260
320
/**************************************************************
293
353
Waits for an event object until it is in the signaled state. If
294
354
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
295
355
waiting thread when the event becomes signaled (or immediately if the
296
 
event is already in the signaled state). */
 
356
event is already in the signaled state).
 
357
 
 
358
Typically, if the event has been signalled after the os_event_reset()
 
359
we'll return immediately because event->is_set == TRUE.
 
360
There are, however, situations (e.g.: sync_array code) where we may
 
361
lose this information. For example:
 
362
 
 
363
thread A calls os_event_reset()
 
364
thread B calls os_event_set()   [event->is_set == TRUE]
 
365
thread C calls os_event_reset() [event->is_set == FALSE]
 
366
thread A calls os_event_wait()  [infinite wait!]
 
367
thread C calls os_event_wait()  [infinite wait!]
 
368
 
 
369
Where such a scenario is possible, to avoid infinite wait, the
 
370
value returned by os_event_reset() should be passed in as
 
371
reset_sig_count. */
297
372
 
298
373
void
299
 
os_event_wait(
300
 
/*==========*/
301
 
        os_event_t      event)  /* in: event to wait */
 
374
os_event_wait_low(
 
375
/*==============*/
 
376
        os_event_t      event,          /* in: event to wait */
 
377
        ib_longlong     reset_sig_count)/* in: zero or the value
 
378
                                        returned by previous call of
 
379
                                        os_event_reset(). */
302
380
{
303
381
#ifdef __WIN__
304
382
        DWORD   err;
305
383
 
306
384
        ut_a(event);
307
385
 
 
386
        UT_NOT_USED(reset_sig_count);
 
387
 
308
388
        /* Specify an infinite time limit for waiting */
309
389
        err = WaitForSingleObject(event->handle, INFINITE);
310
390
 
318
398
 
319
399
        os_fast_mutex_lock(&(event->os_mutex));
320
400
 
321
 
        old_signal_count = event->signal_count;
 
401
        if (reset_sig_count) {
 
402
                old_signal_count = reset_sig_count;
 
403
        } else {
 
404
                old_signal_count = event->signal_count;
 
405
        }
322
406
 
323
407
        for (;;) {
324
408
                if (event->is_set == TRUE
458
542
 
459
543
        mutex_str->handle = mutex;
460
544
        mutex_str->count = 0;
 
545
        mutex_str->event = os_event_create(NULL);
461
546
 
462
547
        if (os_sync_mutex_inited) {
463
548
                /* When creating os_sync_mutex itself we cannot reserve it */
534
619
{
535
620
        ut_a(mutex);
536
621
 
 
622
        if (!os_sync_free_called) {
 
623
                os_event_free_internal(mutex->event);
 
624
        }
 
625
 
537
626
        if (os_sync_mutex_inited) {
538
627
                os_mutex_enter(os_sync_mutex);
539
628
        }