<commit_before>#include "timerfd_ctx.h"

#include <sys/types.h>

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

#include <assert.h>
#include <signal.h>

#include <pthread_np.h>

static void *
worker_function(void *arg)
{
	TimerFDCtx *ctx = arg;

	uint64_t total_expirations = 0;

	siginfo_t info;
	sigset_t rt_set;
	sigset_t block_set;

	sigemptyset(&rt_set);
	sigaddset(&rt_set, SIGRTMIN);
	sigaddset(&rt_set, SIGRTMIN + 1);

	sigfillset(&block_set);

	(void)pthread_sigmask(SIG_BLOCK, &block_set, NULL);

	struct kevent kev;
	EV_SET(&kev, 0, EVFILT_USER, 0, NOTE_TRIGGER, 0,
	    (void *)(intptr_t)pthread_getthreadid_np());
	(void)kevent(ctx->kq, &kev, 1, NULL, 0, NULL);

	for (;;) {
		if (sigwaitinfo(&rt_set, &info) != SIGRTMIN) {
			break;
		}
		int overrun = timer_getoverrun(ctx->complx.timer);
		total_expirations += 1 + (uint64_t)MAX(0, overrun);
		EV_SET(&kev, 0, EVFILT_USER, 0, NOTE_TRIGGER, 0,
		    (void *)(uintptr_t)total_expirations);
		(void)kevent(ctx->kq, &kev, 1, NULL, 0, NULL);
	}

	return NULL;
}

static errno_t
upgrade_to_complex_timer(TimerFDCtx *ctx, int clockid)
{
	errno_t ec;

	if (ctx->kind == TIMERFD_KIND_COMPLEX) {
		return 0;
	}

	if (ctx->kind == TIMERFD_KIND_SIMPLE) {
		struct kevent kev[1];
		EV_SET(&kev[0], 0, EVFILT_TIMER, EV_DELETE, 0, 0, 0);
		(void)kevent(ctx->kq, kev, nitems(kev), NULL, 0, NULL);

		ctx->kind = TIMERFD_KIND_UNDETERMINED;
	}

	assert(ctx->kind == TIMERFD_KIND_UNDETERMINED);

	struct kevent kev;
	EV_SET(&kev, 0, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, 0);
	if (kevent(ctx->kq, &kev, 1, NULL, 0, NULL) < 0) {
		assert(errno != 0);
		return errno;
	}

	if ((ec = pthread_create(&ctx->complx.worker, /**/
		 NULL, worker_function, ctx)) != 0) {
		return ec;
	}

	if (kevent(ctx->kq, NULL, 0, &kev, 1, NULL) < 0) {
		goto out;
	}

	int tid = (int)(intptr_t)kev.udata;

	struct sigevent sigev = {
	    .sigev_notify = SIGEV_THREAD_ID,
	    .sigev_signo = SIGRTMIN,
	    .sigev_notify_thread_id = tid,
	};

	if (timer_create(clockid, &sigev, &ctx->complx.timer) < 0) {
		goto out;
	}

	ctx->complx.current_expirations = 0;
	ctx->kind = TIMERFD_KIND_COMPLEX;
	return 0;

out:
	ec = errno;
	assert(ec != 0);
	pthread_kill(ctx->complx.worker, SIGRTMIN + 1);
	pthread_join(ctx->complx.worker, NULL);
	return ec;
}

errno_t
timerfd_ctx_init(TimerFDCtx *timerfd, int kq, int clockid)
{
	errno_t ec;

	assert(clockid == CLOCK_MONOTONIC || clockid == CLOCK_REALTIME);

	*timerfd = (TimerFDCtx){.kq = kq, .kind = TIMERFD_KIND_UNDETERMINED};

	if ((ec = pthread_mutex_init(&timerfd->mutex, NULL)) != 0) {
		return ec;
	}

	if (clockid == CLOCK_REALTIME) {
		if ((ec = upgrade_to_complex_timer(timerfd, /**/
			 CLOCK_REALTIME)) != 0) {
			(void)pthread_mutex_destroy(&timerfd->mutex);<commit_msg>upgrade_to_complex_timer: clean up error logic a bit<commit_after>#include "timerfd_ctx.h"

#include <sys/types.h>

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

#include <assert.h>
#include <signal.h>

#include <pthread_np.h>

static void *
worker_function(void *arg)
{
	TimerFDCtx *ctx = arg;

	uint64_t total_expirations = 0;

	siginfo_t info;
	sigset_t rt_set;
	sigset_t block_set;

	sigemptyset(&rt_set);
	sigaddset(&rt_set, SIGRTMIN);
	sigaddset(&rt_set, SIGRTMIN + 1);

	sigfillset(&block_set);

	(void)pthread_sigmask(SIG_BLOCK, &block_set, NULL);

	struct kevent kev;
	EV_SET(&kev, 0, EVFILT_USER, 0, NOTE_TRIGGER, 0,
	    (void *)(intptr_t)pthread_getthreadid_np());
	(void)kevent(ctx->kq, &kev, 1, NULL, 0, NULL);

	for (;;) {
		if (sigwaitinfo(&rt_set, &info) != SIGRTMIN) {
			break;
		}
		int overrun = timer_getoverrun(ctx->complx.timer);
		total_expirations += 1 + (uint64_t)MAX(0, overrun);
		EV_SET(&kev, 0, EVFILT_USER, 0, NOTE_TRIGGER, 0,
		    (void *)(uintptr_t)total_expirations);
		(void)kevent(ctx->kq, &kev, 1, NULL, 0, NULL);
	}

	return NULL;
}

static errno_t
upgrade_to_complex_timer(TimerFDCtx *ctx, int clockid)
{
	errno_t ec;

	if (ctx->kind == TIMERFD_KIND_COMPLEX) {
		return 0;
	}

	if (ctx->kind == TIMERFD_KIND_SIMPLE) {
		struct kevent kev[1];
		EV_SET(&kev[0], 0, EVFILT_TIMER, EV_DELETE, 0, 0, 0);
		(void)kevent(ctx->kq, kev, nitems(kev), NULL, 0, NULL);

		ctx->kind = TIMERFD_KIND_UNDETERMINED;
	}

	assert(ctx->kind == TIMERFD_KIND_UNDETERMINED);

	struct kevent kev;
	EV_SET(&kev, 0, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, 0);
	if (kevent(ctx->kq, &kev, 1, NULL, 0, NULL) < 0) {
		return errno;
	}

	if ((ec = pthread_create(&ctx->complx.worker, /**/
		 NULL, worker_function, ctx)) != 0) {
		return ec;
	}

	if (kevent(ctx->kq, NULL, 0, &kev, 1, NULL) < 0) {
		ec = errno;
		goto out;
	}

	int tid = (int)(intptr_t)kev.udata;

	struct sigevent sigev = {
	    .sigev_notify = SIGEV_THREAD_ID,
	    .sigev_signo = SIGRTMIN,
	    .sigev_notify_thread_id = tid,
	};

	if (timer_create(clockid, &sigev, &ctx->complx.timer) < 0) {
		ec = errno;
		goto out;
	}

	ctx->complx.current_expirations = 0;
	ctx->kind = TIMERFD_KIND_COMPLEX;
	return 0;

out:
	pthread_kill(ctx->complx.worker, SIGRTMIN + 1);
	pthread_join(ctx->complx.worker, NULL);
	return ec;
}

errno_t
timerfd_ctx_init(TimerFDCtx *timerfd, int kq, int clockid)
{
	errno_t ec;

	assert(clockid == CLOCK_MONOTONIC || clockid == CLOCK_REALTIME);

	*timerfd = (TimerFDCtx){.kq = kq, .kind = TIMERFD_KIND_UNDETERMINED};

	if ((ec = pthread_mutex_init(&timerfd->mutex, NULL)) != 0) {
		return ec;
	}

	if (clockid == CLOCK_REALTIME) {
		if ((ec = upgrade_to_complex_timer(timerfd, /**/
			 CLOCK_REALTIME)) != 0) {
			(void)pthread_mutex_destroy(&timerfd->mutex);
{'fraction_non_alphanumeric': 0.1607337450054486, 'fraction_numerical': 0.015982564475118054, 'mean_word_length': 4.452475247524752, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 51, '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': '6914268', 'n_tokens_mistral': 2649, 'n_tokens_neox': 2419, 'n_words': 473}