/*
 * 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 char __stack test_thread_stack[THREAD_STACK];
static char __stack 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);
}
