generic-msvc.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*-------------------------------------------------------------------------
  2. *
  3. * generic-msvc.h
  4. * Atomic operations support when using MSVC
  5. *
  6. * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
  7. * Portions Copyright (c) 1994, Regents of the University of California
  8. *
  9. * NOTES:
  10. *
  11. * Documentation:
  12. * * Interlocked Variable Access
  13. * http://msdn.microsoft.com/en-us/library/ms684122%28VS.85%29.aspx
  14. *
  15. * src/include/port/atomics/generic-msvc.h
  16. *
  17. *-------------------------------------------------------------------------
  18. */
  19. #include <intrin.h>
  20. #include <windows.h>
  21. /* intentionally no include guards, should only be included by atomics.h */
  22. #ifndef INSIDE_ATOMICS_H
  23. #error "should be included via atomics.h"
  24. #endif
  25. /* Should work on both MSVC and Borland. */
  26. #pragma intrinsic(_ReadWriteBarrier)
  27. #define pg_compiler_barrier_impl() _ReadWriteBarrier()
  28. #ifndef pg_memory_barrier_impl
  29. #define pg_memory_barrier_impl() MemoryBarrier()
  30. #endif
  31. #if defined(HAVE_ATOMICS)
  32. #define PG_HAVE_ATOMIC_U32_SUPPORT
  33. typedef struct pg_atomic_uint32
  34. {
  35. volatile uint32 value;
  36. } pg_atomic_uint32;
  37. #define PG_HAVE_ATOMIC_U64_SUPPORT
  38. typedef struct __declspec(align(8)) pg_atomic_uint64
  39. {
  40. volatile uint64 value;
  41. } pg_atomic_uint64;
  42. #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
  43. static inline bool
  44. pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
  45. uint32 *expected, uint32 newval)
  46. {
  47. bool ret;
  48. uint32 current;
  49. current = InterlockedCompareExchange(&ptr->value, newval, *expected);
  50. ret = current == *expected;
  51. *expected = current;
  52. return ret;
  53. }
  54. #define PG_HAVE_ATOMIC_FETCH_ADD_U32
  55. static inline uint32
  56. pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
  57. {
  58. return InterlockedExchangeAdd(&ptr->value, add_);
  59. }
  60. /*
  61. * The non-intrinsics versions are only available in vista upwards, so use the
  62. * intrinsic version. Only supported on >486, but we require XP as a minimum
  63. * baseline, which doesn't support the 486, so we don't need to add checks for
  64. * that case.
  65. */
  66. #pragma intrinsic(_InterlockedCompareExchange64)
  67. #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
  68. static inline bool
  69. pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
  70. uint64 *expected, uint64 newval)
  71. {
  72. bool ret;
  73. uint64 current;
  74. current = _InterlockedCompareExchange64(&ptr->value, newval, *expected);
  75. ret = current == *expected;
  76. *expected = current;
  77. return ret;
  78. }
  79. /* Only implemented on itanium and 64bit builds */
  80. #ifdef _WIN64
  81. #pragma intrinsic(_InterlockedExchangeAdd64)
  82. #define PG_HAVE_ATOMIC_FETCH_ADD_U64
  83. static inline uint64
  84. pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
  85. {
  86. return _InterlockedExchangeAdd64(&ptr->value, add_);
  87. }
  88. #endif /* _WIN64 */
  89. #endif /* HAVE_ATOMICS */