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_STORE_H_
28 #define EMBB_BASE_C_INTERNAL_ATOMIC_STORE_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_STORE(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX)\
40   extern void __fastcall EMBB_CAT2(embb_internal__atomic_store_, EMBB_PARAMETER_SIZE_BYTE)_asm( \
41   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value); \
42   EMBB_PLATFORM_INLINE void __fastcall EMBB_CAT2(embb_internal__atomic_store_, EMBB_PARAMETER_SIZE_BYTE)(\
43   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) \
44   { \
45   _ReadWriteBarrier(); \
46   EMBB_CAT2(embb_internal__atomic_store_, \
47   EMBB_PARAMETER_SIZE_BYTE)_asm(pointer_to_value, new_value); \
48   _ReadWriteBarrier(); \
49   }
50 #elif defined(EMBB_PLATFORM_COMPILER_GNUC)
51 #define EMBB_DEFINE_STORE(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX)\
52   EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_store_, EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, \
53   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) {\
54   __asm__ __volatile__("lock xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
55   : "+m" (*pointer_to_value), "+q" (new_value) \
56   : \
57   : "memory"); \
58   }
59 #else
60 #error "No atomic fetch and store implementation found"
61 #endif
62 
63 /*
64 * The three or four macro calls below generate the methods for 1, 2, 4, and
65 * bytes, as stated in the macro definition.
66 */
67 EMBB_DEFINE_STORE(1, "b")
68 EMBB_DEFINE_STORE(2, "w")
69 EMBB_DEFINE_STORE(4, "l")
70 #ifdef EMBB_64_BIT_ATOMIC_AVAILABLE
71 EMBB_DEFINE_STORE(8, "q")
72 #endif
73 
74 #elif defined(EMBB_PLATFORM_ARCH_ARM)
75 
76 #if defined(EMBB_PLATFORM_COMPILER_GNUC)
77 #define EMBB_DEFINE_STORE(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_ARM_SIZE_SUFFIX)\
78   EMBB_PLATFORM_INLINE \
79   void EMBB_CAT2(embb_internal__atomic_store_, EMBB_PARAMETER_SIZE_BYTE)(\
80   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_ATOMIC_, EMBB_PARAMETER_SIZE_BYTE) volatile* \
81   pointer_to_value, \
82   EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) {\
83   __asm__ __volatile__( \
84   "dmb\n\t" \
85   "str" EMBB_ATOMIC_ARM_SIZE_SUFFIX " %1, [%0]" \
86   : \
87   : "r" (pointer_to_value), "r" (new_value) \
88   : "memory"); \
89   }
90 /*    __sync_synchronize(); \
91     *pointer_to_value = new_value; \
92     __sync_synchronize(); \
93   }*/
94 #else
95 #error "No atomic fetch and store implementation found"
96 #endif
97 
98 EMBB_DEFINE_STORE(1, "b")
99 EMBB_DEFINE_STORE(2, "h")
100 EMBB_DEFINE_STORE(4, "")
101 
102 #else
103 #error "Unknown architecture"
104 #endif
105 
106 #endif //DOXYGEN
107 
108 #endif //EMBB_BASE_C_INTERNAL_ATOMIC_STORE_H_
109