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

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

#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE)

static K_THREAD_STACK_DEFINE(stack, STACK_SIZE);

#define SLEEP_MS 100

pthread_mutex_t mutex1;
pthread_mutex_t mutex2;

void *normal_mutex_entry(void *p1)
{
	int i, rc;

	/* Sleep for maximum 300 ms as main thread is sleeping for 100 ms */

	for (i = 0; i < 3; i++) {
		rc = pthread_mutex_trylock(&mutex1);
		if (rc == 0) {
			break;
		}
		k_msleep(SLEEP_MS);
	}

	zassert_false(rc, "try lock failed");
	TC_PRINT("mutex lock is taken\n");
	zassert_false(pthread_mutex_unlock(&mutex1),
		      "mutex unlock is falied");
	return NULL;
}

void *recursive_mutex_entry(void *p1)
{
	zassert_false(pthread_mutex_lock(&mutex2), "mutex is not taken");
	zassert_false(pthread_mutex_lock(&mutex2),
		      "mutex is not taken 2nd time");
	TC_PRINT("recrusive mutex lock is taken\n");
	zassert_false(pthread_mutex_unlock(&mutex2),
		      "mutex is not unlocked");
	zassert_false(pthread_mutex_unlock(&mutex2),
		      "mutex is not unlocked");
	return NULL;
}

/**
 * @brief Test to demonstrate PTHREAD_MUTEX_NORMAL
 *
 * @details Mutex type is setup as normal. pthread_mutex_trylock
 *	    and pthread_mutex_lock are tested with mutex type being
 *	    normal.
 */
void test_posix_normal_mutex(void)
{
	pthread_t thread_1;
	pthread_attr_t attr;
	pthread_mutexattr_t mut_attr;
	struct sched_param schedparam;
	int schedpolicy = SCHED_FIFO;
	int ret, type, protocol, temp;

	schedparam.sched_priority = 2;
	ret = pthread_attr_init(&attr);
	if (ret != 0) {
		zassert_false(pthread_attr_destroy(&attr),
			      "Unable to destroy pthread object attrib");
		zassert_false(pthread_attr_init(&attr),
			      "Unable to create pthread object attrib");
	}

	pthread_attr_setstack(&attr, &stack, STACK_SIZE);
	pthread_attr_setschedpolicy(&attr, schedpolicy);
	pthread_attr_setschedparam(&attr, &schedparam);

	temp = pthread_mutexattr_settype(&mut_attr, PTHREAD_MUTEX_NORMAL);
	zassert_false(temp, "setting mutex type is failed");
	temp = pthread_mutex_init(&mutex1, &mut_attr);
	zassert_false(temp, "mutex initialization is failed");

	temp = pthread_mutexattr_gettype(&mut_attr, &type);
	zassert_false(temp, "reading mutex type is failed");
	temp = pthread_mutexattr_getprotocol(&mut_attr, &protocol);
	zassert_false(temp, "reading mutex protocol is failed");

	pthread_mutex_lock(&mutex1);

	zassert_equal(type, PTHREAD_MUTEX_NORMAL,
		      "mutex type is not normal");

	zassert_equal(protocol, PTHREAD_PRIO_NONE,
		      "mutex protocol is not prio_none");
	ret = pthread_create(&thread_1, &attr, &normal_mutex_entry, NULL);

	if (ret) {
		TC_PRINT("Thread1 creation failed %d", ret);
	}
	k_msleep(SLEEP_MS);
	pthread_mutex_unlock(&mutex1);

	pthread_join(thread_1, NULL);
	temp = pthread_mutex_destroy(&mutex1);
	zassert_false(temp, "Destroying mutex is failed");
}

/**
 * @brief Test to demonstrate PTHREAD_MUTEX_RECURSIVE
 *
 * @details Mutex type is setup as recursive. mutex will be locked
 *	    twice and unlocked for the same number of time.
 *
 */
void test_posix_recursive_mutex(void)
{
	pthread_t thread_2;
	pthread_attr_t attr2;
	pthread_mutexattr_t mut_attr2;
	struct sched_param schedparam2;
	int schedpolicy = SCHED_FIFO;
	int ret, type, protocol, temp;

	schedparam2.sched_priority = 2;
	ret = pthread_attr_init(&attr2);
	if (ret != 0) {
		zassert_false(pthread_attr_destroy(&attr2),
			      "Unable to destroy pthread object attrib");
		zassert_false(pthread_attr_init(&attr2),
			      "Unable to create pthread object attrib");
	}

	pthread_attr_setstack(&attr2, &stack, STACK_SIZE);
	pthread_attr_setschedpolicy(&attr2, schedpolicy);
	pthread_attr_setschedparam(&attr2, &schedparam2);

	temp = pthread_mutexattr_settype(&mut_attr2, PTHREAD_MUTEX_RECURSIVE);
	zassert_false(temp, "setting mutex2 type is failed");
	temp = pthread_mutex_init(&mutex2, &mut_attr2);
	zassert_false(temp, "mutex2 initialization is failed");

	temp = pthread_mutexattr_gettype(&mut_attr2, &type);
	zassert_false(temp, "reading mutex2 type is failed");
	temp = pthread_mutexattr_getprotocol(&mut_attr2, &protocol);
	zassert_false(temp, "reading mutex2 protocol is failed");

	zassert_equal(type, PTHREAD_MUTEX_RECURSIVE,
		      "mutex2 type is not recursive");

	zassert_equal(protocol, PTHREAD_PRIO_NONE,
		      "mutex2 protocol is not prio_none");
	ret = pthread_create(&thread_2, &attr2, &recursive_mutex_entry, NULL);

	zassert_false(ret, "Thread2 creation failed");

	pthread_join(thread_2, NULL);
	temp = pthread_mutex_destroy(&mutex2);
	zassert_false(temp, "Destroying mutex2 is failed");
}
