1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef BASE_STARTUP_PARAM_ATOMIC_H
17 #define BASE_STARTUP_PARAM_ATOMIC_H
18 #include <stdint.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 
24 #if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
25 #include <pthread.h>
26 #include <stdatomic.h>
27 #endif
28 #if defined FUTEX_WAIT || defined FUTEX_WAKE
29 #include <linux/futex.h>
30 #endif
31 
32 #ifdef __cplusplus
33 #if __cplusplus
34 extern "C" {
35 #endif
36 #endif
37 
38 #ifdef __LITEOS_M__
39 #define ATOMIC_UINT32 uint32_t
40 #define ATOMIC_LLONG  long long
41 #define ATOMIC_INIT(commitId, value) *(commitId) = (value)
42 #define ATOMIC_LOAD_EXPLICIT(commitId, order) *(commitId)
43 #define ATOMIC_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value)
44 #define ATOMIC_UINT64_INIT(commitId, value) *(commitId) = (value)
45 #define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) *(commitId)
46 #define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value)
47 #define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) *(commitId) |= (value)
48 #define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) *(commitId) += (value)
49 
50 #define futex_wake(ftx, count) (void)(ftx)
51 #define futex_wait(ftx, value) (void)(ftx)
52 #define futex_wake_private(ftx, count) (void)(ftx)
53 #define futex_wait_private(ftx, value) (void)(ftx)
54 #else
55 
56 // support futex
57 #ifndef __NR_futex
58 #define PARAM_NR_FUTEX 202 /* syscall number */
59 #else
60 #define PARAM_NR_FUTEX __NR_futex
61 #endif
62 
63 #if !(defined FUTEX_WAIT || defined FUTEX_WAKE)
64 #define FUTEX_WAIT 0
65 #define FUTEX_WAKE 1
66 #define FUTEX_PRIVATE_FLAG 128
67 #define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
68 #define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
69 
70 #define PARAM_FUTEX(ftx, op, value, timeout, bitset)                       \
71     do {                                                                   \
72         struct timespec d_timeout = { 0, 1000 * 1000 * (timeout) };        \
73         syscall(PARAM_NR_FUTEX, ftx, op, value, &d_timeout, NULL, bitset); \
74     } while (0)
75 
76 #define futex_wake(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE, count, 0, 0)
77 #define futex_wait(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT, value, 100, 0)
78 #define futex_wake_private(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE_PRIVATE, count, 0, 0)
79 #define futex_wait_private(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT_PRIVATE, value, 100, 0)
80 #endif
81 
82 #if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
83 #define MEMORY_ORDER_RELAXED memory_order_relaxed
84 #define MEMORY_ORDER_CONSUME memory_order_consume
85 #define MEMORY_ORDER_ACQUIRE memory_order_acquire
86 #define MEMORY_ORDER_RELEASE memory_order_release
87 
88 #define ATOMIC_UINT32 atomic_uint
89 #define ATOMIC_LLONG atomic_llong
90 #define ATOMIC_INIT(commitId, value) atomic_init((commitId), (value))
91 #define ATOMIC_UINT64_INIT(commitId, value) atomic_init((commitId), (value))
92 #define ATOMIC_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), (order))
93 #define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order)
94 #define ATOMIC_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order))
95 #define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order))
96 #define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) atomic_fetch_or_explicit((commitId), (value), (order))
97 #define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) atomic_fetch_add_explicit((commitId), (value), (order))
98 
99 #else
100 
101 #define MEMORY_ORDER_RELAXED 0
102 #define MEMORY_ORDER_CONSUME 1
103 #define MEMORY_ORDER_ACQUIRE 2
104 #define MEMORY_ORDER_RELEASE 3
105 
106 #define ATOMIC_UINT32 uint32_t
107 #define ATOMIC_LLONG int64_t
108 
109 static inline void param_atomic_store(ATOMIC_UINT32 *ptr, uint32_t value, int order)
110 {
111     __sync_lock_test_and_set(ptr, value);
112     if (order == MEMORY_ORDER_RELEASE) {
113         __sync_synchronize();
114     }
115 }
116 
117 static inline void param_atomic_uint64_store(ATOMIC_LLONG *ptr, int64_t value, int order)
118 {
119     __sync_lock_test_and_set(ptr, value);
120     if (order == MEMORY_ORDER_RELEASE) {
121         __sync_synchronize();
122     }
123 }
124 
125 static inline void param_atomic_init(ATOMIC_UINT32 *ptr, uint32_t value)
126 {
127     *ptr = 0;
128     __sync_fetch_and_add(ptr, value, 0);
129 }
130 
131 static inline void param_atomic_uint64_init(ATOMIC_LLONG *ptr, int64_t value)
132 {
133     *ptr = 0;
134     __sync_fetch_and_add(ptr, value, 0);
135 }
136 
137 static inline ATOMIC_UINT32 param_atomic_load(ATOMIC_UINT32 *ptr, int order)
138 {
139     return *((volatile ATOMIC_UINT32 *)ptr);
140 }
141 
142 static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order)
143 {
144     return *((volatile ATOMIC_LLONG *)ptr);
145 }
146 
147 #define ATOMIC_INIT(commitId, value) param_atomic_init((commitId), (value))
148 #define ATOMIC_UINT64_INIT(commitId, value) param_atomic_uint64_init((commitId), (value))
149 #define ATOMIC_LOAD_EXPLICIT(commitId, order) param_atomic_load((commitId), order)
150 #define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order)
151 #define ATOMIC_STORE_EXPLICIT(commitId, value, order) param_atomic_store((commitId), (value), (order))
152 #define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) param_atomic_uint64_store((commitId), (value), (order))
153 #define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) __sync_or_and_fetch((commitId), (value))
154 #define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) __sync_add_and_fetch((commitId), (value))
155 #endif
156 #endif // __LITEOS_M__
157 #ifdef __cplusplus
158 #if __cplusplus
159 }
160 #endif
161 #endif
162 
163 #endif // BASE_STARTUP_PARAM_ATOMIC_H