1 /*
2 * Copyright (C) 2020-2021 Alibaba Group Holding Limited
3 */
4
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <time.h>
9 #include <semaphore.h>
10 #include <aos/kernel.h>
11 #include <aos/errno.h>
12
13 #define SEM_NAME_MAX 1024
14
15 /* Initialize an unnamed semaphore */
sem_init(sem_t * sem,int pshared,unsigned int value)16 int sem_init(sem_t *sem, int pshared, unsigned int value)
17 {
18 int ret = 0;
19
20 if ((sem == NULL) || (value > SEM_VALUE_MAX)) {
21 errno = EINVAL;
22 return -1;
23 }
24
25 /* Sharing between processes is not supported. */
26 if (pshared != 0) {
27 errno = ENOTSUP;
28 return -1;
29 }
30
31 ret = aos_sem_new((aos_sem_t *)&(sem->aos_sem), value);
32 if (ret != 0) {
33 errno = -ret;
34 return -1;
35 }
36
37 return 0;
38 }
39
40 /* Initialize and open a named semaphore */
sem_open(const char * name,int oflag,...)41 sem_t *sem_open(const char *name, int oflag, ...)
42 {
43 if ((name == NULL) || ((strlen(name) <= 0) || (strlen(name) > SEM_NAME_MAX))) {
44 errno = EINVAL;
45 return SEM_FAILED;
46 }
47
48 errno = ENOSYS;
49 return SEM_FAILED;
50 }
51
52 /* lock a semaphore */
sem_wait(sem_t * sem)53 int sem_wait(sem_t *sem)
54 {
55 int ret = 0;
56
57 if (sem == NULL) {
58 errno = EINVAL;
59 return -1;
60 }
61
62 ret = aos_sem_wait((aos_sem_t *)&(sem->aos_sem), AOS_WAIT_FOREVER);
63 if (ret != 0) {
64 errno = -ret;
65 return -1;
66 }
67
68 return 0;
69 }
70
71 /* try to lock a semaphore */
sem_trywait(sem_t * sem)72 int sem_trywait(sem_t *sem)
73 {
74 int ret = 0;
75
76 if (sem == NULL) {
77 errno = EINVAL;
78 return -1;
79 }
80
81 ret = aos_sem_wait((aos_sem_t *)&(sem->aos_sem), 0);
82 if (ret == -ETIMEDOUT) {
83 errno = EAGAIN;
84 return -1;
85 } else if (ret < 0) {
86 errno = -ret;
87 return -1;
88 } else {
89 return 0;
90 }
91
92 return 0;
93 }
94
95 /* lock a semaphore */
sem_timedwait(sem_t * sem,const struct timespec * abs_timeout)96 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
97 {
98 int ret = 0;
99 uint64_t timeout_ms = 0;
100 struct timespec cur_time = {0};
101 struct timespec rel_time = {0};
102
103 if ((sem == NULL) || (abs_timeout == NULL)) {
104 errno = EINVAL;
105 return -1;
106 }
107
108 if ((abs_timeout->tv_sec < 0) || (abs_timeout->tv_nsec < 0)
109 || (abs_timeout->tv_nsec >= 1000000000UL)) {
110 errno = EINVAL;
111 return -1;
112 }
113
114 ret = clock_gettime(CLOCK_REALTIME, &cur_time);
115 if (ret != 0) {
116 return ret;
117 }
118 rel_time.tv_sec = abs_timeout->tv_sec - cur_time.tv_sec;
119 rel_time.tv_nsec = abs_timeout->tv_nsec - cur_time.tv_nsec;
120 /* Only millisecond precision is supported in AliOS Things. */
121 timeout_ms = ((rel_time.tv_sec > 0) ? rel_time.tv_sec : 0) * 1000 +
122 ((rel_time.tv_nsec > 0) ? rel_time.tv_nsec : 0) / 1000000;
123
124 ret = aos_sem_wait((aos_sem_t *)&(sem->aos_sem), timeout_ms);
125 if (ret != 0) {
126 errno = -ret;
127 return -1;
128 }
129
130 return 0;
131 }
132
133 /* unlock a semaphore */
sem_post(sem_t * sem)134 int sem_post(sem_t *sem)
135 {
136 if (sem == NULL) {
137 errno = EINVAL;
138 return -1;
139 }
140
141 aos_sem_signal((aos_sem_t *)&(sem->aos_sem));
142
143 return 0;
144 }
145
146 /* get the value of a semaphore */
sem_getvalue(sem_t * sem,int * sval)147 int sem_getvalue(sem_t *sem, int *sval)
148 {
149 if ((sem == NULL) || (sval == NULL)) {
150 errno = EINVAL;
151 return -1;
152 }
153
154 errno = ENOSYS;
155 return -1;
156 }
157
158 /* close a named semaphore */
sem_close(sem_t * sem)159 int sem_close(sem_t *sem)
160 {
161 if (sem == NULL) {
162 errno = EINVAL;
163 return -1;
164 }
165
166 errno = ENOSYS;
167 return -1;
168 }
169
170 /* remove a named semaphore */
sem_unlink(const char * name)171 int sem_unlink(const char *name)
172 {
173 if (name == NULL) {
174 errno = EINVAL;
175 return -1;
176 }
177
178 if (strlen(name) <= 0) {
179 errno = ENOENT;
180 return -1;
181 }
182
183 if (strlen(name) > SEM_NAME_MAX) {
184 errno = ENAMETOOLONG;
185 return -1;
186 }
187
188 errno = ENOSYS;
189 return -1;
190 }
191
192 /* destroy an unnamed semaphore */
sem_destroy(sem_t * sem)193 int sem_destroy(sem_t *sem)
194 {
195 if (sem == NULL) {
196 errno = EINVAL;
197 return -1;
198 }
199
200 aos_sem_free((aos_sem_t *)&(sem->aos_sem));
201
202 return 0;
203 }
204