1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <string.h>
9 #include "wrapper.h"
10 
11 K_MEM_SLAB_DEFINE(cv2_semaphore_slab, sizeof(struct cv2_sem),
12 		  CONFIG_CMSIS_V2_SEMAPHORE_MAX_COUNT, 4);
13 
14 static const osSemaphoreAttr_t init_sema_attrs = {
15 	.name = "ZephyrSem",
16 	.attr_bits = 0,
17 	.cb_mem = NULL,
18 	.cb_size = 0,
19 };
20 
21 /**
22  * @brief Create and Initialize a semaphore object.
23  */
osSemaphoreNew(uint32_t max_count,uint32_t initial_count,const osSemaphoreAttr_t * attr)24 osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count,
25 			       const osSemaphoreAttr_t *attr)
26 {
27 	struct cv2_sem *semaphore;
28 
29 	if (k_is_in_isr()) {
30 		return NULL;
31 	}
32 
33 	if (attr == NULL) {
34 		attr = &init_sema_attrs;
35 	}
36 
37 	if (k_mem_slab_alloc(&cv2_semaphore_slab,
38 			     (void **)&semaphore, K_MSEC(100)) == 0) {
39 		(void)memset(semaphore, 0, sizeof(struct cv2_sem));
40 	} else {
41 		return NULL;
42 	}
43 
44 	k_sem_init(&semaphore->z_semaphore, initial_count, max_count);
45 
46 	if (attr->name == NULL) {
47 		strncpy(semaphore->name, init_sema_attrs.name,
48 			sizeof(semaphore->name) - 1);
49 	} else {
50 		strncpy(semaphore->name, attr->name,
51 			sizeof(semaphore->name) - 1);
52 	}
53 
54 	return (osSemaphoreId_t)semaphore;
55 }
56 
57 /**
58  * @brief Wait until a semaphore becomes available.
59  */
osSemaphoreAcquire(osSemaphoreId_t semaphore_id,uint32_t timeout)60 osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
61 {
62 	struct cv2_sem *semaphore = (struct cv2_sem *) semaphore_id;
63 	int status;
64 
65 	if (semaphore_id == NULL) {
66 		return osErrorParameter;
67 	}
68 
69 	/* Can be called from ISRs only if timeout is set to 0 */
70 	if (timeout > 0 && k_is_in_isr()) {
71 		return osErrorParameter;
72 	}
73 
74 	if (timeout == osWaitForever) {
75 		status = k_sem_take(&semaphore->z_semaphore, K_FOREVER);
76 	} else if (timeout == 0U) {
77 		status = k_sem_take(&semaphore->z_semaphore, K_NO_WAIT);
78 	} else {
79 		status = k_sem_take(&semaphore->z_semaphore,
80 				    K_TICKS(timeout));
81 	}
82 
83 	if (status == -EBUSY) {
84 		return osErrorResource;
85 	} else if (status == -EAGAIN) {
86 		return osErrorTimeout;
87 	} else {
88 		return osOK;
89 	}
90 }
91 
osSemaphoreGetCount(osSemaphoreId_t semaphore_id)92 uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
93 {
94 	struct cv2_sem *semaphore = (struct cv2_sem *)semaphore_id;
95 
96 	if (semaphore_id == NULL) {
97 		return 0;
98 	}
99 
100 	return k_sem_count_get(&semaphore->z_semaphore);
101 }
102 
103 /**
104  * @brief Release a semaphore that was obtained by osSemaphoreWait.
105  */
osSemaphoreRelease(osSemaphoreId_t semaphore_id)106 osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
107 {
108 	struct cv2_sem *semaphore = (struct cv2_sem *) semaphore_id;
109 
110 	if (semaphore_id == NULL) {
111 		return osErrorParameter;
112 	}
113 
114 	/* All tokens have already been released */
115 	if (k_sem_count_get(&semaphore->z_semaphore) ==
116 	    semaphore->z_semaphore.limit) {
117 		return osErrorResource;
118 	}
119 
120 	k_sem_give(&semaphore->z_semaphore);
121 
122 	return osOK;
123 }
124 
125 /**
126  * @brief Delete a semaphore that was created by osSemaphoreCreate.
127  */
osSemaphoreDelete(osSemaphoreId_t semaphore_id)128 osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
129 {
130 	struct cv2_sem *semaphore = (struct cv2_sem *)semaphore_id;
131 
132 	if (semaphore_id == NULL) {
133 		return osErrorParameter;
134 	}
135 
136 	if (k_is_in_isr()) {
137 		return osErrorISR;
138 	}
139 
140 	/* The status code "osErrorResource" (the semaphore specified by
141 	 * parameter semaphore_id is in an invalid semaphore state) is not
142 	 * supported in Zephyr.
143 	 */
144 
145 	k_mem_slab_free(&cv2_semaphore_slab, (void *) &semaphore);
146 
147 	return osOK;
148 }
149 
osSemaphoreGetName(osSemaphoreId_t semaphore_id)150 const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
151 {
152 	struct cv2_sem *semaphore = (struct cv2_sem *)semaphore_id;
153 
154 	if (!k_is_in_isr() && (semaphore_id != NULL)) {
155 		return semaphore->name;
156 	} else {
157 		return NULL;
158 	}
159 }
160