ua_util.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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_types.h"
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /* Assert */
  11. #include <assert.h>
  12. #define UA_assert(ignore) assert(ignore)
  13. /* BSD Queue Macros */
  14. #include "queue.h"
  15. /* C++ Access to datatypes defined inside structs (for queue.h) */
  16. #ifdef __cplusplus
  17. # define memberstruct(container,member) container::member
  18. #else
  19. # define memberstruct(container,member) member
  20. #endif
  21. /* container_of */
  22. #define container_of(ptr, type, member) \
  23. (type *)((uintptr_t)ptr - offsetof(type,member))
  24. /* Thread Local Storage */
  25. #ifdef UA_ENABLE_MULTITHREADING
  26. # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
  27. # define UA_THREAD_LOCAL _Thread_local /* C11 */
  28. # elif defined(__GNUC__)
  29. # define UA_THREAD_LOCAL __thread /* GNU extension */
  30. # elif defined(_MSC_VER)
  31. # define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
  32. # else
  33. # warning The compiler does not allow thread-local variables. \
  34. The library can be built, but will not be thread-safe.
  35. # endif
  36. #endif
  37. #ifndef UA_THREAD_LOCAL
  38. # define UA_THREAD_LOCAL
  39. #endif
  40. /* Atomic Operations
  41. * -----------------
  42. * Atomic operations that synchronize across processor cores (for
  43. * multithreading). Only the inline-functions defined next are used. Replace
  44. * with architecture-specific operations if necessary. */
  45. #ifndef UA_ENABLE_MULTITHREADING
  46. # define UA_atomic_sync()
  47. #else
  48. # ifdef _MSC_VER /* Visual Studio */
  49. # define UA_atomic_sync() _ReadWriteBarrier()
  50. # else /* GCC/Clang */
  51. # define UA_atomic_sync() __sync_synchronize()
  52. # endif
  53. #endif
  54. static UA_INLINE void *
  55. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  56. #ifndef UA_ENABLE_MULTITHREADING
  57. void *old = *addr;
  58. *addr = newptr;
  59. return old;
  60. #else
  61. # ifdef _MSC_VER /* Visual Studio */
  62. return _InterlockedExchangePointer(addr, newptr);
  63. # else /* GCC/Clang */
  64. return __sync_lock_test_and_set(addr, newptr);
  65. # endif
  66. #endif
  67. }
  68. static UA_INLINE void *
  69. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  70. #ifndef UA_ENABLE_MULTITHREADING
  71. void *old = *addr;
  72. if(old == expected) {
  73. *addr = newptr;
  74. }
  75. return old;
  76. #else
  77. # ifdef _MSC_VER /* Visual Studio */
  78. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  79. # else /* GCC/Clang */
  80. return __sync_val_compare_and_swap(addr, expected, newptr);
  81. # endif
  82. #endif
  83. }
  84. static UA_INLINE uint32_t
  85. UA_atomic_add(volatile uint32_t *addr, uint32_t increase) {
  86. #ifndef UA_ENABLE_MULTITHREADING
  87. *addr += increase;
  88. return *addr;
  89. #else
  90. # ifdef _MSC_VER /* Visual Studio */
  91. return _InterlockedExchangeAdd(addr, increase) + increase;
  92. # else /* GCC/Clang */
  93. return __sync_add_and_fetch(addr, increase);
  94. # endif
  95. #endif
  96. }
  97. /* Utility Functions
  98. * ----------------- */
  99. /* Convert given byte string to a positive number. Returns the number of valid
  100. * digits. Stops if a non-digit char is found and returns the number of digits
  101. * up to that point. */
  102. size_t UA_readNumber(UA_Byte *buf, size_t buflen, UA_UInt32 *number);
  103. #ifdef __cplusplus
  104. } // extern "C"
  105. #endif
  106. #endif /* UA_UTIL_H_ */