/*
 * Copyright (c) 2020 Tobias Svehagen
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/wait_q.h>
#include <zephyr/posix/sys/eventfd.h>
#include <zephyr/net/socket.h>
#include <ksched.h>

struct eventfd {
	struct k_poll_signal read_sig;
	struct k_poll_signal write_sig;
	struct k_spinlock lock;
	_wait_q_t wait_q;
	eventfd_t cnt;
	int flags;
};

K_MUTEX_DEFINE(eventfd_mtx);
static struct eventfd efds[CONFIG_EVENTFD_MAX];

static int eventfd_poll_prepare(struct eventfd *efd,
				struct zsock_pollfd *pfd,
				struct k_poll_event **pev,
				struct k_poll_event *pev_end)
{
	if (pfd->events & ZSOCK_POLLIN) {
		if (*pev == pev_end) {
			errno = ENOMEM;
			return -1;
		}

		(*pev)->obj = &efd->read_sig;
		(*pev)->type = K_POLL_TYPE_SIGNAL;
		(*pev)->mode = K_POLL_MODE_NOTIFY_ONLY;
		(*pev)->state = K_POLL_STATE_NOT_READY;
		(*pev)++;
	}

	if (pfd->events & ZSOCK_POLLOUT) {
		if (*pev == pev_end) {
			errno = ENOMEM;
			return -1;
		}

		(*pev)->obj = &efd->write_sig;
		(*pev)->type = K_POLL_TYPE_SIGNAL;
		(*pev)->mode = K_POLL_MODE_NOTIFY_ONLY;
		(*pev)->state = K_POLL_STATE_NOT_READY;
		(*pev)++;
	}

	return 0;
}

static int eventfd_poll_update(struct eventfd *efd,
			       struct zsock_pollfd *pfd,
			       struct k_poll_event **pev)
{
	ARG_UNUSED(efd);

	if (pfd->events & ZSOCK_POLLIN) {
		if ((*pev)->state != K_POLL_STATE_NOT_READY) {
			pfd->revents |= ZSOCK_POLLIN;
		}
		(*pev)++;
	}

	if (pfd->events & ZSOCK_POLLOUT) {
		if ((*pev)->state != K_POLL_STATE_NOT_READY) {
			pfd->revents |= ZSOCK_POLLOUT;
		}
		(*pev)++;
	}

	return 0;
}

static ssize_t eventfd_read_op(void *obj, void *buf, size_t sz)
{
	struct eventfd *efd = obj;
	int result = 0;
	eventfd_t count = 0;
	k_spinlock_key_t key;

	if (sz < sizeof(eventfd_t)) {
		errno = EINVAL;
		return -1;
	}

	for (;;) {
		key = k_spin_lock(&efd->lock);
		if ((efd->flags & EFD_NONBLOCK) && efd->cnt == 0) {
			result = EAGAIN;
			break;
		} else if (efd->cnt == 0) {
			z_pend_curr(&efd->lock, key, &efd->wait_q, K_FOREVER);
		} else {
			count = (efd->flags & EFD_SEMAPHORE) ? 1 : efd->cnt;
			efd->cnt -= count;
			if (efd->cnt == 0) {
				k_poll_signal_reset(&efd->read_sig);
			}
			k_poll_signal_raise(&efd->write_sig, 0);
			break;
		}
	}
	if (z_unpend_all(&efd->wait_q) != 0) {
		z_reschedule(&efd->lock, key);
	} else {
		k_spin_unlock(&efd->lock, key);
	}

	if (result != 0) {
		errno = result;
		return -1;
	}

	*(eventfd_t *)buf = count;

	return sizeof(eventfd_t);
}

static ssize_t eventfd_write_op(void *obj, const void *buf, size_t sz)
{
	struct eventfd *efd = obj;
	int result = 0;
	eventfd_t count;
	bool overflow;
	k_spinlock_key_t key;

	if (sz < sizeof(eventfd_t)) {
		errno = EINVAL;
		return -1;
	}

	count = *((eventfd_t *)buf);

	if (count == UINT64_MAX) {
		errno = EINVAL;
		return -1;
	}

	if (count == 0) {
		return sizeof(eventfd_t);
	}

	for (;;) {
		key = k_spin_lock(&efd->lock);
		overflow = UINT64_MAX - count <= efd->cnt;
		if ((efd->flags & EFD_NONBLOCK) && overflow) {
			result = EAGAIN;
			break;
		} else if (overflow) {
			z_pend_curr(&efd->lock, key, &efd->wait_q, K_FOREVER);
		} else {
			efd->cnt += count;
			if (efd->cnt == (UINT64_MAX - 1)) {
				k_poll_signal_reset(&efd->write_sig);
			}
			k_poll_signal_raise(&efd->read_sig, 0);
			break;
		}
	}
	if (z_unpend_all(&efd->wait_q) != 0) {
		z_reschedule(&efd->lock, key);
	} else {
		k_spin_unlock(&efd->lock, key);
	}

	if (result != 0) {
		errno = result;
		return -1;
	}

	return sizeof(eventfd_t);
}

static int eventfd_close_op(void *obj)
{
	struct eventfd *efd = (struct eventfd *)obj;

	efd->flags = 0;

	return 0;
}

static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args)
{
	struct eventfd *efd = (struct eventfd *)obj;

	switch (request) {
	case F_GETFL:
		return efd->flags & EFD_FLAGS_SET;

	case F_SETFL: {
		int flags;

		flags = va_arg(args, int);

		if (flags & ~EFD_FLAGS_SET) {
			errno = EINVAL;
			return -1;
		}

		efd->flags = flags;

		return 0;
	}

	case ZFD_IOCTL_POLL_PREPARE: {
		struct zsock_pollfd *pfd;
		struct k_poll_event **pev;
		struct k_poll_event *pev_end;

		pfd = va_arg(args, struct zsock_pollfd *);
		pev = va_arg(args, struct k_poll_event **);
		pev_end = va_arg(args, struct k_poll_event *);

		return eventfd_poll_prepare(obj, pfd, pev, pev_end);
	}

	case ZFD_IOCTL_POLL_UPDATE: {
		struct zsock_pollfd *pfd;
		struct k_poll_event **pev;

		pfd = va_arg(args, struct zsock_pollfd *);
		pev = va_arg(args, struct k_poll_event **);

		return eventfd_poll_update(obj, pfd, pev);
	}

	default:
		errno = EOPNOTSUPP;
		return -1;
	}
}

static const struct fd_op_vtable eventfd_fd_vtable = {
	.read = eventfd_read_op,
	.write = eventfd_write_op,
	.close = eventfd_close_op,
	.ioctl = eventfd_ioctl_op,
};

int eventfd(unsigned int initval, int flags)
{
	struct eventfd *efd = NULL;
	int fd = -1;
	int i;

	if (flags & ~EFD_FLAGS_SET) {
		errno = EINVAL;
		return -1;
	}

	k_mutex_lock(&eventfd_mtx, K_FOREVER);

	for (i = 0; i < ARRAY_SIZE(efds); ++i) {
		if (!(efds[i].flags & EFD_IN_USE)) {
			efd = &efds[i];
			break;
		}
	}

	if (efd == NULL) {
		errno = ENOMEM;
		goto exit_mtx;
	}

	fd = z_reserve_fd();
	if (fd < 0) {
		goto exit_mtx;
	}

	efd->flags = EFD_IN_USE | flags;
	efd->cnt = initval;

	k_poll_signal_init(&efd->write_sig);
	k_poll_signal_init(&efd->read_sig);
	z_waitq_init(&efd->wait_q);

	if (initval != 0) {
		k_poll_signal_raise(&efd->read_sig, 0);
	}
	k_poll_signal_raise(&efd->write_sig, 0);

	z_finalize_fd(fd, efd, &eventfd_fd_vtable);

exit_mtx:
	k_mutex_unlock(&eventfd_mtx);
	return fd;
}
