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 #include <pthread.h>
17 #include <unistd.h>
18 #include "hitls_build.h"
19 #include "bsl_errno.h"
20 #include "bsl_sal.h"
21
22 #if defined(HITLS_BSL_SAL_LINUX) && defined(HITLS_BSL_SAL_LOCK)
23 // Used for DEFAULT lock implementation
24 typedef struct {
25 pthread_rwlock_t rwlock;
26 } BslOsalRWLock;
27
SAL_RwLockNew(BSL_SAL_ThreadLockHandle * lock)28 int32_t SAL_RwLockNew(BSL_SAL_ThreadLockHandle *lock)
29 {
30 if (lock == NULL) {
31 return BSL_SAL_ERR_BAD_PARAM;
32 }
33 BslOsalRWLock *newLock = (BslOsalRWLock *)BSL_SAL_Calloc(1, sizeof(BslOsalRWLock));
34 if (newLock == NULL) {
35 return BSL_MALLOC_FAIL;
36 }
37
38 if (pthread_rwlock_init(&newLock->rwlock, (const pthread_rwlockattr_t *)NULL) != 0) {
39 BSL_SAL_FREE(newLock);
40 return BSL_SAL_ERR_UNKNOWN;
41 }
42 *lock = newLock;
43 return BSL_SUCCESS;
44 }
45
SAL_RwReadLock(BSL_SAL_ThreadLockHandle rwLock)46 int32_t SAL_RwReadLock(BSL_SAL_ThreadLockHandle rwLock)
47 {
48 BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
49 if (lock == NULL) {
50 return BSL_SAL_ERR_BAD_PARAM;
51 }
52 if (pthread_rwlock_rdlock(&lock->rwlock) != 0) {
53 return BSL_SAL_ERR_UNKNOWN;
54 }
55 return BSL_SUCCESS;
56 }
57
SAL_RwWriteLock(BSL_SAL_ThreadLockHandle rwLock)58 int32_t SAL_RwWriteLock(BSL_SAL_ThreadLockHandle rwLock)
59 {
60 BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
61 if (lock == NULL) {
62 return BSL_SAL_ERR_BAD_PARAM;
63 }
64 if (pthread_rwlock_wrlock(&lock->rwlock) != 0) {
65 return BSL_SAL_ERR_UNKNOWN;
66 }
67 return BSL_SUCCESS;
68 }
69
SAL_RwUnlock(BSL_SAL_ThreadLockHandle rwLock)70 int32_t SAL_RwUnlock(BSL_SAL_ThreadLockHandle rwLock)
71 {
72 BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
73 if (lock == NULL) {
74 return BSL_SAL_ERR_BAD_PARAM;
75 }
76
77 if (pthread_rwlock_unlock(&lock->rwlock) != 0) {
78 return BSL_SAL_ERR_UNKNOWN;
79 }
80 return BSL_SUCCESS;
81 }
82
SAL_RwLockFree(BSL_SAL_ThreadLockHandle rwLock)83 void SAL_RwLockFree(BSL_SAL_ThreadLockHandle rwLock)
84 {
85 BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
86 if (lock != NULL) {
87 (void)pthread_rwlock_destroy(&(lock->rwlock));
88 BSL_SAL_FREE(lock);
89 }
90 }
91 #endif
92
93 #if defined(HITLS_BSL_SAL_LINUX) && defined(HITLS_BSL_SAL_THREAD)
SAL_GetPid(void)94 uint64_t SAL_GetPid(void)
95 {
96 // By default, gettid is not used to obtain the global tid corresponding to the thread
97 // because other thread functions use the pthread library.
98 // Use pthread_self to obtain the PID used by pthread_create in this process.
99 // However, the pids of the parent and child processes may be the same.
100 return (uint64_t)pthread_self();
101 }
102
SAL_PthreadRunOnce(uint32_t * onceControl,BSL_SAL_ThreadInitRoutine initFunc)103 int32_t SAL_PthreadRunOnce(uint32_t *onceControl, BSL_SAL_ThreadInitRoutine initFunc)
104 {
105 if (onceControl == NULL || initFunc == NULL) {
106 return BSL_SAL_ERR_BAD_PARAM;
107 }
108
109 pthread_once_t *tmpOnce = (pthread_once_t *)onceControl;
110 if (pthread_once(tmpOnce, initFunc) != 0) {
111 return BSL_SAL_ERR_UNKNOWN;
112 }
113 return BSL_SUCCESS;
114 }
115
BSL_SAL_ThreadCreate(BSL_SAL_ThreadId * thread,void * (* startFunc)(void *),void * arg)116 int32_t BSL_SAL_ThreadCreate(BSL_SAL_ThreadId *thread, void *(*startFunc)(void *), void *arg)
117 {
118 if (thread == NULL || startFunc == NULL) {
119 return BSL_SAL_ERR_BAD_PARAM;
120 }
121 int32_t ret = pthread_create((pthread_t *)thread, NULL, startFunc, arg);
122 if (ret != 0) {
123 return BSL_SAL_ERR_UNKNOWN;
124 }
125 return BSL_SUCCESS;
126 }
127
BSL_SAL_ThreadClose(BSL_SAL_ThreadId thread)128 void BSL_SAL_ThreadClose(BSL_SAL_ThreadId thread)
129 {
130 if (thread == NULL) {
131 return;
132 }
133 (void)pthread_join((pthread_t)(uintptr_t)thread, NULL);
134 }
135
BSL_SAL_CreateCondVar(BSL_SAL_CondVar * condVar)136 int32_t BSL_SAL_CreateCondVar(BSL_SAL_CondVar *condVar)
137 {
138 if (condVar == NULL) {
139 return BSL_SAL_ERR_BAD_PARAM;
140 }
141 pthread_cond_t *cond = (pthread_cond_t *)BSL_SAL_Malloc(sizeof(pthread_cond_t));
142 if (cond == NULL) {
143 return BSL_MALLOC_FAIL;
144 }
145 if (pthread_cond_init(cond, NULL) != 0) {
146 BSL_SAL_FREE(cond);
147 return BSL_SAL_ERR_UNKNOWN;
148 }
149 *condVar = cond;
150 return BSL_SUCCESS;
151 }
152
BSL_SAL_CondSignal(BSL_SAL_CondVar condVar)153 int32_t BSL_SAL_CondSignal(BSL_SAL_CondVar condVar)
154 {
155 if (condVar == NULL) {
156 return BSL_SAL_ERR_BAD_PARAM;
157 }
158 if (pthread_cond_signal(condVar) != 0) {
159 return BSL_SAL_ERR_UNKNOWN;
160 }
161 return BSL_SUCCESS;
162 }
163
164 #define SAL_SECS_IN_NS 1000000000 // 1s = 1000000000ns
165 #define SAL_SECS_IN_MS 1000 // 1s = 1000ms
166 #define SAL_MS_IN_NS 1000000 // 1ms = 1000000ns
167
BSL_SAL_CondTimedwaitMs(BSL_SAL_Mutex condMutex,BSL_SAL_CondVar condVar,int32_t timeout)168 int32_t BSL_SAL_CondTimedwaitMs(BSL_SAL_Mutex condMutex, BSL_SAL_CondVar condVar, int32_t timeout)
169 {
170 struct timespec stm = {0};
171 struct timespec etm = {0};
172 long int endNs; // nanosecond
173 long int endSecs; // second
174 if (condMutex == NULL || condVar == NULL) {
175 return BSL_SAL_ERR_BAD_PARAM;
176 }
177 pthread_mutex_lock(condMutex);
178
179 clock_gettime(CLOCK_REALTIME, &stm);
180 endSecs = stm.tv_sec + timeout / SAL_SECS_IN_MS;
181 endNs = stm.tv_nsec + (timeout % SAL_SECS_IN_MS) * SAL_MS_IN_NS;
182 endSecs += endNs / SAL_SECS_IN_NS;
183 endNs %= SAL_SECS_IN_NS;
184 etm.tv_sec = endSecs;
185 etm.tv_nsec = endNs;
186
187 int32_t ret = pthread_cond_timedwait(condVar, condMutex, &etm);
188 pthread_mutex_unlock(condMutex);
189 if (ret != 0) {
190 return BSL_SAL_ERR_UNKNOWN;
191 }
192 return BSL_SUCCESS;
193 }
194
BSL_SAL_DeleteCondVar(BSL_SAL_CondVar condVar)195 int32_t BSL_SAL_DeleteCondVar(BSL_SAL_CondVar condVar)
196 {
197 if (condVar == NULL) {
198 return BSL_SAL_ERR_BAD_PARAM;
199 }
200 int32_t ret = pthread_cond_destroy((pthread_cond_t *)condVar);
201 BSL_SAL_FREE(condVar);
202 if (ret != 0) {
203 return BSL_SAL_ERR_UNKNOWN;
204 }
205 return BSL_SUCCESS;
206 }
207 #endif
208