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 #else 53 54 // support futex 55 #ifndef __NR_futex 56 #define PARAM_NR_FUTEX 202 /* syscall number */ 57 #else 58 #define PARAM_NR_FUTEX __NR_futex 59 #endif 60 61 #if !(defined FUTEX_WAIT || defined FUTEX_WAKE) 62 #define FUTEX_WAIT 0 63 #define FUTEX_WAKE 1 64 #define PARAM_FUTEX(ftx, op, value, timeout, bitset) \ 65 do { \ 66 struct timespec d_timeout = { 0, 1000 * 1000 * (timeout) }; \ 67 syscall(PARAM_NR_FUTEX, ftx, op, value, &d_timeout, NULL, bitset); \ 68 } while (0) 69 70 #define futex_wake(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE, count, 0, 0) 71 #define futex_wait(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT, value, 100, 0) 72 #endif 73 74 #if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__)) 75 #define MEMORY_ORDER_RELAXED memory_order_relaxed 76 #define MEMORY_ORDER_CONSUME memory_order_consume 77 #define MEMORY_ORDER_ACQUIRE memory_order_acquire 78 #define MEMORY_ORDER_RELEASE memory_order_release 79 80 #define ATOMIC_UINT32 atomic_uint 81 #define ATOMIC_LLONG atomic_llong 82 #define ATOMIC_INIT(commitId, value) atomic_init((commitId), (value)) 83 #define ATOMIC_UINT64_INIT(commitId, value) atomic_init((commitId), (value)) 84 #define ATOMIC_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), (order)) 85 #define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order) 86 #define ATOMIC_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order)) 87 #define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order)) 88 #define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) atomic_fetch_or_explicit((commitId), (value), (order)) 89 #define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) atomic_fetch_add_explicit((commitId), (value), (order)) 90 91 #else 92 93 #define MEMORY_ORDER_RELAXED 0 94 #define MEMORY_ORDER_CONSUME 1 95 #define MEMORY_ORDER_ACQUIRE 2 96 #define MEMORY_ORDER_RELEASE 3 97 98 #define ATOMIC_UINT32 uint32_t 99 #define ATOMIC_LLONG int64_t 100 101 static inline void param_atomic_store(ATOMIC_UINT32 *ptr, uint32_t value, int order) 102 { 103 __sync_lock_test_and_set(ptr, value); 104 if (order == MEMORY_ORDER_RELEASE) { 105 __sync_synchronize(); 106 } 107 } 108 109 static inline void param_atomic_uint64_store(ATOMIC_LLONG *ptr, int64_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_init(ATOMIC_UINT32 *ptr, uint32_t value) 118 { 119 *ptr = 0; 120 __sync_fetch_and_add(ptr, value, 0); 121 } 122 123 static inline void param_atomic_uint64_init(ATOMIC_LLONG *ptr, int64_t value) 124 { 125 *ptr = 0; 126 __sync_fetch_and_add(ptr, value, 0); 127 } 128 129 static inline ATOMIC_UINT32 param_atomic_load(ATOMIC_UINT32 *ptr, int order) 130 { 131 return *((volatile ATOMIC_UINT32 *)ptr); 132 } 133 134 static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order) 135 { 136 return *((volatile ATOMIC_LLONG *)ptr); 137 } 138 139 #define ATOMIC_INIT(commitId, value) param_atomic_init((commitId), (value)) 140 #define ATOMIC_UINT64_INIT(commitId, value) param_atomic_uint64_init((commitId), (value)) 141 #define ATOMIC_LOAD_EXPLICIT(commitId, order) param_atomic_load((commitId), order) 142 #define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order) 143 #define ATOMIC_STORE_EXPLICIT(commitId, value, order) param_atomic_store((commitId), (value), (order)) 144 #define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) param_atomic_uint64_store((commitId), (value), (order)) 145 #define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) __sync_or_and_fetch((commitId), (value)) 146 #define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) __sync_add_and_fetch((commitId), (value)) 147 #endif 148 #endif // __LITEOS_M__ 149 #ifdef __cplusplus 150 #if __cplusplus 151 } 152 #endif 153 #endif 154 155 #endif // BASE_STARTUP_PARAM_ATOMIC_H