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

#include "test_sched.h"
#include <ksched.h>

#define THREAD_NUM 4

static struct k_thread tdata_prio[THREAD_NUM];
static struct k_thread tdata;
static int last_prio;
static uint8_t tid_num[4];
static struct k_sem sync_sema;


static void thread_entry(void *p1, void *p2, void *p3)
{
	last_prio = k_thread_priority_get(k_current_get());
}

static void thread_entry_prio(void *p1, void *p2, void *p3)
{
	static int i;

	k_sem_take(&sync_sema, K_MSEC(100));

	tid_num[i++] = POINTER_TO_INT(p1);
}


/* test cases */

/**
 * @brief Validate that the cooperative thread will
 * not be preempted
 *
 * @details Create a cooperative thread with priority higher
 * than the current cooperative thread. Make sure that the higher
 * priority thread will not preempt the lower priority cooperative
 * thread.
 *
 * @ingroup kernel_sched_tests
 */
ZTEST(threads_scheduling, test_priority_cooperative)
{
	int old_prio = k_thread_priority_get(k_current_get());

	/* set current thread to a negative priority */
	last_prio = -1;
	k_thread_priority_set(k_current_get(), last_prio);

	/* spawn thread with higher priority */
	int spawn_prio = last_prio - 1;

	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
				      thread_entry, NULL, NULL, NULL,
				      spawn_prio, 0, K_NO_WAIT);
	/* checkpoint: current thread shouldn't preempted by higher thread */
	zassert_true(last_prio == k_thread_priority_get(k_current_get()));
	k_sleep(K_MSEC(100));
	/* checkpoint: spawned thread get executed */
	zassert_true(last_prio == spawn_prio);
	k_thread_abort(tid);

	/* restore environment */
	k_thread_priority_set(k_current_get(), old_prio);
}

/**
 * @brief Validate preemptiveness of preemptive thread
 *
 * @details Create a preemptive thread which is of priority
 * lower than current thread. Current thread is made has preemptive.
 * Make sure newly created thread is not preempted. Now create a
 * preemptive thread which is of priority higher than current
 * thread. Make sure newly created thread is preempted
 *
 * @ingroup kernel_sched_tests
 */
ZTEST(threads_scheduling, test_priority_preemptible)
{
	int old_prio = k_thread_priority_get(k_current_get());

	/* set current thread to a non-negative priority */
	last_prio = 2;
	k_thread_priority_set(k_current_get(), last_prio);

	int spawn_prio = last_prio - 1;

	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
				      thread_entry, NULL, NULL, NULL,
				      spawn_prio, 0, K_NO_WAIT);
	/* checkpoint: thread is preempted by higher thread */
	zassert_true(last_prio == spawn_prio);

	k_sleep(K_MSEC(100));
	k_thread_abort(tid);

	spawn_prio = last_prio + 1;
	tid = k_thread_create(&tdata, tstack, STACK_SIZE,
			      thread_entry, NULL, NULL, NULL,
			      spawn_prio, 0, K_NO_WAIT);
	/* checkpoint: thread is not preempted by lower thread */
	zassert_false(last_prio == spawn_prio);
	k_thread_abort(tid);

	/* restore environment */
	k_thread_priority_set(k_current_get(), old_prio);
}

/**
 * @brief Validate scheduling sequence of preemptive threads with start delay
 *
 * @details Create four preemptive threads which are of priority
 * higher than current thread. Make sure that the highest priority
 * and longest waiting thread is scheduled first.
 *
 * @ingroup kernel_sched_tests
 */
ZTEST(threads_scheduling_1cpu, test_priority_preemptible_wait_prio)
{
	int old_prio = k_thread_priority_get(k_current_get());
	k_tid_t tid[THREAD_NUM];
	uint8_t tid_chk[4] =  { 0, 1, 2, 3 };

	k_sem_init(&sync_sema, 0, THREAD_NUM);

	/* Ensure that this code starts running at the start of a system tick */
	k_usleep(1);

	/* set current thread to a non-negative priority */
	last_prio = K_PRIO_PREEMPT(2);
	k_thread_priority_set(k_current_get(), last_prio);

	/* the highest-priority thread that has waited the longest */
	tid[0] = k_thread_create(&tdata_prio[0], tstacks[0], STACK_SIZE,
			thread_entry_prio, INT_TO_POINTER(0), NULL, NULL,
			K_PRIO_PREEMPT(0), 0, K_MSEC(10));
	/* the highest-priority thread that has waited the shorter */
	tid[1] = k_thread_create(&tdata_prio[1], tstacks[1], STACK_SIZE,
			thread_entry_prio, INT_TO_POINTER(1), NULL, NULL,
			K_PRIO_PREEMPT(0), 0, K_MSEC(20));
	/* the lowest-priority thread that has waited longest */
	tid[2] = k_thread_create(&tdata_prio[2], tstacks[2], STACK_SIZE,
			thread_entry_prio, INT_TO_POINTER(2), NULL, NULL,
			K_PRIO_PREEMPT(1), 0, K_MSEC(10));
	/* the lowest-priority thread that has waited shorter */
	tid[3] = k_thread_create(&tdata_prio[3], tstacks[3], STACK_SIZE,
			thread_entry_prio, INT_TO_POINTER(3), NULL, NULL,
			K_PRIO_PREEMPT(1), 0, K_MSEC(20));

	/* relinquish CPU for above threads to start */
	k_sleep(K_MSEC(30));

	for (int i = 0; i < THREAD_NUM; i++) {
		k_sem_give(&sync_sema);
	}

	zassert_true((memcmp(tid_num, tid_chk, 4) == 0),
		     "scheduling priority failed");

	/* test case tear down */
	for (int i = 0; i < THREAD_NUM; i++) {
		k_thread_abort(tid[i]);
	}

	/* restore environment */
	k_thread_priority_set(k_current_get(), old_prio);
}

extern void idle(void *p1, void *p2, void *p3);

/**
 * Validate checking priority values
 *
 * Our test cases don't cover every outcome of whether a priority is valid,
 * do so here.
 *
 * @ingroup kernel_sched_tests
 */
ZTEST(threads_scheduling, test_bad_priorities)
{
	struct prio_test {
		int prio;
		void *entry;
		bool result;
	} testcases[] = {
		{ K_IDLE_PRIO, idle, true },
		{ K_IDLE_PRIO, NULL, false },
		{ K_HIGHEST_APPLICATION_THREAD_PRIO - 1, NULL, false },
		{ K_LOWEST_APPLICATION_THREAD_PRIO + 1, NULL, false },
		{ K_HIGHEST_APPLICATION_THREAD_PRIO, NULL, true },
		{ K_LOWEST_APPLICATION_THREAD_PRIO, NULL, true },
		{ CONFIG_MAIN_THREAD_PRIORITY, NULL, true }
	};

	for (int i = 0; i < ARRAY_SIZE(testcases); i++) {
		zassert_equal(_is_valid_prio(testcases[i].prio,
					     testcases[i].entry),
			      testcases[i].result, "failed check %d", i);
		/* XXX why are these even separate APIs? */
		zassert_equal(Z_VALID_PRIO(testcases[i].prio,
					   testcases[i].entry),
			      testcases[i].result, "failed check %d", i);
	}
}
