ua_util_internal.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. #define UA_INTERNAL
  16. #include "ua_types.h"
  17. #include "../deps/queue.h"
  18. _UA_BEGIN_DECLS
  19. /* Macro-Expand for MSVC workarounds */
  20. #define UA_MACRO_EXPAND(x) x
  21. /* Integer Shortnames
  22. * ------------------
  23. * These are not exposed on the public API, since many user-applications make
  24. * the same definitions in their headers. */
  25. typedef UA_Byte u8;
  26. typedef UA_SByte i8;
  27. typedef UA_UInt16 u16;
  28. typedef UA_Int16 i16;
  29. typedef UA_UInt32 u32;
  30. typedef UA_Int32 i32;
  31. typedef UA_UInt64 u64;
  32. typedef UA_Int64 i64;
  33. typedef UA_StatusCode status;
  34. /* Atomic Operations
  35. * -----------------
  36. * Atomic operations that synchronize across processor cores (for
  37. * multithreading). Only the inline-functions defined next are used. Replace
  38. * with architecture-specific operations if necessary. */
  39. #ifndef UA_ENABLE_MULTITHREADING
  40. # define UA_atomic_sync()
  41. #else
  42. # ifdef _MSC_VER /* Visual Studio */
  43. # define UA_atomic_sync() _ReadWriteBarrier()
  44. # else /* GCC/Clang */
  45. # define UA_atomic_sync() __sync_synchronize()
  46. # endif
  47. #endif
  48. static UA_INLINE void *
  49. UA_atomic_xchg(void * volatile * addr, void *newptr) {
  50. #ifndef UA_ENABLE_MULTITHREADING
  51. void *old = *addr;
  52. *addr = newptr;
  53. return old;
  54. #else
  55. # ifdef _MSC_VER /* Visual Studio */
  56. return _InterlockedExchangePointer(addr, newptr);
  57. # else /* GCC/Clang */
  58. return __sync_lock_test_and_set(addr, newptr);
  59. # endif
  60. #endif
  61. }
  62. static UA_INLINE void *
  63. UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
  64. #ifndef UA_ENABLE_MULTITHREADING
  65. void *old = *addr;
  66. if(old == expected) {
  67. *addr = newptr;
  68. }
  69. return old;
  70. #else
  71. # ifdef _MSC_VER /* Visual Studio */
  72. return _InterlockedCompareExchangePointer(addr, expected, newptr);
  73. # else /* GCC/Clang */
  74. return __sync_val_compare_and_swap(addr, expected, newptr);
  75. # endif
  76. #endif
  77. }
  78. static UA_INLINE uint32_t
  79. UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
  80. #ifndef UA_ENABLE_MULTITHREADING
  81. *addr += increase;
  82. return *addr;
  83. #else
  84. # ifdef _MSC_VER /* Visual Studio */
  85. return _InterlockedExchangeAdd(addr, increase) + increase;
  86. # else /* GCC/Clang */
  87. return __sync_add_and_fetch(addr, increase);
  88. # endif
  89. #endif
  90. }
  91. static UA_INLINE size_t
  92. UA_atomic_addSize(volatile size_t *addr, size_t increase) {
  93. #ifndef UA_ENABLE_MULTITHREADING
  94. *addr += increase;
  95. return *addr;
  96. #else
  97. # ifdef _MSC_VER /* Visual Studio */
  98. return _InterlockedExchangeAdd(addr, increase) + increase;
  99. # else /* GCC/Clang */
  100. return __sync_add_and_fetch(addr, increase);
  101. # endif
  102. #endif
  103. }
  104. static UA_INLINE uint32_t
  105. UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
  106. #ifndef UA_ENABLE_MULTITHREADING
  107. *addr -= decrease;
  108. return *addr;
  109. #else
  110. # ifdef _MSC_VER /* Visual Studio */
  111. return _InterlockedExchangeSub(addr, decrease) - decrease;
  112. # else /* GCC/Clang */
  113. return __sync_sub_and_fetch(addr, decrease);
  114. # endif
  115. #endif
  116. }
  117. static UA_INLINE size_t
  118. UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
  119. #ifndef UA_ENABLE_MULTITHREADING
  120. *addr -= decrease;
  121. return *addr;
  122. #else
  123. # ifdef _MSC_VER /* Visual Studio */
  124. return _InterlockedExchangeSub(addr, decrease) - decrease;
  125. # else /* GCC/Clang */
  126. return __sync_sub_and_fetch(addr, decrease);
  127. # endif
  128. #endif
  129. }
  130. /* Utility Functions
  131. * ----------------- */
  132. /* Convert given byte string to a positive number. Returns the number of valid
  133. * digits. Stops if a non-digit char is found and returns the number of digits
  134. * up to that point. */
  135. size_t UA_readNumber(u8 *buf, size_t buflen, u32 *number);
  136. /* Same as UA_ReadNumber but with a base parameter */
  137. size_t UA_readNumberWithBase(u8 *buf, size_t buflen, u32 *number, u8 base);
  138. #ifndef UA_MIN
  139. #define UA_MIN(A,B) (A > B ? B : A)
  140. #endif
  141. #ifndef UA_MAX
  142. #define UA_MAX(A,B) (A > B ? A : B)
  143. #endif
  144. #ifdef UA_DEBUG_DUMP_PKGS
  145. void UA_EXPORT UA_dump_hex_pkg(UA_Byte* buffer, size_t bufferLen);
  146. #endif
  147. _UA_END_DECLS
  148. #endif /* UA_UTIL_H_ */