open62541 1.3.12
Open source implementation of OPC UA
Loading...
Searching...
No Matches
architecture_definitions.h
Go to the documentation of this file.
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 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
7 * Copyright 2018 (c) Jose Cabral, fortiss GmbH
8 */
9
10#ifndef ARCH_UA_ARCHITECTURE_DEFINITIONS_H_
11#define ARCH_UA_ARCHITECTURE_DEFINITIONS_H_
12
13#include <open62541/config.h>
14
15
16#include <string.h>
17#include <stddef.h>
18
19/** Include stdint.h and stdbool.h or workaround for older Visual Studios */
20#ifdef UNDER_CE
21# include "stdint.h"
22#endif
23#if !defined(_MSC_VER) || _MSC_VER >= 1800
24# include <stdint.h>
25# include <stdbool.h> /* C99 Boolean */
26#else
27# include "ms_stdint.h"
28# if !defined(__bool_true_false_are_defined)
29# define bool unsigned char
30# define true 1
31# define false 0
32# define __bool_true_false_are_defined
33# endif
34#endif
35
36/** Include inttypes.h or workaround for older Visual Studios */
37#if !defined(_MSC_VER) || _MSC_VER >= 1800
38# include <inttypes.h>
39#else
40# define __PRI_8_LENGTH_MODIFIER__ "hh"
41# define __PRI_64_LENGTH_MODIFIER__ "ll"
42
43# define PRId8 __PRI_8_LENGTH_MODIFIER__ "d"
44# define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i"
45# define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o"
46# define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u"
47# define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x"
48# define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X"
49
50# define PRId16 "hd"
51# define PRIi16 "hi"
52# define PRIo16 "ho"
53# define PRIu16 "hu"
54# define PRIx16 "hx"
55# define PRIX16 "hX"
56
57# define PRId32 "ld"
58# define PRIi32 "li"
59# define PRIo32 "lo"
60# define PRIu32 "lu"
61# define PRIx32 "lx"
62# define PRIX32 "lX"
63
64# define PRId64 __PRI_64_LENGTH_MODIFIER__ "d"
65# define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i"
66# define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o"
67# define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u"
68# define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x"
69# define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X"
70#endif
71
72
73#if UA_MULTITHREADING >= 100
74# if defined(__GNUC__) /* Also covers clang */
75# define UA_THREAD_LOCAL __thread
76# elif defined(_MSC_VER)
77# define UA_THREAD_LOCAL __declspec(thread)
78# endif
79#endif
80#ifndef UA_THREAD_LOCAL
81# define UA_THREAD_LOCAL
82#endif
83
84
85
86#ifdef UA_ENABLE_MALLOC_SINGLETON
87extern UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size);
88extern UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr);
89extern UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize);
90extern UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size);
91# define UA_malloc(size) UA_mallocSingleton(size)
92# define UA_free(ptr) UA_freeSingleton(ptr)
93# define UA_calloc(num, size) UA_callocSingleton(num, size)
94# define UA_realloc(ptr, size) UA_reallocSingleton(ptr, size)
95#endif
96
97/** Stack-allocation of memory. Use C99 variable-length arrays if possible.
98 * Otherwise revert to alloca. Note that alloca is not supported on some
99 * plattforms. */
100#ifndef UA_STACKARRAY
101# if defined(__GNUC__) || defined(__clang__)
102# define UA_STACKARRAY(TYPE, NAME, SIZE) TYPE NAME[SIZE]
103# else
104# if defined(__GNUC__) || defined(__clang__)
105# define UA_alloca(size) __builtin_alloca (size)
106# elif defined(_WIN32)
107# define UA_alloca(SIZE) _alloca(SIZE)
108# else
109# include <alloca.h>
110# define UA_alloca(SIZE) alloca(SIZE)
111# endif
112# define UA_STACKARRAY(TYPE, NAME, SIZE) \
113 /* cppcheck-suppress allocaCalled */ \
114 TYPE *(NAME) = (TYPE*)UA_alloca(sizeof(TYPE) * (SIZE))
115# endif
116#endif
117
118
119#ifdef UA_DEBUG
120# include <assert.h>
121# define UA_assert(ignore) assert(ignore)
122#else
123# define UA_assert(ignore) do {} while(0)
124#endif
125
126/** Outputs an error message at compile time if the assert fails.
127 * Example usage:
128 * UA_STATIC_ASSERT(sizeof(long)==7, use_another_compiler_luke)
129 * See: https://stackoverflow.com/a/4815532/869402 */
130#if defined(__cplusplus) && __cplusplus >= 201103L /* C++11 or above */
131# define UA_STATIC_ASSERT(cond,msg) static_assert(cond, #msg)
132#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L /* C11 or above */
133# define UA_STATIC_ASSERT(cond,msg) _Static_assert(cond, #msg)
134#elif defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) /* GCC, Clang, MSC */
135# define UA_CTASTR2(pre,post) pre ## post
136# define UA_CTASTR(pre,post) UA_CTASTR2(pre,post)
137# ifndef __COUNTER__ /* PPC GCC fix */
138# define __COUNTER__ __LINE__
139# endif
140# define UA_STATIC_ASSERT(cond,msg) \
141 typedef struct { \
142 int UA_CTASTR(static_assertion_failed_,msg) : !!(cond); \
143 } UA_CTASTR(static_assertion_failed_,__COUNTER__)
144#else /* Everybody else */
145# define UA_STATIC_ASSERT(cond,msg) typedef char static_assertion_##msg[(cond)?1:-1]
146#endif
147
148
149#if defined(_WIN32) && defined(UA_DYNAMIC_LINKING)
150# ifdef UA_DYNAMIC_LINKING_EXPORT /* export dll */
151# ifdef __GNUC__
152# define __attribute__ ((dllexport))
153# else
154# define __declspec(dllexport)
155# endif
156# else /* import dll */
157# ifdef __GNUC__
158# define __attribute__ ((dllimport))
159# else
160# define __declspec(dllimport)
161# endif
162# endif
163#else /* non win32 */
164# if __GNUC__ || __clang__
165# define __attribute__ ((visibility ("default")))
166# endif
167#endif
168#ifndef
169# define /* fallback to default */
170#endif
171
172
173#define UA_THREADSAFE
174
175
176#ifdef _MSC_VER
177# define __inline
178#else
179# define inline
180#endif
181
182
183#ifdef _MSC_VER
184# define__restrict
185#elif defined(__GNUC__)
186# define__restrict__
187#elif defined(__CODEGEARC__)
188# define_RESTRICT
189#else
190# definerestrict
191#endif
192
193
194#if defined(__GNUC__) || defined(__clang__)
195# define UA_LIKELY(x) __builtin_expect((x), 1)
196# define UA_UNLIKELY(x) __builtin_expect((x), 0)
197#else
198# define UA_LIKELY(x) x
199# define UA_UNLIKELY(x) x
200#endif
201
202
203#if defined(__GNUC__) || defined(__clang__)
204# define __attribute__((malloc))
205# define UA_FUNC_ATTR_PURE __attribute__ ((pure))
206# define UA_FUNC_ATTR_CONST __attribute__((const))
207# define __attribute__((warn_unused_result))
208# define UA_FORMAT(X,Y) __attribute__ ((format (printf, X, Y)))
209#elif defined(_MSC_VER) && _MSC_VER >= 1800
210# include <sal.h>
211# define
212# define UA_FUNC_ATTR_PURE
213# define UA_FUNC_ATTR_CONST
214# define _Check_return_
215# define UA_FORMAT(X,Y)
216#else
217# define
218# define UA_FUNC_ATTR_PURE
219# define UA_FUNC_ATTR_CONST
220# define
221# define UA_FORMAT(X,Y)
222#endif
223
224#if defined(__GNUC__) || defined(__clang__)
225# define UA_DEPRECATED __attribute__((deprecated))
226#elif defined(_MSC_VER)
227# define UA_DEPRECATED __declspec(deprecated)
228#else
229# define UA_DEPRECATED
230#endif
231
232
233
234#if defined(UA_INTERNAL) && (defined(__GNUC__) || defined(__clang__))
235# define UA_INTERNAL_DEPRECATED \
236 _Pragma ("GCC warning \"Macro is deprecated for internal use\"")
237#else
238# define UA_INTERNAL_DEPRECATED
239#endif
240
241#if defined(UA_INTERNAL) && (defined(__GNUC__) || defined(__clang__))
242# define UA_INTERNAL_FUNC_ATTR_WARN_UNUSED_RESULT \
243 __attribute__((warn_unused_result))
244#else
245# define UA_INTERNAL_FUNC_ATTR_WARN_UNUSED_RESULT
246#endif
247
248
249#if defined(_WIN32)
250# define UA_LITTLE_ENDIAN 1
251#elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__)
252# define UA_LITTLE_ENDIAN 1
253#elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
254 (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
255# define UA_LITTLE_ENDIAN 1
256#elif defined(__linux__) /* Linux (including Android) */
257# include <endian.h>
258# if __BYTE_ORDER == __LITTLE_ENDIAN
259# define UA_LITTLE_ENDIAN 1
260# endif
261#elif defined(__OpenBSD__) /* OpenBSD */
262# include <sys/endian.h>
263# if BYTE_ORDER == LITTLE_ENDIAN
264# define UA_LITTLE_ENDIAN 1
265# endif
266#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) /* Other BSD */
267# include <sys/endian.h>
268# if _BYTE_ORDER == _LITTLE_ENDIAN
269# define UA_LITTLE_ENDIAN 1
270# endif
271#elif defined(__APPLE__) /* Apple (MacOS, iOS) */
272# include <libkern/OSByteOrder.h>
273# if defined(__LITTLE_ENDIAN__)
274# define UA_LITTLE_ENDIAN 1
275# endif
276#elif defined(__QNX__) || defined(__QNXNTO__) /* QNX */
277# include <gulliver.h>
278# if defined(__LITTLEENDIAN__)
279# define UA_LITTLE_ENDIAN 1
280# endif
281#elif defined(_OS9000) /* OS-9 */
282# if defined(_LIL_END)
283# define UA_LITTLE_ENDIAN 1
284# endif
285#endif
286#ifndef UA_LITTLE_ENDIAN
287# define UA_LITTLE_ENDIAN 0
288#endif
289
290/** Can the integers be memcpy'd onto the network buffer? Add additional checks
291 * here. Some platforms (e.g. QNX) have sizeof(bool) > 1. Manually disable
292 * overlayed integer encoding if that is the case. */
293#if (UA_LITTLE_ENDIAN == 1)
294UA_STATIC_ASSERT(sizeof(bool) == 1, cannot_overlay_integers_with_large_bool);
295# define UA_BINARY_OVERLAYABLE_INTEGER 1
296#else
297# define UA_BINARY_OVERLAYABLE_INTEGER 0
298#endif
299
300
301#ifndef UA_FLOAT_IEEE754
302#if defined(_WIN32)
303# define UA_FLOAT_IEEE754 1
304#elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \
305 defined(__ia64__) || defined(__powerpc__) || defined(__sparc__) || \
306 defined(__arm__)
307# define UA_FLOAT_IEEE754 1
308#elif defined(__STDC_IEC_559__)
309# define UA_FLOAT_IEEE754 1
310#elif defined(ESP_PLATFORM)
311# define UA_FLOAT_IEEE754 1
312#else
313# define UA_FLOAT_IEEE754 0
314#endif
315#endif
316
317/** Wikipedia says (https://en.wikipedia.org/wiki/Endianness): Although the
318 * ubiquitous x86 processors of today use little-endian storage for all types of
319 * data (integer, floating point, BCD), there are a number of hardware
320 * architectures where floating-point numbers are represented in big-endian form
321 * while integers are represented in little-endian form. */
322#if defined(_WIN32)
323# define UA_FLOAT_LITTLE_ENDIAN 1
324#elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__)
325# define UA_FLOAT_LITTLE_ENDIAN 1
326#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
327 (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__) /* Defined only in GCC */
328# define UA_FLOAT_LITTLE_ENDIAN 1
329#elif defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && \
330 (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) /* Defined only in GCC */
331# define UA_FLOAT_LITTLE_ENDIAN 1
332#endif
333#ifndef UA_FLOAT_LITTLE_ENDIAN
334# define UA_FLOAT_LITTLE_ENDIAN 0
335#endif
336
337/** Only if the floating points are litle-endian **and** in IEEE 754 format can
338 * we memcpy directly onto the network buffer. */
339#if (UA_FLOAT_IEEE754 == 1) && (UA_FLOAT_LITTLE_ENDIAN == 1)
340# define UA_BINARY_OVERLAYABLE_FLOAT 1
341#else
342# define UA_BINARY_OVERLAYABLE_FLOAT 0
343#endif
344
345/** Atomic Operations
346 * -----------------
347 * Atomic operations that synchronize across processor cores (for
348 * multithreading). Only the inline-functions defined next are used. Replace
349 * with architecture-specific operations if necessary. */
350#if UA_MULTITHREADING >= 100
351 #ifdef _MSC_VER /* Visual Studio */
352 #define UA_atomic_sync() _ReadWriteBarrier()
353 #else /* GCC/Clang */
354 #define UA_atomic_sync() __sync_synchronize()
355 #endif
356#else
357 #define UA_atomic_sync()
358#endif
359
360/** Intrinsic atomic operations are not available everywhere for MSVC.
361 * Use the win32 API. Prevent duplicate definitions by winsock2. */
362#if UA_MULTITHREADING >= 100 && defined(_WIN32)
363#ifndef _WINSOCKAPI_
364#define _NO_WINSOCKAPI_
365#endif
366#define _WINSOCKAPI_
367#include <windows.h>
368#ifdef _NO_WINSOCKAPI_
369#undef _WINSOCKAPI_
370#endif
371#endif
372
373static void *
374UA_atomic_xchg(void * volatile * addr, void *newptr) {
375#if UA_MULTITHREADING >= 100
376#ifdef _MSC_VER /* Visual Studio */
377 return InterlockedExchangePointer(addr, newptr);
378#else /* GCC/Clang */
379 return __sync_lock_test_and_set(addr, newptr);
380#endif
381#else
382 void *old = *addr;
383 *addr = newptr;
384 return old;
385#endif
386}
387
388static void *
389UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
390#if UA_MULTITHREADING >= 100
391#ifdef _MSC_VER /* Visual Studio */
392 return InterlockedCompareExchangePointer(addr, newptr, expected);
393#else /* GCC/Clang */
394 return __sync_val_compare_and_swap(addr, expected, newptr);
395#endif
396#else
397 void *old = *addr;
398 if(old == expected) {
399 *addr = newptr;
400 }
401 return old;
402#endif
403}
404
405static uint32_t
406UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
407#if UA_MULTITHREADING >= 100
408#ifdef _MSC_VER /* Visual Studio */
409 return InterlockedExchangeAdd(addr, increase) + increase;
410#else /* GCC/Clang */
411 return __sync_add_and_fetch(addr, increase);
412#endif
413#else
414 uint32_t accu = *addr;
415 accu += increase;
416 *addr = accu;
417 return accu;
418#endif
419}
420
421static size_t
422UA_atomic_addSize(volatile size_t *addr, size_t increase) {
423#if UA_MULTITHREADING >= 100
424#ifdef _MSC_VER /* Visual Studio */
425 return InterlockedExchangeAdd((volatile LONG *)addr, (LONG)increase) + increase;
426#else /* GCC/Clang */
427 return __sync_add_and_fetch(addr, increase);
428#endif
429#else
430 size_t accu = *addr;
431 accu += increase;
432 *addr = accu;
433 return accu;
434#endif
435}
436
437static uint32_t
438UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
439#if UA_MULTITHREADING >= 100
440#ifdef _MSC_VER /* Visual Studio */
441 return InterlockedExchangeAdd(addr, - (LONG) decrease) - decrease;
442#else /* GCC/Clang */
443 return __sync_sub_and_fetch(addr, decrease);
444#endif
445#else
446 uint32_t accu = *addr;
447 accu -= decrease;
448 *addr = accu;
449 return accu;
450#endif
451}
452
453static size_t
454UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
455#if UA_MULTITHREADING >= 100
456#ifdef _MSC_VER /* Visual Studio */
457 return InterlockedExchangeAdd((volatile LONG *)addr, -(LONG)decrease) - decrease;
458#else /* GCC/Clang */
459 return __sync_sub_and_fetch(addr, decrease);
460#endif
461#else
462 size_t accu = *addr;
463 accu -= decrease;
464 *addr = accu;
465 return accu;
466#endif
467}
468
469#endif /* ARCH_UA_ARCHITECTURE_DEFINITIONS_H_ */
#define UA_STATIC_ASSERT(cond, msg)
Outputs an error message at compile time if the assert fails.
#define UA_THREAD_LOCAL
This Source Code Form is subject to the terms of the Mozilla Public License, v.