/*
 * Copyright (c) 2018 Intel Corporation
 * Copyright (c) 2023 Meta
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include "posix_internal.h"

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/sys/bitarray.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/sem.h>

struct pthread_key_data {
	sys_snode_t node;
	pthread_thread_data thread_data;
};

LOG_MODULE_REGISTER(pthread_key, CONFIG_PTHREAD_KEY_LOG_LEVEL);

static SYS_SEM_DEFINE(pthread_key_lock, 1, 1);

/* This is non-standard (i.e. an implementation detail) */
#define PTHREAD_KEY_INITIALIZER (-1)

/*
 * We reserve the MSB to mark a pthread_key_t as initialized (from the
 * perspective of the application). With a linear space, this means that
 * the theoretical pthread_key_t range is [0,2147483647].
 */
BUILD_ASSERT(CONFIG_MAX_PTHREAD_KEY_COUNT < PTHREAD_OBJ_MASK_INIT,
	     "CONFIG_MAX_PTHREAD_KEY_COUNT is too high");

static pthread_key_obj posix_key_pool[CONFIG_MAX_PTHREAD_KEY_COUNT];
SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_MAX_PTHREAD_KEY_COUNT);

static inline size_t posix_key_to_offset(pthread_key_obj *k)
{
	return k - posix_key_pool;
}

static inline size_t to_posix_key_idx(pthread_key_t key)
{
	return mark_pthread_obj_uninitialized(key);
}

static pthread_key_obj *get_posix_key(pthread_key_t key)
{
	int actually_initialized;
	size_t bit = to_posix_key_idx(key);

	/* if the provided cond does not claim to be initialized, its invalid */
	if (!is_pthread_obj_initialized(key)) {
		LOG_DBG("Key is uninitialized (%x)", key);
		return NULL;
	}

	/* Mask off the MSB to get the actual bit index */
	if (sys_bitarray_test_bit(&posix_key_bitarray, bit, &actually_initialized) < 0) {
		LOG_DBG("Key is invalid (%x)", key);
		return NULL;
	}

	if (actually_initialized == 0) {
		/* The cond claims to be initialized but is actually not */
		LOG_DBG("Key claims to be initialized (%x)", key);
		return NULL;
	}

	return &posix_key_pool[bit];
}

static pthread_key_obj *to_posix_key(pthread_key_t *key)
{
	size_t bit;
	pthread_key_obj *k;

	if (*key != PTHREAD_KEY_INITIALIZER) {
		return get_posix_key(*key);
	}

	/* Try and automatically associate a pthread_key_obj */
	if (sys_bitarray_alloc(&posix_key_bitarray, 1, &bit) < 0) {
		/* No keys left to allocate */
		return NULL;
	}

	/* Record the associated posix_cond in mu and mark as initialized */
	*key = mark_pthread_obj_initialized(bit);
	k = &posix_key_pool[bit];

	/* Initialize the condition variable here */
	memset(k, 0, sizeof(*k));

	return k;
}

/**
 * @brief Create a key for thread-specific data
 *
 * See IEEE 1003.1
 */
int pthread_key_create(pthread_key_t *key,
		void (*destructor)(void *))
{
	pthread_key_obj *new_key;

	*key = PTHREAD_KEY_INITIALIZER;
	new_key = to_posix_key(key);
	if (new_key == NULL) {
		return ENOMEM;
	}

	sys_slist_init(&(new_key->key_data_l));

	new_key->destructor = destructor;
	LOG_DBG("Initialized key %p (%x)", new_key, *key);

	return 0;
}

/**
 * @brief Delete a key for thread-specific data
 *
 * See IEEE 1003.1
 */
int pthread_key_delete(pthread_key_t key)
{
	size_t bit;
	int ret = 0;
	pthread_key_obj *key_obj = NULL;
	struct pthread_key_data *key_data;
	sys_snode_t *node_l, *next_node_l;

	SYS_SEM_LOCK(&pthread_key_lock) {
		key_obj = get_posix_key(key);
		if (key_obj == NULL) {
			ret = EINVAL;
			SYS_SEM_LOCK_BREAK;
		}

		/* Delete thread-specific elements associated with the key */
		SYS_SLIST_FOR_EACH_NODE_SAFE(&(key_obj->key_data_l), node_l, next_node_l) {

			/* Remove the object from the list key_data_l */
			key_data = (struct pthread_key_data *)sys_slist_get(&(key_obj->key_data_l));

			/* Deallocate the object's memory */
			k_free((void *)key_data);
			LOG_DBG("Freed key data %p for key %x in thread %x", key_data, key,
				pthread_self());
		}

		bit = posix_key_to_offset(key_obj);
		ret = sys_bitarray_free(&posix_key_bitarray, 1, bit);
		__ASSERT_NO_MSG(ret == 0);
	}

	if (ret == 0) {
		LOG_DBG("Deleted key %p (%x)", key_obj, key);
	}

	return ret;
}

/**
 * @brief Associate a thread-specific value with a key
 *
 * See IEEE 1003.1
 */
int pthread_setspecific(pthread_key_t key, const void *value)
{
	pthread_key_obj *key_obj = NULL;
	struct posix_thread *thread;
	struct pthread_key_data *key_data;
	sys_snode_t *node_l = NULL;
	int retval = 0;

	thread = to_posix_thread(pthread_self());
	if (thread == NULL) {
		return EINVAL;
	}

	/* Traverse the list of keys set by the thread, looking for key.
	 * If the key is already in the list, re-assign its value.
	 * Else add the key to the thread's list.
	 */
	SYS_SEM_LOCK(&pthread_key_lock) {
		key_obj = get_posix_key(key);
		if (key_obj == NULL) {
			retval = EINVAL;
			SYS_SEM_LOCK_BREAK;
		}

		SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) {
			pthread_thread_data *thread_spec_data = (pthread_thread_data *)node_l;

			if (thread_spec_data->key == key_obj) {
				/* Key is already present so associate thread specific data */
				thread_spec_data->spec_data = (void *)value;
				LOG_DBG("Paired key %x to value %p for thread %x", key, value,
					pthread_self());
				break;
			}
		}

		if (node_l != NULL) {
			/* Key is already present, so we are done */
			SYS_SEM_LOCK_BREAK;
		}

		/* Key and data need to be added */
		key_data = k_malloc(sizeof(struct pthread_key_data));

		if (key_data == NULL) {
			LOG_DBG("Failed to allocate key data for key %x", key);
			retval = ENOMEM;
			SYS_SEM_LOCK_BREAK;
		}

		LOG_DBG("Allocated key data %p for key %x in thread %x", key_data, key,
			pthread_self());

		/* Associate thread specific data, initialize new key */
		key_data->thread_data.key = key_obj;
		key_data->thread_data.spec_data = (void *)value;

		/* Append new thread key data to thread's key list */
		sys_slist_append((&thread->key_list), (sys_snode_t *)(&key_data->thread_data));

		/* Append new key data to the key object's list */
		sys_slist_append(&(key_obj->key_data_l), (sys_snode_t *)key_data);

		LOG_DBG("Paired key %x to value %p for thread %x", key, value, pthread_self());
	}

	return retval;
}

/**
 * @brief Get the thread-specific value associated with the key
 *
 * See IEEE 1003.1
 */
void *pthread_getspecific(pthread_key_t key)
{
	pthread_key_obj *key_obj;
	struct posix_thread *thread;
	pthread_thread_data *thread_spec_data;
	void *value = NULL;
	sys_snode_t *node_l;

	thread = to_posix_thread(pthread_self());
	if (thread == NULL) {
		return NULL;
	}

	SYS_SEM_LOCK(&pthread_key_lock) {
		key_obj = get_posix_key(key);
		if (key_obj == NULL) {
			value = NULL;
			SYS_SEM_LOCK_BREAK;
		}

		/* Traverse the list of keys set by the thread, looking for key */

		SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) {
			thread_spec_data = (pthread_thread_data *)node_l;
			if (thread_spec_data->key == key_obj) {
				/* Key is present, so get the set thread data */
				value = thread_spec_data->spec_data;
				break;
			}
		}
	}

	return value;
}
