// SPDX-License-Identifier: GPL-2.0
#include "threads.h"
#include "machine.h"
#include "thread.h"

static struct threads_table_entry *threads__table(struct threads *threads, pid_t tid)
{
	/* Cast it to handle tid == -1 */
	return &threads->table[(unsigned int)tid % THREADS__TABLE_SIZE];
}

static size_t key_hash(long key, void *ctx __maybe_unused)
{
	/* The table lookup removes low bit entropy, but this is just ignored here. */
	return key;
}

static bool key_equal(long key1, long key2, void *ctx __maybe_unused)
{
	return key1 == key2;
}

void threads__init(struct threads *threads)
{
	for (int i = 0; i < THREADS__TABLE_SIZE; i++) {
		struct threads_table_entry *table = &threads->table[i];

		hashmap__init(&table->shard, key_hash, key_equal, NULL);
		init_rwsem(&table->lock);
		table->last_match = NULL;
	}
}

void threads__exit(struct threads *threads)
{
	threads__remove_all_threads(threads);
	for (int i = 0; i < THREADS__TABLE_SIZE; i++) {
		struct threads_table_entry *table = &threads->table[i];

		hashmap__clear(&table->shard);
		exit_rwsem(&table->lock);
	}
}

size_t threads__nr(struct threads *threads)
{
	size_t nr = 0;

	for (int i = 0; i < THREADS__TABLE_SIZE; i++) {
		struct threads_table_entry *table = &threads->table[i];

		down_read(&table->lock);
		nr += hashmap__size(&table->shard);
		up_read(&table->lock);
	}
	return nr;
}

/*
 * Front-end cache - TID lookups come in blocks,
 * so most of the time we dont have to look up
 * the full rbtree:
 */
static struct thread *__threads_table_entry__get_last_match(struct threads_table_entry *table,
							    pid_t tid)
{
	struct thread *th, *res = NULL;

	th = table->last_match;
	if (th != NULL) {
		if (thread__tid(th) == tid)
			res = thread__get(th);
	}
	return res;
}

static void __threads_table_entry__set_last_match(struct threads_table_entry *table,
						  struct thread *th)
{
	thread__put(table->last_match);
	table->last_match = thread__get(th);
}

static void threads_table_entry__set_last_match(struct threads_table_entry *table,
						struct thread *th)
{
	down_write(&table->lock);
	__threads_table_entry__set_last_match(table, th);
	up_write(&table->lock);
}

struct thread *threads__find(struct threads *threads, pid_t tid)
{
	struct threads_table_entry *table  = threads__table(threads, tid);
	struct thread *res;

	down_read(&table->lock);
	res = __threads_table_entry__get_last_match(table, tid);
	if (!res) {
		if (hashmap__find(&table->shard, tid, &res))
			res = thread__get(res);
	}
	up_read(&table->lock);
	if (res)
		threads_table_entry__set_last_match(table, res);
	return res;
}

struct thread *threads__findnew(struct threads *threads, pid_t pid, pid_t tid, bool *created)
{
	struct threads_table_entry *table  = threads__table(threads, tid);
	struct thread *res = NULL;

	*created = false;
	down_write(&table->lock);
	res = thread__new(pid, tid);
	if (res) {
		if (hashmap__add(&table->shard, tid, res)) {
			/* Add failed. Assume a race so find other entry. */
			thread__put(res);
			res = NULL;
			if (hashmap__find(&table->shard, tid, &res))
				res = thread__get(res);
		} else {
			res = thread__get(res);
			*created = true;
		}
		if (res)
			__threads_table_entry__set_last_match(table, res);
	}
	up_write(&table->lock);
	return res;
}

void threads__remove_all_threads(struct threads *threads)
{
	for (int i = 0; i < THREADS__TABLE_SIZE; i++) {
		struct threads_table_entry *table = &threads->table[i];
		struct hashmap_entry *cur, *tmp;
		size_t bkt;

		down_write(&table->lock);
		__threads_table_entry__set_last_match(table, NULL);
		hashmap__for_each_entry_safe((&table->shard), cur, tmp, bkt) {
			struct thread *old_value;

			hashmap__delete(&table->shard, cur->key, /*old_key=*/NULL, &old_value);
			thread__put(old_value);
		}
		up_write(&table->lock);
	}
}

void threads__remove(struct threads *threads, struct thread *thread)
{
	struct threads_table_entry *table  = threads__table(threads, thread__tid(thread));
	struct thread *old_value;

	down_write(&table->lock);
	if (table->last_match && RC_CHK_EQUAL(table->last_match, thread))
		__threads_table_entry__set_last_match(table, NULL);

	hashmap__delete(&table->shard, thread__tid(thread), /*old_key=*/NULL, &old_value);
	thread__put(old_value);
	up_write(&table->lock);
}

int threads__for_each_thread(struct threads *threads,
			     int (*fn)(struct thread *thread, void *data),
			     void *data)
{
	for (int i = 0; i < THREADS__TABLE_SIZE; i++) {
		struct threads_table_entry *table = &threads->table[i];
		struct hashmap_entry *cur;
		size_t bkt;

		down_read(&table->lock);
		hashmap__for_each_entry((&table->shard), cur, bkt) {
			int rc = fn((struct thread *)cur->pvalue, data);

			if (rc != 0) {
				up_read(&table->lock);
				return rc;
			}
		}
		up_read(&table->lock);
	}
	return 0;

}
