1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <zephyr/posix/pthread.h>
9
10 /**
11 * @brief Destroy semaphore.
12 *
13 * see IEEE 1003.1
14 */
sem_destroy(sem_t * semaphore)15 int sem_destroy(sem_t *semaphore)
16 {
17 if (semaphore == NULL) {
18 errno = EINVAL;
19 return -1;
20 }
21
22 if (k_sem_count_get(semaphore)) {
23 errno = EBUSY;
24 return -1;
25 }
26
27 k_sem_reset(semaphore);
28 return 0;
29 }
30
31 /**
32 * @brief Get value of semaphore.
33 *
34 * See IEEE 1003.1
35 */
sem_getvalue(sem_t * semaphore,int * value)36 int sem_getvalue(sem_t *semaphore, int *value)
37 {
38 if (semaphore == NULL) {
39 errno = EINVAL;
40 return -1;
41 }
42
43 *value = (int) k_sem_count_get(semaphore);
44
45 return 0;
46 }
47 /**
48 * @brief Initialize semaphore.
49 *
50 * See IEEE 1003.1
51 */
sem_init(sem_t * semaphore,int pshared,unsigned int value)52 int sem_init(sem_t *semaphore, int pshared, unsigned int value)
53 {
54 if (value > CONFIG_SEM_VALUE_MAX) {
55 errno = EINVAL;
56 return -1;
57 }
58
59 /*
60 * Zephyr has no concept of process, so only thread shared
61 * semaphore makes sense in here.
62 */
63 __ASSERT(pshared == 0, "pshared should be 0");
64
65 k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX);
66
67 return 0;
68 }
69
70 /**
71 * @brief Unlock a semaphore.
72 *
73 * See IEEE 1003.1
74 */
sem_post(sem_t * semaphore)75 int sem_post(sem_t *semaphore)
76 {
77 if (semaphore == NULL) {
78 errno = EINVAL;
79 return -1;
80 }
81
82 k_sem_give(semaphore);
83 return 0;
84 }
85
86 /**
87 * @brief Try time limited locking a semaphore.
88 *
89 * See IEEE 1003.1
90 */
sem_timedwait(sem_t * semaphore,struct timespec * abstime)91 int sem_timedwait(sem_t *semaphore, struct timespec *abstime)
92 {
93 int32_t timeout;
94 struct timespec current;
95 int64_t current_ms, abstime_ms;
96
97 __ASSERT(abstime, "abstime pointer NULL");
98
99 if ((abstime->tv_sec < 0) || (abstime->tv_nsec >= NSEC_PER_SEC)) {
100 errno = EINVAL;
101 return -1;
102 }
103
104 if (clock_gettime(CLOCK_REALTIME, ¤t) < 0) {
105 return -1;
106 }
107
108 abstime_ms = (int64_t)_ts_to_ms(abstime);
109 current_ms = (int64_t)_ts_to_ms(¤t);
110
111 if (abstime_ms <= current_ms) {
112 timeout = 0;
113 } else {
114 timeout = (int32_t)(abstime_ms - current_ms);
115 }
116
117 if (k_sem_take(semaphore, K_MSEC(timeout))) {
118 errno = ETIMEDOUT;
119 return -1;
120 }
121
122 return 0;
123 }
124
125 /**
126 * @brief Lock a semaphore if not taken.
127 *
128 * See IEEE 1003.1
129 */
sem_trywait(sem_t * semaphore)130 int sem_trywait(sem_t *semaphore)
131 {
132 if (k_sem_take(semaphore, K_NO_WAIT) == -EBUSY) {
133 errno = EAGAIN;
134 return -1;
135 } else {
136 return 0;
137 }
138 }
139
140 /**
141 * @brief Lock a semaphore.
142 *
143 * See IEEE 1003.1
144 */
sem_wait(sem_t * semaphore)145 int sem_wait(sem_t *semaphore)
146 {
147 /* With K_FOREVER, may return only success. */
148 (void)k_sem_take(semaphore, K_FOREVER);
149 return 0;
150 }
151