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