Skip to content
This repository was archived by the owner on May 28, 2022. It is now read-only.

Commit 156f1bb

Browse files
committed
Get xdispatch working on Linux (#6)
1 parent d09456a commit 156f1bb

File tree

11 files changed

+185
-288
lines changed

11 files changed

+185
-288
lines changed

NGSEngine/src/xdispatch/build.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ fn main() {
2424
build
2525
.file("lib/libpthread_workqueue/posix/manager.c")
2626
.file("lib/libpthread_workqueue/posix/thread_info.c")
27-
.file("lib/libpthread_workqueue/posix/thread_rt.c")
28-
.file("lib/libpthread_workqueue/api.c")
29-
.file("lib/libpthread_workqueue/witem_cache.c");
27+
.file("lib/libpthread_workqueue/posix/thread_rt.c");
3028
}
3129
build
3230
.file("lib/libpthread_workqueue/api.c")
@@ -45,7 +43,6 @@ fn main() {
4543
} else {
4644
build
4745
.file("lib/libkqueue/linux/platform.c")
48-
.file("lib/libkqueue/linux/proc.c")
4946
.file("lib/libkqueue/linux/read.c")
5047
.file("lib/libkqueue/linux/signal.c")
5148
.file("lib/libkqueue/linux/timer.c")
@@ -60,13 +57,16 @@ fn main() {
6057
.file("lib/libkqueue/common/kqueue.c")
6158
.file("lib/libkqueue/common/map.c")
6259
.include("lib/include")
60+
.include("lib/libkqueue/common")
6361
.compile("libkqueue.a");
6462

6563
let mut build = cc::Build::new();
6664
if target_parts[2] == "windows" {
6765
build
6866
.file("lib/xdispatch/platform/windows/platform.c")
6967
.include("lib/xdispatch/platform/windows");
68+
} else {
69+
build.include("lib/xdispatch/platform/posix");
7070
}
7171
build
7272
.file("lib/xdispatch/src/apply.c")

NGSEngine/src/xdispatch/lib/include/kqueue/sys/event.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ int kevent(int kq, const struct kevent *changelist, int nchanges,
203203
struct kevent *eventlist, int nevents,
204204
const struct timespec *timeout);
205205
#ifdef MAKE_STATIC
206-
void libkqueue_init();
206+
int libkqueue_init();
207207
#endif
208208
#endif
209209

NGSEngine/src/xdispatch/lib/libkqueue/linux/platform.c

+35-19
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515
*/
1616

17+
# define _GNU_SOURCE
18+
# include <poll.h>
1719
#include "../common/private.h"
1820

1921
//XXX-FIXME TEMP
@@ -90,25 +92,37 @@ linux_kevent_wait_hires(
9092
struct kqueue *kq,
9193
const struct timespec *timeout)
9294
{
93-
fd_set fds;
9495
int n;
96+
#if HAVE_DECL_PPOLL
97+
struct pollfd fds;
98+
99+
dbg_printf("waiting for events (timeout=%ld sec %ld nsec)",
100+
timeout->tv_sec, timeout->tv_nsec);
101+
fds.fd = kqueue_epfd(kq);
102+
fds.events = POLLIN;
103+
104+
n = ppoll(&fds, 1, timeout, NULL);
105+
#else
95106
int epfd;
107+
fd_set fds;
96108

97109
dbg_printf("waiting for events (timeout=%ld sec %ld nsec)",
98110
timeout->tv_sec, timeout->tv_nsec);
111+
99112
epfd = kqueue_epfd(kq);
100113
FD_ZERO(&fds);
101114
FD_SET(epfd, &fds);
102115
n = pselect(epfd + 1, &fds, NULL , NULL, timeout, NULL);
116+
#endif
117+
103118
if (n < 0) {
104119
if (errno == EINTR) {
105120
dbg_puts("signal caught");
106121
return (-1);
107122
}
108-
dbg_perror("pselect(2)");
123+
dbg_perror("ppoll(2) or pselect(2)");
109124
return (-1);
110125
}
111-
112126
return (n);
113127
}
114128

@@ -120,25 +134,27 @@ linux_kevent_wait(
120134
{
121135
int timeout, nret;
122136

123-
/* Use pselect() if the timeout value is less than one millisecond. */
124-
if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec < 1000000) {
137+
/* Use a high-resolution syscall if the timeout value is less than one millisecond. */
138+
if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec > 0 && ts->tv_nsec < 1000000) {
125139
nret = linux_kevent_wait_hires(kq, ts);
140+
if (nret <= 0)
141+
return (nret);
126142

127-
/* Otherwise, use epoll_wait() directly */
143+
/* epoll_wait() should have ready events */
144+
timeout = 0;
128145
} else {
129-
130146
/* Convert timeout to the format used by epoll_wait() */
131147
if (ts == NULL)
132148
timeout = -1;
133149
else
134150
timeout = (1000 * ts->tv_sec) + (ts->tv_nsec / 1000000);
151+
}
135152

136-
dbg_puts("waiting for events");
137-
nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout);
138-
if (nret < 0) {
139-
dbg_perror("epoll_wait");
140-
return (-1);
141-
}
153+
dbg_puts("waiting for events");
154+
nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout);
155+
if (nret < 0) {
156+
dbg_perror("epoll_wait");
157+
return (-1);
142158
}
143159

144160
return (nret);
@@ -157,7 +173,6 @@ linux_kevent_copyout(struct kqueue *kq, int nready,
157173
for (i = 0; i < nready; i++) {
158174
ev = &epevt[i];
159175
kn = (struct knote *) ev->data.ptr;
160-
knote_lock(kn);
161176
filt = &kq->kq_filt[~(kn->kev.filter)];
162177
rv = filt->kf_copyout(eventlist, kn, ev);
163178
if (slowpath(rv < 0)) {
@@ -174,8 +189,6 @@ linux_kevent_copyout(struct kqueue *kq, int nready,
174189
knote_disable(filt, kn); //FIXME: Error checking
175190
if (eventlist->flags & EV_ONESHOT) {
176191
knote_delete(filt, kn); //FIXME: Error checking
177-
} else {
178-
knote_unlock(kn);
179192
}
180193

181194
/* If an empty kevent structure is returned, the event is discarded. */
@@ -196,7 +209,8 @@ linux_eventfd_init(struct eventfd *e)
196209
{
197210
int evfd;
198211

199-
if ((evfd = eventfd(0, 0)) < 0) {
212+
evfd = eventfd(0, 0);
213+
if (evfd < 0) {
200214
dbg_perror("eventfd");
201215
return (-1);
202216
}
@@ -295,8 +309,7 @@ linux_get_descriptor_type(struct knote *kn)
295309
dbg_perror("fstat(2)");
296310
return (-1);
297311
}
298-
if (! S_ISSOCK(sb.st_mode)) {
299-
//FIXME: could be a pipe, device file, or other non-regular file
312+
if (S_ISREG(sb.st_mode)) {
300313
kn->kn_flags |= KNFL_REGULAR_FILE;
301314
dbg_printf("fd %d is a regular file\n", (int)kn->kev.ident);
302315
return (0);
@@ -305,6 +318,9 @@ linux_get_descriptor_type(struct knote *kn)
305318
/*
306319
* Test if the socket is active or passive.
307320
*/
321+
if (! S_ISSOCK(sb.st_mode))
322+
return (0);
323+
308324
slen = sizeof(lsock);
309325
lsock = 0;
310326
i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen);

NGSEngine/src/xdispatch/lib/libkqueue/linux/platform.h

+18-4
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,35 @@
1919

2020
struct filter;
2121

22+
#include <sys/syscall.h>
2223
#include <sys/epoll.h>
2324
#include <sys/queue.h>
2425
#include <sys/inotify.h>
25-
#include <sys/eventfd.h>
26-
#include <sys/signalfd.h>
27-
#include <sys/timerfd.h>
26+
#if HAVE_SYS_EVENTFD_H
27+
# include <sys/eventfd.h>
28+
#else
29+
# define eventfd(a,b) syscall(SYS_eventfd, (a), (b))
30+
31+
static inline int eventfd_write(int fd, uint64_t val) {
32+
if (write(fd, &val, sizeof(val)) < (ssize_t) sizeof(val))
33+
return (-1);
34+
else
35+
return (0);
36+
}
37+
#endif
38+
#if HAVE_SYS_TIMERFD_H
39+
# include <sys/timerfd.h>
40+
#endif
2841

2942
/*
3043
* Get the current thread ID
3144
*/
3245
# define _GNU_SOURCE
3346
# include <linux/unistd.h>
34-
# include <sys/syscall.h>
3547
# include <unistd.h>
48+
#ifndef __ANDROID__
3649
extern long int syscall (long int __sysno, ...);
50+
#endif
3751

3852
/* Convenience macros to access the epoll descriptor for the kqueue */
3953
#define kqueue_epfd(kq) ((kq)->kq_id)

0 commit comments

Comments
 (0)