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

#include <zephyr/ztest.h>
#include <zephyr/kernel.h>
#include <cmsis_os2.h>

#include <zephyr/irq_offload.h>
#include <zephyr/kernel_structs.h>

#define TIMEOUT_TICKS   (10)
#define FLAG1           (0x00000020)
#define FLAG2           (0x00000004)
#define FLAG            (FLAG1 | FLAG2)
#define ISR_FLAG        (0x50)
#define STACKSZ         CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE

static void thread1(void *arg)
{
	uint32_t flags;

	/* wait for FLAG1. It should return immediately as it is
	 * already triggered.
	 */
	flags = osThreadFlagsWait(FLAG1, osFlagsWaitAny | osFlagsNoClear, 0);
	zassert_equal(flags & FLAG1, FLAG1, "");

	/* Since the flags are not cleared automatically in the previous step,
	 * we should be able to get the same flags upon query below.
	 */
	flags = osThreadFlagsGet();
	zassert_equal(flags & FLAG1, FLAG1, "");

	/* Clear the Flag explicitly */
	flags = osThreadFlagsClear(FLAG1);
	zassert_not_equal(flags, osFlagsErrorParameter,
			  "ThreadFlagsClear failed");

	/* wait for FLAG1. It should timeout here as the flag
	 * though triggered, gets cleared in the previous step.
	 */
	flags = osThreadFlagsWait(FLAG1, osFlagsWaitAny, TIMEOUT_TICKS);
	zassert_equal(flags, osFlagsErrorTimeout, "ThreadFlagsWait failed");
}

static void thread2(void *arg)
{
	uint32_t flags;

	flags = osThreadFlagsWait(FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
	zassert_equal(flags & FLAG, FLAG,
		      "osThreadFlagsWait failed unexpectedly");

	/* validate by passing invalid parameters */
	zassert_equal(osThreadFlagsSet(NULL, 0), osFlagsErrorParameter,
		      "Invalid Thread Flags ID is unexpectedly working!");
	zassert_equal(osThreadFlagsSet(osThreadGetId(), 0x80010000),
		      osFlagsErrorParameter,
		      "Thread with MSB set is set unexpectedly");

	zassert_equal(osThreadFlagsClear(0x80010000), osFlagsErrorParameter,
		      "Thread with MSB set is cleared unexpectedly");

	/* cannot wait for Flag mask with MSB set */
	zassert_equal(osThreadFlagsWait(0x80010000, osFlagsWaitAny, 0),
		      osFlagsErrorParameter,
		      "ThreadFlagsWait passed unexpectedly");
}

static K_THREAD_STACK_DEFINE(test_stack1, STACKSZ);
static osThreadAttr_t thread1_attr = {
	.name = "Thread1",
	.stack_mem = &test_stack1,
	.stack_size = STACKSZ,
	.priority = osPriorityHigh,
};

static K_THREAD_STACK_DEFINE(test_stack2, STACKSZ);
static osThreadAttr_t thread2_attr = {
	.name = "Thread2",
	.stack_mem = &test_stack2,
	.stack_size = STACKSZ,
	.priority = osPriorityHigh,
};

ZTEST(cmsis_thread_flags, test_thread_flags_no_wait_timeout)
{
	osThreadId_t id1;
	uint32_t flags;

	id1 = osThreadNew(thread1, NULL, &thread1_attr);
	zassert_true(id1 != NULL, "Failed creating thread1");

	flags = osThreadFlagsSet(id1, FLAG1);
	zassert_equal(flags & FLAG1, FLAG1, "");

	/* Let id1 run to do the tests for Thread Flags */
	osDelay(TIMEOUT_TICKS);
}

ZTEST(cmsis_thread_flags, test_thread_flags_signalled)
{
	osThreadId_t id;
	uint32_t flags;

	id = osThreadNew(thread2, osThreadGetId(), &thread2_attr);
	zassert_true(id != NULL, "Failed creating thread2");

	flags = osThreadFlagsSet(id, FLAG1);
	zassert_equal(flags & FLAG1, FLAG1, "");

	/* Let id run to do the tests for Thread Flags */
	osDelay(TIMEOUT_TICKS / 2);

	flags = osThreadFlagsSet(id, FLAG2);
	zassert_equal(flags & FLAG2, FLAG2, "");

	/* z_thread has a higher priority over the other threads.
	 * Hence, this thread needs to be put to sleep for thread2
	 * to become the active thread.
	 */
	osDelay(TIMEOUT_TICKS / 2);
}

/* IRQ offload function handler to set Thread flag */
static void offload_function(const void *param)
{
	int flags;

	/* Make sure we're in IRQ context */
	zassert_true(k_is_in_isr(), "Not in IRQ context!");

	flags = osThreadFlagsSet((osThreadId_t)param, ISR_FLAG);
	zassert_equal(flags & ISR_FLAG, ISR_FLAG,
		      "ThreadFlagsSet failed in ISR");
}

void test_thread_flags_from_isr(void *thread_id)
{
	uint32_t flags;

	/**TESTPOINT: Offload to IRQ context*/
	irq_offload(offload_function, (const void *)osThreadGetId());

	flags = osThreadFlagsWait(ISR_FLAG, osFlagsWaitAll, TIMEOUT_TICKS);
	zassert_equal((flags & ISR_FLAG),
		      ISR_FLAG, "unexpected Thread flags value");
}

static K_THREAD_STACK_DEFINE(test_stack3, STACKSZ);
static osThreadAttr_t thread3_attr = {
	.name = "Thread3",
	.stack_mem = &test_stack3,
	.stack_size = STACKSZ,
	.priority = osPriorityHigh,
};

ZTEST(cmsis_thread_flags, test_thread_flags_isr)
{
	osThreadId_t id;

	id = osThreadNew(test_thread_flags_from_isr, osThreadGetId(),
			 &thread3_attr);
	zassert_true(id != NULL, "Failed creating thread");

	osDelay(TIMEOUT_TICKS);
}
ZTEST_SUITE(cmsis_thread_flags, NULL, NULL, NULL, NULL, NULL);
