API参考
载入中...
搜索中...
未找到
sal_atomic.h
1/*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16#ifndef SAL_ATOMIC_H
17#define SAL_ATOMIC_H
18
19#include <stdlib.h>
20#include "bsl_sal.h"
21#include "bsl_errno.h"
22
23/* The value of __STDC_VERSION__ is determined by the compilation option -std.
24 The atomic API is provided only when -std=gnu11 is used. */
25#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) && !defined(HITLS_ATOMIC_THREAD_LOCK)
26#include <stdatomic.h>
27#define SAL_HAVE_C11_ATOMICS
28#endif
29
30#ifdef __cplusplus
31extern "C" {
32#endif // __cplusplus
33
34int BSL_SAL_AtomicAdd(int *val, int amount, int *ref, BSL_SAL_ThreadLockHandle lock);
35
36/* Atom operation mode 1, which uses the function provided by C11. Only the int type is considered.
37 * ATOMIC_INT_LOCK_FREE: If the value is 1, the operation MAY BE lock-free operation.
38 * ATOMIC_INT_LOCK_FREE: If the value is 2, it's the lock-free operation.
39 * memory_order_relaxed only ensures the atomicity of the current operation
40 * and does not consider the synchronization between threads.
41 */
42#if defined(SAL_HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) && ATOMIC_INT_LOCK_FREE > 0 && !defined(HITLS_ATOMIC_THREAD_LOCK)
43#define SAL_USE_ATOMICS_LIB_FUNC
44typedef struct {
45 atomic_int count;
47
48static inline int BSL_SAL_AtomicUpReferences(BSL_SAL_RefCount *references, int *ret)
49{
50 *ret = atomic_fetch_add_explicit(&(references->count), 1, memory_order_relaxed) + 1;
51 return BSL_SUCCESS;
52}
53
54static inline int BSL_SAL_AtomicDownReferences(BSL_SAL_RefCount *references, int *ret)
55{
56 *ret = atomic_fetch_sub_explicit(&(references->count), 1, memory_order_relaxed) - 1;
57 if (*ret == 0) {
58 atomic_thread_fence(memory_order_acquire);
59 }
60 return BSL_SUCCESS;
61}
62
63/* Atom operation mode 2, using the function provided by the GCC. */
64#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 && !defined(HITLS_ATOMIC_THREAD_LOCK)
65#define SAL_USE_ATOMICS_LIB_FUNC
66typedef struct {
67 int count;
69
70static inline int BSL_SAL_AtomicUpReferences(BSL_SAL_RefCount *references, int *ret)
71{
72 *ret = __atomic_fetch_add(&(references->count), 1, __ATOMIC_RELAXED) + 1;
73 return BSL_SUCCESS;
74}
75
76static inline int BSL_SAL_AtomicDownReferences(BSL_SAL_RefCount *references, int *ret)
77{
78 *ret = __atomic_fetch_sub(&(references->count), 1, __ATOMIC_RELAXED) - 1;
79 if (*ret == 0) {
80 const int type = __ATOMIC_ACQUIRE;
81 __atomic_thread_fence(type);
82 }
83 return BSL_SUCCESS;
84}
85
86// Atom operation mode 3, using read/write locks.
87#else
88typedef struct {
89 int count;
92
93static inline int BSL_SAL_AtomicUpReferences(BSL_SAL_RefCount *references, int *ret)
94{
95 return BSL_SAL_AtomicAdd(&(references->count), 1, ret, references->lock);
96}
97
98static inline int BSL_SAL_AtomicDownReferences(BSL_SAL_RefCount *references, int *ret)
99{
100 return BSL_SAL_AtomicAdd(&(references->count), -1, ret, references->lock);
101}
102#endif
103
104#ifdef SAL_USE_ATOMICS_LIB_FUNC
105static inline int BSL_SAL_ReferencesInit(BSL_SAL_RefCount *references)
106{
107 references->count = 1;
108 return BSL_SUCCESS;
109}
110
111static inline void BSL_SAL_ReferencesFree(BSL_SAL_RefCount *references)
112{
113 (void)references;
114 return;
115}
116#else
117static inline int BSL_SAL_ReferencesInit(BSL_SAL_RefCount *references)
118{
119 references->count = 1;
120 return BSL_SAL_ThreadLockNew(&(references->lock));
121}
122
123static inline void BSL_SAL_ReferencesFree(BSL_SAL_RefCount *references)
124{
125 BSL_SAL_ThreadLockFree(references->lock);
126 references->lock = NULL;
127 return;
128}
129#endif
130
138int32_t BSL_SAL_AtomicRefUpCtrl(BSL_SAL_RefCount *references, void *val, uint32_t len);
139
140#ifdef __cplusplus
141}
142#endif // __cplusplus
143
144#endif // SAL_ATOMIC_H
#define BSL_SUCCESS
Return success
定义 bsl_errno.h:33
int32_t BSL_SAL_ThreadLockNew(BSL_SAL_ThreadLockHandle *lock)
Create a thread lock.
定义 sal_threadlock.c:39
void BSL_SAL_ThreadLockFree(BSL_SAL_ThreadLockHandle lock)
Release the thread lock.
定义 sal_threadlock.c:88
void * BSL_SAL_ThreadLockHandle
定义 bsl_sal.h:63
定义 sal_atomic.h:88