1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <cmsis_os.h>
9 #include <string.h>
10 
11 K_MEM_SLAB_DEFINE(cmsis_semaphore_slab, sizeof(struct k_sem),
12 		CONFIG_CMSIS_SEMAPHORE_MAX_COUNT, 4);
13 
14 /**
15  * @brief Create and Initialize a semaphore object.
16  */
osSemaphoreCreate(const osSemaphoreDef_t * semaphore_def,int32_t count)17 osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def,
18 				int32_t count)
19 {
20 	struct k_sem *semaphore;
21 
22 	if (semaphore_def == NULL) {
23 		return NULL;
24 	}
25 
26 	if (k_is_in_isr()) {
27 		return NULL;
28 	}
29 
30 	if (k_mem_slab_alloc(&cmsis_semaphore_slab,
31 				(void **)&semaphore, K_MSEC(100)) == 0) {
32 		(void)memset(semaphore, 0, sizeof(struct k_sem));
33 	} else {
34 		return NULL;
35 	}
36 
37 	k_sem_init(semaphore, count, count);
38 
39 	return (osSemaphoreId)semaphore;
40 }
41 
42 /**
43  * @brief Wait until a semaphore becomes available.
44  */
osSemaphoreWait(osSemaphoreId semaphore_id,uint32_t timeout)45 int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t timeout)
46 {
47 	struct k_sem *semaphore = (struct k_sem *) semaphore_id;
48 	int status;
49 
50 	if (semaphore_id == NULL) {
51 		return -1;
52 	}
53 
54 	if (k_is_in_isr()) {
55 		return -1;
56 	}
57 
58 	if (timeout == osWaitForever) {
59 		status = k_sem_take(semaphore, K_FOREVER);
60 	} else if (timeout == 0U) {
61 		status = k_sem_take(semaphore, K_NO_WAIT);
62 	} else {
63 		status = k_sem_take(semaphore, K_MSEC(timeout));
64 	}
65 
66 	/* If k_sem_take is successful, return the number of available
67 	 * tokens + 1. +1 is for accounting the currently acquired token.
68 	 * If it has timed out, return 0 (no tokens available).
69 	 */
70 	if (status == 0) {
71 		return k_sem_count_get(semaphore) + 1;
72 	} else if (status == -EBUSY || status == -EAGAIN) {
73 		return 0;
74 	} else {
75 		return -1;
76 	}
77 }
78 
79 /**
80  * @brief Release a semaphore that was obtained by osSemaphoreWait.
81  */
osSemaphoreRelease(osSemaphoreId semaphore_id)82 osStatus osSemaphoreRelease(osSemaphoreId semaphore_id)
83 {
84 	struct k_sem *semaphore = (struct k_sem *) semaphore_id;
85 
86 	if (semaphore_id == NULL) {
87 		return osErrorParameter;
88 	}
89 
90 	/* All tokens have already been released */
91 	if (k_sem_count_get(semaphore) == semaphore->limit) {
92 		return osErrorResource;
93 	}
94 
95 	k_sem_give(semaphore);
96 
97 	return osOK;
98 }
99 
100 /**
101  * @brief Delete a semaphore that was created by osSemaphoreCreate.
102  */
osSemaphoreDelete(osSemaphoreId semaphore_id)103 osStatus osSemaphoreDelete(osSemaphoreId semaphore_id)
104 {
105 	struct k_sem *semaphore = (struct k_sem *) semaphore_id;
106 
107 	if (semaphore_id == NULL) {
108 		return osErrorParameter;
109 	}
110 
111 	if (k_is_in_isr()) {
112 		return osErrorISR;
113 	}
114 
115 	/* The status code "osErrorResource" (the semaphore object
116 	 * could not be deleted) is not supported in Zephyr.
117 	 */
118 
119 	k_mem_slab_free(&cmsis_semaphore_slab, (void *)semaphore);
120 
121 	return osOK;
122 }
123