event 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/event/Makefile +28 -27
- data/ext/event/backend.o +0 -0
- data/ext/event/backend/backend.c +64 -0
- data/ext/event/backend/backend.h +10 -1
- data/ext/event/backend/epoll.c +62 -6
- data/ext/event/backend/kqueue.c +88 -6
- data/ext/event/backend/pidfd.c +36 -0
- data/ext/event/backend/uring.c +118 -51
- data/ext/event/event.bundle +0 -0
- data/ext/event/event.c +3 -0
- data/ext/event/event.h +3 -3
- data/ext/event/event.o +0 -0
- data/ext/event/extconf.h +1 -2
- data/ext/event/extconf.rb +4 -1
- data/ext/event/kqueue.o +0 -0
- data/ext/event/mkmf.log +62 -21
- data/lib/event/backend/select.rb +19 -1
- data/lib/event/version.rb +1 -1
- metadata +7 -5
- data/ext/event/epoll.o +0 -0
- data/ext/event/event.so +0 -0
- data/ext/event/uring.o +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 932f834070b1bb738a09a9cb306599f80386755e4bfa2c78b502715acecf56b7
|
4
|
+
data.tar.gz: a04db89605437563a594e9012adb50a60af4a6c6dfacdd048ec0b03048f68010
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 074e688c34260fe28c3f15857c731052a745605deafd7d75bd07f9e0dc59aeed34d6633a05f5259d03a357c7f5c45762ef7de53a2f5dfc5c32213471f66eb847
|
7
|
+
data.tar.gz: 2214b5749ca680a7892e01539ec962b976f4fad480aa4a5d6d0d589981af8944a2ac94b03484e3e7e7936fd4bbf344418b72cb457fa229ffda11ff91bae9e5e8
|
data/ext/event/Makefile
CHANGED
@@ -12,12 +12,12 @@ NULLCMD = :
|
|
12
12
|
#### Start of system configuration section. ####
|
13
13
|
|
14
14
|
srcdir = .
|
15
|
-
topdir = /
|
15
|
+
topdir = /Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0
|
16
16
|
hdrdir = $(topdir)
|
17
|
-
arch_hdrdir = /
|
17
|
+
arch_hdrdir = /Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20
|
18
18
|
PATH_SEPARATOR = :
|
19
19
|
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby:$(srcdir)/backend
|
20
|
-
prefix = $(DESTDIR)/
|
20
|
+
prefix = $(DESTDIR)/Users/samuel/.rubies/ruby-3.0.1
|
21
21
|
rubysitearchprefix = $(rubylibprefix)/$(sitearch)
|
22
22
|
rubyarchprefix = $(rubylibprefix)/$(arch)
|
23
23
|
rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
|
@@ -50,7 +50,7 @@ dvidir = $(docdir)
|
|
50
50
|
htmldir = $(docdir)
|
51
51
|
infodir = $(datarootdir)/info
|
52
52
|
docdir = $(datarootdir)/doc/$(PACKAGE)
|
53
|
-
oldincludedir = $(
|
53
|
+
oldincludedir = $(SDKROOT)/usr/include
|
54
54
|
includedir = $(prefix)/include
|
55
55
|
runstatedir = $(localstatedir)/run
|
56
56
|
localstatedir = $(prefix)/var
|
@@ -65,12 +65,12 @@ archdir = $(rubyarchdir)
|
|
65
65
|
|
66
66
|
|
67
67
|
CC_WRAPPER =
|
68
|
-
CC =
|
69
|
-
CXX =
|
68
|
+
CC = clang -fdeclspec
|
69
|
+
CXX = clang++ -fdeclspec
|
70
70
|
LIBRUBY = $(LIBRUBY_A)
|
71
71
|
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
72
|
-
LIBRUBYARG_SHARED =
|
73
|
-
LIBRUBYARG_STATIC = -
|
72
|
+
LIBRUBYARG_SHARED =
|
73
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework Security -framework Foundation $(MAINLIBS)
|
74
74
|
empty =
|
75
75
|
OUTFLAG = -o $(empty)
|
76
76
|
COUTFLAG = -o $(empty)
|
@@ -81,31 +81,31 @@ cflags = $(optflags) $(debugflags) $(warnflags)
|
|
81
81
|
cxxflags =
|
82
82
|
optflags = -O3
|
83
83
|
debugflags = -ggdb3
|
84
|
-
warnflags = -Wall -Wextra -Wdeprecated-declarations -
|
84
|
+
warnflags = -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens
|
85
85
|
cppflags =
|
86
|
-
CCDLFLAGS = -
|
87
|
-
CFLAGS = $(CCDLFLAGS) $(cflags) -Wall $(ARCH_FLAG)
|
86
|
+
CCDLFLAGS = -fno-common
|
87
|
+
CFLAGS = $(CCDLFLAGS) $(cflags) -pipe -Wall $(ARCH_FLAG)
|
88
88
|
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
89
89
|
DEFS =
|
90
|
-
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" $(DEFS) $(cppflags)
|
90
|
+
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags)
|
91
91
|
CXXFLAGS = $(CCDLFLAGS) $(ARCH_FLAG)
|
92
|
-
ldflags = -L. -fstack-protector-strong -
|
93
|
-
dldflags = -Wl
|
92
|
+
ldflags = -L. -fstack-protector-strong -L/opt/local/lib
|
93
|
+
dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -L/opt/local/lib
|
94
94
|
ARCH_FLAG =
|
95
95
|
DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
|
96
|
-
LDSHARED = $(CC) -
|
97
|
-
LDSHAREDXX = $(CXX) -
|
98
|
-
AR =
|
96
|
+
LDSHARED = $(CC) -dynamic -bundle
|
97
|
+
LDSHAREDXX = $(CXX) -dynamic -bundle
|
98
|
+
AR = ar
|
99
99
|
EXEEXT =
|
100
100
|
|
101
101
|
RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
|
102
|
-
RUBY_SO_NAME = ruby
|
102
|
+
RUBY_SO_NAME = ruby.3.0
|
103
103
|
RUBYW_INSTALL_NAME =
|
104
104
|
RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
|
105
105
|
RUBYW_BASE_NAME = rubyw
|
106
106
|
RUBY_BASE_NAME = ruby
|
107
107
|
|
108
|
-
arch = x86_64-
|
108
|
+
arch = x86_64-darwin20
|
109
109
|
sitearch = $(arch)
|
110
110
|
ruby_version = 3.0.0
|
111
111
|
ruby = $(bindir)/$(RUBY_BASE_NAME)
|
@@ -114,8 +114,8 @@ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h
|
|
114
114
|
|
115
115
|
RM = rm -f
|
116
116
|
RM_RF = $(RUBY) -run -e rm -- -rf
|
117
|
-
RMDIRS = rmdir
|
118
|
-
MAKEDIRS = /
|
117
|
+
RMDIRS = rmdir -p
|
118
|
+
MAKEDIRS = /opt/local/bin/gmkdir -p
|
119
119
|
INSTALL = /usr/bin/install -c
|
120
120
|
INSTALL_PROG = $(INSTALL) -m 0755
|
121
121
|
INSTALL_DATA = $(INSTALL) -m 644
|
@@ -125,8 +125,8 @@ TOUCH = exit >
|
|
125
125
|
#### End of system configuration section. ####
|
126
126
|
|
127
127
|
preload =
|
128
|
-
libpath = . $(libdir)
|
129
|
-
LIBPATH = -L. -L$(libdir) -
|
128
|
+
libpath = . $(libdir) /opt/local/lib
|
129
|
+
LIBPATH = -L. -L$(libdir) -L/opt/local/lib
|
130
130
|
DEFFILE =
|
131
131
|
|
132
132
|
CLEANFILES = mkmf.log
|
@@ -137,16 +137,16 @@ extout =
|
|
137
137
|
extout_prefix =
|
138
138
|
target_prefix = /event
|
139
139
|
LOCAL_LIBS =
|
140
|
-
LIBS =
|
140
|
+
LIBS =
|
141
141
|
ORIG_SRCS = event.c
|
142
|
-
SRCS = $(ORIG_SRCS) event.c
|
143
|
-
OBJS = event.o
|
142
|
+
SRCS = $(ORIG_SRCS) event.c backend.c kqueue.c
|
143
|
+
OBJS = event.o backend.o kqueue.o
|
144
144
|
HDRS = $(srcdir)/event.h $(srcdir)/extconf.h
|
145
145
|
LOCAL_HDRS =
|
146
146
|
TARGET = event
|
147
147
|
TARGET_NAME = event
|
148
148
|
TARGET_ENTRY = Init_$(TARGET_NAME)
|
149
|
-
DLLIB = $(TARGET).
|
149
|
+
DLLIB = $(TARGET).bundle
|
150
150
|
EXTSTATIC =
|
151
151
|
STATIC_LIB =
|
152
152
|
|
@@ -260,6 +260,7 @@ $(TARGET_SO): $(OBJS) Makefile
|
|
260
260
|
$(ECHO) linking shared-object event/$(DLLIB)
|
261
261
|
-$(Q)$(RM) $(@)
|
262
262
|
$(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
263
|
+
$(Q) $(POSTLINK)
|
263
264
|
|
264
265
|
|
265
266
|
|
data/ext/event/backend.o
ADDED
Binary file
|
@@ -0,0 +1,64 @@
|
|
1
|
+
// Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
//
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
// of this software and associated documentation files (the "Software"), to deal
|
5
|
+
// in the Software without restriction, including without limitation the rights
|
6
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
// copies of the Software, and to permit persons to whom the Software is
|
8
|
+
// furnished to do so, subject to the following conditions:
|
9
|
+
//
|
10
|
+
// The above copyright notice and this permission notice shall be included in
|
11
|
+
// all copies or substantial portions of the Software.
|
12
|
+
//
|
13
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
// THE SOFTWARE.
|
20
|
+
|
21
|
+
#include "backend.h"
|
22
|
+
|
23
|
+
#if HAVE_RB_FIBER_TRANSFER_KW
|
24
|
+
#define HAVE_RB_FIBER_TRANSFER 1
|
25
|
+
#else
|
26
|
+
#define HAVE_RB_FIBER_TRANSFER 0
|
27
|
+
#endif
|
28
|
+
|
29
|
+
static ID id_transfer, id_wait;
|
30
|
+
static VALUE rb_Process_Status = Qnil;
|
31
|
+
|
32
|
+
void Init_Event_Backend(VALUE Event_Backend) {
|
33
|
+
id_transfer = rb_intern("transfer");
|
34
|
+
id_wait = rb_intern("wait");
|
35
|
+
// id_alive_p = rb_intern("alive?");
|
36
|
+
rb_Process_Status = rb_const_get_at(rb_mProcess, rb_intern("Status"));
|
37
|
+
}
|
38
|
+
|
39
|
+
VALUE
|
40
|
+
Event_Backend_transfer(VALUE fiber) {
|
41
|
+
#if HAVE_RB_FIBER_TRANSFER
|
42
|
+
return rb_fiber_transfer(fiber, 0, NULL);
|
43
|
+
#else
|
44
|
+
return rb_funcall(fiber, id_transfer, 0);
|
45
|
+
#endif
|
46
|
+
}
|
47
|
+
|
48
|
+
VALUE
|
49
|
+
Event_Backend_transfer_result(VALUE fiber, VALUE result) {
|
50
|
+
// if (!RTEST(rb_fiber_alive_p(fiber))) {
|
51
|
+
// return Qnil;
|
52
|
+
// }
|
53
|
+
|
54
|
+
#if HAVE_RB_FIBER_TRANSFER
|
55
|
+
return rb_fiber_transfer(fiber, 1, &result);
|
56
|
+
#else
|
57
|
+
return rb_funcall(fiber, id_transfer, 1, result);
|
58
|
+
#endif
|
59
|
+
}
|
60
|
+
|
61
|
+
VALUE Event_Backend_process_status_wait(rb_pid_t pid)
|
62
|
+
{
|
63
|
+
return rb_funcall(rb_Process_Status, id_wait, 2, PIDT2NUM(pid), INT2NUM(WNOHANG));
|
64
|
+
}
|
data/ext/event/backend/backend.h
CHANGED
@@ -18,6 +18,9 @@
|
|
18
18
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
// THE SOFTWARE.
|
20
20
|
|
21
|
+
#include <ruby.h>
|
22
|
+
#include <ruby/thread.h>
|
23
|
+
|
21
24
|
enum Event {
|
22
25
|
READABLE = 1,
|
23
26
|
PRIORITY = 2,
|
@@ -26,4 +29,10 @@ enum Event {
|
|
26
29
|
HANGUP = 16
|
27
30
|
};
|
28
31
|
|
29
|
-
|
32
|
+
void
|
33
|
+
Init_Event_Backend();
|
34
|
+
|
35
|
+
VALUE Event_Backend_transfer(VALUE fiber);
|
36
|
+
VALUE Event_Backend_transfer_result(VALUE fiber, VALUE argument);
|
37
|
+
|
38
|
+
VALUE Event_Backend_process_status_wait(rb_pid_t pid);
|
data/ext/event/backend/epoll.c
CHANGED
@@ -25,8 +25,10 @@
|
|
25
25
|
#include <time.h>
|
26
26
|
#include <errno.h>
|
27
27
|
|
28
|
+
#include "pidfd.c"
|
29
|
+
|
28
30
|
static VALUE Event_Backend_EPoll = Qnil;
|
29
|
-
static ID id_fileno
|
31
|
+
static ID id_fileno;
|
30
32
|
|
31
33
|
enum {EPOLL_MAX_EVENTS = 64};
|
32
34
|
|
@@ -111,6 +113,60 @@ VALUE Event_Backend_EPoll_close(VALUE self) {
|
|
111
113
|
return Qnil;
|
112
114
|
}
|
113
115
|
|
116
|
+
struct process_wait_arguments {
|
117
|
+
struct Event_Backend_EPoll *data;
|
118
|
+
pid_t pid;
|
119
|
+
int flags;
|
120
|
+
int descriptor;
|
121
|
+
};
|
122
|
+
|
123
|
+
static
|
124
|
+
VALUE process_wait_transfer(VALUE _arguments) {
|
125
|
+
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
126
|
+
|
127
|
+
Event_Backend_transfer(arguments->data->loop);
|
128
|
+
|
129
|
+
return Event_Backend_process_status_wait(arguments->pid);
|
130
|
+
}
|
131
|
+
|
132
|
+
static
|
133
|
+
VALUE process_wait_ensure(VALUE _arguments) {
|
134
|
+
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
135
|
+
|
136
|
+
// epoll_ctl(arguments->data->descriptor, EPOLL_CTL_DEL, arguments->descriptor, NULL);
|
137
|
+
|
138
|
+
close(arguments->descriptor);
|
139
|
+
|
140
|
+
return Qnil;
|
141
|
+
}
|
142
|
+
|
143
|
+
VALUE Event_Backend_EPoll_process_wait(VALUE self, VALUE fiber, VALUE pid, VALUE flags) {
|
144
|
+
struct Event_Backend_EPoll *data = NULL;
|
145
|
+
TypedData_Get_Struct(self, struct Event_Backend_EPoll, &Event_Backend_EPoll_Type, data);
|
146
|
+
|
147
|
+
struct process_wait_arguments process_wait_arguments = {
|
148
|
+
.data = data,
|
149
|
+
.pid = NUM2PIDT(pid),
|
150
|
+
.flags = NUM2INT(flags),
|
151
|
+
};
|
152
|
+
|
153
|
+
process_wait_arguments.descriptor = pidfd_open(process_wait_arguments.pid, 0);
|
154
|
+
rb_update_max_fd(process_wait_arguments.descriptor);
|
155
|
+
|
156
|
+
struct epoll_event event = {
|
157
|
+
.events = EPOLLIN|EPOLLRDHUP|EPOLLONESHOT,
|
158
|
+
.data = {.ptr = (void*)fiber},
|
159
|
+
};
|
160
|
+
|
161
|
+
int result = epoll_ctl(data->descriptor, EPOLL_CTL_ADD, process_wait_arguments.descriptor, &event);
|
162
|
+
|
163
|
+
if (result == -1) {
|
164
|
+
rb_sys_fail("epoll_ctl(process_wait)");
|
165
|
+
}
|
166
|
+
|
167
|
+
return rb_ensure(process_wait_transfer, (VALUE)&process_wait_arguments, process_wait_ensure, (VALUE)&process_wait_arguments);
|
168
|
+
}
|
169
|
+
|
114
170
|
static inline
|
115
171
|
uint32_t epoll_flags_from_events(int events) {
|
116
172
|
uint32_t flags = 0;
|
@@ -161,7 +217,7 @@ static
|
|
161
217
|
VALUE io_wait_transfer(VALUE _arguments) {
|
162
218
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
163
219
|
|
164
|
-
VALUE result =
|
220
|
+
VALUE result = Event_Backend_transfer(arguments->data->loop);
|
165
221
|
|
166
222
|
return INT2NUM(events_from_epoll_flags(NUM2INT(result)));
|
167
223
|
};
|
@@ -272,13 +328,13 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
|
|
272
328
|
.timeout = 0
|
273
329
|
};
|
274
330
|
|
275
|
-
|
331
|
+
select_internal_with_gvl(&arguments);
|
276
332
|
|
277
333
|
if (arguments.count == 0) {
|
278
334
|
arguments.timeout = make_timeout(duration);
|
279
335
|
|
280
336
|
if (arguments.timeout != 0) {
|
281
|
-
|
337
|
+
select_internal_without_gvl(&arguments);
|
282
338
|
}
|
283
339
|
}
|
284
340
|
|
@@ -288,7 +344,7 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
|
|
288
344
|
|
289
345
|
// fprintf(stderr, "-> fiber=%p descriptor=%d\n", (void*)fiber, events[i].data.fd);
|
290
346
|
|
291
|
-
|
347
|
+
Event_Backend_transfer_result(fiber, result);
|
292
348
|
}
|
293
349
|
|
294
350
|
return INT2NUM(arguments.count);
|
@@ -296,7 +352,6 @@ VALUE Event_Backend_EPoll_select(VALUE self, VALUE duration) {
|
|
296
352
|
|
297
353
|
void Init_Event_Backend_EPoll(VALUE Event_Backend) {
|
298
354
|
id_fileno = rb_intern("fileno");
|
299
|
-
id_transfer = rb_intern("transfer");
|
300
355
|
|
301
356
|
Event_Backend_EPoll = rb_define_class_under(Event_Backend, "EPoll", rb_cObject);
|
302
357
|
|
@@ -306,4 +361,5 @@ void Init_Event_Backend_EPoll(VALUE Event_Backend) {
|
|
306
361
|
|
307
362
|
rb_define_method(Event_Backend_EPoll, "io_wait", Event_Backend_EPoll_io_wait, 3);
|
308
363
|
rb_define_method(Event_Backend_EPoll, "select", Event_Backend_EPoll_select, 1);
|
364
|
+
rb_define_method(Event_Backend_EPoll, "process_wait", Event_Backend_EPoll_process_wait, 3);
|
309
365
|
}
|
data/ext/event/backend/kqueue.c
CHANGED
@@ -24,9 +24,10 @@
|
|
24
24
|
#include <sys/event.h>
|
25
25
|
#include <sys/ioctl.h>
|
26
26
|
#include <time.h>
|
27
|
+
#include <errno.h>
|
27
28
|
|
28
29
|
static VALUE Event_Backend_KQueue = Qnil;
|
29
|
-
static ID id_fileno
|
30
|
+
static ID id_fileno;
|
30
31
|
|
31
32
|
enum {KQUEUE_MAX_EVENTS = 64};
|
32
33
|
|
@@ -112,6 +113,86 @@ VALUE Event_Backend_KQueue_close(VALUE self) {
|
|
112
113
|
return Qnil;
|
113
114
|
}
|
114
115
|
|
116
|
+
struct process_wait_arguments {
|
117
|
+
struct Event_Backend_KQueue *data;
|
118
|
+
pid_t pid;
|
119
|
+
int flags;
|
120
|
+
};
|
121
|
+
|
122
|
+
static
|
123
|
+
int process_add_filters(int descriptor, int ident, VALUE fiber) {
|
124
|
+
struct kevent event = {0};
|
125
|
+
|
126
|
+
event.ident = ident;
|
127
|
+
event.filter = EVFILT_PROC;
|
128
|
+
event.flags = EV_ADD | EV_ENABLE | EV_ONESHOT;
|
129
|
+
event.fflags = NOTE_EXIT;
|
130
|
+
event.udata = (void*)fiber;
|
131
|
+
|
132
|
+
int result = kevent(descriptor, &event, 1, NULL, 0, NULL);
|
133
|
+
|
134
|
+
if (result == -1) {
|
135
|
+
// No such process - the process has probably already terminated:
|
136
|
+
if (errno == ESRCH) {
|
137
|
+
return 0;
|
138
|
+
}
|
139
|
+
|
140
|
+
rb_sys_fail("kevent(process_add_filters)");
|
141
|
+
}
|
142
|
+
|
143
|
+
return 1;
|
144
|
+
}
|
145
|
+
|
146
|
+
static
|
147
|
+
void process_remove_filters(int descriptor, int ident) {
|
148
|
+
struct kevent event = {0};
|
149
|
+
|
150
|
+
event.ident = ident;
|
151
|
+
event.filter = EVFILT_PROC;
|
152
|
+
event.flags = EV_DELETE;
|
153
|
+
event.fflags = NOTE_EXIT;
|
154
|
+
|
155
|
+
// Ignore the result.
|
156
|
+
kevent(descriptor, &event, 1, NULL, 0, NULL);
|
157
|
+
}
|
158
|
+
|
159
|
+
static
|
160
|
+
VALUE process_wait_transfer(VALUE _arguments) {
|
161
|
+
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
162
|
+
|
163
|
+
Event_Backend_transfer(arguments->data->loop);
|
164
|
+
|
165
|
+
return Event_Backend_process_status_wait(arguments->pid);
|
166
|
+
}
|
167
|
+
|
168
|
+
static
|
169
|
+
VALUE process_wait_rescue(VALUE _arguments, VALUE exception) {
|
170
|
+
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
171
|
+
|
172
|
+
process_remove_filters(arguments->data->descriptor, arguments->pid);
|
173
|
+
|
174
|
+
rb_exc_raise(exception);
|
175
|
+
}
|
176
|
+
|
177
|
+
VALUE Event_Backend_KQueue_process_wait(VALUE self, VALUE fiber, VALUE pid, VALUE flags) {
|
178
|
+
struct Event_Backend_KQueue *data = NULL;
|
179
|
+
TypedData_Get_Struct(self, struct Event_Backend_KQueue, &Event_Backend_KQueue_Type, data);
|
180
|
+
|
181
|
+
struct process_wait_arguments process_wait_arguments = {
|
182
|
+
.data = data,
|
183
|
+
.pid = NUM2PIDT(pid),
|
184
|
+
.flags = NUM2INT(flags),
|
185
|
+
};
|
186
|
+
|
187
|
+
int waiting = process_add_filters(data->descriptor, process_wait_arguments.pid, fiber);
|
188
|
+
|
189
|
+
if (waiting) {
|
190
|
+
return rb_rescue(process_wait_transfer, (VALUE)&process_wait_arguments, process_wait_rescue, (VALUE)&process_wait_arguments);
|
191
|
+
} else {
|
192
|
+
return Event_Backend_process_status_wait(process_wait_arguments.pid);
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
115
196
|
static
|
116
197
|
int io_add_filters(int descriptor, int ident, int events, VALUE fiber) {
|
117
198
|
int count = 0;
|
@@ -143,7 +224,7 @@ int io_add_filters(int descriptor, int ident, int events, VALUE fiber) {
|
|
143
224
|
int result = kevent(descriptor, kevents, count, NULL, 0, NULL);
|
144
225
|
|
145
226
|
if (result == -1) {
|
146
|
-
rb_sys_fail("kevent(
|
227
|
+
rb_sys_fail("kevent(io_add_filters)");
|
147
228
|
}
|
148
229
|
|
149
230
|
return events;
|
@@ -200,7 +281,7 @@ static
|
|
200
281
|
VALUE io_wait_transfer(VALUE _arguments) {
|
201
282
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
202
283
|
|
203
|
-
VALUE result =
|
284
|
+
VALUE result = Event_Backend_transfer(arguments->data->loop);
|
204
285
|
|
205
286
|
return INT2NUM(events_from_kqueue_filter(NUM2INT(result)));
|
206
287
|
};
|
@@ -325,7 +406,8 @@ VALUE Event_Backend_KQueue_select(VALUE self, VALUE duration) {
|
|
325
406
|
for (int i = 0; i < arguments.count; i += 1) {
|
326
407
|
VALUE fiber = (VALUE)arguments.events[i].udata;
|
327
408
|
VALUE result = INT2NUM(arguments.events[i].filter);
|
328
|
-
|
409
|
+
|
410
|
+
Event_Backend_transfer_result(fiber, result);
|
329
411
|
}
|
330
412
|
|
331
413
|
return INT2NUM(arguments.count);
|
@@ -333,14 +415,14 @@ VALUE Event_Backend_KQueue_select(VALUE self, VALUE duration) {
|
|
333
415
|
|
334
416
|
void Init_Event_Backend_KQueue(VALUE Event_Backend) {
|
335
417
|
id_fileno = rb_intern("fileno");
|
336
|
-
id_transfer = rb_intern("transfer");
|
337
418
|
|
338
419
|
Event_Backend_KQueue = rb_define_class_under(Event_Backend, "KQueue", rb_cObject);
|
339
420
|
|
340
421
|
rb_define_alloc_func(Event_Backend_KQueue, Event_Backend_KQueue_allocate);
|
341
422
|
rb_define_method(Event_Backend_KQueue, "initialize", Event_Backend_KQueue_initialize, 1);
|
342
|
-
rb_define_method(Event_Backend_KQueue, "
|
423
|
+
rb_define_method(Event_Backend_KQueue, "close", Event_Backend_KQueue_close, 0);
|
343
424
|
|
344
425
|
rb_define_method(Event_Backend_KQueue, "io_wait", Event_Backend_KQueue_io_wait, 3);
|
345
426
|
rb_define_method(Event_Backend_KQueue, "select", Event_Backend_KQueue_select, 1);
|
427
|
+
rb_define_method(Event_Backend_KQueue, "process_wait", Event_Backend_KQueue_process_wait, 3);
|
346
428
|
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
// Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
//
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
// of this software and associated documentation files (the "Software"), to deal
|
5
|
+
// in the Software without restriction, including without limitation the rights
|
6
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
// copies of the Software, and to permit persons to whom the Software is
|
8
|
+
// furnished to do so, subject to the following conditions:
|
9
|
+
//
|
10
|
+
// The above copyright notice and this permission notice shall be included in
|
11
|
+
// all copies or substantial portions of the Software.
|
12
|
+
//
|
13
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
// THE SOFTWARE.
|
20
|
+
|
21
|
+
#include <sys/types.h>
|
22
|
+
#include <sys/syscall.h>
|
23
|
+
#include <unistd.h>
|
24
|
+
#include <poll.h>
|
25
|
+
#include <stdlib.h>
|
26
|
+
#include <stdio.h>
|
27
|
+
|
28
|
+
#ifndef __NR_pidfd_open
|
29
|
+
#define __NR_pidfd_open 434 /* System call # on most architectures */
|
30
|
+
#endif
|
31
|
+
|
32
|
+
static int
|
33
|
+
pidfd_open(pid_t pid, unsigned int flags)
|
34
|
+
{
|
35
|
+
return syscall(__NR_pidfd_open, pid, flags);
|
36
|
+
}
|
data/ext/event/backend/uring.c
CHANGED
@@ -25,8 +25,10 @@
|
|
25
25
|
#include <poll.h>
|
26
26
|
#include <time.h>
|
27
27
|
|
28
|
+
#include "pidfd.c"
|
29
|
+
|
28
30
|
static VALUE Event_Backend_URing = Qnil;
|
29
|
-
static ID id_fileno
|
31
|
+
static ID id_fileno;
|
30
32
|
|
31
33
|
enum {URING_ENTRIES = 128};
|
32
34
|
enum {URING_MAX_EVENTS = 128};
|
@@ -111,6 +113,66 @@ VALUE Event_Backend_URing_close(VALUE self) {
|
|
111
113
|
return Qnil;
|
112
114
|
}
|
113
115
|
|
116
|
+
struct io_uring_sqe * io_get_sqe(struct Event_Backend_URing *data) {
|
117
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&data->ring);
|
118
|
+
|
119
|
+
while (sqe == NULL) {
|
120
|
+
io_uring_submit(&data->ring);
|
121
|
+
sqe = io_uring_get_sqe(&data->ring);
|
122
|
+
}
|
123
|
+
|
124
|
+
// fprintf(stderr, "io_get_sqe -> %p\n", sqe);
|
125
|
+
|
126
|
+
return sqe;
|
127
|
+
}
|
128
|
+
|
129
|
+
struct process_wait_arguments {
|
130
|
+
struct Event_Backend_URing *data;
|
131
|
+
pid_t pid;
|
132
|
+
int flags;
|
133
|
+
int descriptor;
|
134
|
+
};
|
135
|
+
|
136
|
+
static
|
137
|
+
VALUE process_wait_transfer(VALUE _arguments) {
|
138
|
+
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
139
|
+
|
140
|
+
Event_Backend_transfer(arguments->data->loop);
|
141
|
+
|
142
|
+
return Event_Backend_process_status_wait(arguments->pid);
|
143
|
+
}
|
144
|
+
|
145
|
+
static
|
146
|
+
VALUE process_wait_ensure(VALUE _arguments) {
|
147
|
+
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
148
|
+
|
149
|
+
close(arguments->descriptor);
|
150
|
+
|
151
|
+
return Qnil;
|
152
|
+
}
|
153
|
+
|
154
|
+
VALUE Event_Backend_URing_process_wait(VALUE self, VALUE fiber, VALUE pid, VALUE flags) {
|
155
|
+
struct Event_Backend_URing *data = NULL;
|
156
|
+
TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
|
157
|
+
|
158
|
+
struct process_wait_arguments process_wait_arguments = {
|
159
|
+
.data = data,
|
160
|
+
.pid = NUM2PIDT(pid),
|
161
|
+
.flags = NUM2INT(flags),
|
162
|
+
};
|
163
|
+
|
164
|
+
process_wait_arguments.descriptor = pidfd_open(process_wait_arguments.pid, 0);
|
165
|
+
rb_update_max_fd(process_wait_arguments.descriptor);
|
166
|
+
|
167
|
+
struct io_uring_sqe *sqe = io_get_sqe(data);
|
168
|
+
assert(sqe);
|
169
|
+
|
170
|
+
io_uring_prep_poll_add(sqe, process_wait_arguments.descriptor, POLLIN|POLLHUP|POLLERR);
|
171
|
+
io_uring_sqe_set_data(sqe, (void*)fiber);
|
172
|
+
|
173
|
+
return rb_ensure(process_wait_transfer, (VALUE)&process_wait_arguments, process_wait_ensure, (VALUE)&process_wait_arguments);
|
174
|
+
}
|
175
|
+
|
114
176
|
static inline
|
115
177
|
short poll_flags_from_events(int events) {
|
116
178
|
short flags = 0;
|
@@ -142,22 +204,13 @@ struct io_wait_arguments {
|
|
142
204
|
short flags;
|
143
205
|
};
|
144
206
|
|
145
|
-
struct io_uring_sqe * io_get_sqe(struct Event_Backend_URing *data) {
|
146
|
-
struct io_uring_sqe *sqe = io_uring_get_sqe(&data->ring);
|
147
|
-
|
148
|
-
while (sqe == NULL) {
|
149
|
-
sqe = io_uring_get_sqe(&data->ring);
|
150
|
-
}
|
151
|
-
|
152
|
-
return sqe;
|
153
|
-
}
|
154
|
-
|
155
207
|
static
|
156
208
|
VALUE io_wait_rescue(VALUE _arguments, VALUE exception) {
|
157
209
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
158
210
|
struct Event_Backend_URing *data = arguments->data;
|
159
211
|
|
160
212
|
struct io_uring_sqe *sqe = io_get_sqe(data);
|
213
|
+
assert(sqe);
|
161
214
|
|
162
215
|
// fprintf(stderr, "poll_remove(%p, %p)\n", sqe, (void*)arguments->fiber);
|
163
216
|
|
@@ -171,8 +224,8 @@ static
|
|
171
224
|
VALUE io_wait_transfer(VALUE _arguments) {
|
172
225
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
173
226
|
struct Event_Backend_URing *data = arguments->data;
|
174
|
-
|
175
|
-
VALUE result =
|
227
|
+
|
228
|
+
VALUE result = Event_Backend_transfer(data->loop);
|
176
229
|
|
177
230
|
// We explicitly filter the resulting events based on the requested events.
|
178
231
|
// In some cases, poll will report events we didn't ask for.
|
@@ -187,8 +240,7 @@ VALUE Event_Backend_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
|
|
187
240
|
|
188
241
|
int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
|
189
242
|
struct io_uring_sqe *sqe = io_get_sqe(data);
|
190
|
-
|
191
|
-
if (!sqe) return INT2NUM(0);
|
243
|
+
assert(sqe);
|
192
244
|
|
193
245
|
short flags = poll_flags_from_events(NUM2INT(events));
|
194
246
|
|
@@ -196,7 +248,8 @@ VALUE Event_Backend_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE event
|
|
196
248
|
|
197
249
|
io_uring_prep_poll_add(sqe, descriptor, flags);
|
198
250
|
io_uring_sqe_set_data(sqe, (void*)fiber);
|
199
|
-
io_uring_submit
|
251
|
+
// fprintf(stderr, "io_uring_submit\n");
|
252
|
+
// io_uring_submit(&data->ring);
|
200
253
|
|
201
254
|
struct io_wait_arguments io_wait_arguments = {
|
202
255
|
.data = data,
|
@@ -238,6 +291,7 @@ VALUE Event_Backend_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffe
|
|
238
291
|
|
239
292
|
int descriptor = NUM2INT(rb_funcall(io, id_fileno, 0));
|
240
293
|
struct io_uring_sqe *sqe = io_get_sqe(data);
|
294
|
+
assert(sqe);
|
241
295
|
|
242
296
|
struct iovec iovecs[1];
|
243
297
|
iovecs[0].iov_base = RSTRING_PTR(buffer) + NUM2SIZET(offset);
|
@@ -249,7 +303,7 @@ VALUE Event_Backend_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffe
|
|
249
303
|
|
250
304
|
// fprintf(stderr, "prep_readv(%p, %d, %ld)\n", sqe, descriptor, iovecs[0].iov_len);
|
251
305
|
|
252
|
-
int result = NUM2INT(
|
306
|
+
int result = NUM2INT(Event_Backend_transfer(data->loop));
|
253
307
|
|
254
308
|
if (result < 0) {
|
255
309
|
rb_syserr_fail(-result, strerror(-result));
|
@@ -281,7 +335,7 @@ VALUE Event_Backend_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buff
|
|
281
335
|
|
282
336
|
// fprintf(stderr, "prep_writev(%p, %d, %ld)\n", sqe, descriptor, iovecs[0].iov_len);
|
283
337
|
|
284
|
-
int result = NUM2INT(
|
338
|
+
int result = NUM2INT(Event_Backend_transfer(data->loop));
|
285
339
|
|
286
340
|
if (result < 0) {
|
287
341
|
rb_syserr_fail(-result, strerror(-result));
|
@@ -324,8 +378,7 @@ int timeout_nonblocking(struct __kernel_timespec *timespec) {
|
|
324
378
|
struct select_arguments {
|
325
379
|
struct Event_Backend_URing *data;
|
326
380
|
|
327
|
-
int
|
328
|
-
struct io_uring_cqe **cqes;
|
381
|
+
int result;
|
329
382
|
|
330
383
|
struct __kernel_timespec storage;
|
331
384
|
struct __kernel_timespec *timeout;
|
@@ -335,12 +388,10 @@ static
|
|
335
388
|
void * select_internal(void *_arguments) {
|
336
389
|
struct select_arguments * arguments = (struct select_arguments *)_arguments;
|
337
390
|
|
338
|
-
|
391
|
+
io_uring_submit(&arguments->data->ring);
|
339
392
|
|
340
|
-
|
341
|
-
|
342
|
-
arguments->count = 0;
|
343
|
-
}
|
393
|
+
struct io_uring_cqe *cqe = NULL;
|
394
|
+
arguments->result = io_uring_wait_cqe_timeout(&arguments->data->ring, &cqe, arguments->timeout);
|
344
395
|
|
345
396
|
return NULL;
|
346
397
|
}
|
@@ -349,21 +400,52 @@ static
|
|
349
400
|
int select_internal_without_gvl(struct select_arguments *arguments) {
|
350
401
|
rb_thread_call_without_gvl(select_internal, (void *)arguments, RUBY_UBF_IO, 0);
|
351
402
|
|
352
|
-
if (arguments->
|
353
|
-
|
403
|
+
if (arguments->result == -ETIME) {
|
404
|
+
arguments->result = 0;
|
405
|
+
} else if (arguments->result < 0) {
|
406
|
+
rb_syserr_fail(-arguments->result, "select_internal_without_gvl:io_uring_wait_cqes");
|
407
|
+
} else {
|
408
|
+
// At least 1 event is waiting:
|
409
|
+
arguments->result = 1;
|
410
|
+
}
|
411
|
+
|
412
|
+
return arguments->result;
|
413
|
+
}
|
414
|
+
|
415
|
+
static inline
|
416
|
+
unsigned select_process_completions(struct io_uring *ring) {
|
417
|
+
unsigned completed = 0;
|
418
|
+
unsigned head;
|
419
|
+
struct io_uring_cqe *cqe;
|
420
|
+
|
421
|
+
io_uring_for_each_cqe(ring, head, cqe) {
|
422
|
+
++completed;
|
423
|
+
|
424
|
+
// If the operation was cancelled, or the operation has no user data (fiber):
|
425
|
+
if (cqe->res == -ECANCELED || cqe->user_data == 0 || cqe->user_data == LIBURING_UDATA_TIMEOUT) {
|
426
|
+
continue;
|
427
|
+
}
|
428
|
+
|
429
|
+
VALUE fiber = (VALUE)cqe->user_data;
|
430
|
+
VALUE result = INT2NUM(cqe->res);
|
431
|
+
|
432
|
+
// fprintf(stderr, "cqe res=%d user_data=%p\n", cqe->res, (void*)cqe->user_data);
|
433
|
+
|
434
|
+
Event_Backend_transfer_result(fiber, result);
|
435
|
+
}
|
436
|
+
|
437
|
+
if (completed) {
|
438
|
+
io_uring_cq_advance(ring, completed);
|
354
439
|
}
|
355
440
|
|
356
|
-
return
|
441
|
+
return completed;
|
357
442
|
}
|
358
443
|
|
359
444
|
VALUE Event_Backend_URing_select(VALUE self, VALUE duration) {
|
360
445
|
struct Event_Backend_URing *data = NULL;
|
361
446
|
TypedData_Get_Struct(self, struct Event_Backend_URing, &Event_Backend_URing_Type, data);
|
362
447
|
|
363
|
-
|
364
|
-
|
365
|
-
// This is a non-blocking operation:
|
366
|
-
int result = io_uring_peek_batch_cqe(&data->ring, cqes, URING_MAX_EVENTS);
|
448
|
+
int result = select_process_completions(&data->ring);
|
367
449
|
|
368
450
|
if (result < 0) {
|
369
451
|
rb_syserr_fail(-result, strerror(-result));
|
@@ -371,7 +453,6 @@ VALUE Event_Backend_URing_select(VALUE self, VALUE duration) {
|
|
371
453
|
// We might need to wait for events:
|
372
454
|
struct select_arguments arguments = {
|
373
455
|
.data = data,
|
374
|
-
.cqes = cqes,
|
375
456
|
.timeout = NULL,
|
376
457
|
};
|
377
458
|
|
@@ -379,33 +460,18 @@ VALUE Event_Backend_URing_select(VALUE self, VALUE duration) {
|
|
379
460
|
|
380
461
|
if (!timeout_nonblocking(arguments.timeout)) {
|
381
462
|
result = select_internal_without_gvl(&arguments);
|
463
|
+
} else {
|
464
|
+
io_uring_submit(&data->ring);
|
382
465
|
}
|
383
466
|
}
|
384
467
|
|
385
|
-
|
386
|
-
|
387
|
-
for (int i = 0; i < result; i += 1) {
|
388
|
-
// If the operation was cancelled, or the operation has no user data (fiber):
|
389
|
-
if (cqes[i]->res == -ECANCELED || cqes[i]->user_data == 0) {
|
390
|
-
continue;
|
391
|
-
}
|
392
|
-
|
393
|
-
VALUE fiber = (VALUE)io_uring_cqe_get_data(cqes[i]);
|
394
|
-
VALUE result = INT2NUM(cqes[i]->res);
|
395
|
-
|
396
|
-
// fprintf(stderr, "cqes[i] res=%d user_data=%p\n", cqes[i]->res, (void*)cqes[i]->user_data);
|
397
|
-
|
398
|
-
io_uring_cqe_seen(&data->ring, cqes[i]);
|
399
|
-
|
400
|
-
rb_funcall(fiber, id_transfer, 1, result);
|
401
|
-
}
|
468
|
+
result = select_process_completions(&data->ring);
|
402
469
|
|
403
470
|
return INT2NUM(result);
|
404
471
|
}
|
405
472
|
|
406
473
|
void Init_Event_Backend_URing(VALUE Event_Backend) {
|
407
474
|
id_fileno = rb_intern("fileno");
|
408
|
-
id_transfer = rb_intern("transfer");
|
409
475
|
|
410
476
|
Event_Backend_URing = rb_define_class_under(Event_Backend, "URing", rb_cObject);
|
411
477
|
|
@@ -418,4 +484,5 @@ void Init_Event_Backend_URing(VALUE Event_Backend) {
|
|
418
484
|
|
419
485
|
rb_define_method(Event_Backend_URing, "io_read", Event_Backend_URing_io_read, 5);
|
420
486
|
rb_define_method(Event_Backend_URing, "io_write", Event_Backend_URing_io_write, 5);
|
487
|
+
rb_define_method(Event_Backend_URing, "process_wait", Event_Backend_URing_process_wait, 3);
|
421
488
|
}
|
Binary file
|
data/ext/event/event.c
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
// THE SOFTWARE.
|
20
20
|
|
21
21
|
#include "event.h"
|
22
|
+
#include "backend/backend.h"
|
22
23
|
|
23
24
|
VALUE Event = Qnil;
|
24
25
|
VALUE Event_Backend = Qnil;
|
@@ -32,6 +33,8 @@ void Init_event()
|
|
32
33
|
Event = rb_define_module("Event");
|
33
34
|
Event_Backend = rb_define_module_under(Event, "Backend");
|
34
35
|
|
36
|
+
Init_Event_Backend(Event_Backend);
|
37
|
+
|
35
38
|
#ifdef EVENT_BACKEND_URING
|
36
39
|
Init_Event_Backend_URing(Event_Backend);
|
37
40
|
#endif
|
data/ext/event/event.h
CHANGED
@@ -26,14 +26,14 @@
|
|
26
26
|
|
27
27
|
void Init_event();
|
28
28
|
|
29
|
-
#
|
29
|
+
#ifdef HAVE_LIBURING_H
|
30
30
|
#include "backend/uring.h"
|
31
31
|
#endif
|
32
32
|
|
33
|
-
#
|
33
|
+
#ifdef HAVE_SYS_EPOLL_H
|
34
34
|
#include "backend/epoll.h"
|
35
35
|
#endif
|
36
36
|
|
37
|
-
#
|
37
|
+
#ifdef HAVE_SYS_EVENT_H
|
38
38
|
#include "backend/kqueue.h"
|
39
39
|
#endif
|
data/ext/event/event.o
CHANGED
Binary file
|
data/ext/event/extconf.h
CHANGED
data/ext/event/extconf.rb
CHANGED
@@ -30,9 +30,12 @@ dir_config(extension_name)
|
|
30
30
|
|
31
31
|
$CFLAGS << " -Wall"
|
32
32
|
|
33
|
-
$srcs = ["event.c"]
|
33
|
+
$srcs = ["event.c", "backend/backend.c"]
|
34
34
|
$VPATH << "$(srcdir)/backend"
|
35
35
|
|
36
|
+
# have_func('rb_fiber_transfer')
|
37
|
+
have_func('rb_fiber_transfer_kw')
|
38
|
+
|
36
39
|
if have_library('uring') and have_header('liburing.h')
|
37
40
|
$srcs << "backend/uring.c"
|
38
41
|
end
|
data/ext/event/kqueue.o
ADDED
Binary file
|
data/ext/event/mkmf.log
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
have_func: checking for rb_fiber_transfer_kw()... -------------------- no
|
2
2
|
|
3
|
-
"
|
3
|
+
"clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -L. -L/Users/samuel/.rubies/ruby-3.0.1/lib -L/opt/local/lib -L. -fstack-protector-strong -L/opt/local/lib -lruby.3.0-static -framework Security -framework Foundation -lpthread -lgmp -ldl -lobjc "
|
4
4
|
checked program was:
|
5
5
|
/* begin */
|
6
6
|
1: #include "ruby.h"
|
@@ -11,7 +11,11 @@ checked program was:
|
|
11
11
|
6: }
|
12
12
|
/* end */
|
13
13
|
|
14
|
-
"
|
14
|
+
"clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -L. -L/Users/samuel/.rubies/ruby-3.0.1/lib -L/opt/local/lib -L. -fstack-protector-strong -L/opt/local/lib -lruby.3.0-static -framework Security -framework Foundation -lpthread -lgmp -ldl -lobjc "
|
15
|
+
conftest.c:14:57: error: use of undeclared identifier 'rb_fiber_transfer_kw'
|
16
|
+
int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_fiber_transfer_kw; return !p; }
|
17
|
+
^
|
18
|
+
1 error generated.
|
15
19
|
checked program was:
|
16
20
|
/* begin */
|
17
21
|
1: #include "ruby.h"
|
@@ -27,27 +31,69 @@ checked program was:
|
|
27
31
|
11:
|
28
32
|
12: return !!argv[argc];
|
29
33
|
13: }
|
30
|
-
14:
|
31
|
-
|
34
|
+
14: int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_fiber_transfer_kw; return !p; }
|
35
|
+
/* end */
|
36
|
+
|
37
|
+
"clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -L. -L/Users/samuel/.rubies/ruby-3.0.1/lib -L/opt/local/lib -L. -fstack-protector-strong -L/opt/local/lib -lruby.3.0-static -framework Security -framework Foundation -lpthread -lgmp -ldl -lobjc "
|
38
|
+
Undefined symbols for architecture x86_64:
|
39
|
+
"_rb_fiber_transfer_kw", referenced from:
|
40
|
+
_t in conftest-3b7f21.o
|
41
|
+
ld: symbol(s) not found for architecture x86_64
|
42
|
+
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
43
|
+
checked program was:
|
44
|
+
/* begin */
|
45
|
+
1: #include "ruby.h"
|
46
|
+
2:
|
47
|
+
3: /*top*/
|
48
|
+
4: extern int t(void);
|
49
|
+
5: int main(int argc, char **argv)
|
50
|
+
6: {
|
51
|
+
7: if (argc > 1000000) {
|
52
|
+
8: int (* volatile tp)(void)=(int (*)(void))&t;
|
53
|
+
9: printf("%d", (*tp)());
|
54
|
+
10: }
|
55
|
+
11:
|
56
|
+
12: return !!argv[argc];
|
57
|
+
13: }
|
58
|
+
14: extern void rb_fiber_transfer_kw();
|
59
|
+
15: int t(void) { rb_fiber_transfer_kw(); return 0; }
|
32
60
|
/* end */
|
33
61
|
|
34
62
|
--------------------
|
35
63
|
|
36
|
-
|
64
|
+
have_library: checking for -luring... -------------------- no
|
37
65
|
|
38
|
-
"
|
66
|
+
"clang -fdeclspec -o conftest -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -L. -L/Users/samuel/.rubies/ruby-3.0.1/lib -L/opt/local/lib -L. -fstack-protector-strong -L/opt/local/lib -lruby.3.0-static -framework Security -framework Foundation -lpthread -lgmp -ldl -lobjc -luring "
|
67
|
+
ld: library not found for -luring
|
68
|
+
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
39
69
|
checked program was:
|
40
70
|
/* begin */
|
41
|
-
1: #include "ruby.h"
|
42
|
-
2:
|
43
|
-
3:
|
71
|
+
1: #include "ruby.h"
|
72
|
+
2:
|
73
|
+
3: /*top*/
|
74
|
+
4: extern int t(void);
|
75
|
+
5: int main(int argc, char **argv)
|
76
|
+
6: {
|
77
|
+
7: if (argc > 1000000) {
|
78
|
+
8: int (* volatile tp)(void)=(int (*)(void))&t;
|
79
|
+
9: printf("%d", (*tp)());
|
80
|
+
10: }
|
81
|
+
11:
|
82
|
+
12: return !!argv[argc];
|
83
|
+
13: }
|
84
|
+
14:
|
85
|
+
15: int t(void) { ; return 0; }
|
44
86
|
/* end */
|
45
87
|
|
46
88
|
--------------------
|
47
89
|
|
48
|
-
have_header: checking for sys/epoll.h... --------------------
|
90
|
+
have_header: checking for sys/epoll.h... -------------------- no
|
49
91
|
|
50
|
-
"
|
92
|
+
"clang -E -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -o conftest.i"
|
93
|
+
conftest.c:3:10: fatal error: 'sys/epoll.h' file not found
|
94
|
+
#include <sys/epoll.h>
|
95
|
+
^~~~~~~~~~~~~
|
96
|
+
1 error generated.
|
51
97
|
checked program was:
|
52
98
|
/* begin */
|
53
99
|
1: #include "ruby.h"
|
@@ -57,13 +103,9 @@ checked program was:
|
|
57
103
|
|
58
104
|
--------------------
|
59
105
|
|
60
|
-
have_header: checking for sys/event.h... --------------------
|
106
|
+
have_header: checking for sys/event.h... -------------------- yes
|
61
107
|
|
62
|
-
"
|
63
|
-
conftest.c:3:10: fatal error: sys/event.h: No such file or directory
|
64
|
-
3 | #include <sys/event.h>
|
65
|
-
| ^~~~~~~~~~~~~
|
66
|
-
compilation terminated.
|
108
|
+
"clang -E -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/x86_64-darwin20 -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0/ruby/backward -I/Users/samuel/.rubies/ruby-3.0.1/include/ruby-3.0.0 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -pipe -Wall conftest.c -o conftest.i"
|
67
109
|
checked program was:
|
68
110
|
/* begin */
|
69
111
|
1: #include "ruby.h"
|
@@ -77,8 +119,7 @@ extconf.h is:
|
|
77
119
|
/* begin */
|
78
120
|
1: #ifndef EXTCONF_H
|
79
121
|
2: #define EXTCONF_H
|
80
|
-
3: #define
|
81
|
-
4: #
|
82
|
-
5: #endif
|
122
|
+
3: #define HAVE_SYS_EVENT_H 1
|
123
|
+
4: #endif
|
83
124
|
/* end */
|
84
125
|
|
data/lib/event/backend/select.rb
CHANGED
@@ -52,6 +52,24 @@ module Event
|
|
52
52
|
@readable.delete(io) if remove_readable
|
53
53
|
@writable.delete(io) if remove_writable
|
54
54
|
end
|
55
|
+
|
56
|
+
def process_wait(fiber, pid, flags)
|
57
|
+
r, w = IO.pipe
|
58
|
+
|
59
|
+
thread = Thread.new do
|
60
|
+
Process::Status.wait(pid, flags)
|
61
|
+
ensure
|
62
|
+
w.close
|
63
|
+
end
|
64
|
+
|
65
|
+
self.io_wait(fiber, r, READABLE)
|
66
|
+
|
67
|
+
return thread.value
|
68
|
+
ensure
|
69
|
+
r.close
|
70
|
+
w.close
|
71
|
+
thread&.kill
|
72
|
+
end
|
55
73
|
|
56
74
|
def select(duration = nil)
|
57
75
|
readable, writable, _ = ::IO.select(@readable.keys, @writable.keys, nil, duration)
|
@@ -69,7 +87,7 @@ module Event
|
|
69
87
|
end
|
70
88
|
|
71
89
|
ready.each do |fiber, events|
|
72
|
-
fiber.transfer(events)
|
90
|
+
fiber.transfer(events) if fiber.alive?
|
73
91
|
end
|
74
92
|
end
|
75
93
|
end
|
data/lib/event/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bake
|
@@ -74,22 +74,24 @@ extensions:
|
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
76
|
- ext/event/Makefile
|
77
|
+
- ext/event/backend.o
|
78
|
+
- ext/event/backend/backend.c
|
77
79
|
- ext/event/backend/backend.h
|
78
80
|
- ext/event/backend/epoll.c
|
79
81
|
- ext/event/backend/epoll.h
|
80
82
|
- ext/event/backend/kqueue.c
|
81
83
|
- ext/event/backend/kqueue.h
|
84
|
+
- ext/event/backend/pidfd.c
|
82
85
|
- ext/event/backend/uring.c
|
83
86
|
- ext/event/backend/uring.h
|
84
|
-
- ext/event/
|
87
|
+
- ext/event/event.bundle
|
85
88
|
- ext/event/event.c
|
86
89
|
- ext/event/event.h
|
87
90
|
- ext/event/event.o
|
88
|
-
- ext/event/event.so
|
89
91
|
- ext/event/extconf.h
|
90
92
|
- ext/event/extconf.rb
|
93
|
+
- ext/event/kqueue.o
|
91
94
|
- ext/event/mkmf.log
|
92
|
-
- ext/event/uring.o
|
93
95
|
- lib/event.rb
|
94
96
|
- lib/event/backend.rb
|
95
97
|
- lib/event/backend/select.rb
|
data/ext/event/epoll.o
DELETED
Binary file
|
data/ext/event/event.so
DELETED
Binary file
|
data/ext/event/uring.o
DELETED
Binary file
|