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
param_atomic_store(ATOMIC_UINT32 *ptr, uint32_t value, int order)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
param_atomic_uint64_store(ATOMIC_LLONG *ptr, int64_t value, int order)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
param_atomic_init(ATOMIC_UINT32 *ptr, uint32_t value)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
param_atomic_uint64_init(ATOMIC_LLONG *ptr, int64_t value)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
param_atomic_load(ATOMIC_UINT32 *ptr, int order)137 static inline ATOMIC_UINT32 param_atomic_load(ATOMIC_UINT32 *ptr, int order)
138 {
139 return *((volatile ATOMIC_UINT32 *)ptr);
140 }
141
param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order)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