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