ua_util.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. /* container_of */
  16. #define container_of(ptr, type, member) \
  17. (type *)((uintptr_t)ptr - offsetof(type,member))
  18. /* Thread Local Storage */
  19. #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
  20. # define UA_THREAD_LOCAL _Thread_local /* C11 */
  21. #elif defined(__GNUC__)
  22. # define UA_THREAD_LOCAL __thread /* GNU extension */
  23. #elif defined(_MSC_VER)
  24. # define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
  25. #else
  26. # define UA_THREAD_LOCAL
  27. # warning The compiler does not allow thread-local variables. \
  28. The library can be built, but will not be thread-safe.
  29. #endif
  30. /* Integer Shortnames
  31. * ------------------
  32. * These are not exposed on the public API, since many user-applications make
  33. * the same definitions in their headers. */
  34. typedef UA_Byte u8;
  35. typedef UA_SByte i8;
  36. typedef UA_UInt16 u16;
  37. typedef UA_Int16 i16;
  38. typedef UA_UInt32 u32;
  39. typedef UA_Int32 i32;
  40. typedef UA_UInt64 u64;
  41. typedef UA_Int64 i64;
  42. /* Atomic Operations
  43. * -----------------
  44. * Atomic operations that synchronize across processor cores (for
  45. * multithreading). Only the inline-functions defined next are used. Replace
  46. * with architecture-specific operations if necessary. */
  47. #ifndef UA_ENABLE_MULTITHREADING
  48. # define UA_atomic_sync()
  49. #else
  50. # ifdef _MSC_VER /* Visual Studio */
  51. # define UA_atomic_sync() _ReadWriteBarrier()
  52. # else /* GCC/Clang */
  53. # define UA_atomic_sync() __sync_synchronize()
  54. # endif
  55. #endif
  56. static UA_INLINE void *
  57. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  58. #ifndef UA_ENABLE_MULTITHREADING
  59. void *old = *addr;
  60. *addr = newptr;
  61. return old;
  62. #else
  63. # ifdef _MSC_VER /* Visual Studio */
  64. return _InterlockedExchangePointer(addr, newptr);
  65. # else /* GCC/Clang */
  66. return __sync_lock_test_and_set(addr, newptr);
  67. # endif
  68. #endif
  69. }
  70. static UA_INLINE void *
  71. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  72. #ifndef UA_ENABLE_MULTITHREADING
  73. void *old = *addr;
  74. if(old == expected) {
  75. *addr = newptr;
  76. }
  77. return old;
  78. #else
  79. # ifdef _MSC_VER /* Visual Studio */
  80. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  81. # else /* GCC/Clang */
  82. return __sync_val_compare_and_swap(addr, expected, newptr);
  83. # endif
  84. #endif
  85. }
  86. static UA_INLINE uint32_t
  87. UA_atomic_add(volatile uint32_t *addr, uint32_t increase) {
  88. #ifndef UA_ENABLE_MULTITHREADING
  89. *addr += increase;
  90. return *addr;
  91. #else
  92. # ifdef _MSC_VER /* Visual Studio */
  93. return _InterlockedExchangeAdd(addr, increase) + increase;
  94. # else /* GCC/Clang */
  95. return __sync_add_and_fetch(addr, increase);
  96. # endif
  97. #endif
  98. }
  99. /* Utility Functions
  100. * ----------------- */
  101. /* Convert given byte string to a positive number. Returns the number of valid
  102. * digits. Stops if a non-digit char is found and returns the number of digits
  103. * up to that point. */
  104. size_t UA_readNumber(u8 *buf, size_t buflen, u32 *number);
  105. #define MIN(A,B) (A > B ? B : A)
  106. #define MAX(A,B) (A > B ? A : B)
  107. /* The typename string can be disabled to safe memory */
  108. #ifdef UA_ENABLE_TYPENAMES
  109. # define UA_TYPENAME(name) name,
  110. #else
  111. # define UA_TYPENAME(name)
  112. #endif
  113. #ifdef __cplusplus
  114. } // extern "C"
  115. #endif
  116. #endif /* UA_UTIL_H_ */