~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
}