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

#include <ztest.h>
#include <zephyr.h>
#include <errno.h>

/**
 * @brief Test the thread context
 *
 * @defgroup kernel_threadcontext_tests Thread Context Tests
 *
 * @ingroup all_tests
 *
 * @{
 * @}
 */
#define N_THREADS 2
#define STACK_SIZE (384 + CONFIG_TEST_EXTRA_STACK_SIZE)

static K_THREAD_STACK_ARRAY_DEFINE(stacks, N_THREADS, STACK_SIZE);
static struct k_thread threads[N_THREADS];

K_THREAD_STACK_DEFINE(eno_stack, STACK_SIZE);
struct k_thread eno_thread;

static int errno_values[N_THREADS + 1] = {
	0xbabef00d,
	0xdeadbeef,
	0xabad1dea,
};

struct result {
	void *q;
	int pass;
};

struct result result[N_THREADS];

struct k_fifo fifo;

static void errno_thread(void *_n, void *_my_errno, void *_unused)
{
	int n = POINTER_TO_INT(_n);
	int my_errno = POINTER_TO_INT(_my_errno);

	errno = my_errno;

	k_msleep(30 - (n * 10));
	if (errno == my_errno) {
		result[n].pass = TC_PASS;
	}

	zassert_equal(errno, my_errno, NULL);

	k_fifo_put(&fifo, &result[n]);
}

/**
 * @brief Verify thread context
 *
 * @ingroup kernel_threadcontext_tests
 *
 * @details Check whether variable value per-thread are saved during
 *	context switch
 */
void test_thread_context(void)
{
	int rv = TC_PASS, test_errno;

	k_fifo_init(&fifo);

	errno = errno_values[N_THREADS];
	test_errno = errno;

	for (int ii = 0; ii < N_THREADS; ii++) {
		result[ii].pass = TC_FAIL;
	}

	/**TESTPOINT: thread- threads stacks are separate */
	for (int ii = 0; ii < N_THREADS; ii++) {
		k_thread_create(&threads[ii], stacks[ii], STACK_SIZE,
				errno_thread, INT_TO_POINTER(ii),
				INT_TO_POINTER(errno_values[ii]), NULL,
				K_PRIO_PREEMPT(ii + 5), 0, K_NO_WAIT);
	}

	for (int ii = 0; ii < N_THREADS; ii++) {
		struct result *p = k_fifo_get(&fifo, K_MSEC(100));

		if (!p || (p->pass != TC_PASS)) {
			rv = TC_FAIL;
		}
	}

	zassert_equal(errno, test_errno, NULL);

	if (errno != errno_values[N_THREADS]) {
		rv = TC_FAIL;
	}

	/* Make sure all the test thread end. */
	for (int ii = 0; ii < N_THREADS; ii++) {
		k_thread_join(&threads[ii], K_FOREVER);
	}

	if (rv != TC_PASS) {
		ztest_test_fail();
	}
}


#define ERROR_ANY 0xfc

void thread_entry_user(void *p1, void *p2, void *p3)
{
#ifdef CONFIG_ARCH_POSIX
	/* The errno in native posix will be handled by native
	 * operation system, so we skip it.
	 */
	ztest_test_skip();
#else
	int got_errno;

	/* assign the error number to C standard errno */
	errno = ERROR_ANY;

	/* got errno zephyr stored */
	got_errno = *(z_errno());

	zassert_equal(errno, got_errno, "errno is not corresponding.");
#endif
}

/**
 * @brief Verify errno works well
 *
 * @details Check whether a C standard errno can be stored successfully,
 *  no matter it is using tls or not.
 *
 * @ingroup kernel_threadcontext_tests
 */
void test_errno(void)
{
	k_tid_t tid;
	uint32_t perm = K_INHERIT_PERMS;

	if (k_is_user_context()) {
		perm = perm | K_USER;
	}

	tid = k_thread_create(&eno_thread, eno_stack, STACK_SIZE,
				thread_entry_user, NULL, NULL, NULL,
				K_PRIO_PREEMPT(1), perm,
				K_NO_WAIT);

	k_thread_join(tid, K_FOREVER);
}
