| /* |
| * Copyright (c) 2018 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <cmsis_os.h> |
| #include <string.h> |
| |
| K_MEM_SLAB_DEFINE(cmsis_semaphore_slab, sizeof(struct k_sem), |
| CONFIG_CMSIS_SEMAPHORE_MAX_COUNT, 4); |
| |
| /** |
| * @brief Create and Initialize a semaphore object. |
| */ |
| osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, |
| int32_t count) |
| { |
| struct k_sem *semaphore; |
| |
| if (semaphore_def == NULL) { |
| return NULL; |
| } |
| |
| if (k_is_in_isr()) { |
| return NULL; |
| } |
| |
| if (k_mem_slab_alloc(&cmsis_semaphore_slab, |
| (void **)&semaphore, K_MSEC(100)) == 0) { |
| (void)memset(semaphore, 0, sizeof(struct k_sem)); |
| } else { |
| return NULL; |
| } |
| |
| k_sem_init(semaphore, count, count); |
| |
| return (osSemaphoreId)semaphore; |
| } |
| |
| /** |
| * @brief Wait until a semaphore becomes available. |
| */ |
| int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t timeout) |
| { |
| struct k_sem *semaphore = (struct k_sem *) semaphore_id; |
| int status; |
| |
| if (semaphore_id == NULL) { |
| return -1; |
| } |
| |
| if (k_is_in_isr()) { |
| return -1; |
| } |
| |
| if (timeout == osWaitForever) { |
| status = k_sem_take(semaphore, K_FOREVER); |
| } else if (timeout == 0U) { |
| status = k_sem_take(semaphore, K_NO_WAIT); |
| } else { |
| status = k_sem_take(semaphore, K_MSEC(timeout)); |
| } |
| |
| /* If k_sem_take is successful, return the number of available |
| * tokens + 1. +1 is for accounting the currently acquired token. |
| * If it has timed out, return 0 (no tokens available). |
| */ |
| if (status == 0) { |
| return k_sem_count_get(semaphore) + 1; |
| } else if (status == -EBUSY || status == -EAGAIN) { |
| return 0; |
| } else { |
| return -1; |
| } |
| } |
| |
| /** |
| * @brief Release a semaphore that was obtained by osSemaphoreWait. |
| */ |
| osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) |
| { |
| struct k_sem *semaphore = (struct k_sem *) semaphore_id; |
| |
| if (semaphore_id == NULL) { |
| return osErrorParameter; |
| } |
| |
| /* All tokens have already been released */ |
| if (k_sem_count_get(semaphore) == semaphore->limit) { |
| return osErrorResource; |
| } |
| |
| k_sem_give(semaphore); |
| |
| return osOK; |
| } |
| |
| /** |
| * @brief Delete a semaphore that was created by osSemaphoreCreate. |
| */ |
| osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) |
| { |
| struct k_sem *semaphore = (struct k_sem *) semaphore_id; |
| |
| if (semaphore_id == NULL) { |
| return osErrorParameter; |
| } |
| |
| if (k_is_in_isr()) { |
| return osErrorISR; |
| } |
| |
| /* The status code "osErrorResource" (the semaphore object |
| * could not be deleted) is not supported in Zephyr. |
| */ |
| |
| k_mem_slab_free(&cmsis_semaphore_slab, (void *) &semaphore); |
| |
| return osOK; |
| } |