InnoDB Plugin  1.0
os0sync.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2014, 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 /**************************************************/
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 
43 typedef HANDLE os_native_event_t;
45 typedef CRITICAL_SECTION fast_mutex_t;
47 typedef CONDITION_VARIABLE os_cond_t;
48 #else
49 
50 typedef pthread_mutex_t fast_mutex_t;
52 typedef pthread_cond_t os_cond_t;
53 #endif
54 
59 #ifdef UNIV_PFS_MUTEX
60  struct PSI_mutex* pfs_psi;
62 #endif
63 };
64 
66 typedef struct os_event* os_event_t;
67 
69 struct os_event {
70 #ifdef __WIN__
71  HANDLE handle;
73 #endif
80  ib_int64_t signal_count;
84  UT_LIST_NODE_T(os_event_t) os_event_list;
86 };
87 
89 #define OS_SYNC_INFINITE_TIME ULINT_UNDEFINED
90 
92 #define OS_SYNC_TIME_EXCEEDED 1
93 
95 typedef struct os_mutex_t* os_ib_mutex_t;
96 
99 
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 /*********************************************************/
110 UNIV_INTERN
111 void
112 os_sync_init(void);
113 /*==============*/
114 /*********************************************************/
116 UNIV_INTERN
117 void
118 os_sync_free(void);
119 /*==============*/
120 /*********************************************************/
125 UNIV_INTERN
126 os_event_t
127 os_event_create(void);
128 /*==================*/
129 /**********************************************************/
132 UNIV_INTERN
133 void
135 /*=========*/
136  os_event_t event);
137 /**********************************************************/
144 UNIV_INTERN
145 ib_int64_t
147 /*===========*/
148  os_event_t event);
149 /**********************************************************/
151 UNIV_INTERN
152 void
154 /*==========*/
155  os_event_t event);
157 /**********************************************************/
174 UNIV_INTERN
175 void
177 /*==============*/
178  os_event_t event,
179  ib_int64_t reset_sig_count);
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 /**********************************************************/
190 UNIV_INTERN
191 ulint
193 /*===================*/
194  os_event_t event,
195  ulint time_in_usec,
198  ib_int64_t reset_sig_count);
201 /*********************************************************/
205 UNIV_INTERN
207 os_mutex_create(void);
208 /*=================*/
209 /**********************************************************/
211 UNIV_INTERN
212 void
214 /*===========*/
215  os_ib_mutex_t mutex);
216 /**********************************************************/
218 UNIV_INTERN
219 void
221 /*==========*/
222  os_ib_mutex_t mutex);
223 /**********************************************************/
225 UNIV_INTERN
226 void
228 /*==========*/
229  os_ib_mutex_t mutex);
230 /**********************************************************/
234 UNIV_INLINE
235 ulint
237 /*==================*/
238  os_fast_mutex_t* fast_mutex);
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 /*********************************************************/
270 UNIV_INLINE
271 void
272 pfs_os_fast_mutex_init(
273 /*===================*/
274  PSI_mutex_key key,
276  os_fast_mutex_t* fast_mutex);
277 /**********************************************************/
282 UNIV_INLINE
283 void
284 pfs_os_fast_mutex_free(
285 /*===================*/
286  os_fast_mutex_t* fast_mutex);
287 /**********************************************************/
291 UNIV_INLINE
292 void
293 pfs_os_fast_mutex_lock(
294 /*===================*/
295  os_fast_mutex_t* fast_mutex,
296  const char* file_name,
298  ulint line);
299 /**********************************************************/
303 UNIV_INLINE
304 void
305 pfs_os_fast_mutex_unlock(
306 /*=====================*/
307  os_fast_mutex_t* fast_mutex);
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 /**********************************************************/
326 UNIV_INTERN
327 void
329 /*======================*/
330  fast_mutex_t* fast_mutex);
331 /*********************************************************/
333 UNIV_INTERN
334 void
336 /*====================*/
337  fast_mutex_t* fast_mutex);
338 /**********************************************************/
340 UNIV_INTERN
341 void
343 /*====================*/
344  fast_mutex_t* fast_mutex);
345 /**********************************************************/
347 UNIV_INTERN
348 void
350 /*====================*/
351  fast_mutex_t* fast_mutex);
353 /**********************************************************/
356 #if defined(HAVE_IB_GCC_ATOMIC_BUILTINS)
357 
358 # define HAVE_ATOMIC_BUILTINS
359 
360 # ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE
361 # define HAVE_ATOMIC_BUILTINS_BYTE
362 # endif
363 
364 # ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_64
365 # define HAVE_ATOMIC_BUILTINS_64
366 # endif
367 
368 /**********************************************************/
372 # define os_compare_and_swap(ptr, old_val, new_val) \
373  __sync_bool_compare_and_swap(ptr, old_val, new_val)
374 
375 # define os_compare_and_swap_ulint(ptr, old_val, new_val) \
376  os_compare_and_swap(ptr, old_val, new_val)
377 
378 # define os_compare_and_swap_lint(ptr, old_val, new_val) \
379  os_compare_and_swap(ptr, old_val, new_val)
380 
381 # define os_compare_and_swap_uint32(ptr, old_val, new_val) \
382  os_compare_and_swap(ptr, old_val, new_val)
383 
384 # ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
385 # define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
386  os_compare_and_swap(ptr, old_val, new_val)
387 # define INNODB_RW_LOCKS_USE_ATOMICS
388 # define IB_ATOMICS_STARTUP_MSG \
389  "Mutexes and rw_locks use GCC atomic builtins"
390 # else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
391 # define IB_ATOMICS_STARTUP_MSG \
392  "Mutexes use GCC atomic builtins, rw_locks do not"
393 # endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
394 
395 /**********************************************************/
399 # define os_atomic_increment(ptr, amount) \
400  __sync_add_and_fetch(ptr, amount)
401 
402 # define os_atomic_increment_lint(ptr, amount) \
403  os_atomic_increment(ptr, amount)
404 
405 # define os_atomic_increment_uint32(ptr, amount ) \
406  os_atomic_increment(ptr, amount)
407 
408 # define os_atomic_increment_ulint(ptr, amount) \
409  os_atomic_increment(ptr, amount)
410 
411 # define os_atomic_increment_uint64(ptr, amount) \
412  os_atomic_increment(ptr, amount)
413 
414 /* Returns the resulting value, ptr is pointer to target, amount is the
415 amount to decrement. */
416 
417 # define os_atomic_decrement(ptr, amount) \
418  __sync_sub_and_fetch(ptr, amount)
419 
420 # define os_atomic_decrement_uint32(ptr, amount) \
421  os_atomic_decrement(ptr, amount)
422 
423 # define os_atomic_decrement_lint(ptr, amount) \
424  os_atomic_decrement(ptr, amount)
425 
426 # define os_atomic_decrement_ulint(ptr, amount) \
427  os_atomic_decrement(ptr, amount)
428 
429 # define os_atomic_decrement_uint64(ptr, amount) \
430  os_atomic_decrement(ptr, amount)
431 
432 /**********************************************************/
435 # define os_atomic_test_and_set_byte(ptr, new_val) \
436  __sync_lock_test_and_set(ptr, (byte) new_val)
437 
438 # define os_atomic_test_and_set_ulint(ptr, new_val) \
439  __sync_lock_test_and_set(ptr, new_val)
440 
441 #elif defined(HAVE_IB_SOLARIS_ATOMICS)
442 
443 # define HAVE_ATOMIC_BUILTINS
444 # define HAVE_ATOMIC_BUILTINS_BYTE
445 # define HAVE_ATOMIC_BUILTINS_64
446 
447 /* If not compiling with GCC or GCC doesn't support the atomic
448 intrinsics and running on Solaris >= 10 use Solaris atomics */
449 
450 # include <atomic.h>
451 
452 /**********************************************************/
456 # define os_compare_and_swap_uint32(ptr, old_val, new_val) \
457  (atomic_cas_32(ptr, old_val, new_val) == old_val)
458 
459 # define os_compare_and_swap_ulint(ptr, old_val, new_val) \
460  (atomic_cas_ulong(ptr, old_val, new_val) == old_val)
461 
462 # define os_compare_and_swap_lint(ptr, old_val, new_val) \
463  ((lint) atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val)
464 
465 # ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS
466 # if SIZEOF_PTHREAD_T == 4
467 # define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
468  ((pthread_t) atomic_cas_32(ptr, old_val, new_val) == old_val)
469 # elif SIZEOF_PTHREAD_T == 8
470 # define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
471  ((pthread_t) atomic_cas_64(ptr, old_val, new_val) == old_val)
472 # else
473 # error "SIZEOF_PTHREAD_T != 4 or 8"
474 # endif /* SIZEOF_PTHREAD_T CHECK */
475 # define INNODB_RW_LOCKS_USE_ATOMICS
476 # define IB_ATOMICS_STARTUP_MSG \
477  "Mutexes and rw_locks use Solaris atomic functions"
478 # else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
479 # define IB_ATOMICS_STARTUP_MSG \
480  "Mutexes use Solaris atomic functions, rw_locks do not"
481 # endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
482 
483 /**********************************************************/
487 # define os_atomic_increment_uint32(ptr, amount) \
488  atomic_add_32_nv(ptr, amount)
489 
490 # define os_atomic_increment_ulint(ptr, amount) \
491  atomic_add_long_nv(ptr, amount)
492 
493 # define os_atomic_increment_lint(ptr, amount) \
494  os_atomic_increment_ulint((ulong_t*) ptr, amount)
495 
496 # define os_atomic_increment_uint64(ptr, amount) \
497  atomic_add_64_nv(ptr, amount)
498 
499 /* Returns the resulting value, ptr is pointer to target, amount is the
500 amount to decrement. */
501 
502 # define os_atomic_decrement_uint32(ptr, amount) \
503  os_atomic_increment_uint32(ptr, -(amount))
504 
505 # define os_atomic_decrement_lint(ptr, amount) \
506  os_atomic_increment_ulint((ulong_t*) ptr, -(amount))
507 
508 # define os_atomic_decrement_ulint(ptr, amount) \
509  os_atomic_increment_ulint(ptr, -(amount))
510 
511 # define os_atomic_decrement_uint64(ptr, amount) \
512  os_atomic_increment_uint64(ptr, -(amount))
513 
514 /**********************************************************/
517 # define os_atomic_test_and_set_byte(ptr, new_val) \
518  atomic_swap_uchar(ptr, new_val)
519 
520 # define os_atomic_test_and_set_ulint(ptr, new_val) \
521  atomic_swap_ulong(ptr, new_val)
522 
523 #elif defined(HAVE_WINDOWS_ATOMICS)
524 
525 # define HAVE_ATOMIC_BUILTINS
526 # define HAVE_ATOMIC_BUILTINS_BYTE
527 
528 # ifndef _WIN32
529 # define HAVE_ATOMIC_BUILTINS_64
530 # endif
531 
532 /**********************************************************/
536 UNIV_INLINE
537 lint
538 win_cmp_and_xchg_lint(
539 /*==================*/
540  volatile lint* ptr,
541  lint new_val,
542  lint old_val);
544 /**********************************************************/
547 UNIV_INLINE
548 lint
549 win_xchg_and_add(
550 /*=============*/
551  volatile lint* ptr,
552  lint val);
554 /**********************************************************/
558 UNIV_INLINE
559 ulint
560 win_cmp_and_xchg_ulint(
561 /*===================*/
562  volatile ulint* ptr,
563  ulint new_val,
564  ulint old_val);
566 /**********************************************************/
570 UNIV_INLINE
571 DWORD
572 win_cmp_and_xchg_dword(
573 /*===================*/
574  volatile DWORD* ptr,
575  DWORD new_val,
576  DWORD old_val);
578 /**********************************************************/
582 # define os_compare_and_swap_uint32(ptr, old_val, new_val) \
583  (InterlockedCompareExchange(reinterpret_cast<volatile long*>(ptr), \
584  new_val, old_val) == old_val)
585 
586 # define os_compare_and_swap_ulint(ptr, old_val, new_val) \
587  (win_cmp_and_xchg_ulint(ptr, new_val, old_val) == old_val)
588 
589 # define os_compare_and_swap_lint(ptr, old_val, new_val) \
590  (win_cmp_and_xchg_lint(ptr, new_val, old_val) == old_val)
591 
592 /* windows thread objects can always be passed to windows atomic functions */
593 # define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
594  (win_cmp_and_xchg_dword(ptr, new_val, old_val) == old_val)
595 
596 # define INNODB_RW_LOCKS_USE_ATOMICS
597 # define IB_ATOMICS_STARTUP_MSG \
598  "Mutexes and rw_locks use Windows interlocked functions"
599 
600 /**********************************************************/
604 # define os_atomic_increment_lint(ptr, amount) \
605  (win_xchg_and_add(ptr, amount) + amount)
606 
607 # define os_atomic_increment_uint32(ptr, amount) \
608  ((ulint) InterlockedExchangeAdd((long*) ptr, amount))
609 
610 # define os_atomic_increment_ulint(ptr, amount) \
611  ((ulint) (win_xchg_and_add((lint*) ptr, (lint) amount) + amount))
612 
613 # define os_atomic_increment_uint64(ptr, amount) \
614  ((ib_uint64_t) (InterlockedExchangeAdd64( \
615  (ib_int64_t*) ptr, \
616  (ib_int64_t) amount) + amount))
617 
618 /**********************************************************/
622 # define os_atomic_decrement_uint32(ptr, amount) \
623  ((ulint) InterlockedExchangeAdd((long*) ptr, (-amount)))
624 
625 # define os_atomic_decrement_lint(ptr, amount) \
626  (win_xchg_and_add(ptr, -(lint) amount) - amount)
627 
628 # define os_atomic_decrement_ulint(ptr, amount) \
629  ((ulint) (win_xchg_and_add((lint*) ptr, -(lint) amount) - amount))
630 
631 # define os_atomic_decrement_uint64(ptr, amount) \
632  ((ib_uint64_t) (InterlockedExchangeAdd64( \
633  (ib_int64_t*) ptr, \
634  -(ib_int64_t) amount) - amount))
635 
636 /**********************************************************/
641 # define os_atomic_test_and_set_byte(ptr, new_val) \
642  ((byte) InterlockedExchange(ptr, new_val))
643 
644 # define os_atomic_test_and_set_ulong(ptr, new_val) \
645  InterlockedExchange(ptr, new_val)
646 
647 #else
648 # define IB_ATOMICS_STARTUP_MSG \
649  "Mutexes and rw_locks use InnoDB's own implementation"
650 #endif
651 #ifdef HAVE_ATOMIC_BUILTINS
652 #define os_atomic_inc_ulint(m,v,d) os_atomic_increment_ulint(v, d)
653 #define os_atomic_dec_ulint(m,v,d) os_atomic_decrement_ulint(v, d)
654 #else
655 #define os_atomic_inc_ulint(m,v,d) os_atomic_inc_ulint_func(m, v, d)
656 #define os_atomic_dec_ulint(m,v,d) os_atomic_dec_ulint_func(m, v, d)
657 #endif /* HAVE_ATOMIC_BUILTINS */
658 
659 /**********************************************************/
663 #ifdef HAVE_ATOMIC_BUILTINS
664 #define os_increment_counter_by_amount(mutex, counter, amount) \
665  (void) os_atomic_increment_ulint(&counter, amount)
666 
667 #define os_decrement_counter_by_amount(mutex, counter, amount) \
668  (void) os_atomic_increment_ulint(&counter, (-((lint) amount)))
669 #else
670 #define os_increment_counter_by_amount(mutex, counter, amount) \
671  do { \
672  mutex_enter(&(mutex)); \
673  (counter) += (amount); \
674  mutex_exit(&(mutex)); \
675  } while (0)
676 
677 #define os_decrement_counter_by_amount(mutex, counter, amount) \
678  do { \
679  ut_a(counter >= amount); \
680  mutex_enter(&(mutex)); \
681  (counter) -= (amount); \
682  mutex_exit(&(mutex)); \
683  } while (0)
684 #endif /* HAVE_ATOMIC_BUILTINS */
685 
686 #define os_inc_counter(mutex, counter) \
687  os_increment_counter_by_amount(mutex, counter, 1)
688 
689 #define os_dec_counter(mutex, counter) \
690  do { \
691  os_decrement_counter_by_amount(mutex, counter, 1);\
692  } while (0);
693 
695 #if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined __WIN__
696 /* Performance regression was observed at some conditions for Intel
697 architecture. Disable memory barrier for Intel architecture for now. */
698 # define os_rmb
699 # define os_wmb
700 # define IB_MEMORY_BARRIER_STARTUP_MSG \
701  "Memory barrier is not used"
702 #elif defined(HAVE_IB_GCC_ATOMIC_THREAD_FENCE)
703 # define HAVE_MEMORY_BARRIER
704 # define os_rmb __atomic_thread_fence(__ATOMIC_ACQUIRE)
705 # define os_wmb __atomic_thread_fence(__ATOMIC_RELEASE)
706 # define IB_MEMORY_BARRIER_STARTUP_MSG \
707  "GCC builtin __atomic_thread_fence() is used for memory barrier"
708 
709 #elif defined(HAVE_IB_GCC_SYNC_SYNCHRONISE)
710 # define HAVE_MEMORY_BARRIER
711 # define os_rmb __sync_synchronize()
712 # define os_wmb __sync_synchronize()
713 # define IB_MEMORY_BARRIER_STARTUP_MSG \
714  "GCC builtin __sync_synchronize() is used for memory barrier"
715 
716 #elif defined(HAVE_IB_MACHINE_BARRIER_SOLARIS)
717 # define HAVE_MEMORY_BARRIER
718 # include <mbarrier.h>
719 # define os_rmb __machine_r_barrier()
720 # define os_wmb __machine_w_barrier()
721 # define IB_MEMORY_BARRIER_STARTUP_MSG \
722  "Solaris memory ordering functions are used for memory barrier"
723 
724 #elif defined(HAVE_WINDOWS_MM_FENCE) && defined(_WIN64)
725 # define HAVE_MEMORY_BARRIER
726 # include <mmintrin.h>
727 # define os_rmb _mm_lfence()
728 # define os_wmb _mm_sfence()
729 # define IB_MEMORY_BARRIER_STARTUP_MSG \
730  "_mm_lfence() and _mm_sfence() are used for memory barrier"
731 
732 #else
733 # define os_rmb
734 # define os_wmb
735 # define IB_MEMORY_BARRIER_STARTUP_MSG \
736  "Memory barrier is not used"
737 #endif
738 
739 #ifndef UNIV_NONINL
740 #include "os0sync.ic"
741 #endif
742 
743 #endif