1 /*
2  * Copyright (c) 2014-2017, Siemens AG. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifndef EMBB_BASE_C_INTERNAL_ATOMIC_LOAD_H_
28 #define EMBB_BASE_C_INTERNAL_ATOMIC_LOAD_H_
29 
30 #ifndef DOXYGEN
31 
32 /*
33 * See file and_assign.h for a detailed (and operation independent) description
34 * of the following macro.
35 */
36 #ifdef EMBB_PLATFORM_ARCH_X86
37 
38 #ifdef EMBB_PLATFORM_COMPILER_MSVC
39 #define EMBB_DEFINE_LOAD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \
40   extern EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) __fastcall EMBB_CAT2(embb_internal__atomic_load_, EMBB_PARAMETER_SIZE_BYTE)_asm( \
41   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value); \
42   EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) __fastcall EMBB_CAT2(embb_internal__atomic_load_, EMBB_PARAMETER_SIZE_BYTE)(\
43   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value) { \
44   register EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) result; \
45   _ReadWriteBarrier(); \
46   result = EMBB_CAT2(embb_internal__atomic_load_, \
47   EMBB_PARAMETER_SIZE_BYTE)_asm(pointer_to_value); \
48   _ReadWriteBarrier(); \
49   return result; \
50   }
51 #elif defined(EMBB_PLATFORM_COMPILER_GNUC)
52 #define EMBB_DEFINE_LOAD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \
53   EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) \
54   EMBB_CAT2(embb_internal__atomic_load_, EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value) { \
55   /* no fence required for loads */ \
56   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) result; \
57   __asm__ __volatile__("mov" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
58   : "=q" (result) \
59   : "m" (*pointer_to_value) \
60   : "memory"); \
61   return result; \
62   }
63 #else
64 #error "No atomic fetch and store implementation found"
65 #endif
66 
67 /*
68 * The three or four macro calls below generate the methods for 1, 2, 4, and
69 * bytes, as stated in the macro definition.
70 */
71 EMBB_DEFINE_LOAD(1, "b")
72 EMBB_DEFINE_LOAD(2, "w")
73 EMBB_DEFINE_LOAD(4, "l")
74 #ifdef EMBB_64_BIT_ATOMIC_AVAILABLE
75 EMBB_DEFINE_LOAD(8, "q")
76 #endif
77 
78 #elif defined(EMBB_PLATFORM_ARCH_ARM)
79 
80 #if defined(EMBB_PLATFORM_COMPILER_GNUC)
81 #define EMBB_DEFINE_LOAD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_ARM_SIZE_SUFFIX) \
82   EMBB_PLATFORM_INLINE \
83   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) \
84   EMBB_CAT2(embb_internal__atomic_load_, EMBB_PARAMETER_SIZE_BYTE)(\
85   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) \
86   volatile* pointer_to_value) { \
87   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) \
88   result;                   \
89   __asm__ __volatile__(\
90   "dmb\n\t" \
91   "ldr" EMBB_ATOMIC_ARM_SIZE_SUFFIX " %0, [%1]\n\t" \
92   "dmb" \
93   : "=&r" (result) \
94   : "r" (pointer_to_value) \
95   : "memory"); \
96   return result; \
97   }
98 #else
99 #error "No atomic fetch and store implementation found"
100 #endif
101 
102 EMBB_DEFINE_LOAD(1, "b")
103 EMBB_DEFINE_LOAD(2, "h")
104 EMBB_DEFINE_LOAD(4, "")
105 
106 #else
107 #error "Unknown architecture"
108 #endif
109 
110 #endif //DOXYGEN
111 
112 #endif //EMBB_BASE_C_INTERNAL_ATOMIC_LOAD_H_
113 
114