/*
 * 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>

struct pthread_key_data {
	sys_snode_t node;
	pthread_thread_data thread_data;
};

LOG_MODULE_REGISTER(pthread_key, CONFIG_PTHREAD_KEY_LOG_LEVEL);

static struct k_spinlock pthread_key_lock;

/* 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;
	__unused int ret;
	pthread_key_obj *key_obj;
	struct pthread_key_data *key_data;
	sys_snode_t *node_l, *next_node_l;
	k_spinlock_key_t key_key;

	key_key = k_spin_lock(&pthread_key_lock);

	key_obj = get_posix_key(key);
	if (key_obj == NULL) {
		k_spin_unlock(&pthread_key_lock, key_key);
		return EINVAL;
	}

	/* 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);

	k_spin_unlock(&pthread_key_lock, key_key);

	LOG_DBG("Deleted key %p (%x)", key_obj, key);

	return 0;
}

/**
 * @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;
	struct posix_thread *thread;
	struct pthread_key_data *key_data;
	pthread_thread_data *thread_spec_data;
	k_spinlock_key_t key_key;
	sys_snode_t *node_l;
	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.
	 */
	key_key = k_spin_lock(&pthread_key_lock);

	key_obj = get_posix_key(key);
	if (key_obj == NULL) {
		k_spin_unlock(&pthread_key_lock, key_key);
		return EINVAL;
	}

	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 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());
			goto out;
		}
	}

	if (node_l == NULL) {
		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;
			goto out;
		}

		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());
	}

out:
	k_spin_unlock(&pthread_key_lock, key_key);

	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;
	k_spinlock_key_t key_key;

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

	key_key = k_spin_lock(&pthread_key_lock);

	key_obj = get_posix_key(key);
	if (key_obj == NULL) {
		k_spin_unlock(&pthread_key_lock, key_key);
		return NULL;
	}

	/* 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;
		}
	}

	k_spin_unlock(&pthread_key_lock, key_key);

	return value;
}
