ua_util.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.*/
  4. #ifndef UA_UTIL_H_
  5. #define UA_UTIL_H_
  6. #include "ua_config.h"
  7. /* Assert */
  8. #include <assert.h>
  9. #define UA_assert(ignore) assert(ignore)
  10. /* BSD Queue Macros */
  11. #include "queue.h"
  12. /* container_of */
  13. #define container_of(ptr, type, member) \
  14. (type *)((uintptr_t)ptr - offsetof(type,member))
  15. /* Thread Local Storage */
  16. #ifdef UA_ENABLE_MULTITHREADING
  17. # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
  18. # define UA_THREAD_LOCAL _Thread_local /* C11 */
  19. # elif defined(__GNUC__)
  20. # define UA_THREAD_LOCAL __thread /* GNU extension */
  21. # elif defined(_MSC_VER)
  22. # define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
  23. # else
  24. # error The compiler does not support thread-local variables.
  25. # endif
  26. #else
  27. # define UA_THREAD_LOCAL
  28. #endif
  29. /* Atomic Operations
  30. * -----------------
  31. * Atomic operations that synchronize across processor cores (for
  32. * multithreading). Only the inline-functions defined next are used. Replace
  33. * with architecture-specific operations if necessary. */
  34. #ifndef UA_ENABLE_MULTITHREADING
  35. # define UA_atomic_sync()
  36. #else
  37. # ifdef _MSC_VER /* Visual Studio */
  38. # define UA_atomic_sync() _ReadWriteBarrier()
  39. # else /* GCC/Clang */
  40. # define UA_atomic_sync() __sync_synchronize()
  41. # endif
  42. #endif
  43. static UA_INLINE void *
  44. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  45. #ifndef UA_ENABLE_MULTITHREADING
  46. void *old = *addr;
  47. *addr = newptr;
  48. return old;
  49. #else
  50. # ifdef _MSC_VER /* Visual Studio */
  51. return _InterlockedExchangePointer(addr, newptr);
  52. # else /* GCC/Clang */
  53. return __sync_lock_test_and_set(addr, newptr);
  54. # endif
  55. #endif
  56. }
  57. static UA_INLINE void *
  58. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  59. #ifndef UA_ENABLE_MULTITHREADING
  60. void *old = *addr;
  61. if(old == expected) {
  62. *addr = newptr;
  63. }
  64. return old;
  65. #else
  66. # ifdef _MSC_VER /* Visual Studio */
  67. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  68. # else /* GCC/Clang */
  69. return __sync_val_compare_and_swap(addr, expected, newptr);
  70. # endif
  71. #endif
  72. }
  73. static UA_INLINE uint32_t
  74. UA_atomic_add(volatile uint32_t *addr, uint32_t increase) {
  75. #ifndef UA_ENABLE_MULTITHREADING
  76. *addr += increase;
  77. return *addr;
  78. #else
  79. # ifdef _MSC_VER /* Visual Studio */
  80. return _InterlockedExchangeAdd(addr, increase) + increase;
  81. # else /* GCC/Clang */
  82. return __sync_add_and_fetch(addr, increase);
  83. # endif
  84. #endif
  85. }
  86. #endif /* UA_UTIL_H_ */