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

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

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

/* the number of semaphore give/take cycles */
#define N_TEST_SEMA 1000

#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
/* stack used by the threads */
static K_THREAD_STACK_DEFINE(thread_one_stack, STACK_SIZE);

static struct k_thread thread_one_data;

K_SEM_DEFINE(lock_unlock_sema, 0, N_TEST_SEMA);

K_SEM_DEFINE(sem_bench, 0, 1);

timing_t timestamp_start_sema_t_c;
timing_t timestamp_end_sema_t_c;
timing_t timestamp_start_sema_g_c;
timing_t timestamp_end_sema_g_c;

void thread_sema_test1(void *p1, void *p2, void *p3)
{
	timestamp_start_sema_t_c = timing_counter_get();
	k_sem_take(&sem_bench, K_FOREVER);
	timestamp_end_sema_g_c = timing_counter_get();
}

int sema_context_switch(void)
{
	uint32_t diff;

	timing_start();

	k_thread_create(&thread_one_data, thread_one_stack,
			STACK_SIZE, thread_sema_test1,
			NULL, NULL, NULL,
			K_PRIO_PREEMPT(3), 0, K_FOREVER);
	k_thread_name_set(&thread_one_data, "sema_test1");
	k_thread_start(&thread_one_data);

	timestamp_end_sema_t_c = timing_counter_get();
	diff = timing_cycles_get(&timestamp_start_sema_t_c, &timestamp_end_sema_t_c);
	PRINT_STATS("Semaphore take time (context switch)", diff, false, "");


	timestamp_start_sema_g_c = timing_counter_get();
	k_sem_give(&sem_bench);
	diff = timing_cycles_get(&timestamp_start_sema_g_c, &timestamp_end_sema_g_c);
	PRINT_STATS("Semaphore give time (context switch)", diff, false, "");

	timing_stop();

	return 0;
}

/**
 *
 * @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(void)
{
	int i;
	uint32_t diff;
	timing_t timestamp_start;
	timing_t timestamp_end;
	const char *notes = "";
	int  end;

	bench_test_start();
	timing_start();

	timestamp_start = timing_counter_get();

	for (i = 0; i < N_TEST_SEMA; i++) {
		k_sem_give(&lock_unlock_sema);
	}

	timestamp_end = timing_counter_get();
	end = bench_test_end();
	timing_stop();

	if (end != 0) {
		error_count++;
		notes = TICK_OCCURRENCE_ERROR;
	}

	diff = timing_cycles_get(&timestamp_start, &timestamp_end);
	PRINT_STATS_AVG("Average semaphore signal time", diff, N_TEST_SEMA,
			false, notes);

	bench_test_start();
	timing_start();

	timestamp_start = timing_counter_get();

	for (i = 0; i < N_TEST_SEMA; i++) {
		k_sem_take(&lock_unlock_sema, K_FOREVER);
	}

	timestamp_end = timing_counter_get();
	end = bench_test_end();
	timing_stop();

	if (end != 0) {
		error_count++;
		notes = TICK_OCCURRENCE_ERROR;
	}

	diff = timing_cycles_get(&timestamp_start, &timestamp_end);
	PRINT_STATS_AVG("Average semaphore test time", diff, N_TEST_SEMA,
			false, notes);

	return 0;
}
