File: compat.c

package info (click to toggle)
kronosnet 1.32-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,080 kB
  • sloc: ansic: 25,419; sh: 5,295; makefile: 664
file content (114 lines) | stat: -rw-r--r-- 2,335 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright (C) 2016-2025 Red Hat, Inc.  All rights reserved.
 *
 * Author: Jan Friesse <jfriesse@redhat.com>
 *
 * This software licensed under LGPL-2.0+
 */

#include "config.h"

#include <unistd.h>
#include <errno.h>
#include <sys/syscall.h>

#include "compat.h"

#ifndef HAVE_SYS_EPOLL_H
#ifdef HAVE_KEVENT

/* for FreeBSD which has kevent instead of epoll */

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <errno.h>

static int32_t
_poll_to_filter_(int32_t event)
{
	int32_t out = 0;
	if (event & POLLIN)
		out |= EVFILT_READ;
	if (event & POLLOUT)
		out |= EVFILT_WRITE;
	return out;
}

int epoll_create(int size)
{
	return kqueue();
}


int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
	int ret = 0;
	struct kevent ke;
	short filters = _poll_to_filter_(event->events);

	switch (op) {
		/* The kevent man page says that EV_ADD also does MOD */
		case EPOLL_CTL_ADD:
		case EPOLL_CTL_MOD:
			EV_SET(&ke, fd, filters, EV_ADD | EV_ENABLE, 0, 0, event->data.ptr);
			break;
		case EPOLL_CTL_DEL:
			EV_SET(&ke, fd, filters, EV_DELETE, 0, 0, event->data.ptr);
			break;
		default:
			errno = EINVAL;
			return -1;
	}
	ret = kevent(epfd, &ke, 1, NULL, 0, NULL);
	return ret;
}

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout_ms)
{
	struct kevent kevents[maxevents];
        struct timespec timeout = { 0, 0 };
        struct timespec *timeout_ptr = &timeout;
	uint32_t revents;
	int event_count;
	int i;
	int returned_events;

	if (timeout_ms != -1) {
	        timeout.tv_sec = timeout_ms/1000;
		timeout.tv_nsec += (timeout_ms % 1000) * 1000000ULL;
	}
	else {
		timeout_ptr = NULL;
	}

	event_count = kevent(epfd, NULL, 0, kevents, maxevents, timeout_ptr);
	if (event_count == -1) {
		return -1;
	}

	returned_events = 0;
	for (i = 0; i < event_count; i++) {
		revents = 0;

		if (kevents[i].flags & EV_ERROR) {
			revents |= POLLERR;
		}
		if (kevents[i].flags & EV_EOF) {
			revents |= POLLHUP;
		}
		if (kevents[i].filter == EVFILT_READ) {
			revents |= POLLIN;
		}
		if (kevents[i].filter == EVFILT_WRITE) {
			revents |= POLLOUT;
		}
		events[returned_events].events = revents;
		events[returned_events].data.ptr = kevents[i].udata;
		returned_events++;
	}

	return returned_events;
}
#endif /* HAVE_KEVENT */
#endif /* HAVE_SYS_EPOLL_H */