~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
Copyright (c) 2008, Google Inc.
5
6
Portions of this file contain modifications contributed and copyrighted by
7
Google, Inc. Those modifications are gratefully acknowledged and are described
8
briefly in the InnoDB documentation. The contributions by Google are
9
incorporated with their permission, and subject to the conditions contained in
10
the file COPYING.Google.
11
12
This program is free software; you can redistribute it and/or modify it under
13
the terms of the GNU General Public License as published by the Free Software
14
Foundation; version 2 of the License.
15
16
This program is distributed in the hope that it will be useful, but WITHOUT
17
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
20
You should have received a copy of the GNU General Public License along with
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22
Place, Suite 330, Boston, MA 02111-1307 USA
23
24
*****************************************************************************/
25
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
26
/**************************************************//**
27
@file include/sync0sync.ic
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
28
Mutex, the basic synchronization primitive
29
30
Created 9/5/1995 Heikki Tuuri
31
*******************************************************/
32
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
33
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
34
Sets the waiters field in a mutex. */
35
UNIV_INTERN
36
void
37
mutex_set_waiters(
38
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
39
	mutex_t*	mutex,	/*!< in: mutex */
40
	ulint		n);	/*!< in: value to set */
41
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
42
Reserves a mutex for the current thread. If the mutex is reserved, the
43
function spins a preset time (controlled by SYNC_SPIN_ROUNDS) waiting
44
for the mutex before suspending the thread. */
45
UNIV_INTERN
46
void
47
mutex_spin_wait(
48
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
49
	mutex_t*	mutex,		/*!< in: pointer to mutex */
50
	const char*	file_name,	/*!< in: file name where mutex
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
51
					requested */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
52
	ulint		line);		/*!< in: line where requested */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
53
#ifdef UNIV_SYNC_DEBUG
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
54
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
55
Sets the debug information for a reserved mutex. */
56
UNIV_INTERN
57
void
58
mutex_set_debug_info(
59
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
60
	mutex_t*	mutex,		/*!< in: mutex */
61
	const char*	file_name,	/*!< in: file where requested */
62
	ulint		line);		/*!< in: line where requested */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
63
#endif /* UNIV_SYNC_DEBUG */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
64
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
65
Releases the threads waiting in the primary wait array for this mutex. */
66
UNIV_INTERN
67
void
68
mutex_signal_object(
69
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
70
	mutex_t*	mutex);	/*!< in: mutex */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
71
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
72
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
73
Performs an atomic test-and-set instruction to the lock_word field of a
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
74
mutex.
75
@return	the previous value of lock_word: 0 or 1 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
76
UNIV_INLINE
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
77
byte
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
78
mutex_test_and_set(
79
/*===============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
80
	mutex_t*	mutex)	/*!< in: mutex */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
81
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
82
#if defined(HAVE_ATOMIC_BUILTINS)
83
	return(os_atomic_test_and_set_byte(&mutex->lock_word, 1));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
84
#else
85
	ibool	ret;
86
87
	ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex));
88
89
	if (ret == 0) {
90
		/* We check that os_fast_mutex_trylock does not leak
91
		and allow race conditions */
92
		ut_a(mutex->lock_word == 0);
93
94
		mutex->lock_word = 1;
95
	}
96
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
97
	return((byte)ret);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
98
#endif
99
}
100
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
101
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
102
Performs a reset instruction to the lock_word field of a mutex. This
103
instruction also serializes memory operations to the program order. */
104
UNIV_INLINE
105
void
106
mutex_reset_lock_word(
107
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
108
	mutex_t*	mutex)	/*!< in: mutex */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
109
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
110
#if defined(HAVE_ATOMIC_BUILTINS)
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
111
	/* In theory __sync_lock_release should be used to release the lock.
112
	Unfortunately, it does not work properly alone. The workaround is
113
	that more conservative __sync_lock_test_and_set is used instead. */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
114
	os_atomic_test_and_set_byte(&mutex->lock_word, 0);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
115
#else
116
	mutex->lock_word = 0;
117
118
	os_fast_mutex_unlock(&(mutex->os_fast_mutex));
119
#endif
120
}
121
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
122
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
123
Gets the value of the lock word. */
124
UNIV_INLINE
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
125
lock_word_t
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
126
mutex_get_lock_word(
127
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
128
	const mutex_t*	mutex)	/*!< in: mutex */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
129
{
130
	ut_ad(mutex);
131
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
132
	return(mutex->lock_word);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
133
}
134
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
135
/******************************************************************//**
136
Gets the waiters field in a mutex.
137
@return	value to set */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
138
UNIV_INLINE
139
ulint
140
mutex_get_waiters(
141
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
142
	const mutex_t*	mutex)	/*!< in: mutex */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
143
{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
144
	const volatile ulint*	ptr;	/*!< declared volatile to ensure that
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
145
					the value is read from memory */
146
	ut_ad(mutex);
147
148
	ptr = &(mutex->waiters);
149
150
	return(*ptr);		/* Here we assume that the read of a single
151
				word from memory is atomic */
152
}
153
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
154
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
155
Unlocks a mutex owned by the current thread. */
156
UNIV_INLINE
157
void
158
mutex_exit(
159
/*=======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
160
	mutex_t*	mutex)	/*!< in: pointer to mutex */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
161
{
162
	ut_ad(mutex_own(mutex));
163
164
	ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
165
166
#ifdef UNIV_SYNC_DEBUG
167
	sync_thread_reset_level(mutex);
168
#endif
169
	mutex_reset_lock_word(mutex);
170
171
	/* A problem: we assume that mutex_reset_lock word
172
	is a memory barrier, that is when we read the waiters
173
	field next, the read must be serialized in memory
174
	after the reset. A speculative processor might
175
	perform the read first, which could leave a waiting
176
	thread hanging indefinitely.
177
178
	Our current solution call every second
179
	sync_arr_wake_threads_if_sema_free()
180
	to wake up possible hanging threads if
181
	they are missed in mutex_signal_object. */
182
183
	if (mutex_get_waiters(mutex) != 0) {
184
185
		mutex_signal_object(mutex);
186
	}
187
188
#ifdef UNIV_SYNC_PERF_STAT
189
	mutex_exit_count++;
190
#endif
191
}
192
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
193
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
194
Locks a mutex for the current thread. If the mutex is reserved, the function
195
spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for the mutex
196
before suspending the thread. */
197
UNIV_INLINE
198
void
199
mutex_enter_func(
200
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
201
	mutex_t*	mutex,		/*!< in: pointer to mutex */
202
	const char*	file_name,	/*!< in: file name where locked */
203
	ulint		line)		/*!< in: line where locked */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
204
{
205
	ut_ad(mutex_validate(mutex));
206
	ut_ad(!mutex_own(mutex));
207
208
	/* Note that we do not peek at the value of lock_word before trying
209
	the atomic test_and_set; we could peek, and possibly save time. */
210
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
211
	ut_d(mutex->count_using++);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
212
213
	if (!mutex_test_and_set(mutex)) {
214
		ut_d(mutex->thread_id = os_thread_get_curr_id());
215
#ifdef UNIV_SYNC_DEBUG
216
		mutex_set_debug_info(mutex, file_name, line);
217
#endif
218
		return;	/* Succeeded! */
219
	}
220
221
	mutex_spin_wait(mutex, file_name, line);
222
}