Skip to content

Commit a6c88da

Browse files
committed
Implement UM#add
1 parent b3cef2b commit a6c88da

File tree

6 files changed

+109
-15
lines changed

6 files changed

+109
-15
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
- Add `#open`
2+
- Fix `#spin`
3+
- Fix handling of signal interruption.
4+
- Reimplement and simplify um_op
5+
- Add `UM::Queue`, `#push`, `#pop`, `#shift`, `#unshift`
6+
- Add `UM::Mutex`, `#synchronize`
17
- Add `#recv_each`
28
- Add `#getsockopt`, `#setsockopt`
39
- Simplify and improve op management

ext/um/um.c

+14
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,20 @@ VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value) {
499499
return raise_if_exception(ret);
500500
}
501501

502+
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
503+
struct um_op op;
504+
um_prep_op(machine, &op, OP_BIND);
505+
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
506+
io_uring_prep_open(sqe, StringValueCStr(pathname), flags, mode);
507+
508+
VALUE ret = um_fiber_switch(machine);
509+
if (um_check_completion(machine, &op))
510+
ret = INT2NUM(op.result.res);
511+
512+
RB_GC_GUARD(ret);
513+
return raise_if_exception(ret);
514+
}
515+
502516
/*******************************************************************************
503517
multishot ops
504518
*******************************************************************************/

ext/um/um.h

+1
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int buffer_o
192192
VALUE um_read_each(struct um *machine, int fd, int bgid);
193193
VALUE um_write(struct um *machine, int fd, VALUE str, int len);
194194
VALUE um_close(struct um *machine, int fd);
195+
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
195196

196197
VALUE um_accept(struct um *machine, int fd);
197198
VALUE um_accept_each(struct um *machine, int fd);

ext/um/um_class.c

+38-15
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,28 @@ VALUE UM_queue_shift(VALUE self, VALUE queue) {
258258

259259
#endif
260260

261+
struct um_open_ctx {
262+
VALUE self;
263+
VALUE fd;
264+
};
265+
266+
VALUE UM_open_ensure(VALUE arg) {
267+
struct um_open_ctx *ctx = (struct um_open_ctx *)arg;
268+
UM_close(ctx->self, ctx->fd);
269+
return ctx->self;
270+
}
271+
272+
VALUE UM_open(VALUE self, VALUE pathname, VALUE flags) {
273+
struct um *machine = get_machine(self);
274+
VALUE ret = um_open(machine, pathname, NUM2INT(flags), S_IRWXU);
275+
if (rb_block_given_p()) {
276+
struct um_open_ctx ctx = { self, ret };
277+
return rb_ensure(rb_yield, ret, UM_open_ensure, (VALUE)&ctx);
278+
}
279+
else
280+
return ret;
281+
}
282+
261283
VALUE UM_kernel_version(VALUE self) {
262284
return INT2NUM(UM_KERNEL_VERSION);
263285
}
@@ -269,41 +291,42 @@ void Init_UM(void) {
269291
rb_define_alloc_func(cUM, UM_allocate);
270292

271293
rb_define_method(cUM, "initialize", UM_initialize, 0);
272-
rb_define_method(cUM, "setup_buffer_ring", UM_setup_buffer_ring, 2);
273294
rb_define_method(cUM, "pending_count", UM_pending_count, 0);
295+
rb_define_method(cUM, "setup_buffer_ring", UM_setup_buffer_ring, 2);
296+
rb_define_singleton_method(cUM, "kernel_version", UM_kernel_version, 0);
297+
274298

275-
rb_define_method(cUM, "snooze", UM_snooze, 0);
276-
rb_define_method(cUM, "yield", UM_yield, 0);
277299
rb_define_method(cUM, "schedule", UM_schedule, 2);
300+
rb_define_method(cUM, "snooze", UM_snooze, 0);
278301
rb_define_method(cUM, "timeout", UM_timeout, 2);
302+
rb_define_method(cUM, "yield", UM_yield, 0);
279303

280-
rb_define_method(cUM, "sleep", UM_sleep, 1);
304+
rb_define_method(cUM, "close", UM_close, 1);
305+
rb_define_method(cUM, "open", UM_open, 2);
281306
rb_define_method(cUM, "read", UM_read, -1);
282307
rb_define_method(cUM, "read_each", UM_read_each, 2);
308+
rb_define_method(cUM, "sleep", UM_sleep, 1);
283309
rb_define_method(cUM, "write", UM_write, -1);
284-
rb_define_method(cUM, "close", UM_close, 1);
285310

286311
rb_define_method(cUM, "accept", UM_accept, 1);
287312
rb_define_method(cUM, "accept_each", UM_accept_each, 1);
288-
rb_define_method(cUM, "socket", UM_socket, 4);
313+
rb_define_method(cUM, "bind", UM_bind, 3);
289314
rb_define_method(cUM, "connect", UM_connect, 3);
290-
rb_define_method(cUM, "send", UM_send, 4);
315+
rb_define_method(cUM, "getsockopt", UM_getsockopt, 3);
316+
rb_define_method(cUM, "listen", UM_listen, 2);
291317
rb_define_method(cUM, "recv", UM_recv, 4);
292318
rb_define_method(cUM, "recv_each", UM_recv_each, 3);
293-
rb_define_method(cUM, "bind", UM_bind, 3);
294-
rb_define_method(cUM, "listen", UM_listen, 2);
295-
rb_define_method(cUM, "getsockopt", UM_getsockopt, 3);
319+
rb_define_method(cUM, "send", UM_send, 4);
296320
rb_define_method(cUM, "setsockopt", UM_setsockopt, 4);
321+
rb_define_method(cUM, "socket", UM_socket, 4);
297322

298323
#ifdef HAVE_IO_URING_PREP_FUTEX
299-
rb_define_method(cUM, "synchronize", UM_mutex_synchronize, 1);
300-
rb_define_method(cUM, "push", UM_queue_push, 2);
301324
rb_define_method(cUM, "pop", UM_queue_pop, 1);
302-
rb_define_method(cUM, "unshift", UM_queue_unshift, 2);
325+
rb_define_method(cUM, "push", UM_queue_push, 2);
303326
rb_define_method(cUM, "shift", UM_queue_shift, 1);
327+
rb_define_method(cUM, "synchronize", UM_mutex_synchronize, 1);
328+
rb_define_method(cUM, "unshift", UM_queue_unshift, 2);
304329
#endif
305330

306-
rb_define_singleton_method(cUM, "kernel_version", UM_kernel_version, 0);
307-
308331
um_define_net_constants(cUM);
309332
}

ext/um/um_const.c

+20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include "ruby.h"
2+
3+
#include <fcntl.h>
4+
25
#include <arpa/inet.h>
36
#include <sys/types.h>
47
#include <sys/socket.h>
@@ -12,6 +15,23 @@
1215
#define DEF_CONST_INT(mod, v) rb_define_const(mod, #v, INT2NUM(v))
1316

1417
void um_define_net_constants(VALUE mod) {
18+
DEF_CONST_INT(mod, O_APPEND);
19+
DEF_CONST_INT(mod, O_CLOEXEC);
20+
DEF_CONST_INT(mod, O_CREAT);
21+
DEF_CONST_INT(mod, O_DIRECT);
22+
DEF_CONST_INT(mod, O_DIRECTORY);
23+
DEF_CONST_INT(mod, O_DSYNC);
24+
DEF_CONST_INT(mod, O_EXCL);
25+
DEF_CONST_INT(mod, O_NOCTTY);
26+
DEF_CONST_INT(mod, O_NOFOLLOW);
27+
DEF_CONST_INT(mod, O_PATH);
28+
DEF_CONST_INT(mod, O_RDONLY);
29+
DEF_CONST_INT(mod, O_RDWR);
30+
DEF_CONST_INT(mod, O_SYNC);
31+
DEF_CONST_INT(mod, O_TMPFILE);
32+
DEF_CONST_INT(mod, O_TRUNC);
33+
DEF_CONST_INT(mod, O_WRONLY);
34+
1535
DEF_CONST_INT(mod, SOCK_STREAM);
1636
DEF_CONST_INT(mod, SOCK_DGRAM);
1737
DEF_CONST_INT(mod, SOCK_RAW);

test/test_um.rb

+30
Original file line numberDiff line numberDiff line change
@@ -963,3 +963,33 @@ def test_shift_shift_1
963963
end
964964
end
965965

966+
class OpenTest < UMBaseTest
967+
PATH = '/tmp/um_open_test'
968+
969+
def setup
970+
super
971+
FileUtils.rm(PATH, force: true)
972+
end
973+
974+
def test_open
975+
fd = machine.open(PATH, UM::O_CREAT | UM::O_WRONLY)
976+
assert_kind_of Integer, fd
977+
assert File.file?(PATH)
978+
979+
machine.write(fd, 'foo')
980+
machine.close(fd)
981+
982+
assert_equal 'foo', IO.read(PATH)
983+
end
984+
985+
def test_open_with_block
986+
res = machine.open(PATH, UM::O_CREAT | UM::O_WRONLY) do |fd|
987+
machine.write(fd, 'bar')
988+
fd
989+
end
990+
991+
assert_kind_of Integer, res
992+
assert_raises(Errno::EBADF) { machine.close(res) }
993+
assert_equal 'bar', IO.read(PATH)
994+
end
995+
end

0 commit comments

Comments
 (0)