1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under 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 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-11-15
13 * Description: posix sem功能实现
14 */
15 #include "semaphore.h"
16 #include "prt_posix_internal.h"
17 #include "prt_sem_external.h"
18 #include "prt_sem.h"
19 #include "prt_sys_external.h"
20
sem_init(sem_t * sem,int shared,unsigned int value)21 int sem_init(sem_t *sem, int shared, unsigned int value)
22 {
23 U32 ret;
24 uintptr_t intSave;
25 SemHandle semHandle;
26 struct TagSemCb *semCb;
27
28 (void)shared;
29 if (sem == NULL) {
30 errno = EINVAL;
31 return PTHREAD_OP_FAIL;
32 }
33 if (value > OS_SEM_COUNT_MAX) {
34 errno = EINVAL;
35 return PTHREAD_OP_FAIL;
36 }
37
38 intSave = OsIntLock();
39
40 ret = PRT_SemCreate(value, &semHandle);
41 if (ret != OS_OK) {
42 OsIntRestore(intSave);
43 errno = EINVAL;
44 return PTHREAD_OP_FAIL;
45 }
46
47 // 创建成功
48 semCb = GET_SEM(semHandle);
49 snprintf_s(semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, MAX_POSIX_SEMAPHORE_NAME_LEN, "defaultSem%d", semHandle);
50 sem->refCount++;
51 sem->semHandle = semHandle;
52 OsIntRestore(intSave);
53
54 return OS_OK;
55 }
56
sem_open(const char * name,int flags,...)57 sem_t *sem_open(const char *name, int flags, ...)
58 {
59 U32 i;
60 U32 ret;
61 U32 val;
62 int mode;
63 va_list arg;
64 uintptr_t intSave;
65 struct TagSemCb *semCb;
66 bool created = FALSE;
67 SemHandle sem;
68
69 if (name == NULL) {
70 errno = EINVAL;
71 return SEM_FAILED;
72 }
73
74 if (strlen(name) >= MAX_POSIX_SEMAPHORE_NAME_LEN) {
75 errno = EINVAL;
76 return SEM_FAILED;
77 }
78
79 va_start(arg, flags);
80 mode = (int)va_arg(arg, unsigned int);
81 val = va_arg(arg, unsigned int);
82 va_end(arg);
83 (void)mode;
84 intSave = PRT_HwiLock();
85 for (i = 0; i < g_maxSem; i++) {
86 semCb = GET_SEM(i);
87 if (strcmp((const char *)semCb->name, name) == 0) {
88 created = TRUE;
89 break;
90 }
91 }
92
93 if (created == TRUE) {
94 if (((U32)flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {
95 PRT_HwiRestore(intSave);
96 errno = EEXIST;
97 return SEM_FAILED;
98 }
99 semCb->handle.refCount++;
100 PRT_HwiRestore(intSave);
101 return (sem_t *)&(semCb->handle);
102 }
103 if ((flags & O_CREAT) == 0) {
104 PRT_HwiRestore(intSave);
105 errno = ENOENT;
106 return SEM_FAILED;
107 }
108 if (val > OS_SEM_COUNT_MAX) {
109 PRT_HwiRestore(intSave);
110 errno = EINVAL;
111 return SEM_FAILED;
112 }
113
114 ret = PRT_SemCreate(val, &sem);
115 if (ret != OS_OK) {
116 PRT_HwiRestore(intSave);
117 errno = EAGAIN;
118 return SEM_FAILED;
119 }
120
121 semCb = GET_SEM(sem);
122 if (strncpy_s((char *)semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, name, strlen(name) + 1) != 0) {
123 OS_GOTO_SYS_ERROR1();
124 }
125
126 semCb->handle.semHandle = sem;
127 semCb->handle.refCount++;
128 PRT_HwiRestore(intSave);
129
130 return (sem_t *)&(semCb->handle);
131 }
132
sem_close(sem_t * sem)133 int sem_close(sem_t *sem)
134 {
135 uintptr_t intSave;
136 struct TagSemCb *semCb;
137
138 if (sem == NULL) {
139 errno = EINVAL;
140 return PTHREAD_OP_FAIL;
141 }
142
143 semCb = GET_SEM(sem->semHandle);
144
145 intSave = PRT_HwiLock();
146 if (semCb->name[0] == 0) {
147 PRT_HwiRestore(intSave);
148 return OS_OK;
149 }
150
151 if (semCb->handle.refCount > 0) {
152 semCb->handle.refCount--;
153 } else {
154 PRT_HwiRestore(intSave);
155 errno = EINVAL;
156 return PTHREAD_OP_FAIL;
157 }
158
159 PRT_HwiRestore(intSave);
160 return OS_OK;
161 }
162
sem_getvalue(sem_t * __restrict sem,int * __restrict val)163 int sem_getvalue(sem_t *__restrict sem, int *__restrict val)
164 {
165 U32 ret;
166 uintptr_t intSave;
167 struct TagSemCb *semCb;
168
169 if (val == NULL || sem == NULL) {
170 errno = EINVAL;
171 return PTHREAD_OP_FAIL;
172 }
173
174 semCb = GET_SEM(sem->semHandle);
175 intSave = PRT_HwiLock();
176 if (semCb->name[0] == 0) {
177 PRT_HwiRestore(intSave);
178 errno = EINVAL;
179 return PTHREAD_OP_FAIL;
180 }
181 ret = PRT_SemGetCount(sem->semHandle, (U32 *)val);
182 if (ret != OS_OK) {
183 PRT_HwiRestore(intSave);
184 errno = EINVAL;
185 return PTHREAD_OP_FAIL;
186 }
187 PRT_HwiRestore(intSave);
188
189 return OS_OK;
190 }
191
sem_wait(sem_t * sem)192 int sem_wait(sem_t *sem)
193 {
194 U32 ret;
195 uintptr_t intSave;
196 struct TagSemCb *semCb;
197
198 if (sem == NULL) {
199 errno = EINVAL;
200 return PTHREAD_OP_FAIL;
201 }
202 semCb = GET_SEM(sem->semHandle);
203 intSave = PRT_HwiLock();
204 if (semCb->name[0] == 0) {
205 PRT_HwiRestore(intSave);
206 errno = EINVAL;
207 return PTHREAD_OP_FAIL;
208 }
209
210 ret = PRT_SemPend(sem->semHandle, OS_WAIT_FOREVER);
211 if (ret != OS_OK) {
212 PRT_HwiRestore(intSave);
213 errno = EINVAL;
214 return PTHREAD_OP_FAIL;
215 }
216 PRT_HwiRestore(intSave);
217
218 return OS_OK;
219 }
220
sem_trywait(sem_t * sem)221 int sem_trywait(sem_t *sem)
222 {
223 U32 ret;
224 uintptr_t intSave;
225 struct TagSemCb *semCb;
226
227 if (sem == NULL) {
228 errno = EINVAL;
229 return PTHREAD_OP_FAIL;
230 }
231 semCb = GET_SEM(sem->semHandle);
232 intSave = PRT_HwiLock();
233 if (semCb->name[0] == 0) {
234 PRT_HwiRestore(intSave);
235 errno = EINVAL;
236 return PTHREAD_OP_FAIL;
237 }
238
239 ret = PRT_SemPend(sem->semHandle, 0);
240 if (ret != OS_OK) {
241 PRT_HwiRestore(intSave);
242 errno = EAGAIN;
243 return PTHREAD_OP_FAIL;
244 }
245 PRT_HwiRestore(intSave);
246
247 return OS_OK;
248 }
249
sem_timedwait(sem_t * __restrict sem,const struct timespec * __restrict at)250 int sem_timedwait(sem_t *__restrict sem, const struct timespec *__restrict at)
251 {
252 U32 ret;
253 U32 ticks;
254
255 if (at == NULL || sem == NULL) {
256 errno = EINVAL;
257 return PTHREAD_OP_FAIL;
258 }
259 if ((at->tv_sec < 0) || (at->tv_nsec < 0) || (at->tv_nsec > OS_SYS_NS_PER_SECOND)) {
260 errno = EINVAL;
261 return PTHREAD_OP_FAIL;
262 }
263
264 ret = OsTimeOut2Ticks(at, &ticks);
265 if (ret != OS_OK) {
266 errno = EINVAL;
267 return PTHREAD_OP_FAIL;
268 }
269 ret = PRT_SemPend(sem->semHandle, ticks);
270 if (ret == OS_ERRNO_SEM_TIMEOUT) {
271 errno = ETIMEDOUT;
272 return PTHREAD_OP_FAIL;
273 } else if (ret != OS_OK) {
274 errno = EINVAL;
275 return PTHREAD_OP_FAIL;
276 }
277
278 return OS_OK;
279 }
280
sem_post(sem_t * sem)281 int sem_post(sem_t *sem)
282 {
283 U32 ret;
284 uintptr_t intSave;
285 struct TagSemCb *semCb;
286
287 if (sem == NULL) {
288 errno = EINVAL;
289 return PTHREAD_OP_FAIL;
290 }
291 semCb = GET_SEM(sem->semHandle);
292
293 intSave = PRT_HwiLock();
294 if (semCb->name[0] == 0) {
295 PRT_HwiRestore(intSave);
296 errno = EINVAL;
297 return PTHREAD_OP_FAIL;
298 }
299
300 ret = PRT_SemPost(sem->semHandle);
301 if (ret != OS_OK) {
302 PRT_HwiRestore(intSave);
303 errno = EINVAL;
304 return PTHREAD_OP_FAIL;
305 }
306 PRT_HwiRestore(intSave);
307
308 return OS_OK;
309 }
310
sem_destroy(sem_t * sem)311 int sem_destroy(sem_t *sem)
312 {
313 U32 ret;
314 struct TagSemCb *semCb;
315
316 if (sem == NULL) {
317 errno = EINVAL;
318 return PTHREAD_OP_FAIL;
319 }
320 semCb = GET_SEM(sem->semHandle);
321
322 ret = PRT_SemDelete(sem->semHandle);
323 if (ret != OS_OK) {
324 errno = EINVAL;
325 return PTHREAD_OP_FAIL;
326 }
327
328 (void)memset_s(semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, 0, MAX_POSIX_SEMAPHORE_NAME_LEN + 1);
329 sem->semHandle = 0xffffU;
330 sem->refCount = 0;
331
332 return OS_OK;
333 }
334
sem_unlink(const char * name)335 int sem_unlink(const char *name)
336 {
337 U32 i;
338 uintptr_t intSave;
339 struct TagSemCb *semCb;
340 bool find = FALSE;
341 U32 ret = OS_OK;
342
343 if (name == NULL) {
344 errno = EINVAL;
345 return PTHREAD_OP_FAIL;
346 }
347 intSave = PRT_HwiLock();
348 for (i = 0; i < g_maxSem; i++) {
349 semCb = GET_SEM(i);
350 if (strcmp((const char *)semCb->name, name) == 0) {
351 find = TRUE;
352 break;
353 }
354 }
355 if (find == FALSE) {
356 PRT_HwiRestore(intSave);
357 errno = EINVAL;
358 return PTHREAD_OP_FAIL;
359 }
360
361 if (semCb->handle.refCount == 0) {
362 ret = PRT_SemDelete((SemHandle)i);
363 if (ret != OS_OK) {
364 PRT_HwiRestore(intSave);
365 errno = EINVAL;
366 return PTHREAD_OP_FAIL;
367 }
368 }
369
370 (void)memset_s(semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, 0, MAX_POSIX_SEMAPHORE_NAME_LEN + 1);
371 semCb->handle.refCount = 0;
372 PRT_HwiRestore(intSave);
373
374 return OS_OK;
375 }
376