2
0

generic-msvc.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*-------------------------------------------------------------------------
  2. *
  3. * generic-msvc.h
  4. * Atomic operations support when using MSVC
  5. *
  6. * Portions Copyright (c) 1996-2022, 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. /* intentionally no include guards, should only be included by atomics.h */
  21. #ifndef INSIDE_ATOMICS_H
  22. #error "should be included via atomics.h"
  23. #endif
  24. #pragma intrinsic(_ReadWriteBarrier)
  25. #define pg_compiler_barrier_impl() _ReadWriteBarrier()
  26. #ifndef pg_memory_barrier_impl
  27. #define pg_memory_barrier_impl() MemoryBarrier()
  28. #endif
  29. #if defined(HAVE_ATOMICS)
  30. #define PG_HAVE_ATOMIC_U32_SUPPORT
  31. typedef struct pg_atomic_uint32
  32. {
  33. volatile uint32 value;
  34. } pg_atomic_uint32;
  35. #define PG_HAVE_ATOMIC_U64_SUPPORT
  36. typedef struct __declspec(align(8)) pg_atomic_uint64
  37. {
  38. volatile uint64 value;
  39. } pg_atomic_uint64;
  40. #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
  41. static inline bool
  42. pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
  43. uint32 *expected, uint32 newval)
  44. {
  45. bool ret;
  46. uint32 current;
  47. current = InterlockedCompareExchange(&ptr->value, newval, *expected);
  48. ret = current == *expected;
  49. *expected = current;
  50. return ret;
  51. }
  52. #define PG_HAVE_ATOMIC_FETCH_ADD_U32
  53. static inline uint32
  54. pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
  55. {
  56. return InterlockedExchangeAdd(&ptr->value, add_);
  57. }
  58. /*
  59. * The non-intrinsics versions are only available in vista upwards, so use the
  60. * intrinsic version. Only supported on >486, but we require XP as a minimum
  61. * baseline, which doesn't support the 486, so we don't need to add checks for
  62. * that case.
  63. */
  64. #pragma intrinsic(_InterlockedCompareExchange64)
  65. #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
  66. static inline bool
  67. pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
  68. uint64 *expected, uint64 newval)
  69. {
  70. bool ret;
  71. uint64 current;
  72. current = _InterlockedCompareExchange64(&ptr->value, newval, *expected);
  73. ret = current == *expected;
  74. *expected = current;
  75. return ret;
  76. }
  77. /* Only implemented on itanium and 64bit builds */
  78. #ifdef _WIN64
  79. #pragma intrinsic(_InterlockedExchangeAdd64)
  80. #define PG_HAVE_ATOMIC_FETCH_ADD_U64
  81. static inline uint64
  82. pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
  83. {
  84. return _InterlockedExchangeAdd64(&ptr->value, add_);
  85. }
  86. #endif /* _WIN64 */
  87. #endif /* HAVE_ATOMICS */