/*
 * Copyright (c) 2012-2015 Wind River Systems, Inc.
 * Copyright (c) 2023 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/*
 * @file measure time for sema lock and release
 *
 * This file contains the test that measures semaphore give and take time
 * in the kernel. There is no contention on the semaphore being tested.
 */

#include <zephyr/kernel.h>
#include <zephyr/timing/timing.h>
#include "utils.h"
#include "timing_sc.h"

static struct k_sem  sem;

static void alt_thread_entry(void *p1, void *p2, void *p3)
{
	uint32_t   num_iterations = (uint32_t)(uintptr_t)p1;
	timing_t   mid;

	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	for (uint32_t i = 0; i < num_iterations; i++) {

		/*
		 * 2. Give the semaphore, thereby forcing a context switch back
		 * to <start_thread>.
		 */

		mid = timing_timestamp_get();
		k_sem_give(&sem);

		/* 5. Share the <mid> timestamp. */

		timestamp.sample = mid;

		/* 6. Give <sem> so <start_thread> resumes execution */

		k_sem_give(&sem);
	}
}

static void start_thread_entry(void *p1, void *p2, void *p3)
{
	uint32_t   num_iterations = (uint32_t)(uintptr_t)p1;
	timing_t   start;
	timing_t   mid;
	timing_t   finish;
	uint32_t   i;
	uint64_t   take_sum = 0ull;
	uint64_t   give_sum = 0ull;

	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	k_thread_start(&alt_thread);

	for (i = 0; i < num_iterations; i++) {

		/*
		 * 1. Block on taking the semaphore and force a context switch
		 * to <alt_thread>.
		 */

		start = timing_timestamp_get();
		k_sem_take(&sem, K_FOREVER);

		/* 3. Get the <finish> timestamp. */

		finish = timing_timestamp_get();

		/*
		 * 4. Let <alt_thread> run so it can share its <mid>
		 * timestamp.
		 */

		k_sem_take(&sem, K_FOREVER);

		/* 7. Retrieve the <mid> timestamp */

		mid = timestamp.sample;

		take_sum += timing_cycles_get(&start, &mid);
		give_sum += timing_cycles_get(&mid, &finish);
	}

	k_thread_join(&alt_thread, K_FOREVER);

	/* Share the totals with the main thread */

	timestamp.cycles = take_sum;

	k_sem_take(&sem, K_FOREVER);

	timestamp.cycles = give_sum;
}

void sema_context_switch(uint32_t num_iterations,
			 uint32_t start_options, uint32_t alt_options)
{
	uint64_t  cycles;
	char description[80];
	int  priority;

	timing_start();

	priority = k_thread_priority_get(k_current_get());

	k_thread_create(&start_thread, start_stack,
			K_THREAD_STACK_SIZEOF(start_stack),
			start_thread_entry,
			(void *)(uintptr_t)num_iterations, NULL, NULL,
			priority - 2, start_options, K_FOREVER);

	k_thread_create(&alt_thread, alt_stack,
			K_THREAD_STACK_SIZEOF(alt_stack),
			alt_thread_entry,
			(void *)(uintptr_t)num_iterations, NULL, NULL,
			priority - 1, alt_options, K_FOREVER);

	k_thread_access_grant(&start_thread, &sem, &alt_thread);

	k_thread_access_grant(&alt_thread, &sem);

	/* Start the test threads */

	k_thread_start(&start_thread);

	/* Retrieve the number of cycles spent taking the semaphore */

	cycles = timestamp.cycles;
	cycles -= timestamp_overhead_adjustment(start_options, alt_options);

	snprintf(description, sizeof(description),
		 "Take a semaphore (context switch %c -> %c)",
		 ((start_options & K_USER) == K_USER) ? 'U' : 'K',
		 ((alt_options & K_USER) == K_USER) ? 'U' : 'K');
	PRINT_STATS_AVG(description, (uint32_t)cycles,
			num_iterations, false, "");

	/* Unblock <start_thread> */

	k_sem_give(&sem);

	/* Retrieve the number of cycles spent taking the semaphore */

	cycles = timestamp.cycles;
	cycles -= timestamp_overhead_adjustment(start_options, alt_options);

	snprintf(description, sizeof(description),
		 "Give a semaphore (context switch %c -> %c)",
		 ((alt_options & K_USER) == K_USER) ? 'U' : 'K',
		 ((start_options & K_USER) == K_USER) ? 'U' : 'K');
	PRINT_STATS_AVG(description, (uint32_t)cycles,
			num_iterations, false, "");

	k_thread_join(&start_thread, K_FOREVER);

	timing_stop();

	return;
}

/**
 * This is the entry point for the test that performs uncontested operations
 * on the semaphore. It gives the semaphore many times, takes the semaphore
 * many times and then sends the results back to the main thread.
 */
static void immediate_give_take(void *p1, void *p2, void *p3)
{
	uint32_t   num_iterations = (uint32_t)(uintptr_t)p1;
	timing_t   start;
	timing_t   finish;
	uint64_t   give_cycles;
	uint64_t   take_cycles;

	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	/* 1. Give a semaphore. No threads are waiting on it */

	start = timing_timestamp_get();

	for (uint32_t i = 0; i < num_iterations; i++) {
		k_sem_give(&sem);
	}

	finish = timing_timestamp_get();
	give_cycles = timing_cycles_get(&start, &finish);

	/* 2. Take a semaphore--no contention */

	start = timing_timestamp_get();

	for (uint32_t i = 0; i < num_iterations; i++) {
		k_sem_take(&sem, K_NO_WAIT);
	}

	finish = timing_timestamp_get();
	take_cycles = timing_cycles_get(&start, &finish);

	/* 3. Post the number of cycles spent giving the semaphore */

	timestamp.cycles = give_cycles;

	/* 4. Wait for the main thread to retrieve the data */

	k_sem_take(&sem, K_FOREVER);

	/* 7. Post the number of cycles spent taking the semaphore */

	timestamp.cycles = take_cycles;
}


/**
 *
 * @brief The function tests semaphore test/signal time
 *
 * The routine performs unlock the quite amount of semaphores and then
 * acquires them in order to measure the necessary time.
 *
 * @return 0 on success
 */
int sema_test_signal(uint32_t num_iterations, uint32_t options)
{
	uint64_t cycles;
	int priority;
	char description[80];

	timing_start();

	k_sem_init(&sem, 0, num_iterations);

	priority = k_thread_priority_get(k_current_get());

	k_thread_create(&start_thread, start_stack,
			K_THREAD_STACK_SIZEOF(start_stack),
			immediate_give_take,
			(void *)(uintptr_t)num_iterations, NULL, NULL,
			priority - 1, options, K_FOREVER);

	k_thread_access_grant(&start_thread, &sem);
	k_thread_start(&start_thread);

	/* 5. Retrieve the number of cycles spent giving the semaphore */

	cycles = timestamp.cycles;
	cycles -= timestamp_overhead_adjustment(options, options);

	snprintf(description, sizeof(description),
		 "Give a semaphore (no waiters) from %s thread",
		 (options & K_USER) == K_USER ? "user" : "kernel");

	PRINT_STATS_AVG(description, (uint32_t)cycles,
			num_iterations, false, "");

	/* 6. Unblock <start_thread> */

	k_sem_give(&sem);

	/* 8. Wait for <start_thread> to finish */

	k_thread_join(&start_thread, K_FOREVER);

	/* 9. Retrieve the number of cycles spent taking the semaphore */

	cycles = timestamp.cycles;
	cycles -= timestamp_overhead_adjustment(options, options);

	snprintf(description, sizeof(description),
		 "Take a semaphore (no blocking) from %s thread",
		 (options & K_USER) == K_USER ? "user" : "kernel");

	PRINT_STATS_AVG(description, (uint32_t)cycles,
			num_iterations, false, "");

	timing_stop();

	return 0;
}
