/*
 * Copyright (c) 2020 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/kernel.h>
#include <zephyr/random/random.h>
#include <zephyr/ztest.h>
#include <zephyr/sys/p4wq.h>

#define MAX_NUM_THREADS (CONFIG_MP_MAX_NUM_CPUS * 2)
#define NUM_THREADS (arch_num_cpus() * 2)
#define MAX_ITEMS (MAX_NUM_THREADS * 8)
#define MAX_EVENTS 1024

K_P4WQ_DEFINE(wq, MAX_NUM_THREADS, 2048);

static struct k_p4wq_work simple_item;
static volatile int has_run;
static volatile int run_count;
static volatile int spin_release;

struct test_item {
	struct k_p4wq_work item;
	bool active;
	bool running;
};

static struct k_spinlock lock;
static struct test_item items[MAX_ITEMS];
static int active_items;
static int event_count;
static bool stress_complete;

static void stress_handler(struct k_p4wq_work *item);

static void stress_sub(struct test_item *item)
{
	/* Choose a random preemptible priority higher than the idle
	 * priority, and a random deadline sometime within the next
	 * 2ms
	 */
	item->item.priority = sys_rand32_get() % (K_LOWEST_THREAD_PRIO - 1);
	item->item.deadline = sys_rand32_get() % k_ms_to_cyc_ceil32(2);
	item->item.handler = stress_handler;
	item->running = false;
	item->active = true;
	active_items++;
	k_p4wq_submit(&wq, &item->item);
}

static void stress_handler(struct k_p4wq_work *item)
{
	k_spinlock_key_t k = k_spin_lock(&lock);
	struct test_item *titem = CONTAINER_OF(item, struct test_item, item);

	titem->running = true;

	int curr_pri = k_thread_priority_get(k_current_get());

	zassert_true(curr_pri == item->priority,
		     "item ran with wrong priority: want %d have %d",
		     item->priority, curr_pri);

	if (stress_complete) {
		k_spin_unlock(&lock, k);
		return;
	}

	active_items--;

	/* Pick 0-3 random item slots and submit them if they aren't
	 * already.  Make sure we always have at least one active.
	 */
	int num_tries = sys_rand8_get() % 4;

	for (int i = 0; (active_items == 0) || (i < num_tries); i++) {
		int ii = sys_rand32_get() % MAX_ITEMS;

		if (items[ii].item.thread == NULL &&
		    &items[ii] != titem && !items[ii].active) {
			stress_sub(&items[ii]);
		}
	}

	if (event_count++ >= MAX_EVENTS) {
		stress_complete = true;
	}

	titem->active = false;
	k_spin_unlock(&lock, k);
}

/* Simple stress test designed to flood the queue and retires as many
 * items of random priority as possible.  Note that because of the
 * random priorities, this tends to produce a lot of "out of worker
 * threads" warnings from the queue as we randomly try to submit more
 * schedulable (i.e. high priority) items than there are threads to
 * run them.
 */
ZTEST(lib_p4wq, test_stress)
{
	k_thread_priority_set(k_current_get(), -1);
	memset(items, 0, sizeof(items));

	stress_complete = false;
	active_items = 1;
	items[0].item.priority = -1;
	stress_handler(&items[0].item);

	while (!stress_complete) {
		k_msleep(100);
	}
	k_msleep(10);

	zassert_true(event_count > 1, "stress tests didn't run");
}

static int active_count(void)
{
	/* Whitebox: count the number of BLOCKED threads, because the
	 * queue will unpend them synchronously in submit but the
	 * "active" list is maintained from the thread itself against
	 * which we can't synchronize easily.
	 */
	int count = 0;
	sys_dnode_t *dummy;

	SYS_DLIST_FOR_EACH_NODE(&wq.waitq.waitq, dummy) {
		count++;
	}

	count = MAX_NUM_THREADS - count;
	return count;
}

static void spin_handler(struct k_p4wq_work *item)
{
	while (!spin_release) {
		k_busy_wait(10);
	}
}

/* Selects and adds a new item to the queue, returns an indication of
 * whether the item changed the number of active threads.  Does not
 * return the item itself, not needed.
 */
static bool add_new_item(int pri)
{
	static int num_items;
	int n0 = active_count();
	struct k_p4wq_work *item = &items[num_items++].item;

	__ASSERT_NO_MSG(num_items < MAX_ITEMS);
	item->priority = pri;
	item->deadline = k_us_to_cyc_ceil32(100);
	item->handler = spin_handler;
	k_p4wq_submit(&wq, item);
	k_usleep(1);

	return (active_count() != n0);
}

/* Whitebox test of thread state: make sure that as we add threads
 * they get scheduled as needed, up to NUM_CPUS (at which point the
 * queue should STOP scheduling new threads).  Then add more at higher
 * priorities and verify that they get scheduled too (to allow
 * preemption), up to the maximum number of threads that we created.
 */
ZTEST(lib_p4wq, test_fill_queue)
{
	int p0 = 4;

	/* The work item priorities are 0-4, this thread should be -1
	 * so it's guaranteed not to be preempted
	 */
	k_thread_priority_set(k_current_get(), -1);

	/* Spawn enough threads so the queue saturates the CPU count
	 * (note they have lower priority than the current thread so
	 * we can be sure to run).  They should all be made active
	 * when added.
	 */
	unsigned int num_cpus = arch_num_cpus();
	unsigned int num_threads = NUM_THREADS;

	for (int i = 0; i < num_cpus; i++) {
		zassert_true(add_new_item(p0), "thread should be active");
	}

	/* Add one more, it should NOT be scheduled */
	zassert_false(add_new_item(p0), "thread should not be active");

	/* Now add more at higher priorities, they should get
	 * scheduled (so that they can preempt the running ones) until
	 * we run out of threads.
	 */
	for (int pri = p0 - 1; pri >= p0 - 4; pri++) {
		for (int i = 0; i < num_cpus; i++) {
			bool active = add_new_item(pri);

			if (!active) {
				zassert_equal(active_count(), num_threads,
					      "thread max not reached");
				goto done;
			}
		}
	}

 done:
	/* Clean up and wait for the threads to be idle */
	spin_release = 1;
	do {
		k_msleep(1);
	} while (active_count() != 0);
	k_msleep(1);
}

static void resubmit_handler(struct k_p4wq_work *item)
{
	if (run_count++ == 0) {
		k_p4wq_submit(&wq, item);
	} else {
		/* While we're here: validate that it doesn't show
		 * itself as "live" while executing
		 */
		zassert_false(k_p4wq_cancel(&wq, item),
			      "item should not be cancelable while running");
	}
}

/* Validate item can be resubmitted from its own handler */
ZTEST(lib_p4wq, test_resubmit)
{
	run_count = 0;
	simple_item = (struct k_p4wq_work){};
	simple_item.handler = resubmit_handler;
	k_p4wq_submit(&wq, &simple_item);

	k_msleep(100);
	zassert_equal(run_count, 2, "Wrong run count: %d\n", run_count);
}

void simple_handler(struct k_p4wq_work *work)
{
	zassert_equal(work, &simple_item, "bad work item pointer");
	zassert_false(has_run, "ran twice");
	has_run = true;
}

/* Simple test that submitted items run, and at the correct priority */
ZTEST(lib_p4wq_1cpu, test_p4wq_simple)
{
	int prio = 2;

	k_thread_priority_set(k_current_get(), prio);

	/* Lower priority item, should not run until we yield */
	simple_item.priority = prio + 1;
	simple_item.deadline = 0;
	simple_item.handler = simple_handler;

	has_run = false;
	k_p4wq_submit(&wq, &simple_item);
	zassert_false(has_run, "ran too early");

	k_msleep(10);
	zassert_true(has_run, "low-priority item didn't run");

	/* Higher priority, should preempt us */
	has_run = false;
	simple_item.priority = prio - 1;
	k_p4wq_submit(&wq, &simple_item);
	zassert_true(has_run, "high-priority item didn't run");
}

ZTEST_SUITE(lib_p4wq, NULL, NULL, NULL, NULL, NULL);
ZTEST_SUITE(lib_p4wq_1cpu, NULL, NULL, ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
