threading-windows.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2015 Hugh Bailey <[email protected]>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #pragma once
  17. #include <intrin.h>
  18. #include <string.h>
  19. #if !defined(_M_IX86) && !defined(_M_X64) && !defined(_M_ARM) && \
  20. !defined(_M_ARM64)
  21. #error Processor not supported
  22. #endif
  23. static inline long os_atomic_inc_long(volatile long *val)
  24. {
  25. return _InterlockedIncrement(val);
  26. }
  27. static inline long os_atomic_dec_long(volatile long *val)
  28. {
  29. return _InterlockedDecrement(val);
  30. }
  31. static inline void os_atomic_store_long(volatile long *ptr, long val)
  32. {
  33. #if defined(_M_ARM64)
  34. _ReadWriteBarrier();
  35. __stlr32((volatile unsigned *)ptr, val);
  36. _ReadWriteBarrier();
  37. #elif defined(_M_ARM)
  38. __dmb(_ARM_BARRIER_ISH);
  39. __iso_volatile_store32((volatile __int32 *)ptr, val);
  40. __dmb(_ARM_BARRIER_ISH);
  41. #else
  42. _InterlockedExchange(ptr, val);
  43. #endif
  44. }
  45. static inline long os_atomic_set_long(volatile long *ptr, long val)
  46. {
  47. return _InterlockedExchange(ptr, val);
  48. }
  49. static inline long os_atomic_exchange_long(volatile long *ptr, long val)
  50. {
  51. return os_atomic_set_long(ptr, val);
  52. }
  53. static inline long os_atomic_load_long(const volatile long *ptr)
  54. {
  55. #if defined(_M_ARM64)
  56. const long val = __ldar32((volatile unsigned *)ptr);
  57. #else
  58. const long val = __iso_volatile_load32((const volatile __int32 *)ptr);
  59. #endif
  60. #if defined(_M_ARM)
  61. __dmb(_ARM_BARRIER_ISH);
  62. #else
  63. _ReadWriteBarrier();
  64. #endif
  65. return val;
  66. }
  67. static inline bool os_atomic_compare_swap_long(volatile long *val, long old_val,
  68. long new_val)
  69. {
  70. return _InterlockedCompareExchange(val, new_val, old_val) == old_val;
  71. }
  72. static inline bool os_atomic_compare_exchange_long(volatile long *val,
  73. long *old_ptr, long new_val)
  74. {
  75. const long old_val = *old_ptr;
  76. const long previous =
  77. _InterlockedCompareExchange(val, new_val, old_val);
  78. *old_ptr = previous;
  79. return previous == old_val;
  80. }
  81. static inline void os_atomic_store_bool(volatile bool *ptr, bool val)
  82. {
  83. #if defined(_M_ARM64)
  84. _ReadWriteBarrier();
  85. __stlr8((volatile unsigned char *)ptr, val);
  86. _ReadWriteBarrier();
  87. #elif defined(_M_ARM)
  88. __dmb(_ARM_BARRIER_ISH);
  89. __iso_volatile_store8((volatile char *)ptr, val);
  90. __dmb(_ARM_BARRIER_ISH);
  91. #else
  92. _InterlockedExchange8((volatile char *)ptr, (char)val);
  93. #endif
  94. }
  95. static inline bool os_atomic_set_bool(volatile bool *ptr, bool val)
  96. {
  97. const char c = _InterlockedExchange8((volatile char *)ptr, (char)val);
  98. bool b;
  99. /* Avoid unnecesary char to bool conversion. Value known 0 or 1. */
  100. memcpy(&b, &c, sizeof(b));
  101. return b;
  102. }
  103. static inline bool os_atomic_exchange_bool(volatile bool *ptr, bool val)
  104. {
  105. return os_atomic_set_bool(ptr, val);
  106. }
  107. static inline bool os_atomic_load_bool(const volatile bool *ptr)
  108. {
  109. bool b;
  110. #if defined(_M_ARM64)
  111. const unsigned char c = __ldar8((volatile unsigned char *)ptr);
  112. #else
  113. const char c = __iso_volatile_load8((const volatile char *)ptr);
  114. #endif
  115. #if defined(_M_ARM)
  116. __dmb(_ARM_BARRIER_ISH);
  117. #else
  118. _ReadWriteBarrier();
  119. #endif
  120. /* Avoid unnecesary char to bool conversion. Value known 0 or 1. */
  121. memcpy(&b, &c, sizeof(b));
  122. return b;
  123. }