/*
 * Copyright (c) 2016-2017 Nordic Semiconductor ASA
 * Copyright (c) 2016 Vinayak Kariappa Chettimada
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stddef.h>
#include <zephyr/types.h>
#include <sys/printk.h>
#include "memq.h"
#include "mayfly.h"

static struct {
	memq_link_t *head;
	memq_link_t *tail;
	uint8_t        enable_req;
	uint8_t        enable_ack;
	uint8_t        disable_req;
	uint8_t        disable_ack;
} mft[MAYFLY_CALLEE_COUNT][MAYFLY_CALLER_COUNT];

static memq_link_t mfl[MAYFLY_CALLEE_COUNT][MAYFLY_CALLER_COUNT];
static uint8_t mfp[MAYFLY_CALLEE_COUNT];

#if defined(MAYFLY_UT)
static uint8_t _state;
#endif /* MAYFLY_UT */

void mayfly_init(void)
{
	uint8_t callee_id;

	callee_id = MAYFLY_CALLEE_COUNT;
	while (callee_id--) {
		uint8_t caller_id;

		caller_id = MAYFLY_CALLER_COUNT;
		while (caller_id--) {
			memq_init(&mfl[callee_id][caller_id],
				  &mft[callee_id][caller_id].head,
				  &mft[callee_id][caller_id].tail);
		}
	}
}

void mayfly_enable(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
{
	if (enable) {
		if (mft[callee_id][caller_id].enable_req ==
		    mft[callee_id][caller_id].enable_ack) {
			mft[callee_id][caller_id].enable_req++;
		}

		mayfly_enable_cb(caller_id, callee_id, enable);
	} else {
		if (mft[callee_id][caller_id].disable_req ==
		    mft[callee_id][caller_id].disable_ack) {
			mft[callee_id][caller_id].disable_req++;

			/* set mayfly callee pending */
			mfp[callee_id] = 1U;

			/* pend the callee for execution */
			mayfly_pend(caller_id, callee_id);
		}
	}
}

uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
			struct mayfly *m)
{
	uint8_t state;
	uint8_t ack;

	chain = chain || !mayfly_prio_is_equal(caller_id, callee_id) ||
		!mayfly_is_enabled(caller_id, callee_id) ||
		(mft[callee_id][caller_id].disable_req !=
		 mft[callee_id][caller_id].disable_ack);

	/* shadow the ack */
	ack = m->_ack;

	/* already in queue */
	state = (m->_req - ack) & 0x03;
	if (state != 0U) {
		if (chain) {
			if (state != 1U) {
				/* mark as ready in queue */
				m->_req = ack + 1;

				goto mayfly_enqueue_pend;
			}

			/* already ready */
			return 1;
		}

		/* mark as done in queue, and fall thru */
		m->_req = ack + 2;
	}

	/* handle mayfly(s) that can be inline */
	if (!chain) {
		/* call fp */
		m->fp(m->param);

		return 0;
	}

	/* new, add as ready in the queue */
	m->_req = ack + 1;
	memq_enqueue(m->_link, m, &mft[callee_id][caller_id].tail);

mayfly_enqueue_pend:
	/* set mayfly callee pending */
	mfp[callee_id] = 1U;

	/* pend the callee for execution */
	mayfly_pend(caller_id, callee_id);

	return 0;
}

static void dequeue(uint8_t callee_id, uint8_t caller_id, memq_link_t *link,
		    struct mayfly *m)
{
	uint8_t req;

	req = m->_req;
	if (((req - m->_ack) & 0x03) != 1U) {
		uint8_t ack;

#if defined(MAYFLY_UT)
		uint32_t mayfly_ut_run_test(void);
		void mayfly_ut_mfy(void *param);

		if (_state && m->fp == mayfly_ut_mfy) {
			static uint8_t single;

			if (!single) {
				single = 1U;
				mayfly_ut_run_test();
			}
		}
#endif /* MAYFLY_UT */

		/* dequeue mayfly struct */
		memq_dequeue(mft[callee_id][caller_id].tail,
			     &mft[callee_id][caller_id].head,
			     0);

		/* release link into dequeued mayfly struct */
		m->_link = link;

		/* reset mayfly state to idle */
		ack = m->_ack;
		m->_ack = req;

		/* re-insert, if re-pended by interrupt */
		if (((m->_req - ack) & 0x03) == 1U) {
#if defined(MAYFLY_UT)
			printk("%s: RACE\n", __func__);
#endif /* MAYFLY_UT */

			m->_ack = ack;
			memq_enqueue(link, m, &mft[callee_id][callee_id].tail);
		}
	}
}

void mayfly_run(uint8_t callee_id)
{
	uint8_t disable = 0U;
	uint8_t enable = 0U;
	uint8_t caller_id;

	if (!mfp[callee_id]) {
		return;
	}
	mfp[callee_id] = 0U;

	/* iterate through each caller queue to this callee_id */
	caller_id = MAYFLY_CALLER_COUNT;
	while (caller_id--) {
		memq_link_t *link;
		struct mayfly *m = 0;

		/* fetch mayfly in callee queue, if any */
		link = memq_peek(mft[callee_id][caller_id].head,
				 mft[callee_id][caller_id].tail,
				 (void **)&m);
		while (link) {
			uint8_t state;

#if defined(MAYFLY_UT)
			_state = 0U;
#endif /* MAYFLY_UT */

			/* execute work if ready */
			state = (m->_req - m->_ack) & 0x03;
			if (state == 1U) {
#if defined(MAYFLY_UT)
				_state = 1U;
#endif /* MAYFLY_UT */

				/* mark mayfly as ran */
				m->_ack--;

				/* call the mayfly function */
				m->fp(m->param);
			}

			/* dequeue if not re-pended */
			dequeue(callee_id, caller_id, link, m);

			/* fetch next mayfly in callee queue, if any */
			link = memq_peek(mft[callee_id][caller_id].head,
					 mft[callee_id][caller_id].tail,
					 (void **)&m);

/**
 * When using cooperative thread implementation, an issue has been seen where
 * pended mayflies are never executed in certain scenarios.
 * This happens when mayflies with higher caller_id are constantly pended, in
 * which case lower value caller ids never get to be executed.
 * By allowing complete traversal of mayfly queues for all caller_ids, this
 * does not happen, however this means that more than one mayfly function is
 * potentially executed in a mayfly_run(), with added execution time as
 * consequence.
 */
#if defined(CONFIG_BT_MAYFLY_YIELD_AFTER_CALL)
			/* yield out of mayfly_run if a mayfly function was
			 * called.
			 */
			if (state == 1U) {
				/* pend callee (tailchain) if mayfly queue is
				 * not empty or all caller queues are not
				 * processed.
				 */
				if (caller_id || link) {
					/* set mayfly callee pending */
					mfp[callee_id] = 1U;

					/* pend the callee for execution */
					mayfly_pend(callee_id, callee_id);

					return;
				}
			}
#endif
		}

		if (mft[callee_id][caller_id].disable_req !=
		    mft[callee_id][caller_id].disable_ack) {
			disable = 1U;

			mft[callee_id][caller_id].disable_ack =
				mft[callee_id][caller_id].disable_req;
		}

		if (mft[callee_id][caller_id].enable_req !=
		    mft[callee_id][caller_id].enable_ack) {
			enable = 1U;

			mft[callee_id][caller_id].enable_ack =
				mft[callee_id][caller_id].enable_req;
		}
	}

	if (disable && !enable) {
		mayfly_enable_cb(callee_id, callee_id, 0);
	}
}

#if defined(MAYFLY_UT)
#define MAYFLY_CALL_ID_CALLER MAYFLY_CALL_ID_0
#define MAYFLY_CALL_ID_CALLEE MAYFLY_CALL_ID_2

void mayfly_ut_mfy(void *param)
{
	printk("%s: ran.\n", __func__);

	(*((uint32_t *)param))++;
}

void mayfly_ut_test(void *param)
{
	static uint32_t *count;
	static memq_link_t link;
	static struct mayfly mfy = {0, 0, &link, NULL, mayfly_ut_mfy};
	uint32_t err;

	printk("%s: req= %u, ack= %u\n", __func__, mfy._req, mfy._ack);

	if (param) {
		count = param;
	}

	mfy.param = count;

	err = mayfly_enqueue(MAYFLY_CALL_ID_CALLER, MAYFLY_CALL_ID_CALLEE, 1,
			     &mfy);
	if (err) {
		printk("%s: FAILED (%u).\n", __func__, err);
	} else {
		printk("%s: SUCCESS.\n", __func__);
	}
}

uint32_t mayfly_ut_run_test(void)
{
	static memq_link_t link;
	static struct mayfly mfy = {0, 0, &link, NULL, mayfly_ut_test};
	uint32_t err;

	printk("%s: req= %u, ack= %u\n", __func__, mfy._req, mfy._ack);

	err = mayfly_enqueue(MAYFLY_CALL_ID_CALLEE, MAYFLY_CALL_ID_CALLER, 0,
			     &mfy);

	if (err) {
		printk("%s: FAILED.\n", __func__);
		return err;
	}

	printk("%s: SUCCESS.\n", __func__);

	return 0;
}

uint32_t mayfly_ut(void)
{
	static uint32_t count;
	static memq_link_t link;
	static struct mayfly mfy = {0, 0, &link, &count, mayfly_ut_test};
	uint32_t err;

	printk("%s: req= %u, ack= %u\n", __func__, mfy._req, mfy._ack);

	err = mayfly_enqueue(MAYFLY_CALL_ID_PROGRAM, MAYFLY_CALL_ID_CALLER, 0,
			     &mfy);

	if (err) {
		printk("%s: FAILED.\n", __func__);
		return err;
	}

	printk("%s: count = %u.\n", __func__, count);
	printk("%s: SUCCESS.\n", __func__);
	return 0;
}
#endif /* MAYFLY_UT */
