~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to plugin/innobase/include/os0sync.h

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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/os0sync.h
 
28
The interface to the operating system
 
29
synchronization primitives.
 
30
 
 
31
Created 9/6/1995 Heikki Tuuri
 
32
*******************************************************/
 
33
 
 
34
#ifndef os0sync_h
 
35
#define os0sync_h
 
36
 
 
37
#include "univ.i"
 
38
#include "ut0lst.h"
 
39
 
 
40
#ifdef __WIN__
 
41
 
 
42
/** Native mutex */
 
43
#define os_fast_mutex_t CRITICAL_SECTION
 
44
 
 
45
/** Native event */
 
46
typedef HANDLE          os_native_event_t;
 
47
 
 
48
/** Operating system event */
 
49
typedef struct os_event_struct  os_event_struct_t;
 
50
/** Operating system event handle */
 
51
typedef os_event_struct_t*      os_event_t;
 
52
 
 
53
/** An asynchronous signal sent between threads */
 
54
struct os_event_struct {
 
55
        os_native_event_t                 handle;
 
56
                                        /*!< Windows event */
 
57
        UT_LIST_NODE_T(os_event_struct_t) os_event_list;
 
58
                                        /*!< list of all created events */
 
59
};
 
60
#else
 
61
/** Native mutex */
 
62
typedef pthread_mutex_t os_fast_mutex_t;
 
63
 
 
64
/** Operating system event */
 
65
typedef struct os_event_struct  os_event_struct_t;
 
66
/** Operating system event handle */
 
67
typedef os_event_struct_t*      os_event_t;
 
68
 
 
69
/** An asynchronous signal sent between threads */
 
70
struct os_event_struct {
 
71
        os_fast_mutex_t os_mutex;       /*!< this mutex protects the next
 
72
                                        fields */
 
73
        ibool           is_set;         /*!< this is TRUE when the event is
 
74
                                        in the signaled state, i.e., a thread
 
75
                                        does not stop if it tries to wait for
 
76
                                        this event */
 
77
        ib_int64_t      signal_count;   /*!< this is incremented each time
 
78
                                        the event becomes signaled */
 
79
        pthread_cond_t  cond_var;       /*!< condition variable is used in
 
80
                                        waiting for the event */
 
81
        UT_LIST_NODE_T(os_event_struct_t) os_event_list;
 
82
                                        /*!< list of all created events */
 
83
};
 
84
#endif
 
85
 
 
86
/** Operating system mutex */
 
87
typedef struct os_mutex_struct  os_mutex_str_t;
 
88
/** Operating system mutex handle */
 
89
typedef os_mutex_str_t*         os_mutex_t;
 
90
 
 
91
/** Denotes an infinite delay for os_event_wait_time() */
 
92
#define OS_SYNC_INFINITE_TIME   ((ulint)(-1))
 
93
 
 
94
/** Return value of os_event_wait_time() when the time is exceeded */
 
95
#define OS_SYNC_TIME_EXCEEDED   1
 
96
 
 
97
/** Mutex protecting counts and the event and OS 'slow' mutex lists */
 
98
extern os_mutex_t       os_sync_mutex;
 
99
 
 
100
/** This is incremented by 1 in os_thread_create and decremented by 1 in
 
101
os_thread_exit */
 
102
extern ulint            os_thread_count;
 
103
 
 
104
extern ulint            os_event_count;
 
105
extern ulint            os_mutex_count;
 
106
extern ulint            os_fast_mutex_count;
 
107
 
 
108
/*********************************************************//**
 
109
Initializes global event and OS 'slow' mutex lists. */
 
110
UNIV_INTERN
 
111
void
 
112
os_sync_init(void);
 
113
/*==============*/
 
114
/*********************************************************//**
 
115
Frees created events and OS 'slow' mutexes. */
 
116
UNIV_INTERN
 
117
void
 
118
os_sync_free(void);
 
119
/*==============*/
 
120
/*********************************************************//**
 
121
Creates an event semaphore, i.e., a semaphore which may just have two states:
 
122
signaled and nonsignaled. The created event is manual reset: it must be reset
 
123
explicitly by calling sync_os_reset_event.
 
124
@return the event handle */
 
125
UNIV_INTERN
 
126
os_event_t
 
127
os_event_create(
 
128
/*============*/
 
129
        const char*     name);  /*!< in: the name of the event, if NULL
 
130
                                the event is created without a name */
 
131
/**********************************************************//**
 
132
Sets an event semaphore to the signaled state: lets waiting threads
 
133
proceed. */
 
134
UNIV_INTERN
 
135
void
 
136
os_event_set(
 
137
/*=========*/
 
138
        os_event_t      event); /*!< in: event to set */
 
139
/**********************************************************//**
 
140
Resets an event semaphore to the nonsignaled state. Waiting threads will
 
141
stop to wait for the event.
 
142
The return value should be passed to os_even_wait_low() if it is desired
 
143
that this thread should not wait in case of an intervening call to
 
144
os_event_set() between this os_event_reset() and the
 
145
os_event_wait_low() call. See comments for os_event_wait_low(). */
 
146
UNIV_INTERN
 
147
ib_int64_t
 
148
os_event_reset(
 
149
/*===========*/
 
150
        os_event_t      event); /*!< in: event to reset */
 
151
/**********************************************************//**
 
152
Frees an event object. */
 
153
UNIV_INTERN
 
154
void
 
155
os_event_free(
 
156
/*==========*/
 
157
        os_event_t      event); /*!< in: event to free */
 
158
 
 
159
/**********************************************************//**
 
160
Waits for an event object until it is in the signaled state. If
 
161
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
 
162
waiting thread when the event becomes signaled (or immediately if the
 
163
event is already in the signaled state).
 
164
 
 
165
Typically, if the event has been signalled after the os_event_reset()
 
166
we'll return immediately because event->is_set == TRUE.
 
167
There are, however, situations (e.g.: sync_array code) where we may
 
168
lose this information. For example:
 
169
 
 
170
thread A calls os_event_reset()
 
171
thread B calls os_event_set()   [event->is_set == TRUE]
 
172
thread C calls os_event_reset() [event->is_set == FALSE]
 
173
thread A calls os_event_wait()  [infinite wait!]
 
174
thread C calls os_event_wait()  [infinite wait!]
 
175
 
 
176
Where such a scenario is possible, to avoid infinite wait, the
 
177
value returned by os_event_reset() should be passed in as
 
178
reset_sig_count. */
 
179
UNIV_INTERN
 
180
void
 
181
os_event_wait_low(
 
182
/*==============*/
 
183
        os_event_t      event,          /*!< in: event to wait */
 
184
        ib_int64_t      reset_sig_count);/*!< in: zero or the value
 
185
                                        returned by previous call of
 
186
                                        os_event_reset(). */
 
187
 
 
188
#define os_event_wait(event) os_event_wait_low(event, 0)
 
189
 
 
190
/**********************************************************//**
 
191
Waits for an event object until it is in the signaled state or
 
192
a timeout is exceeded. In Unix the timeout is always infinite.
 
193
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
 
194
UNIV_INTERN
 
195
ulint
 
196
os_event_wait_time(
 
197
/*===============*/
 
198
        os_event_t      event,  /*!< in: event to wait */
 
199
        ulint           time);  /*!< in: timeout in microseconds, or
 
200
                                OS_SYNC_INFINITE_TIME */
 
201
#ifdef __WIN__
 
202
/**********************************************************//**
 
203
Waits for any event in an OS native event array. Returns if even a single
 
204
one is signaled or becomes signaled.
 
205
@return index of the event which was signaled */
 
206
UNIV_INTERN
 
207
ulint
 
208
os_event_wait_multiple(
 
209
/*===================*/
 
210
        ulint                   n,      /*!< in: number of events in the
 
211
                                        array */
 
212
        os_native_event_t*      native_event_array);
 
213
                                        /*!< in: pointer to an array of event
 
214
                                        handles */
 
215
#endif
 
216
/*********************************************************//**
 
217
Creates an operating system mutex semaphore. Because these are slow, the
 
218
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
 
219
@return the mutex handle */
 
220
UNIV_INTERN
 
221
os_mutex_t
 
222
os_mutex_create(
 
223
/*============*/
 
224
        const char*     name);  /*!< in: the name of the mutex, if NULL
 
225
                                the mutex is created without a name */
 
226
/**********************************************************//**
 
227
Acquires ownership of a mutex semaphore. */
 
228
UNIV_INTERN
 
229
void
 
230
os_mutex_enter(
 
231
/*===========*/
 
232
        os_mutex_t      mutex); /*!< in: mutex to acquire */
 
233
/**********************************************************//**
 
234
Releases ownership of a mutex. */
 
235
UNIV_INTERN
 
236
void
 
237
os_mutex_exit(
 
238
/*==========*/
 
239
        os_mutex_t      mutex); /*!< in: mutex to release */
 
240
/**********************************************************//**
 
241
Frees an mutex object. */
 
242
UNIV_INTERN
 
243
void
 
244
os_mutex_free(
 
245
/*==========*/
 
246
        os_mutex_t      mutex); /*!< in: mutex to free */
 
247
/**********************************************************//**
 
248
Acquires ownership of a fast mutex. Currently in Windows this is the same
 
249
as os_fast_mutex_lock!
 
250
@return 0 if success, != 0 if was reserved by another thread */
 
251
UNIV_INLINE
 
252
ulint
 
253
os_fast_mutex_trylock(
 
254
/*==================*/
 
255
        os_fast_mutex_t*        fast_mutex);    /*!< in: mutex to acquire */
 
256
/**********************************************************//**
 
257
Releases ownership of a fast mutex. */
 
258
UNIV_INTERN
 
259
void
 
260
os_fast_mutex_unlock(
 
261
/*=================*/
 
262
        os_fast_mutex_t*        fast_mutex);    /*!< in: mutex to release */
 
263
/*********************************************************//**
 
264
Initializes an operating system fast mutex semaphore. */
 
265
UNIV_INTERN
 
266
void
 
267
os_fast_mutex_init(
 
268
/*===============*/
 
269
        os_fast_mutex_t*        fast_mutex);    /*!< in: fast mutex */
 
270
/**********************************************************//**
 
271
Acquires ownership of a fast mutex. */
 
272
UNIV_INTERN
 
273
void
 
274
os_fast_mutex_lock(
 
275
/*===============*/
 
276
        os_fast_mutex_t*        fast_mutex);    /*!< in: mutex to acquire */
 
277
/**********************************************************//**
 
278
Frees an mutex object. */
 
279
UNIV_INTERN
 
280
void
 
281
os_fast_mutex_free(
 
282
/*===============*/
 
283
        os_fast_mutex_t*        fast_mutex);    /*!< in: mutex to free */
 
284
 
 
285
/**********************************************************//**
 
286
Atomic compare-and-swap and increment for InnoDB. */
 
287
 
 
288
#ifdef HAVE_GCC_ATOMIC_BUILTINS
 
289
/**********************************************************//**
 
290
Returns true if swapped, ptr is pointer to target, old_val is value to
 
291
compare to, new_val is the value to swap in. */
 
292
# define os_compare_and_swap(ptr, old_val, new_val) \
 
293
        __sync_bool_compare_and_swap(ptr, old_val, new_val)
 
294
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
 
295
        os_compare_and_swap(ptr, old_val, new_val)
 
296
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
 
297
        os_compare_and_swap(ptr, old_val, new_val)
 
298
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
299
        os_compare_and_swap(ptr, old_val, new_val)
 
300
/**********************************************************//**
 
301
Returns the resulting value, ptr is pointer to target, amount is the
 
302
amount of increment. */
 
303
# define os_atomic_increment(ptr, amount) \
 
304
        __sync_add_and_fetch(ptr, amount)
 
305
# define os_atomic_increment_lint(ptr, amount) \
 
306
        os_atomic_increment(ptr, amount)
 
307
# define os_atomic_increment_ulint(ptr, amount) \
 
308
        os_atomic_increment(ptr, amount)
 
309
/**********************************************************//**
 
310
Returns the old value of *ptr, atomically sets *ptr to new_val */
 
311
# define os_atomic_test_and_set_byte(ptr, new_val) \
 
312
        __sync_lock_test_and_set(ptr, new_val)
 
313
/* If not compiling with GCC or GCC doesn't support the atomic
 
314
intrinsics and running on Solaris >= 10 use Solaris atomics */
 
315
#elif defined(HAVE_SOLARIS_ATOMICS)
 
316
#include <atomic.h>
 
317
/**********************************************************//**
 
318
Returns true if swapped, ptr is pointer to target, old_val is value to
 
319
compare to, new_val is the value to swap in. */
 
320
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
 
321
        (atomic_cas_ulong(ptr, old_val, new_val) == old_val)
 
322
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
 
323
        ((lint)atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val)
 
324
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
 
325
#  if   SIZEOF_PTHREAD_T == 4
 
326
#   define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
327
        ((pthread_t)atomic_cas_32(ptr, old_val, new_val) == old_val)
 
328
#  elif SIZEOF_PTHREAD_T == 8
 
329
#   define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
330
        ((pthread_t)atomic_cas_64(ptr, old_val, new_val) == old_val)
 
331
#  else
 
332
#   error "SIZEOF_PTHREAD_T != 4 or 8"
 
333
#  endif /* SIZEOF_PTHREAD_T CHECK */
 
334
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
 
335
 
 
336
/**********************************************************//**
 
337
Returns the resulting value, ptr is pointer to target, amount is the
 
338
amount of increment. */
 
339
# define os_atomic_increment_lint(ptr, amount) \
 
340
        atomic_add_long_nv((ulong_t*) ptr, amount)
 
341
# define os_atomic_increment_ulint(ptr, amount) \
 
342
        atomic_add_long_nv(ptr, amount)
 
343
/**********************************************************//**
 
344
Returns the old value of *ptr, atomically sets *ptr to new_val */
 
345
# define os_atomic_test_and_set_byte(ptr, new_val) \
 
346
        atomic_swap_uchar(ptr, new_val)
 
347
/* On Windows, use Windows atomics / interlocked */
 
348
#elif defined(HAVE_WINDOWS_ATOMICS)
 
349
# ifdef _WIN64
 
350
#  define win_cmp_and_xchg InterlockedCompareExchange64
 
351
#  define win_xchg_and_add InterlockedExchangeAdd64
 
352
# else /* _WIN64 */
 
353
#  define win_cmp_and_xchg InterlockedCompareExchange
 
354
#  define win_xchg_and_add InterlockedExchangeAdd
 
355
# endif
 
356
/**********************************************************//**
 
357
Returns true if swapped, ptr is pointer to target, old_val is value to
 
358
compare to, new_val is the value to swap in. */
 
359
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
 
360
        (win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
 
361
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
 
362
        (win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
 
363
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
 
364
#  define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
365
        (InterlockedCompareExchange(ptr, new_val, old_val) == old_val)
 
366
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
 
367
/**********************************************************//**
 
368
Returns the resulting value, ptr is pointer to target, amount is the
 
369
amount of increment. */
 
370
# define os_atomic_increment_lint(ptr, amount) \
 
371
        (win_xchg_and_add(ptr, amount) + amount)
 
372
# define os_atomic_increment_ulint(ptr, amount) \
 
373
        ((ulint) (win_xchg_and_add(ptr, amount) + amount))
 
374
/**********************************************************//**
 
375
Returns the old value of *ptr, atomically sets *ptr to new_val.
 
376
InterlockedExchange() operates on LONG, and the LONG will be
 
377
clobbered */
 
378
# define os_atomic_test_and_set_byte(ptr, new_val) \
 
379
        ((byte) InterlockedExchange(ptr, new_val))
 
380
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
 
381
 
 
382
#ifndef UNIV_NONINL
 
383
#include "os0sync.ic"
 
384
#endif
 
385
 
 
386
#endif