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

/**
 * @file measure context switch time between cooperative threads
 *
 * This file contains thread (coop) context switch time measurement.
 * The thread starts two cooperative thread. One thread waits on a semaphore. The other,
 * after starting, releases a semaphore which enable the first thread to run.
 * Each thread increases a common global counter and context switch back and
 * forth by yielding the cpu. When counter reaches the maximal value, threads
 * stop and the average time of context switch is displayed.
 */

#include "timestamp.h"
#include "utils.h"

#include <arch/cpu.h>

/* number of context switches */
#define NCTXSWITCH   10000
#ifndef STACKSIZE
#define STACKSIZE    512
#endif

/* stack used by the fibers */
static K_THREAD_STACK_DEFINE(thread_one_stack, STACKSIZE);
static K_THREAD_STACK_DEFINE(thread_two_stack, STACKSIZE);
static struct k_thread thread_one_data;
static struct k_thread thread_two_data;

static u32_t timestamp;

/* context switches counter */
static volatile u32_t ctx_switch_counter;

/* context switch balancer. Incremented by one thread, decremented by another*/
static volatile int ctx_switch_balancer;

K_SEM_DEFINE(sync_sema, 0, 1);

/**
 *
 * thread_onne
 *
 * Fiber makes all the test preparations: registers the interrupt handler,
 * gets the first timestamp and invokes the software interrupt.
 *
 * @return N/A
 */
static void thread_one(void)
{
	k_sem_take(&sync_sema, K_FOREVER);
	timestamp = TIME_STAMP_DELTA_GET(0);
	while (ctx_switch_counter < NCTXSWITCH) {
		k_yield();
		ctx_switch_counter++;
		ctx_switch_balancer--;
	}
	timestamp = TIME_STAMP_DELTA_GET(timestamp);
}

/**
 *
 * @brief Check the time when it gets executed after the semaphore
 *
 * Fiber starts, waits on semaphore. When the interrupt handler releases
 * the semaphore, thread  measures the time.
 *
 * @return 0 on success
 */
static void thread_two(void)
{
	k_sem_give(&sync_sema);
	while (ctx_switch_counter < NCTXSWITCH) {
		k_yield();
		ctx_switch_counter++;
		ctx_switch_balancer++;
	}
}

/**
 *
 * @brief The test main function
 *
 * @return 0 on success
 */
int coop_ctx_switch(void)
{
	PRINT_FORMAT(" 6 - Measure average context switch time between threads (coop)");
	ctx_switch_counter = 0;
	ctx_switch_balancer = 0;

	bench_test_start();
	k_thread_create(&thread_one_data, thread_one_stack, STACKSIZE,
			(k_thread_entry_t) thread_one, NULL, NULL, NULL,
			6, 0, K_NO_WAIT);
	k_thread_create(&thread_two_data, thread_two_stack, STACKSIZE,
			(k_thread_entry_t) thread_two, NULL, NULL, NULL,
			6, 0, K_NO_WAIT);

	if (ctx_switch_balancer > 3 || ctx_switch_balancer < -3) {
		PRINT_FORMAT(" Balance is %d. FAILED", ctx_switch_balancer);
	} else if (bench_test_end() != 0) {
		error_count++;
		PRINT_OVERFLOW_ERROR();
	} else {
		PRINT_FORMAT(" Average context switch time is %u tcs = %u"
			     " nsec",
			     timestamp / ctx_switch_counter,
			     SYS_CLOCK_HW_CYCLES_TO_NS_AVG(timestamp,
							   ctx_switch_counter));
	}

	return 0;
}
