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

#include <zephyr/kernel.h>
#include <string.h>
#include "wrapper.h"

K_MEM_SLAB_DEFINE(cv2_mutex_slab, sizeof(struct cv2_mutex),
		  CONFIG_CMSIS_V2_MUTEX_MAX_COUNT, 4);

static const osMutexAttr_t init_mutex_attrs = {
	.name = "ZephyrMutex",
	.attr_bits = osMutexPrioInherit,
	.cb_mem = NULL,
	.cb_size = 0,
};

/**
 * @brief Create and Initialize a Mutex object.
 */
osMutexId_t osMutexNew(const osMutexAttr_t *attr)
{
	struct cv2_mutex *mutex;

	if (k_is_in_isr()) {
		return NULL;
	}

	if (attr == NULL) {
		attr = &init_mutex_attrs;
	}

	__ASSERT(attr->attr_bits & osMutexPrioInherit,
		 "Zephyr supports osMutexPrioInherit by default. Do not unselect it\n");

	__ASSERT(!(attr->attr_bits & osMutexRobust),
		 "Zephyr does not support osMutexRobust.\n");

	if (k_mem_slab_alloc(&cv2_mutex_slab, (void **)&mutex, K_MSEC(100)) == 0) {
		memset(mutex, 0, sizeof(struct cv2_mutex));
	} else {
		return NULL;
	}

	k_mutex_init(&mutex->z_mutex);
	mutex->state = attr->attr_bits;

	if (attr->name == NULL) {
		strncpy(mutex->name, init_mutex_attrs.name,
			sizeof(mutex->name) - 1);
	} else {
		strncpy(mutex->name, attr->name, sizeof(mutex->name) - 1);
	}

	return (osMutexId_t)mutex;
}

/**
 * @brief Wait until a Mutex becomes available.
 */
osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)
{
	struct cv2_mutex *mutex = (struct cv2_mutex *) mutex_id;
	int status;

	if (mutex_id == NULL) {
		return osErrorParameter;
	}

	if (k_is_in_isr()) {
		return osErrorISR;
	}

	if (mutex->z_mutex.lock_count == 0U ||
	    mutex->z_mutex.owner == _current) {
	}

	/* Throw an error if the mutex is not configured to be recursive and
	 * the current thread is trying to acquire the mutex again.
	 */
	if ((mutex->state & osMutexRecursive) == 0U) {
		if ((mutex->z_mutex.owner == _current) &&
		    (mutex->z_mutex.lock_count != 0U)) {
			return osErrorResource;
		}
	}

	if (timeout == osWaitForever) {
		status = k_mutex_lock(&mutex->z_mutex, K_FOREVER);
	} else if (timeout == 0U) {
		status = k_mutex_lock(&mutex->z_mutex, K_NO_WAIT);
	} else {
		status = k_mutex_lock(&mutex->z_mutex,
				      K_TICKS(timeout));
	}

	if (status == -EBUSY) {
		return osErrorResource;
	} else if (status == -EAGAIN) {
		return osErrorTimeout;
	} else {
		return osOK;
	}
}

/**
 * @brief Release a Mutex that was obtained by osMutexWait.
 */
osStatus_t osMutexRelease(osMutexId_t mutex_id)
{
	struct cv2_mutex *mutex = (struct cv2_mutex *) mutex_id;

	if (mutex_id == NULL) {
		return osErrorParameter;
	}

	if (k_is_in_isr()) {
		return osErrorISR;
	}

	/* Mutex was not obtained before or was not owned by current thread */
	if ((mutex->z_mutex.lock_count == 0U) ||
	    (mutex->z_mutex.owner != _current)) {
		return osErrorResource;
	}

	k_mutex_unlock(&mutex->z_mutex);

	return osOK;
}

/**
 * @brief Delete a Mutex that was created by osMutexCreate.
 */
osStatus_t osMutexDelete(osMutexId_t mutex_id)
{
	struct cv2_mutex *mutex = (struct cv2_mutex *)mutex_id;

	if (mutex_id == NULL) {
		return osErrorParameter;
	}

	if (k_is_in_isr()) {
		return osErrorISR;
	}

	/* The status code "osErrorResource" (mutex specified by parameter
	 * mutex_id is in an invalid mutex state) is not supported in Zephyr.
	 */

	k_mem_slab_free(&cv2_mutex_slab, (void *) &mutex);

	return osOK;
}


osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)
{
	struct cv2_mutex *mutex = (struct cv2_mutex *)mutex_id;

	if (k_is_in_isr() || (mutex == NULL)) {
		return NULL;
	}

	/* Mutex was not obtained before */
	if (mutex->z_mutex.lock_count == 0U) {
		return NULL;
	}

	return get_cmsis_thread_id(mutex->z_mutex.owner);
}

const char *osMutexGetName(osMutexId_t mutex_id)
{
	struct cv2_mutex *mutex = (struct cv2_mutex *)mutex_id;

	if (k_is_in_isr() || (mutex == NULL)) {
		return NULL;
	}

	return mutex->name;
}
