~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/include/sync0sync.ic

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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
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
 
 
26
/**************************************************//**
 
27
@file include/sync0sync.ic
 
28
Mutex, the basic synchronization primitive
 
29
 
 
30
Created 9/5/1995 Heikki Tuuri
 
31
*******************************************************/
 
32
 
 
33
/******************************************************************//**
 
34
Sets the waiters field in a mutex. */
 
35
UNIV_INTERN
 
36
void
 
37
mutex_set_waiters(
 
38
/*==============*/
 
39
        mutex_t*        mutex,  /*!< in: mutex */
 
40
        ulint           n);     /*!< in: value to set */
 
41
/******************************************************************//**
 
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
/*============*/
 
49
        mutex_t*        mutex,          /*!< in: pointer to mutex */
 
50
        const char*     file_name,      /*!< in: file name where mutex
 
51
                                        requested */
 
52
        ulint           line);          /*!< in: line where requested */
 
53
#ifdef UNIV_SYNC_DEBUG
 
54
/******************************************************************//**
 
55
Sets the debug information for a reserved mutex. */
 
56
UNIV_INTERN
 
57
void
 
58
mutex_set_debug_info(
 
59
/*=================*/
 
60
        mutex_t*        mutex,          /*!< in: mutex */
 
61
        const char*     file_name,      /*!< in: file where requested */
 
62
        ulint           line);          /*!< in: line where requested */
 
63
#endif /* UNIV_SYNC_DEBUG */
 
64
/******************************************************************//**
 
65
Releases the threads waiting in the primary wait array for this mutex. */
 
66
UNIV_INTERN
 
67
void
 
68
mutex_signal_object(
 
69
/*================*/
 
70
        mutex_t*        mutex); /*!< in: mutex */
 
71
 
 
72
/******************************************************************//**
 
73
Performs an atomic test-and-set instruction to the lock_word field of a
 
74
mutex.
 
75
@return the previous value of lock_word: 0 or 1 */
 
76
UNIV_INLINE
 
77
byte
 
78
mutex_test_and_set(
 
79
/*===============*/
 
80
        mutex_t*        mutex)  /*!< in: mutex */
 
81
{
 
82
#if defined(HAVE_ATOMIC_BUILTINS)
 
83
        return(os_atomic_test_and_set_byte(&mutex->lock_word, 1));
 
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
 
 
97
        return((byte)ret);
 
98
#endif
 
99
}
 
100
 
 
101
/******************************************************************//**
 
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
/*==================*/
 
108
        mutex_t*        mutex)  /*!< in: mutex */
 
109
{
 
110
#if defined(HAVE_ATOMIC_BUILTINS)
 
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. */
 
114
        os_atomic_test_and_set_byte(&mutex->lock_word, 0);
 
115
#else
 
116
        mutex->lock_word = 0;
 
117
 
 
118
        os_fast_mutex_unlock(&(mutex->os_fast_mutex));
 
119
#endif
 
120
}
 
121
 
 
122
/******************************************************************//**
 
123
Gets the value of the lock word. */
 
124
UNIV_INLINE
 
125
lock_word_t
 
126
mutex_get_lock_word(
 
127
/*================*/
 
128
        const mutex_t*  mutex)  /*!< in: mutex */
 
129
{
 
130
        ut_ad(mutex);
 
131
 
 
132
        return(mutex->lock_word);
 
133
}
 
134
 
 
135
/******************************************************************//**
 
136
Gets the waiters field in a mutex.
 
137
@return value to set */
 
138
UNIV_INLINE
 
139
ulint
 
140
mutex_get_waiters(
 
141
/*==============*/
 
142
        const mutex_t*  mutex)  /*!< in: mutex */
 
143
{
 
144
        const volatile ulint*   ptr;    /*!< declared volatile to ensure that
 
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
 
 
154
/******************************************************************//**
 
155
Unlocks a mutex owned by the current thread. */
 
156
UNIV_INLINE
 
157
void
 
158
mutex_exit(
 
159
/*=======*/
 
160
        mutex_t*        mutex)  /*!< in: pointer to mutex */
 
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
 
 
193
/******************************************************************//**
 
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
/*=============*/
 
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 */
 
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
 
 
211
        ut_d(mutex->count_using++);
 
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
}