~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 1995, 2011, Oracle and/or its affiliates. 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.,
 
22
51 Franklin Street, Suite 500, Boston, MA 02110-1335 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
#include "sync0types.h"
 
40
 
 
41
#ifdef __WIN__
 
42
/** Native event (slow)*/
 
43
typedef HANDLE                  os_native_event_t;
 
44
/** Native mutex */
 
45
typedef CRITICAL_SECTION        fast_mutex_t;
 
46
/** Native condition variable. */
 
47
typedef CONDITION_VARIABLE      os_cond_t;
 
48
#else
 
49
/** Native mutex */
 
50
typedef pthread_mutex_t         fast_mutex_t;
 
51
/** Native condition variable */
 
52
typedef pthread_cond_t          os_cond_t;
 
53
#endif
 
54
 
 
55
/** Structure that includes Performance Schema Probe pfs_psi
 
56
in the os_fast_mutex structure if UNIV_PFS_MUTEX is defined */
 
57
struct os_fast_mutex_t {
 
58
        fast_mutex_t            mutex;  /*!< os_fast_mutex */
 
59
#ifdef UNIV_PFS_MUTEX
 
60
        struct PSI_mutex*       pfs_psi;/*!< The performance schema
 
61
                                        instrumentation hook */
 
62
#endif
 
63
};
 
64
 
 
65
/** Operating system event handle */
 
66
typedef struct os_event*        os_event_t;
 
67
 
 
68
/** An asynchronous signal sent between threads */
 
69
struct os_event {
 
70
#ifdef __WIN__
 
71
        HANDLE          handle;         /*!< kernel event object, slow,
 
72
                                        used on older Windows */
 
73
#endif
 
74
        os_fast_mutex_t os_mutex;       /*!< this mutex protects the next
 
75
                                        fields */
 
76
        ibool           is_set;         /*!< this is TRUE when the event is
 
77
                                        in the signaled state, i.e., a thread
 
78
                                        does not stop if it tries to wait for
 
79
                                        this event */
 
80
        ib_int64_t      signal_count;   /*!< this is incremented each time
 
81
                                        the event becomes signaled */
 
82
        os_cond_t       cond_var;       /*!< condition variable is used in
 
83
                                        waiting for the event */
 
84
        UT_LIST_NODE_T(os_event_t) os_event_list;
 
85
                                        /*!< list of all created events */
 
86
};
 
87
 
 
88
/** Denotes an infinite delay for os_event_wait_time() */
 
89
#define OS_SYNC_INFINITE_TIME   ULINT_UNDEFINED
 
90
 
 
91
/** Return value of os_event_wait_time() when the time is exceeded */
 
92
#define OS_SYNC_TIME_EXCEEDED   1
 
93
 
 
94
/** Operating system mutex handle */
 
95
typedef struct os_mutex_t*      os_ib_mutex_t;
 
96
 
 
97
/** Mutex protecting counts and the event and OS 'slow' mutex lists */
 
98
extern os_ib_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(void);
 
128
/*==================*/
 
129
/**********************************************************//**
 
130
Sets an event semaphore to the signaled state: lets waiting threads
 
131
proceed. */
 
132
UNIV_INTERN
 
133
void
 
134
os_event_set(
 
135
/*=========*/
 
136
        os_event_t      event); /*!< in: event to set */
 
137
/**********************************************************//**
 
138
Resets an event semaphore to the nonsignaled state. Waiting threads will
 
139
stop to wait for the event.
 
140
The return value should be passed to os_even_wait_low() if it is desired
 
141
that this thread should not wait in case of an intervening call to
 
142
os_event_set() between this os_event_reset() and the
 
143
os_event_wait_low() call. See comments for os_event_wait_low(). */
 
144
UNIV_INTERN
 
145
ib_int64_t
 
146
os_event_reset(
 
147
/*===========*/
 
148
        os_event_t      event); /*!< in: event to reset */
 
149
/**********************************************************//**
 
150
Frees an event object. */
 
151
UNIV_INTERN
 
152
void
 
153
os_event_free(
 
154
/*==========*/
 
155
        os_event_t      event); /*!< in: event to free */
 
156
 
 
157
/**********************************************************//**
 
158
Waits for an event object until it is in the signaled state.
 
159
 
 
160
Typically, if the event has been signalled after the os_event_reset()
 
161
we'll return immediately because event->is_set == TRUE.
 
162
There are, however, situations (e.g.: sync_array code) where we may
 
163
lose this information. For example:
 
164
 
 
165
thread A calls os_event_reset()
 
166
thread B calls os_event_set()   [event->is_set == TRUE]
 
167
thread C calls os_event_reset() [event->is_set == FALSE]
 
168
thread A calls os_event_wait()  [infinite wait!]
 
169
thread C calls os_event_wait()  [infinite wait!]
 
170
 
 
171
Where such a scenario is possible, to avoid infinite wait, the
 
172
value returned by os_event_reset() should be passed in as
 
173
reset_sig_count. */
 
174
UNIV_INTERN
 
175
void
 
176
os_event_wait_low(
 
177
/*==============*/
 
178
        os_event_t      event,          /*!< in: event to wait */
 
179
        ib_int64_t      reset_sig_count);/*!< in: zero or the value
 
180
                                        returned by previous call of
 
181
                                        os_event_reset(). */
 
182
 
 
183
#define os_event_wait(event) os_event_wait_low(event, 0)
 
184
#define os_event_wait_time(event, t) os_event_wait_time_low(event, t, 0)
 
185
 
 
186
/**********************************************************//**
 
187
Waits for an event object until it is in the signaled state or
 
188
a timeout is exceeded. In Unix the timeout is always infinite.
 
189
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
 
190
UNIV_INTERN
 
191
ulint
 
192
os_event_wait_time_low(
 
193
/*===================*/
 
194
        os_event_t      event,                  /*!< in: event to wait */
 
195
        ulint           time_in_usec,           /*!< in: timeout in
 
196
                                                microseconds, or
 
197
                                                OS_SYNC_INFINITE_TIME */
 
198
        ib_int64_t      reset_sig_count);       /*!< in: zero or the value
 
199
                                                returned by previous call of
 
200
                                                os_event_reset(). */
 
201
/*********************************************************//**
 
202
Creates an operating system mutex semaphore. Because these are slow, the
 
203
mutex semaphore of InnoDB itself (ib_mutex_t) should be used where possible.
 
204
@return the mutex handle */
 
205
UNIV_INTERN
 
206
os_ib_mutex_t
 
207
os_mutex_create(void);
 
208
/*=================*/
 
209
/**********************************************************//**
 
210
Acquires ownership of a mutex semaphore. */
 
211
UNIV_INTERN
 
212
void
 
213
os_mutex_enter(
 
214
/*===========*/
 
215
        os_ib_mutex_t   mutex); /*!< in: mutex to acquire */
 
216
/**********************************************************//**
 
217
Releases ownership of a mutex. */
 
218
UNIV_INTERN
 
219
void
 
220
os_mutex_exit(
 
221
/*==========*/
 
222
        os_ib_mutex_t   mutex); /*!< in: mutex to release */
 
223
/**********************************************************//**
 
224
Frees an mutex object. */
 
225
UNIV_INTERN
 
226
void
 
227
os_mutex_free(
 
228
/*==========*/
 
229
        os_ib_mutex_t   mutex); /*!< in: mutex to free */
 
230
/**********************************************************//**
 
231
Acquires ownership of a fast mutex. Currently in Windows this is the same
 
232
as os_fast_mutex_lock!
 
233
@return 0 if success, != 0 if was reserved by another thread */
 
234
UNIV_INLINE
 
235
ulint
 
236
os_fast_mutex_trylock(
 
237
/*==================*/
 
238
        os_fast_mutex_t*        fast_mutex);    /*!< in: mutex to acquire */
 
239
 
 
240
/**********************************************************************
 
241
Following os_fast_ mutex APIs would be performance schema instrumented:
 
242
 
 
243
os_fast_mutex_init
 
244
os_fast_mutex_lock
 
245
os_fast_mutex_unlock
 
246
os_fast_mutex_free
 
247
 
 
248
These mutex APIs will point to corresponding wrapper functions that contain
 
249
the performance schema instrumentation.
 
250
 
 
251
NOTE! The following macro should be used in mutex operation, not the
 
252
corresponding function. */
 
253
 
 
254
#ifdef UNIV_PFS_MUTEX
 
255
# define os_fast_mutex_init(K, M)                       \
 
256
        pfs_os_fast_mutex_init(K, M)
 
257
 
 
258
# define os_fast_mutex_lock(M)                          \
 
259
        pfs_os_fast_mutex_lock(M, __FILE__, __LINE__)
 
260
 
 
261
# define os_fast_mutex_unlock(M)        pfs_os_fast_mutex_unlock(M)
 
262
 
 
263
# define os_fast_mutex_free(M)          pfs_os_fast_mutex_free(M)
 
264
 
 
265
/*********************************************************//**
 
266
NOTE! Please use the corresponding macro os_fast_mutex_init(), not directly
 
267
this function!
 
268
A wrapper function for os_fast_mutex_init_func(). Initializes an operating
 
269
system fast mutex semaphore. */
 
270
UNIV_INLINE
 
271
void
 
272
pfs_os_fast_mutex_init(
 
273
/*===================*/
 
274
        PSI_mutex_key           key,            /*!< in: Performance Schema
 
275
                                                key */
 
276
        os_fast_mutex_t*        fast_mutex);    /*!< out: fast mutex */
 
277
/**********************************************************//**
 
278
NOTE! Please use the corresponding macro os_fast_mutex_free(), not directly
 
279
this function!
 
280
Wrapper function for pfs_os_fast_mutex_free(). Also destroys the performance
 
281
schema probes when freeing the mutex */
 
282
UNIV_INLINE
 
283
void
 
284
pfs_os_fast_mutex_free(
 
285
/*===================*/
 
286
        os_fast_mutex_t*        fast_mutex);    /*!< in/out: mutex to free */
 
287
/**********************************************************//**
 
288
NOTE! Please use the corresponding macro os_fast_mutex_lock, not directly
 
289
this function!
 
290
Wrapper function of os_fast_mutex_lock. Acquires ownership of a fast mutex. */
 
291
UNIV_INLINE
 
292
void
 
293
pfs_os_fast_mutex_lock(
 
294
/*===================*/
 
295
        os_fast_mutex_t*        fast_mutex,     /*!< in/out: mutex to acquire */
 
296
        const char*             file_name,      /*!< in: file name where
 
297
                                                 locked */
 
298
        ulint                   line);          /*!< in: line where locked */
 
299
/**********************************************************//**
 
300
NOTE! Please use the corresponding macro os_fast_mutex_unlock, not directly
 
301
this function!
 
302
Wrapper function of os_fast_mutex_unlock. Releases ownership of a fast mutex. */
 
303
UNIV_INLINE
 
304
void
 
305
pfs_os_fast_mutex_unlock(
 
306
/*=====================*/
 
307
        os_fast_mutex_t*        fast_mutex);    /*!< in/out: mutex to release */
 
308
 
 
309
#else /* UNIV_PFS_MUTEX */
 
310
 
 
311
# define os_fast_mutex_init(K, M)                       \
 
312
        os_fast_mutex_init_func(&((os_fast_mutex_t*)(M))->mutex)
 
313
 
 
314
# define os_fast_mutex_lock(M)                          \
 
315
        os_fast_mutex_lock_func(&((os_fast_mutex_t*)(M))->mutex)
 
316
 
 
317
# define os_fast_mutex_unlock(M)                        \
 
318
        os_fast_mutex_unlock_func(&((os_fast_mutex_t*)(M))->mutex)
 
319
 
 
320
# define os_fast_mutex_free(M)                          \
 
321
        os_fast_mutex_free_func(&((os_fast_mutex_t*)(M))->mutex)
 
322
#endif /* UNIV_PFS_MUTEX */
 
323
 
 
324
/**********************************************************//**
 
325
Releases ownership of a fast mutex. */
 
326
UNIV_INTERN
 
327
void
 
328
os_fast_mutex_unlock_func(
 
329
/*======================*/
 
330
        fast_mutex_t*           fast_mutex);    /*!< in: mutex to release */
 
331
/*********************************************************//**
 
332
Initializes an operating system fast mutex semaphore. */
 
333
UNIV_INTERN
 
334
void
 
335
os_fast_mutex_init_func(
 
336
/*====================*/
 
337
        fast_mutex_t*           fast_mutex);    /*!< in: fast mutex */
 
338
/**********************************************************//**
 
339
Acquires ownership of a fast mutex. */
 
340
UNIV_INTERN
 
341
void
 
342
os_fast_mutex_lock_func(
 
343
/*====================*/
 
344
        fast_mutex_t*           fast_mutex);    /*!< in: mutex to acquire */
 
345
/**********************************************************//**
 
346
Frees an mutex object. */
 
347
UNIV_INTERN
 
348
void
 
349
os_fast_mutex_free_func(
 
350
/*====================*/
 
351
        fast_mutex_t*           fast_mutex);    /*!< in: mutex to free */
 
352
 
 
353
/**********************************************************//**
 
354
Atomic compare-and-swap and increment for InnoDB. */
 
355
 
 
356
#if defined(HAVE_IB_GCC_ATOMIC_BUILTINS)
 
357
 
 
358
# define HAVE_ATOMIC_BUILTINS
 
359
 
 
360
# ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_64
 
361
#  define HAVE_ATOMIC_BUILTINS_64
 
362
# endif
 
363
 
 
364
/**********************************************************//**
 
365
Returns true if swapped, ptr is pointer to target, old_val is value to
 
366
compare to, new_val is the value to swap in. */
 
367
 
 
368
# define os_compare_and_swap(ptr, old_val, new_val) \
 
369
        __sync_bool_compare_and_swap(ptr, old_val, new_val)
 
370
 
 
371
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
 
372
        os_compare_and_swap(ptr, old_val, new_val)
 
373
 
 
374
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
 
375
        os_compare_and_swap(ptr, old_val, new_val)
 
376
 
 
377
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
 
378
#  define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
379
        os_compare_and_swap(ptr, old_val, new_val)
 
380
#  define INNODB_RW_LOCKS_USE_ATOMICS
 
381
#  define IB_ATOMICS_STARTUP_MSG \
 
382
        "Mutexes and rw_locks use GCC atomic builtins"
 
383
# else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
 
384
#  define IB_ATOMICS_STARTUP_MSG \
 
385
        "Mutexes use GCC atomic builtins, rw_locks do not"
 
386
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
 
387
 
 
388
/**********************************************************//**
 
389
Returns the resulting value, ptr is pointer to target, amount is the
 
390
amount of increment. */
 
391
 
 
392
# define os_atomic_increment(ptr, amount) \
 
393
        __sync_add_and_fetch(ptr, amount)
 
394
 
 
395
# define os_atomic_increment_lint(ptr, amount) \
 
396
        os_atomic_increment(ptr, amount)
 
397
 
 
398
# define os_atomic_increment_ulint(ptr, amount) \
 
399
        os_atomic_increment(ptr, amount)
 
400
 
 
401
# define os_atomic_increment_uint64(ptr, amount) \
 
402
        os_atomic_increment(ptr, amount)
 
403
 
 
404
/* Returns the resulting value, ptr is pointer to target, amount is the
 
405
amount to decrement. */
 
406
 
 
407
# define os_atomic_decrement(ptr, amount) \
 
408
        __sync_sub_and_fetch(ptr, amount)
 
409
 
 
410
# define os_atomic_decrement_lint(ptr, amount) \
 
411
        os_atomic_decrement(ptr, amount)
 
412
 
 
413
# define os_atomic_decrement_ulint(ptr, amount) \
 
414
        os_atomic_decrement(ptr, amount)
 
415
 
 
416
# define os_atomic_decrement_uint64(ptr, amount) \
 
417
        os_atomic_decrement(ptr, amount)
 
418
 
 
419
/**********************************************************//**
 
420
Returns the old value of *ptr, atomically sets *ptr to new_val */
 
421
 
 
422
# define os_atomic_test_and_set_byte(ptr, new_val) \
 
423
        __sync_lock_test_and_set(ptr, (byte) new_val)
 
424
 
 
425
# define os_atomic_test_and_set_ulint(ptr, new_val) \
 
426
        __sync_lock_test_and_set(ptr, new_val)
 
427
 
 
428
#elif defined(HAVE_IB_SOLARIS_ATOMICS)
 
429
 
 
430
# define HAVE_ATOMIC_BUILTINS
 
431
# define HAVE_ATOMIC_BUILTINS_64
 
432
 
 
433
/* If not compiling with GCC or GCC doesn't support the atomic
 
434
intrinsics and running on Solaris >= 10 use Solaris atomics */
 
435
 
 
436
# include <atomic.h>
 
437
 
 
438
/**********************************************************//**
 
439
Returns true if swapped, ptr is pointer to target, old_val is value to
 
440
compare to, new_val is the value to swap in. */
 
441
 
 
442
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
 
443
        (atomic_cas_ulong(ptr, old_val, new_val) == old_val)
 
444
 
 
445
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
 
446
        ((lint) atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val)
 
447
 
 
448
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS
 
449
#  if SIZEOF_PTHREAD_T == 4
 
450
#   define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
451
        ((pthread_t) atomic_cas_32(ptr, old_val, new_val) == old_val)
 
452
#  elif SIZEOF_PTHREAD_T == 8
 
453
#   define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
454
        ((pthread_t) atomic_cas_64(ptr, old_val, new_val) == old_val)
 
455
#  else
 
456
#   error "SIZEOF_PTHREAD_T != 4 or 8"
 
457
#  endif /* SIZEOF_PTHREAD_T CHECK */
 
458
#  define INNODB_RW_LOCKS_USE_ATOMICS
 
459
#  define IB_ATOMICS_STARTUP_MSG \
 
460
        "Mutexes and rw_locks use Solaris atomic functions"
 
461
# else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
 
462
#  define IB_ATOMICS_STARTUP_MSG \
 
463
        "Mutexes use Solaris atomic functions, rw_locks do not"
 
464
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
 
465
 
 
466
/**********************************************************//**
 
467
Returns the resulting value, ptr is pointer to target, amount is the
 
468
amount of increment. */
 
469
 
 
470
# define os_atomic_increment_ulint(ptr, amount) \
 
471
        atomic_add_long_nv(ptr, amount)
 
472
 
 
473
# define os_atomic_increment_lint(ptr, amount) \
 
474
        os_atomic_increment_ulint((ulong_t*) ptr, amount)
 
475
 
 
476
# define os_atomic_increment_uint64(ptr, amount) \
 
477
        atomic_add_64_nv(ptr, amount)
 
478
 
 
479
/* Returns the resulting value, ptr is pointer to target, amount is the
 
480
amount to decrement. */
 
481
 
 
482
# define os_atomic_decrement_lint(ptr, amount) \
 
483
        os_atomic_increment_ulint((ulong_t*) ptr, -(amount))
 
484
 
 
485
# define os_atomic_decrement_ulint(ptr, amount) \
 
486
        os_atomic_increment_ulint(ptr, -(amount))
 
487
 
 
488
# define os_atomic_decrement_uint64(ptr, amount) \
 
489
        os_atomic_increment_uint64(ptr, -(amount))
 
490
 
 
491
/**********************************************************//**
 
492
Returns the old value of *ptr, atomically sets *ptr to new_val */
 
493
 
 
494
# define os_atomic_test_and_set_byte(ptr, new_val) \
 
495
        atomic_swap_uchar(ptr, new_val)
 
496
 
 
497
# define os_atomic_test_and_set_ulint(ptr, new_val) \
 
498
        atomic_swap_ulong(ptr, new_val)
 
499
 
 
500
#elif defined(HAVE_WINDOWS_ATOMICS)
 
501
 
 
502
# define HAVE_ATOMIC_BUILTINS
 
503
 
 
504
# ifndef _WIN32
 
505
#  define HAVE_ATOMIC_BUILTINS_64
 
506
# endif
 
507
 
 
508
/**********************************************************//**
 
509
Atomic compare and exchange of signed integers (both 32 and 64 bit).
 
510
@return value found before the exchange.
 
511
If it is not equal to old_value the exchange did not happen. */
 
512
UNIV_INLINE
 
513
lint
 
514
win_cmp_and_xchg_lint(
 
515
/*==================*/
 
516
        volatile lint*  ptr,            /*!< in/out: source/destination */
 
517
        lint            new_val,        /*!< in: exchange value */
 
518
        lint            old_val);       /*!< in: value to compare to */
 
519
 
 
520
/**********************************************************//**
 
521
Atomic addition of signed integers.
 
522
@return Initial value of the variable pointed to by ptr */
 
523
UNIV_INLINE
 
524
lint
 
525
win_xchg_and_add(
 
526
/*=============*/
 
527
        volatile lint*  ptr,    /*!< in/out: address of destination */
 
528
        lint            val);   /*!< in: number to be added */
 
529
 
 
530
/**********************************************************//**
 
531
Atomic compare and exchange of unsigned integers.
 
532
@return value found before the exchange.
 
533
If it is not equal to old_value the exchange did not happen. */
 
534
UNIV_INLINE
 
535
ulint
 
536
win_cmp_and_xchg_ulint(
 
537
/*===================*/
 
538
        volatile ulint* ptr,            /*!< in/out: source/destination */
 
539
        ulint           new_val,        /*!< in: exchange value */
 
540
        ulint           old_val);       /*!< in: value to compare to */
 
541
 
 
542
/**********************************************************//**
 
543
Atomic compare and exchange of 32 bit unsigned integers.
 
544
@return value found before the exchange.
 
545
If it is not equal to old_value the exchange did not happen. */
 
546
UNIV_INLINE
 
547
DWORD
 
548
win_cmp_and_xchg_dword(
 
549
/*===================*/
 
550
        volatile DWORD* ptr,            /*!< in/out: source/destination */
 
551
        DWORD           new_val,        /*!< in: exchange value */
 
552
        DWORD           old_val);       /*!< in: value to compare to */
 
553
 
 
554
/**********************************************************//**
 
555
Returns true if swapped, ptr is pointer to target, old_val is value to
 
556
compare to, new_val is the value to swap in. */
 
557
 
 
558
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
 
559
        (win_cmp_and_xchg_ulint(ptr, new_val, old_val) == old_val)
 
560
 
 
561
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
 
562
        (win_cmp_and_xchg_lint(ptr, new_val, old_val) == old_val)
 
563
 
 
564
/* windows thread objects can always be passed to windows atomic functions */
 
565
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
 
566
        (win_cmp_and_xchg_dword(ptr, new_val, old_val) == old_val)
 
567
 
 
568
# define INNODB_RW_LOCKS_USE_ATOMICS
 
569
# define IB_ATOMICS_STARTUP_MSG \
 
570
        "Mutexes and rw_locks use Windows interlocked functions"
 
571
 
 
572
/**********************************************************//**
 
573
Returns the resulting value, ptr is pointer to target, amount is the
 
574
amount of increment. */
 
575
 
 
576
# define os_atomic_increment_lint(ptr, amount) \
 
577
        (win_xchg_and_add(ptr, amount) + amount)
 
578
 
 
579
# define os_atomic_increment_ulint(ptr, amount) \
 
580
        ((ulint) (win_xchg_and_add((lint*) ptr, (lint) amount) + amount))
 
581
 
 
582
# define os_atomic_increment_uint64(ptr, amount)                \
 
583
        ((ib_uint64_t) (InterlockedExchangeAdd64(               \
 
584
                                (ib_int64_t*) ptr,              \
 
585
                                (ib_int64_t) amount) + amount))
 
586
 
 
587
/**********************************************************//**
 
588
Returns the resulting value, ptr is pointer to target, amount is the
 
589
amount to decrement. There is no atomic substract function on Windows */
 
590
 
 
591
# define os_atomic_decrement_lint(ptr, amount) \
 
592
        (win_xchg_and_add(ptr, -(lint) amount) - amount)
 
593
 
 
594
# define os_atomic_decrement_ulint(ptr, amount) \
 
595
        ((ulint) (win_xchg_and_add((lint*) ptr, -(lint) amount) - amount))
 
596
 
 
597
# define os_atomic_decrement_uint64(ptr, amount)                \
 
598
        ((ib_uint64_t) (InterlockedExchangeAdd64(               \
 
599
                                (ib_int64_t*) ptr,              \
 
600
                                -(ib_int64_t) amount) - amount))
 
601
 
 
602
/**********************************************************//**
 
603
Returns the old value of *ptr, atomically sets *ptr to new_val.
 
604
InterlockedExchange() operates on LONG, and the LONG will be
 
605
clobbered */
 
606
 
 
607
# define os_atomic_test_and_set_byte(ptr, new_val) \
 
608
        ((byte) InterlockedExchange(ptr, new_val))
 
609
 
 
610
# define os_atomic_test_and_set_ulong(ptr, new_val) \
 
611
        InterlockedExchange(ptr, new_val)
 
612
 
 
613
#else
 
614
# define IB_ATOMICS_STARTUP_MSG \
 
615
        "Mutexes and rw_locks use InnoDB's own implementation"
 
616
#endif
 
617
#ifdef HAVE_ATOMIC_BUILTINS
 
618
#define os_atomic_inc_ulint(m,v,d)      os_atomic_increment_ulint(v, d)
 
619
#define os_atomic_dec_ulint(m,v,d)      os_atomic_decrement_ulint(v, d)
 
620
#else
 
621
#define os_atomic_inc_ulint(m,v,d)      os_atomic_inc_ulint_func(m, v, d)
 
622
#define os_atomic_dec_ulint(m,v,d)      os_atomic_dec_ulint_func(m, v, d)
 
623
#endif /* HAVE_ATOMIC_BUILTINS */
 
624
 
 
625
/**********************************************************//**
 
626
Following macros are used to update specified counter atomically
 
627
if HAVE_ATOMIC_BUILTINS defined. Otherwise, use mutex passed in
 
628
for synchronization */
 
629
#ifdef HAVE_ATOMIC_BUILTINS
 
630
#define os_increment_counter_by_amount(mutex, counter, amount)  \
 
631
        (void) os_atomic_increment_ulint(&counter, amount)
 
632
 
 
633
#define os_decrement_counter_by_amount(mutex, counter, amount)  \
 
634
        (void) os_atomic_increment_ulint(&counter, (-((lint) amount)))
 
635
#else
 
636
#define os_increment_counter_by_amount(mutex, counter, amount)  \
 
637
        do {                                                    \
 
638
                mutex_enter(&(mutex));                          \
 
639
                (counter) += (amount);                          \
 
640
                mutex_exit(&(mutex));                           \
 
641
        } while (0)
 
642
 
 
643
#define os_decrement_counter_by_amount(mutex, counter, amount)  \
 
644
        do {                                                    \
 
645
                ut_a(counter >= amount);                        \
 
646
                mutex_enter(&(mutex));                          \
 
647
                (counter) -= (amount);                          \
 
648
                mutex_exit(&(mutex));                           \
 
649
        } while (0)
 
650
#endif  /* HAVE_ATOMIC_BUILTINS */
 
651
 
 
652
#define os_inc_counter(mutex, counter)                          \
 
653
        os_increment_counter_by_amount(mutex, counter, 1)
 
654
 
 
655
#define os_dec_counter(mutex, counter)                          \
 
656
        do {                                                    \
 
657
                os_decrement_counter_by_amount(mutex, counter, 1);\
 
658
        } while (0);
 
659
 
 
660
#ifndef UNIV_NONINL
 
661
#include "os0sync.ic"
 
662
#endif
 
663
 
 
664
#endif