ua_util.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. *
  5. * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2014, 2017 (c) Florian Palm
  7. * Copyright 2015 (c) LEvertz
  8. * Copyright 2015-2016 (c) Sten Grüner
  9. * Copyright 2015 (c) Chris Iatrou
  10. * Copyright 2015-2016 (c) Oleksiy Vasylyev
  11. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  12. */
  13. #ifndef UA_UTIL_H_
  14. #define UA_UTIL_H_
  15. #include "ua_types.h"
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif
  19. /* BSD Queue Macros */
  20. #include "../deps/queue.h"
  21. /* Macro-Expand for MSVC workarounds */
  22. #define UA_MACRO_EXPAND(x) x
  23. /* Thread-Local Storage
  24. * --------------------
  25. * Thread-local storage is not required by the main library functionality. It is
  26. * only used for some testing strategies. ``UA_THREAD_LOCAL`` is empty if the
  27. * feature is not available. */
  28. #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
  29. # define UA_THREAD_LOCAL _Thread_local /* C11 */
  30. #elif defined(__cplusplus) && __cplusplus > 199711L
  31. # define UA_THREAD_LOCAL thread_local /* C++11 */
  32. #elif defined(__GNUC__)
  33. # define UA_THREAD_LOCAL __thread /* GNU extension */
  34. #elif defined(_MSC_VER)
  35. # define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
  36. #else
  37. # define UA_THREAD_LOCAL
  38. #endif
  39. /* Integer Shortnames
  40. * ------------------
  41. * These are not exposed on the public API, since many user-applications make
  42. * the same definitions in their headers. */
  43. typedef UA_Byte u8;
  44. typedef UA_SByte i8;
  45. typedef UA_UInt16 u16;
  46. typedef UA_Int16 i16;
  47. typedef UA_UInt32 u32;
  48. typedef UA_Int32 i32;
  49. typedef UA_UInt64 u64;
  50. typedef UA_Int64 i64;
  51. typedef UA_StatusCode status;
  52. /* Atomic Operations
  53. * -----------------
  54. * Atomic operations that synchronize across processor cores (for
  55. * multithreading). Only the inline-functions defined next are used. Replace
  56. * with architecture-specific operations if necessary. */
  57. #ifndef UA_ENABLE_MULTITHREADING
  58. # define UA_atomic_sync()
  59. #else
  60. # ifdef _MSC_VER /* Visual Studio */
  61. # define UA_atomic_sync() _ReadWriteBarrier()
  62. # else /* GCC/Clang */
  63. # define UA_atomic_sync() __sync_synchronize()
  64. # endif
  65. #endif
  66. static UA_INLINE void *
  67. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  68. #ifndef UA_ENABLE_MULTITHREADING
  69. void *old = *addr;
  70. *addr = newptr;
  71. return old;
  72. #else
  73. # ifdef _MSC_VER /* Visual Studio */
  74. return _InterlockedExchangePointer(addr, newptr);
  75. # else /* GCC/Clang */
  76. return __sync_lock_test_and_set(addr, newptr);
  77. # endif
  78. #endif
  79. }
  80. static UA_INLINE void *
  81. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  82. #ifndef UA_ENABLE_MULTITHREADING
  83. void *old = *addr;
  84. if(old == expected) {
  85. *addr = newptr;
  86. }
  87. return old;
  88. #else
  89. # ifdef _MSC_VER /* Visual Studio */
  90. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  91. # else /* GCC/Clang */
  92. return __sync_val_compare_and_swap(addr, expected, newptr);
  93. # endif
  94. #endif
  95. }
  96. static UA_INLINE uint32_t
  97. UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
  98. #ifndef UA_ENABLE_MULTITHREADING
  99. *addr += increase;
  100. return *addr;
  101. #else
  102. # ifdef _MSC_VER /* Visual Studio */
  103. return _InterlockedExchangeAdd(addr, increase) + increase;
  104. # else /* GCC/Clang */
  105. return __sync_add_and_fetch(addr, increase);
  106. # endif
  107. #endif
  108. }
  109. static UA_INLINE size_t
  110. UA_atomic_addSize(volatile size_t *addr, size_t increase) {
  111. #ifndef UA_ENABLE_MULTITHREADING
  112. *addr += increase;
  113. return *addr;
  114. #else
  115. # ifdef _MSC_VER /* Visual Studio */
  116. return _InterlockedExchangeAdd(addr, increase) + increase;
  117. # else /* GCC/Clang */
  118. return __sync_add_and_fetch(addr, increase);
  119. # endif
  120. #endif
  121. }
  122. static UA_INLINE uint32_t
  123. UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
  124. #ifndef UA_ENABLE_MULTITHREADING
  125. *addr -= decrease;
  126. return *addr;
  127. #else
  128. # ifdef _MSC_VER /* Visual Studio */
  129. return _InterlockedExchangeSub(addr, decrease) - decrease;
  130. # else /* GCC/Clang */
  131. return __sync_sub_and_fetch(addr, decrease);
  132. # endif
  133. #endif
  134. }
  135. static UA_INLINE size_t
  136. UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
  137. #ifndef UA_ENABLE_MULTITHREADING
  138. *addr -= decrease;
  139. return *addr;
  140. #else
  141. # ifdef _MSC_VER /* Visual Studio */
  142. return _InterlockedExchangeSub(addr, decrease) - decrease;
  143. # else /* GCC/Clang */
  144. return __sync_sub_and_fetch(addr, decrease);
  145. # endif
  146. #endif
  147. }
  148. /* Utility Functions
  149. * ----------------- */
  150. /* Convert given byte string to a positive number. Returns the number of valid
  151. * digits. Stops if a non-digit char is found and returns the number of digits
  152. * up to that point. */
  153. size_t UA_readNumber(u8 *buf, size_t buflen, u32 *number);
  154. #define MIN(A,B) (A > B ? B : A)
  155. #define MAX(A,B) (A > B ? A : B)
  156. #ifdef UA_DEBUG_DUMP_PKGS
  157. void UA_EXPORT UA_dump_hex_pkg(UA_Byte* buffer, size_t bufferLen);
  158. #endif
  159. #ifdef __cplusplus
  160. } // extern "C"
  161. #endif
  162. #endif /* UA_UTIL_H_ */