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

#include <ztest.h>
#include <kernel.h>
#include <pthread.h>
#include <sys/util.h>

#define N_THR 2
#define N_KEY 2
#define STACKSZ (1024 + CONFIG_TEST_EXTRA_STACKSIZE)
#define BUFFSZ 48

K_THREAD_STACK_ARRAY_DEFINE(stackp, N_THR, STACKSZ);

pthread_key_t key, keys[N_KEY];
static pthread_once_t key_once, keys_once;

void *thread_top(void *p1)
{
	int ret = -1;

	void *value;
	void *getval;
	char *buffer[BUFFSZ];

	value = k_malloc(sizeof(buffer));

	zassert_true((int) POINTER_TO_INT(value),
		     "thread could not allocate storage");

	ret = pthread_setspecific(key, value);

	/* TESTPOINT: Check if thread's value is associated with key */
	zassert_false(ret, "pthread_setspecific failed");

	getval = 0;

	getval = pthread_getspecific(key);

	/* TESTPOINT: Check if pthread_getspecific returns the same value
	 * set by pthread_setspecific
	 */
	zassert_equal(value, getval,
			"set and retrieved values are different");

	printk("set value = %d and retrieved value = %d\n",
		(int) POINTER_TO_INT(value), (int) POINTER_TO_INT(getval));

	return NULL;
}

void *thread_func(void *p1)
{
	int i, ret = -1;

	void *value;
	void *getval;
	char *buffer[BUFFSZ];

	value = k_malloc(sizeof(buffer));

	zassert_true((int) POINTER_TO_INT(value),
		     "thread could not allocate storage");

	for (i = 0; i < N_KEY; i++) {
		ret = pthread_setspecific(keys[i], value);

		/* TESTPOINT: Check if thread's value is associated with keys */
		zassert_false(ret, "pthread_setspecific failed");
	}

	for (i = 0; i < N_KEY; i++) {
		getval = 0;
		getval = pthread_getspecific(keys[i]);

		/* TESTPOINT: Check if pthread_getspecific returns the same
		 * value set by pthread_setspecific for each of the keys
		 */
		zassert_equal(value, getval,
				"set and retrieved values are different");

		printk("key %d: set value = %d and retrieved value = %d\n",
				i, (int) POINTER_TO_INT(value),
				(int) POINTER_TO_INT(getval));
	}
	return NULL;
}

static void make_key(void)
{
	int ret = 0;

	ret = pthread_key_create(&key, NULL);
	zassert_false(ret, "insufficient memory to create key");
}

static void make_keys(void)
{
	int i, ret = 0;

	for (i = 0; i < N_KEY; i++) {
		ret = pthread_key_create(&keys[i], NULL);
		zassert_false(ret, "insufficient memory to create keys");
	}
}

/**
 * @brief Test to demonstrate pthread_key APIs usage
 *
 * @details The tests spawn a thread which uses pthread_once() to
 * create a key via pthread_key_create() API. It then sets the
 * thread-specific value to the key using pthread_setspecific() and
 * gets it back using pthread_getspecific and asserts that they
 * are equal. It then deletes the key using pthread_key_delete().
 * Both the sub-tests do the above, but one with multiple threads
 * using the same key and the other with a single thread using
 * multiple keys.
 */

void test_posix_multiple_threads_single_key(void)
{
	int i, ret = -1;

	pthread_attr_t attr[N_THR];
	struct sched_param schedparam;
	pthread_t newthread[N_THR];
	void *retval;

	ret = pthread_once(&key_once, make_key);

	/* TESTPOINT: Check if key is created */
	zassert_false(ret, "attempt to create key failed");

	printk("\nDifferent threads set different values to same key:\n");

	/* Creating threads with lowest application priority */
	for (i = 0; i < N_THR; i++) {
		ret = pthread_attr_init(&attr[i]);
		if (ret != 0) {
			zassert_false(pthread_attr_destroy(&attr[i]),
					"Unable to destroy pthread object attr");
			zassert_false(pthread_attr_init(&attr[i]),
					"Unable to create pthread object attr");
		}

		schedparam.sched_priority = 2;
		pthread_attr_setschedparam(&attr[i], &schedparam);
		pthread_attr_setstack(&attr[i], &stackp[i][0], STACKSZ);

		ret = pthread_create(&newthread[i], &attr[i], thread_top,
				INT_TO_POINTER(i));

		/* TESTPOINT: Check if threads are created successfully */
		zassert_false(ret, "attempt to create threads failed");
	}

	for (i = 0; i < N_THR; i++) {
		printk("thread %d: ", i);
		pthread_join(newthread[i], &retval);
	}

	ret = pthread_key_delete(key);

	/* TESTPOINT: Check if key is deleted */
	zassert_false(ret, "attempt to delete key failed");
	printk("\n");
}

void test_posix_single_thread_multiple_keys(void)
{
	int i, ret = -1;

	pthread_attr_t attr;
	struct sched_param schedparam;
	pthread_t newthread;

	ret = pthread_once(&keys_once, make_keys);

	/* TESTPOINT: Check if keys are created successfully */
	zassert_false(ret, "attempt to create keys failed");

	printk("\nSingle thread associates its value with different keys:\n");
	ret = pthread_attr_init(&attr);
	if (ret != 0) {
		zassert_false(pthread_attr_destroy(&attr),
				"Unable to destroy pthread object attr");
		zassert_false(pthread_attr_init(&attr),
				"Unable to create pthread object attr");
	}

	schedparam.sched_priority = 2;
	pthread_attr_setschedparam(&attr, &schedparam);
	pthread_attr_setstack(&attr, &stackp[0][0], STACKSZ);

	ret = pthread_create(&newthread, &attr, thread_func,
			(void *)0);

	/*TESTPOINT: Check if thread is created successfully */
	zassert_false(ret, "attempt to create thread failed");

	pthread_join(newthread, NULL);

	for (i = 0; i < N_KEY; i++) {
		ret = pthread_key_delete(keys[i]);

		/* TESTPOINT: Check if keys are deleted */
		zassert_false(ret, "attempt to delete keys failed");
	}
	printk("\n");
}
