xref: /kernel/liteos_m/kal/posix/src/semaphore.c (revision 3d8536b4)
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 *    conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 *    of conditions and the following disclaimer in the documentation and/or other materials
13 *    provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 *    to endorse or promote products derived from this software without specific prior written
17 *    permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <stdint.h>
33#include <semaphore.h>
34#include <errno.h>
35#include "los_sem.h"
36#include "time_internal.h"
37
38#define _SEM_MAGIC 0xEBCFDEA1
39
40#define s_magic __val[0]
41#define s_handle __val[1]
42
43static inline int MapError(UINT32 err)
44{
45    switch (err) {
46        case LOS_OK:
47            return 0;
48        case LOS_ERRNO_SEM_INVALID:
49        case LOS_ERRNO_SEM_UNAVAILABLE:
50            return EINVAL;
51        case LOS_ERRNO_SEM_ALL_BUSY:
52            return ENOSPC;
53        case LOS_ERRNO_SEM_OVERFLOW:
54            return ENOMEM;
55        case LOS_ERRNO_SEM_PENDED:
56            return EBUSY;
57        case LOS_ERRNO_SEM_PEND_IN_LOCK:
58            return EPERM;
59        case LOS_ERRNO_SEM_PEND_INTERR:
60            return EINTR;
61        case LOS_ERRNO_SEM_TIMEOUT:
62            return ETIMEDOUT;
63        default:
64            return EINVAL;
65    }
66}
67
68int sem_init(sem_t *sem, int shared, unsigned int value)
69{
70    UINT32 semHandle = 0;
71    UINT32 ret;
72
73    (VOID)shared;
74    if ((sem == NULL) || (value >= OS_SEM_COUNTING_MAX_COUNT)) {
75        errno = EINVAL;
76        return -1;
77    }
78
79    ret = LOS_SemCreate(value, &semHandle);
80    if (ret != LOS_OK) {
81        errno = MapError(ret);
82        return -1;
83    }
84
85    sem->s_magic = (INT32)_SEM_MAGIC;
86    sem->s_handle = (INT32)semHandle;
87
88    return 0;
89}
90
91int sem_destroy(sem_t *sem)
92{
93    UINT32 ret;
94
95    if ((sem == NULL) || (sem->s_magic != (INT32)_SEM_MAGIC)) {
96        errno = EINVAL;
97        return -1;
98    }
99
100    ret = LOS_SemDelete((UINT32)sem->s_handle);
101    if (ret != LOS_OK) {
102        errno = MapError(ret);
103        return -1;
104    }
105
106    return 0;
107}
108
109int sem_wait(sem_t *sem)
110{
111    UINT32 ret;
112
113    if ((sem == NULL) || (sem->s_magic != (INT32)_SEM_MAGIC)) {
114        errno = EINVAL;
115        return -1;
116    }
117
118    ret = LOS_SemPend((UINT32)sem->s_handle, LOS_WAIT_FOREVER);
119    if (ret != LOS_OK) {
120        errno = MapError(ret);
121        return -1;
122    }
123
124    return 0;
125}
126
127int sem_post(sem_t *sem)
128{
129    UINT32 ret;
130
131    if ((sem == NULL) || (sem->s_magic != (INT32)_SEM_MAGIC)) {
132        errno = EINVAL;
133        return -1;
134    }
135
136    ret = LOS_SemPost((UINT32)sem->s_handle);
137    if (ret != LOS_OK) {
138        errno = MapError(ret);
139        return -1;
140    }
141
142    return 0;
143}
144
145int sem_trywait(sem_t *sem)
146{
147    UINT32 ret;
148
149    if ((sem == NULL) || (sem->s_magic != (INT32)_SEM_MAGIC)) {
150        errno = EINVAL;
151        return -1;
152    }
153
154    ret = LOS_SemPend((UINT32)sem->s_handle, LOS_NO_WAIT);
155    if (ret != LOS_OK) {
156        errno = MapError(ret);
157        return -1;
158    }
159
160    return 0;
161}
162
163int sem_timedwait(sem_t *sem, const struct timespec *timeout)
164{
165    UINT32 ret;
166    UINT64 tickCnt;
167
168    if ((sem == NULL) || (sem->s_magic != (INT32)_SEM_MAGIC)) {
169        errno = EINVAL;
170        return -1;
171    }
172
173    ret = OsGetTickTimeFromNow(timeout, CLOCK_REALTIME, &tickCnt);
174    if (ret != 0) {
175        errno = (INT32)ret;
176        return -1;
177    }
178
179    if (tickCnt > LOS_WAIT_FOREVER) {
180        tickCnt = LOS_WAIT_FOREVER;
181    }
182
183    ret = LOS_SemPend((UINT32)sem->s_handle, (UINT32)tickCnt);
184    if (ret != LOS_OK) {
185        errno = MapError(ret);
186        return -1;
187    }
188
189    return 0;
190}
191
192int sem_getvalue(sem_t *sem, int *currVal)
193{
194    UINT32 ret;
195
196    if ((sem == NULL) || (sem->s_magic != (INT32)_SEM_MAGIC)|| (currVal == NULL)) {
197        errno = EINVAL;
198        return -1;
199    }
200
201    ret = LOS_SemGetValue(sem->s_handle, currVal);
202    if (ret) {
203        errno = EINVAL;
204        return -1;
205    }
206
207    return LOS_OK;
208}