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