Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <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, 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 {
		return 0;
	}
}

/**
 * @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;
}