/*
 * Copyright (c) 2016 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/*
 * @file
 * @brief Test nanokernel sleep and wakeup APIs
 *
 * This module tests the following sleep and wakeup scenarios:
 * 1. k_sleep() without cancellation
 * 2. k_sleep() cancelled via k_wakeup()
 * 3. k_sleep() cancelled via k_wakeup()
 * 4. k_sleep() cancelled via k_wakeup()
 * 5. k_sleep() - no cancellation exists
 */

#include <tc_util.h>
#include <arch/cpu.h>
#include <misc/util.h>
#include <irq_offload.h>
#include <stdbool.h>

#include <util_test_common.h>

#if defined(CONFIG_ASSERT) && defined(CONFIG_DEBUG)
#define THREAD_STACK    (384 + CONFIG_TEST_EXTRA_STACKSIZE)
#else
#define THREAD_STACK    (256 + CONFIG_TEST_EXTRA_STACKSIZE)
#endif

#define TEST_THREAD_PRIORITY	-4
#define HELPER_THREAD_PRIORITY  -10

#define ONE_SECOND  (MSEC_PER_SEC)
#define TICKS_PER_MS  MSEC_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC

static struct k_sem test_thread_sem;
static struct k_sem helper_thread_sem;
static struct k_sem task_sem;

static K_THREAD_STACK_DEFINE(test_thread_stack, THREAD_STACK);
static K_THREAD_STACK_DEFINE(helper_thread_stack, THREAD_STACK);

static k_tid_t  test_thread_id;
static k_tid_t  helper_thread_id;

static struct k_thread test_thread_data;
static struct k_thread helper_thread_data;

static bool test_failure = true;     /* Assume the test will fail */

static void test_objects_init(void)
{
	k_sem_init(&test_thread_sem, 0, UINT_MAX);
	k_sem_init(&helper_thread_sem, 0, UINT_MAX);
	k_sem_init(&task_sem, 0, UINT_MAX);

	TC_PRINT("Kernel objects initialized\n");
}

static void align_to_tick_boundary(void)
{
	u32_t tick;

	tick = k_uptime_get_32();
	while (k_uptime_get_32() == tick) {
		/* Busy wait to align to tick boundary */
	}

}

/* Shouldn't ever sleep for less than requested time, but allow for 1
 * tick of "too long" slop for aliasing between wakeup and
 * measurement. Qemu at least will leak the external world's clock
 * rate into the simulator when the host is under load.
 */
static int sleep_time_valid(u32_t start, u32_t end, u32_t dur)
{
	u32_t dt = end - start;

	return dt >= dur && dt <= (dur + 1);
}

static void test_thread(int arg1, int arg2)
{
	u32_t start_tick;
	u32_t end_tick;

	k_sem_take(&test_thread_sem, K_FOREVER);

	TC_PRINT("Testing normal expiration of k_sleep()\n");
	align_to_tick_boundary();

	start_tick = k_uptime_get_32();

	/* FIXME: one tick less to account for
	 * one  extra tick for _TICK_ALIGN in k_sleep*/
	k_sleep(ONE_SECOND - TICKS_PER_MS);
	end_tick = k_uptime_get_32();

	if (!sleep_time_valid(start_tick, end_tick, ONE_SECOND)) {
		TC_ERROR(" *** k_sleep() slept for %d ticks not %d.",
				 end_tick - start_tick, ONE_SECOND);

		return;
	}

	TC_PRINT("Testing: test thread sleep + helper thread wakeup test\n");
	k_sem_give(&helper_thread_sem);   /* Activate helper fiber */
	align_to_tick_boundary();

	start_tick = k_uptime_get_32();
	/* FIXME: one tick less to account for
	 * one  extra tick for _TICK_ALIGN in k_sleep*/
	k_sleep(ONE_SECOND - TICKS_PER_MS);
	end_tick = k_uptime_get_32();

	if (end_tick - start_tick > 1) {
		TC_ERROR(" *** k_wakeup() took too long (%d ticks) \n",
				 end_tick - start_tick);
		return;
	}

	TC_PRINT("Testing: test thread sleep + isr offload wakeup test\n");
	k_sem_give(&helper_thread_sem);   /* Activate helper fiber */
	align_to_tick_boundary();

	start_tick = k_uptime_get_32();
	/* FIXME: one tick less to account for
	 * one  extra tick for _TICK_ALIGN in k_sleep*/
	k_sleep(ONE_SECOND - TICKS_PER_MS);
	end_tick = k_uptime_get_32();

	if (end_tick - start_tick > 1) {
		TC_ERROR(" *** k_wakeup() took too long (%d ticks)\n",
				 end_tick - start_tick);
		return;
	}

	TC_PRINT("Testing: test thread sleep + main wakeup test thread\n");
	k_sem_give(&task_sem);    /* Activate task */
	align_to_tick_boundary();

	start_tick = k_uptime_get_32();

	/* FIXME: one tick less to account for
	 * one  extra tick for _TICK_ALIGN in k_sleep*/
	k_sleep(ONE_SECOND - TICKS_PER_MS);           /* Task will execute */
	end_tick = k_uptime_get_32();

	if (end_tick - start_tick > 1) {
		TC_ERROR(" *** k_wakeup() took too long (%d ticks) at LAST\n",
				 end_tick - start_tick);
		return;
	}

	test_failure = false;
}

static void irq_offload_isr(void *arg)
{

	k_wakeup((k_tid_t) arg);
}

static void helper_thread(int arg1, int arg2)
{

	k_sem_take(&helper_thread_sem, K_FOREVER);

	/* Wake the test fiber */
	k_wakeup(test_thread_id);
	k_sem_take(&helper_thread_sem, K_FOREVER);

	/* Wake the test fiber from an ISR */
	irq_offload(irq_offload_isr, (void *)test_thread_id);
}

void main(void)
{
	int       status = TC_FAIL;
	u32_t  start_tick;
	u32_t  end_tick;

	TC_START("Test kernel Sleep and Wakeup APIs\n");

	test_objects_init();

	test_thread_id = k_thread_create(&test_thread_data, test_thread_stack,
					 THREAD_STACK,
					 (k_thread_entry_t) test_thread,
					 0, 0, NULL, TEST_THREAD_PRIORITY,
					 0, 0);

	TC_PRINT("Test thread started: id = %p\n", test_thread_id);

	helper_thread_id = k_thread_create(&helper_thread_data,
					   helper_thread_stack, THREAD_STACK,
					   (k_thread_entry_t) helper_thread,
					   0, 0, NULL, HELPER_THREAD_PRIORITY,
					   0, 0);

	TC_PRINT("Helper thread started: id = %p\n", helper_thread_id);

	/* Activate test_thread */
	k_sem_give(&test_thread_sem);

	/* Wait for test_thread to activate us */
	k_sem_take(&task_sem, K_FOREVER);

	/* Wake the test fiber */
	k_wakeup(test_thread_id);

	if (test_failure) {
		goto done_tests;
	}

	TC_PRINT("Testing kernel k_sleep()\n");
	align_to_tick_boundary();
	start_tick = k_uptime_get_32();
	/* FIXME: one tick less to account for
	 * one  extra tick for _TICK_ALIGN in k_sleep*/
	k_sleep(ONE_SECOND - TICKS_PER_MS);
	end_tick = k_uptime_get_32();

	if (!sleep_time_valid(start_tick, end_tick, ONE_SECOND)) {
		TC_ERROR("k_sleep() slept for %d ticks, not %d\n",
			end_tick - start_tick, ONE_SECOND);
		goto done_tests;
	}

	status = TC_PASS;

done_tests:
	TC_END_REPORT(status);
}
