<commit_before>#include <sys/eventfd.h>
#undef read
#undef write
#undef close

#include <sys/types.h>

#include <sys/event.h>
#include <sys/param.h>

#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "eventfd_ctx.h"

struct eventfd_context {
	int fd;
	int flags;
	EventFDCtx ctx;
	struct eventfd_context *next;
};

static struct eventfd_context *eventfd_contexts;
pthread_mutex_t eventfd_context_mtx = PTHREAD_MUTEX_INITIALIZER;

struct eventfd_context *
get_eventfd_context(int fd, bool create_new)
{
	for (struct eventfd_context *ctx = eventfd_contexts; ctx;
	     ctx = ctx->next) {
		if (fd == ctx->fd) {
			return ctx;
		}
	}

	if (create_new) {
		struct eventfd_context *new_ctx =
		    malloc(sizeof(struct eventfd_context));
		if (!new_ctx) {
			return NULL;
		}
		new_ctx->fd = -1;
		new_ctx->next = eventfd_contexts;
		eventfd_contexts = new_ctx;
		return new_ctx;
	}

	return NULL;
}

static int
eventfd_impl(unsigned int initval, int flags)
{
	if (flags & ~(EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK)) {
		errno = EINVAL;
		return -1;
	}

	/*
	 * Don't check that EFD_CLOEXEC is set -- but our kqueue based eventfd
	 * will always be CLOEXEC.
	 */

	struct eventfd_context *ctx = get_eventfd_context(-1, true);
	if (!ctx) {
		errno = EMFILE;
		return -1;
	}

	int ctx_flags = 0;
	if (flags & EFD_SEMAPHORE) {
		ctx_flags |= EVENTFD_CTX_FLAG_SEMAPHORE;
	}

	errno_t ec;
	if ((ec = eventfd_ctx_init(&ctx->ctx, initval, ctx_flags)) != 0) {
		errno = ec;
		return -1;
	}

	ctx->fd = eventfd_ctx_fd(&ctx->ctx);
	ctx->flags = flags;

	return ctx->fd;
}

int
eventfd(unsigned int initval, int flags)
{
	pthread_mutex_lock(&eventfd_context_mtx);
	int ret = eventfd_impl(initval, flags);
	pthread_mutex_unlock(&eventfd_context_mtx);
	return ret;
}

static errno_t
eventfd_ctx_read_or_block(EventFDCtx *eventfd_ctx, uint64_t *value,
    bool nonblock)
{
	for (;;) {
		errno_t ec = eventfd_ctx_read(eventfd_ctx, value);
		if (nonblock || ec != EAGAIN) {
			return (ec);
		}

		struct kevent kevs[32];
		int n = kevent(eventfd_ctx->kq_, NULL, 0, /**/
		    kevs, nitems(kevs), NULL);
		if (n < 0) {
			return (errno);
		}
	}
}

ssize_t
eventfd_helper_read(struct eventfd_context *ctx, void *buf, size_t nbytes)
{
	EventFDCtx *efd_ctx = &ctx->ctx;
	int flags = ctx->flags;
	pthread_mutex_unlock(&eventfd_context_mtx);

	if (nbytes != sizeof(uint64_t)) {
		errno = EINVAL;<commit_msg>use poll to wait for eventfd<commit_after>#include <sys/eventfd.h>
#undef read
#undef write
#undef close

#include <sys/types.h>

#include <sys/event.h>
#include <sys/param.h>

#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "eventfd_ctx.h"

struct eventfd_context {
	int fd;
	int flags;
	EventFDCtx ctx;
	struct eventfd_context *next;
};

static struct eventfd_context *eventfd_contexts;
pthread_mutex_t eventfd_context_mtx = PTHREAD_MUTEX_INITIALIZER;

struct eventfd_context *
get_eventfd_context(int fd, bool create_new)
{
	for (struct eventfd_context *ctx = eventfd_contexts; ctx;
	     ctx = ctx->next) {
		if (fd == ctx->fd) {
			return ctx;
		}
	}

	if (create_new) {
		struct eventfd_context *new_ctx =
		    malloc(sizeof(struct eventfd_context));
		if (!new_ctx) {
			return NULL;
		}
		new_ctx->fd = -1;
		new_ctx->next = eventfd_contexts;
		eventfd_contexts = new_ctx;
		return new_ctx;
	}

	return NULL;
}

static int
eventfd_impl(unsigned int initval, int flags)
{
	if (flags & ~(EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK)) {
		errno = EINVAL;
		return -1;
	}

	/*
	 * Don't check that EFD_CLOEXEC is set -- but our kqueue based eventfd
	 * will always be CLOEXEC.
	 */

	struct eventfd_context *ctx = get_eventfd_context(-1, true);
	if (!ctx) {
		errno = EMFILE;
		return -1;
	}

	int ctx_flags = 0;
	if (flags & EFD_SEMAPHORE) {
		ctx_flags |= EVENTFD_CTX_FLAG_SEMAPHORE;
	}

	errno_t ec;
	if ((ec = eventfd_ctx_init(&ctx->ctx, initval, ctx_flags)) != 0) {
		errno = ec;
		return -1;
	}

	ctx->fd = eventfd_ctx_fd(&ctx->ctx);
	ctx->flags = flags;

	return ctx->fd;
}

int
eventfd(unsigned int initval, int flags)
{
	pthread_mutex_lock(&eventfd_context_mtx);
	int ret = eventfd_impl(initval, flags);
	pthread_mutex_unlock(&eventfd_context_mtx);
	return ret;
}

static errno_t
eventfd_ctx_read_or_block(EventFDCtx *eventfd_ctx, uint64_t *value,
    bool nonblock)
{
	for (;;) {
		errno_t ec = eventfd_ctx_read(eventfd_ctx, value);
		if (nonblock || ec != EAGAIN) {
			return (ec);
		}

		struct pollfd pfd = {.fd = eventfd_ctx->kq_, .events = POLLIN};
		if (poll(&pfd, 1, -1) < 0) {
			return (errno);
		}
	}
}

ssize_t
eventfd_helper_read(struct eventfd_context *ctx, void *buf, size_t nbytes)
{
	EventFDCtx *efd_ctx = &ctx->ctx;
	int flags = ctx->flags;
	pthread_mutex_unlock(&eventfd_context_mtx);

	if (nbytes != sizeof(uint64_t)) {
		errno = EINVAL;
{'fraction_non_alphanumeric': 0.13085427135678393, 'fraction_numerical': 0.005829145728643216, 'mean_word_length': 4.167185877466252, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4758376', 'n_tokens_mistral': 2134, 'n_tokens_neox': 2018, 'n_words': 454}