ua_util.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. # warning The compiler does not allow thread-local variables. The library can be built, but will not be thread-safe.
  25. # endif
  26. #endif
  27. #ifndef UA_THREAD_LOCAL
  28. # define UA_THREAD_LOCAL
  29. #endif
  30. /* Atomic Operations
  31. * -----------------
  32. * Atomic operations that synchronize across processor cores (for
  33. * multithreading). Only the inline-functions defined next are used. Replace
  34. * with architecture-specific operations if necessary. */
  35. #ifndef UA_ENABLE_MULTITHREADING
  36. # define UA_atomic_sync()
  37. #else
  38. # ifdef _MSC_VER /* Visual Studio */
  39. # define UA_atomic_sync() _ReadWriteBarrier()
  40. # else /* GCC/Clang */
  41. # define UA_atomic_sync() __sync_synchronize()
  42. # endif
  43. #endif
  44. static UA_INLINE void *
  45. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  46. #ifndef UA_ENABLE_MULTITHREADING
  47. void *old = *addr;
  48. *addr = newptr;
  49. return old;
  50. #else
  51. # ifdef _MSC_VER /* Visual Studio */
  52. return _InterlockedExchangePointer(addr, newptr);
  53. # else /* GCC/Clang */
  54. return __sync_lock_test_and_set(addr, newptr);
  55. # endif
  56. #endif
  57. }
  58. static UA_INLINE void *
  59. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  60. #ifndef UA_ENABLE_MULTITHREADING
  61. void *old = *addr;
  62. if(old == expected) {
  63. *addr = newptr;
  64. }
  65. return old;
  66. #else
  67. # ifdef _MSC_VER /* Visual Studio */
  68. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  69. # else /* GCC/Clang */
  70. return __sync_val_compare_and_swap(addr, expected, newptr);
  71. # endif
  72. #endif
  73. }
  74. static UA_INLINE uint32_t
  75. UA_atomic_add(volatile uint32_t *addr, uint32_t increase) {
  76. #ifndef UA_ENABLE_MULTITHREADING
  77. *addr += increase;
  78. return *addr;
  79. #else
  80. # ifdef _MSC_VER /* Visual Studio */
  81. return _InterlockedExchangeAdd(addr, increase) + increase;
  82. # else /* GCC/Clang */
  83. return __sync_add_and_fetch(addr, increase);
  84. # endif
  85. #endif
  86. }
  87. #endif /* UA_UTIL_H_ */