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

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

#ifdef CONFIG_TIMESLICING

/* nrf 51 has lower ram, so creating less number of threads */
#if CONFIG_SRAM_SIZE <= 24
	#define NUM_THREAD 2
#elif (CONFIG_SRAM_SIZE <= 32) \
	|| defined(CONFIG_SOC_EMSK_EM7D)
	#define NUM_THREAD 3
#else
	#define NUM_THREAD 10
#endif
#define BASE_PRIORITY 0
#define ITRERATION_COUNT 5

BUILD_ASSERT(NUM_THREAD <= MAX_NUM_THREAD);
/* slice size in millisecond */
#define SLICE_SIZE 200
#define PERTHREAD_SLICE_TICKS 64
#define TICK_SLOP 4
/* busy for more than one slice */
#define BUSY_MS (SLICE_SIZE + 20)
static struct k_thread t[NUM_THREAD];

static K_SEM_DEFINE(sema1, 0, NUM_THREAD);
/* elapsed_slice taken by last thread */
static int64_t elapsed_slice;

static int thread_idx;

static void thread_tslice(void *p1, void *p2, void *p3)
{
	int idx = POINTER_TO_INT(p1);

	/* Print New line for last thread */
	int thread_parameter = (idx == (NUM_THREAD - 1)) ? '\n' :
			       (idx + 'A');

	int64_t expected_slice_min = k_ticks_to_ms_floor64(k_ms_to_ticks_ceil32(SLICE_SIZE) - 1);
	int64_t expected_slice_max = k_ticks_to_ms_ceil64(k_ms_to_ticks_ceil32(SLICE_SIZE) + 1);

	/* Clumsy, but need to handle the precision loss with
	 * submillisecond ticks.  It's always possible to alias and
	 * produce a tdelta of "1", no matter how fast ticks are.
	 */
	if (expected_slice_max == expected_slice_min) {
		expected_slice_max = expected_slice_min + 1;
	}

	while (1) {
		int64_t tdelta = k_uptime_delta(&elapsed_slice);
		TC_PRINT("%c", thread_parameter);
		/* Test Fails if thread exceed allocated time slice or
		 * Any thread is scheduled out of order.
		 */
		zassert_true(((tdelta >= expected_slice_min) &&
			      (tdelta <= expected_slice_max) &&
			      (idx == thread_idx)), NULL);
		thread_idx = (thread_idx + 1) % (NUM_THREAD);

		/* Keep the current thread busy for more than one slice,
		 * even though, when timeslice used up the next thread
		 * should be scheduled in.
		 */
		spin_for_ms(BUSY_MS);
		k_sem_give(&sema1);
	}
}

/* test cases */

/**
 * @brief Check the behavior of preemptive threads when the
 * time slice is disabled and enabled
 *
 * @details Create multiple preemptive threads with same priorities
 * and few with same priorities and enable the time slice.
 * Ensure that each thread is given the time slice period to execute.
 *
 * @ingroup kernel_sched_tests
 */
void test_slice_scheduling(void)
{
	k_tid_t tid[NUM_THREAD];
	int old_prio = k_thread_priority_get(k_current_get());
	int count = 0;

	/* disable timeslice */
	k_sched_time_slice_set(0, K_PRIO_PREEMPT(0));

	/* update priority for current thread */
	k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(BASE_PRIORITY));

	/* create threads with equal preemptive priority */
	for (int i = 0; i < NUM_THREAD; i++) {
		tid[i] = k_thread_create(&t[i], tstacks[i], STACK_SIZE,
					 thread_tslice,
					 INT_TO_POINTER(i), NULL, NULL,
					 K_PRIO_PREEMPT(BASE_PRIORITY), 0,
					 K_NO_WAIT);
	}

	/* enable time slice */
	k_sched_time_slice_set(SLICE_SIZE, K_PRIO_PREEMPT(BASE_PRIORITY));

	while (count < ITRERATION_COUNT) {
		k_uptime_delta(&elapsed_slice);

		/* Keep the current thread busy for more than one slice,
		 * even though, when timeslice used up the next thread
		 * should be scheduled in.
		 */
		spin_for_ms(BUSY_MS);

		/* relinquish CPU and wait for each thread to complete */
		for (int i = 0; i < NUM_THREAD; i++) {
			k_sem_take(&sema1, K_FOREVER);
		}
		count++;
	}


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

	/* disable time slice */
	k_sched_time_slice_set(0, K_PRIO_PREEMPT(0));

	k_thread_priority_set(k_current_get(), old_prio);
}

static volatile int32_t perthread_count;
static volatile uint32_t last_cyc;
static volatile bool perthread_running;
static K_SEM_DEFINE(perthread_sem, 0, 1);

static void slice_expired(struct k_thread *thread, void *data)
{
	zassert_equal(thread, data, "wrong callback data pointer");

	uint32_t now = k_cycle_get_32();
	uint32_t dt = k_cyc_to_ticks_near32(now - last_cyc);

	zassert_true(perthread_running, "thread didn't start");
	zassert_true(dt >= (PERTHREAD_SLICE_TICKS - TICK_SLOP),
		     "slice expired >%d ticks too soon (dt=%d)", TICK_SLOP, dt);
	zassert_true((dt - PERTHREAD_SLICE_TICKS) <= TICK_SLOP,
		     "slice expired >%d ticks late (dt=%d)", TICK_SLOP, dt);

	last_cyc = now;

	/* First time through, just let the slice expire and keep
	 * running.  Second time, abort the thread and wake up the
	 * main test function.
	 */
	if (perthread_count++ != 0) {
		k_thread_abort(thread);
		perthread_running = false;
		k_sem_give(&perthread_sem);
	}
}

static void slice_perthread_fn(void *a, void *b, void *c)
{
	ARG_UNUSED(a); ARG_UNUSED(b); ARG_UNUSED(c);
	while (true) {
		perthread_running = true;
		k_busy_wait(10);
	}
}

void test_slice_perthread(void)
{
	if (!IS_ENABLED(CONFIG_TIMESLICE_PER_THREAD)) {
		ztest_test_skip();
		return;
	}

	/* Create the thread but don't start it */
	k_thread_create(&t[0], tstacks[0], STACK_SIZE,
			slice_perthread_fn, NULL, NULL, NULL,
			1, 0, K_FOREVER);
	k_thread_time_slice_set(&t[0], PERTHREAD_SLICE_TICKS, slice_expired, &t[0]);

	/* Tick align, set up, then start */
	k_usleep(1);
	last_cyc = k_cycle_get_32();
	k_thread_start(&t[0]);

	k_sem_take(&perthread_sem, K_FOREVER);
	zassert_false(perthread_running, "thread failed to suspend");
}

#else /* CONFIG_TIMESLICING */
void test_slice_scheduling(void)
{
	ztest_test_skip();
}
void test_slice_perthread(void)
{
	ztest_test_skip();
}
#endif /* CONFIG_TIMESLICING */
