From 32bc376e494b5477b921b6d198b7aeda0c8efe12 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 10 Mar 2011 02:12:46 +0000 Subject: rework flags passing for ease-of-use Arguments now take symbols and arrays of symbols just like the SignalFD.new method. This fixes some use of signed vs unsigned integer conversions as well. --- ext/sleepy_penguin/epoll.c | 53 +++++++--------- ext/sleepy_penguin/eventfd.c | 26 ++++---- ext/sleepy_penguin/inotify.c | 14 ++--- ext/sleepy_penguin/signalfd.c | 8 +-- ext/sleepy_penguin/sleepy_penguin.h | 69 +++----------------- ext/sleepy_penguin/timerfd.c | 16 ++--- ext/sleepy_penguin/util.c | 122 ++++++++++++++++++++++++++++++++++++ 7 files changed, 184 insertions(+), 124 deletions(-) create mode 100644 ext/sleepy_penguin/util.c (limited to 'ext/sleepy_penguin') diff --git a/ext/sleepy_penguin/epoll.c b/ext/sleepy_penguin/epoll.c index 38f9113..395bd7f 100644 --- a/ext/sleepy_penguin/epoll.c +++ b/ext/sleepy_penguin/epoll.c @@ -156,24 +156,11 @@ static void ep_check(struct rb_epoll *ep) */ static VALUE init(int argc, VALUE *argv, VALUE self) { - int flags; struct rb_epoll *ep = ep_get(self); VALUE fl; rb_scan_args(argc, argv, "01", &fl); - if (NIL_P(fl)) { - flags = 0; - } else { - switch (TYPE(fl)) { - case T_FIXNUM: - case T_BIGNUM: - flags = NUM2INT(fl); - break; - default: - rb_raise(rb_eArgError, "flags must be an integer"); - } - } - ep->flags = flags; + ep->flags = rb_sp_get_flags(self, fl); my_epoll_create(ep); return self; @@ -183,11 +170,11 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op) { struct epoll_event event; struct rb_epoll *ep = ep_get(self); - int fd = my_fileno(io); + int fd = rb_sp_fileno(io); int rv; ep_check(ep); - event.events = NUM2UINT(flags); + event.events = rb_sp_get_uflags(self, flags); pack_event_data(&event, io); rv = epoll_ctl(ep->fd, op, fd, &event); @@ -204,6 +191,7 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op) rb_ary_store(ep->marks, fd, io); /* fall-through */ case EPOLL_CTL_MOD: + flags = UINT2NUM(event.events); rb_ary_store(ep->flag_cache, fd, flags); break; case EPOLL_CTL_DEL: @@ -222,12 +210,12 @@ static VALUE set(VALUE self, VALUE io, VALUE flags) { struct epoll_event event; struct rb_epoll *ep = ep_get(self); - int fd = my_fileno(io); + int fd = rb_sp_fileno(io); int rv; VALUE cur_io = rb_ary_entry(ep->marks, fd); ep_check(ep); - event.events = NUM2UINT(flags); + event.events = rb_sp_get_uflags(self, flags); pack_event_data(&event, io); if (cur_io == io) { @@ -261,6 +249,7 @@ fallback_add: } rb_ary_store(ep->marks, fd, io); } + flags = UINT2NUM(event.events); rb_ary_store(ep->flag_cache, fd, flags); return INT2NUM(rv); @@ -275,16 +264,16 @@ fallback_add: static VALUE delete(VALUE self, VALUE io) { struct rb_epoll *ep = ep_get(self); - int fd = my_fileno(io); + int fd = rb_sp_fileno(io); int rv; VALUE cur_io; ep_check(ep); - if (my_io_closed(io)) + if (rb_sp_io_closed(io)) goto out; cur_io = rb_ary_entry(ep->marks, fd); - if (NIL_P(cur_io) || my_io_closed(cur_io)) + if (NIL_P(cur_io) || rb_sp_io_closed(cur_io)) return Qnil; rv = epoll_ctl(ep->fd, EPOLL_CTL_DEL, fd, NULL); @@ -576,7 +565,7 @@ static VALUE io_for(VALUE self, VALUE obj) { struct rb_epoll *ep = ep_get(self); - return rb_ary_entry(ep->marks, my_fileno(obj)); + return rb_ary_entry(ep->marks, rb_sp_fileno(obj)); } /* @@ -590,7 +579,7 @@ static VALUE flags_for(VALUE self, VALUE obj) { struct rb_epoll *ep = ep_get(self); - return rb_ary_entry(ep->flag_cache, my_fileno(obj)); + return rb_ary_entry(ep->flag_cache, rb_sp_fileno(obj)); } /* @@ -606,7 +595,7 @@ static VALUE include_p(VALUE self, VALUE obj) { struct rb_epoll *ep = ep_get(self); - return NIL_P(rb_ary_entry(ep->marks, my_fileno(obj))) ? Qfalse : Qtrue; + return NIL_P(rb_ary_entry(ep->marks, rb_sp_fileno(obj))) ? Qfalse : Qtrue; } /* @@ -664,35 +653,35 @@ void sleepy_penguin_init_epoll(void) rb_define_const(cEpoll, "CLOEXEC", INT2NUM(EPOLL_CLOEXEC)); /* watch for read/recv operations */ - rb_define_const(cEpoll, "IN", INT2NUM(EPOLLIN)); + rb_define_const(cEpoll, "IN", UINT2NUM(EPOLLIN)); /* watch for write/send operations */ - rb_define_const(cEpoll, "OUT", INT2NUM(EPOLLOUT)); + rb_define_const(cEpoll, "OUT", UINT2NUM(EPOLLOUT)); #ifdef EPOLLRDHUP /* watch a specified IO for shutdown(SHUT_WR) on the remote-end */ - rb_define_const(cEpoll, "RDHUP", INT2NUM(EPOLLRDHUP)); + rb_define_const(cEpoll, "RDHUP", UINT2NUM(EPOLLRDHUP)); #endif /* watch for urgent read(2) data */ - rb_define_const(cEpoll, "PRI", INT2NUM(EPOLLPRI)); + rb_define_const(cEpoll, "PRI", UINT2NUM(EPOLLPRI)); /* * watch for errors, there is no need to specify this, * it is always monitored when an IO is watched */ - rb_define_const(cEpoll, "ERR", INT2NUM(EPOLLERR)); + rb_define_const(cEpoll, "ERR", UINT2NUM(EPOLLERR)); /* * watch for hangups, there is no need to specify this, * it is always monitored when an IO is watched */ - rb_define_const(cEpoll, "HUP", INT2NUM(EPOLLHUP)); + rb_define_const(cEpoll, "HUP", UINT2NUM(EPOLLHUP)); /* notifications are only Edge Triggered, see epoll(7) */ - rb_define_const(cEpoll, "ET", INT2NUM(EPOLLET)); + rb_define_const(cEpoll, "ET", UINT2NUM((uint32_t)EPOLLET)); /* unwatch the descriptor once any event has fired */ - rb_define_const(cEpoll, "ONESHOT", INT2NUM(EPOLLONESHOT)); + rb_define_const(cEpoll, "ONESHOT", UINT2NUM(EPOLLONESHOT)); id_for_fd = rb_intern("for_fd"); active = st_init_numtable(); diff --git a/ext/sleepy_penguin/eventfd.c b/ext/sleepy_penguin/eventfd.c index 6c2f800..704df7e 100644 --- a/ext/sleepy_penguin/eventfd.c +++ b/ext/sleepy_penguin/eventfd.c @@ -4,16 +4,16 @@ #include "nonblock.h" static ID id_for_fd; -static VALUE create(int argc, VALUE *argv, VALUE klass) +static VALUE s_new(int argc, VALUE *argv, VALUE klass) { VALUE _initval, _flags; unsigned initval; - int flags = 0; + int flags; int fd; rb_scan_args(argc, argv, "11", &_initval, &_flags); initval = NUM2UINT(_initval); - flags = NIL_P(_flags) ? 0 : NUM2INT(_flags); + flags = rb_sp_get_flags(klass, _flags); fd = eventfd(initval, flags); if (fd == -1) { @@ -55,7 +55,7 @@ static VALUE incr(VALUE self, VALUE value) struct efd_args x; ssize_t w; - x.fd = my_fileno(self); + x.fd = rb_sp_fileno(self); x.val = (uint64_t)NUM2ULL(value); retry: @@ -74,7 +74,7 @@ static VALUE getvalue(VALUE self) struct efd_args x; ssize_t w; - x.fd = my_fileno(self); + x.fd = rb_sp_fileno(self); retry: w = (ssize_t)rb_thread_blocking_region(efd_read, &x, RUBY_UBF_IO, 0); @@ -90,7 +90,7 @@ retry: static VALUE incr(VALUE self, VALUE value) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); uint64_t val = (uint64_t)NUM2ULL(value); ssize_t w; @@ -108,7 +108,7 @@ retry: static VALUE getvalue(VALUE self) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); uint64_t val; ssize_t r; @@ -127,7 +127,7 @@ retry: static VALUE getvalue_nonblock(VALUE self) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); uint64_t val; ssize_t r; @@ -141,7 +141,7 @@ static VALUE getvalue_nonblock(VALUE self) static VALUE incr_nonblock(VALUE self, VALUE value) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); uint64_t val = (uint64_t)NUM2ULL(value); ssize_t w; @@ -159,15 +159,15 @@ void sleepy_penguin_init_eventfd(void) mSleepyPenguin = rb_define_module("SleepyPenguin"); cEventFD = rb_define_class_under(mSleepyPenguin, "EventFD", rb_cIO); - rb_define_singleton_method(cEventFD, "new", create, -1); + rb_define_singleton_method(cEventFD, "new", s_new, -1); #ifdef EFD_NONBLOCK - rb_define_const(cEventFD, "NONBLOCK", UINT2NUM(EFD_NONBLOCK)); + rb_define_const(cEventFD, "NONBLOCK", INT2NUM(EFD_NONBLOCK)); #endif #ifdef EFD_CLOEXEC - rb_define_const(cEventFD, "CLOEXEC", UINT2NUM(EFD_CLOEXEC)); + rb_define_const(cEventFD, "CLOEXEC", INT2NUM(EFD_CLOEXEC)); #endif #ifdef EFD_SEMAPHORE - rb_define_const(cEventFD, "SEMAPHORE", UINT2NUM(EFD_SEMAPHORE)); + rb_define_const(cEventFD, "SEMAPHORE", INT2NUM(EFD_SEMAPHORE)); #endif rb_define_method(cEventFD, "value", getvalue, 0); rb_define_method(cEventFD, "incr", incr, 1); diff --git a/ext/sleepy_penguin/inotify.c b/ext/sleepy_penguin/inotify.c index f222429..28477c3 100644 --- a/ext/sleepy_penguin/inotify.c +++ b/ext/sleepy_penguin/inotify.c @@ -77,7 +77,7 @@ static VALUE s_new(int argc, VALUE *argv, VALUE klass) int fd; rb_scan_args(argc, argv, "01", &_flags); - flags = NIL_P(_flags) ? 0 : NUM2INT(_flags); + flags = rb_sp_get_flags(klass, _flags); fd = inotify_init1(flags); if (fd == -1) { @@ -106,9 +106,9 @@ static VALUE s_new(int argc, VALUE *argv, VALUE klass) */ static VALUE add_watch(VALUE self, VALUE path, VALUE vmask) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); const char *pathname = StringValueCStr(path); - uint32_t mask = NUM2UINT(vmask); + uint32_t mask = rb_sp_get_uflags(self, vmask); int rc = inotify_add_watch(fd, pathname, mask); if (rc == -1) { @@ -132,7 +132,7 @@ static VALUE add_watch(VALUE self, VALUE path, VALUE vmask) static VALUE rm_watch(VALUE self, VALUE vwd) { uint32_t wd = NUM2UINT(vwd); - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); int rc = inotify_rm_watch(fd, wd); if (rc == -1) @@ -168,7 +168,7 @@ static VALUE event_new(struct inotify_event *e) */ static VALUE take(int argc, VALUE *argv, VALUE self) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); VALUE buf = rb_ivar_get(self, id_inotify_buf); VALUE tmp = rb_ivar_get(self, id_inotify_tmp); struct inotify_event *ptr; @@ -328,7 +328,7 @@ void sleepy_penguin_init_inotify(void) IN(ONESHOT); /* for inotify_init1() */ - IN(NONBLOCK); - IN(CLOEXEC); + rb_define_const(cInotify, "NONBLOCK", INT2NUM(IN_NONBLOCK)); + rb_define_const(cInotify, "CLOEXEC", INT2NUM(IN_CLOEXEC)); } #endif /* HAVE_SYS_INOTIFY_H */ diff --git a/ext/sleepy_penguin/signalfd.c b/ext/sleepy_penguin/signalfd.c index 17cd41e..d7d7434 100644 --- a/ext/sleepy_penguin/signalfd.c +++ b/ext/sleepy_penguin/signalfd.c @@ -93,11 +93,11 @@ static VALUE update_bang(int argc, VALUE *argv, VALUE self) VALUE vmask, vflags; sigset_t mask; int flags; - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); int rc; rb_scan_args(argc, argv, "02", &vmask, &vflags); - flags = NIL_P(vflags) ? cur_flags(fd) : NUM2INT(vflags); + flags = NIL_P(vflags) ? cur_flags(fd) : rb_sp_get_flags(self, vflags); value2sigset(&mask, vmask); rc = signalfd(fd, &mask, flags); @@ -132,7 +132,7 @@ static VALUE s_new(int argc, VALUE *argv, VALUE klass) int fd; rb_scan_args(argc, argv, "02", &vmask, &vflags); - flags = NIL_P(vflags) ? 0 : NUM2INT(vflags); + flags = rb_sp_get_flags(klass, vflags); value2sigset(&mask, vmask); fd = signalfd(-1, &mask, flags); @@ -205,7 +205,7 @@ static VALUE sfd_take(VALUE self) struct signalfd_siginfo *ssi = DATA_PTR(rv); ssize_t r; - ssi->ssi_fd = my_fileno(self); + ssi->ssi_fd = rb_sp_fileno(self); r = do_sfd_read(ssi); if (r < 0) rb_sys_fail("read(signalfd)"); diff --git a/ext/sleepy_penguin/sleepy_penguin.h b/ext/sleepy_penguin/sleepy_penguin.h index 50f6272..ce71f58 100644 --- a/ext/sleepy_penguin/sleepy_penguin.h +++ b/ext/sleepy_penguin/sleepy_penguin.h @@ -12,64 +12,13 @@ #include #include -#if ! HAVE_RB_IO_T -# define rb_io_t OpenFile -#endif - -#ifdef GetReadFile -# define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr))) -#else -# if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8) -# define FPTR_TO_FD(fptr) fileno(fptr->f) -# else -# define FPTR_TO_FD(fptr) fptr->fd -# endif -#endif - -static int fixint_closed_p(VALUE io) -{ - return (fcntl(FIX2INT(io), F_GETFD) == -1 && errno == EBADF); -} - -#if defined(RFILE) && defined(HAVE_ST_FD) -static int my_rb_io_closed(VALUE io) -{ - return RFILE(io)->fptr->fd < 0; -} -#else -static int my_rb_io_closed(VALUE io) -{ - return rb_funcall(io, rb_intern("closed?"), 0) == Qtrue; -} -#endif - -static int my_io_closed(VALUE io) -{ - switch (TYPE(io)) { - case T_FIXNUM: - return fixint_closed_p(io); - case T_FILE: - break; - default: - io = rb_convert_type(io, T_FILE, "IO", "to_io"); - } - - return my_rb_io_closed(io); -} - -static int my_fileno(VALUE io) -{ - rb_io_t *fptr; - - switch (TYPE(io)) { - case T_FIXNUM: return FIX2INT(io); - case T_FILE: - GetOpenFile(io, fptr); - return FPTR_TO_FD(fptr); - } - io = rb_convert_type(io, T_FILE, "IO", "to_io"); - GetOpenFile(io, fptr); - return FPTR_TO_FD(fptr); -} - +unsigned rb_sp_get_uflags(VALUE klass, VALUE flags); +int rb_sp_get_flags(VALUE klass, VALUE flags); +int rb_sp_io_closed(VALUE io); +int rb_sp_fileno(VALUE io); + +#define get_uflags rb_sp_get_uflags +#define get_flags rb_sp_get_flags +#define my_io_closed rb_sp_io_closed +#define my_fileno rb_sp_fileno #endif /* SLEEPY_PENGUIN_H */ diff --git a/ext/sleepy_penguin/timerfd.c b/ext/sleepy_penguin/timerfd.c index 684291e..dccb255 100644 --- a/ext/sleepy_penguin/timerfd.c +++ b/ext/sleepy_penguin/timerfd.c @@ -7,12 +7,12 @@ static ID id_for_fd; static VALUE s_new(int argc, VALUE *argv, VALUE klass) { VALUE cid, fl; - int clockid, flags = 0; + int clockid, flags; int fd; rb_scan_args(argc, argv, "02", &cid, &fl); - clockid = NIL_P(cid) ? CLOCK_MONOTONIC : NUM2INT(cid); - flags = NIL_P(fl) ? 0 : NUM2INT(fl); + clockid = NIL_P(cid) ? CLOCK_MONOTONIC : rb_sp_get_flags(klass, cid); + flags = rb_sp_get_flags(klass, fl); fd = timerfd_create(clockid, flags); if (fd == -1) { @@ -37,8 +37,8 @@ static VALUE itimerspec2ary(struct itimerspec *its) static VALUE settime(VALUE self, VALUE fl, VALUE interval, VALUE value) { - int fd = my_fileno(self); - int flags = NUM2INT(fl); + int fd = rb_sp_fileno(self); + int flags = rb_sp_get_flags(self, fl); struct itimerspec old, new; value2timespec(&new.it_interval, interval); @@ -52,7 +52,7 @@ static VALUE settime(VALUE self, VALUE fl, VALUE interval, VALUE value) static VALUE gettime(VALUE self) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); struct itimerspec curr; if (timerfd_gettime(fd, &curr) == -1) @@ -74,7 +74,7 @@ static VALUE tfd_read(void *args) static VALUE expirations(VALUE self) { ssize_t r; - uint64_t buf = (int)my_fileno(self); + uint64_t buf = (int)rb_sp_fileno(self); r = (VALUE)rb_thread_blocking_region(tfd_read, &buf, RUBY_UBF_IO, 0); if (r == -1) @@ -86,7 +86,7 @@ static VALUE expirations(VALUE self) #include "nonblock.h" static VALUE expirations(VALUE self) { - int fd = my_fileno(self); + int fd = rb_sp_fileno(self); uint64_t buf; ssize_t r; diff --git a/ext/sleepy_penguin/util.c b/ext/sleepy_penguin/util.c new file mode 100644 index 0000000..d8b27d4 --- /dev/null +++ b/ext/sleepy_penguin/util.c @@ -0,0 +1,122 @@ +#include "sleepy_penguin.h" + +static VALUE klass_for(VALUE klass) +{ + return (TYPE(klass) == T_CLASS) ? klass : CLASS_OF(klass); +} + +int rb_sp_get_flags(VALUE klass, VALUE flags) +{ + switch (TYPE(flags)) { + case T_NIL: return 0; + case T_FIXNUM: return FIX2INT(flags); + case T_BIGNUM: return NUM2INT(flags); + case T_SYMBOL: + return NUM2INT(rb_const_get(klass_for(klass), SYM2ID(flags))); + case T_ARRAY: { + VALUE *ptr = RARRAY_PTR(flags); + long len = RARRAY_LEN(flags); + int rv = 0; + + klass = klass_for(klass); + while (--len >= 0) { + VALUE tmp = *ptr++; + + Check_Type(tmp, T_SYMBOL); + tmp = rb_const_get(klass, SYM2ID(tmp)); + rv |= NUM2INT(tmp); + } + return rv; + } + } + rb_raise(rb_eTypeError, "invalid flags"); + return 0; +} + +unsigned rb_sp_get_uflags(VALUE klass, VALUE flags) +{ + switch (TYPE(flags)) { + case T_NIL: return 0; + case T_FIXNUM: return FIX2UINT(flags); + case T_BIGNUM: return NUM2UINT(flags); + case T_SYMBOL: + return NUM2UINT(rb_const_get(klass_for(klass), SYM2ID(flags))); + case T_ARRAY: { + VALUE *ptr = RARRAY_PTR(flags); + long len = RARRAY_LEN(flags); + unsigned rv = 0; + + klass = klass_for(klass); + while (--len >= 0) { + VALUE tmp = *ptr++; + + Check_Type(tmp, T_SYMBOL); + tmp = rb_const_get(klass, SYM2ID(tmp)); + rv |= NUM2UINT(tmp); + } + return rv; + } + } + rb_raise(rb_eTypeError, "invalid flags"); + return 0; +} + +#if ! HAVE_RB_IO_T +# define rb_io_t OpenFile +#endif + +#ifdef GetReadFile +# define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr))) +#else +# if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8) +# define FPTR_TO_FD(fptr) fileno(fptr->f) +# else +# define FPTR_TO_FD(fptr) fptr->fd +# endif +#endif + +static int fixint_closed_p(VALUE io) +{ + return (fcntl(FIX2INT(io), F_GETFD) == -1 && errno == EBADF); +} + +#if defined(RFILE) && defined(HAVE_ST_FD) +static int my_rb_io_closed(VALUE io) +{ + return RFILE(io)->fptr->fd < 0; +} +#else +static int my_rb_io_closed(VALUE io) +{ + return rb_funcall(io, rb_intern("closed?"), 0) == Qtrue; +} +#endif + +int rb_sp_io_closed(VALUE io) +{ + switch (TYPE(io)) { + case T_FIXNUM: + return fixint_closed_p(io); + case T_FILE: + break; + default: + io = rb_convert_type(io, T_FILE, "IO", "to_io"); + } + + return my_rb_io_closed(io); +} + +int rb_sp_fileno(VALUE io) +{ + rb_io_t *fptr; + + switch (TYPE(io)) { + case T_FIXNUM: return FIX2INT(io); + case T_FILE: + GetOpenFile(io, fptr); + return FPTR_TO_FD(fptr); + } + io = rb_convert_type(io, T_FILE, "IO", "to_io"); + GetOpenFile(io, fptr); + return FPTR_TO_FD(fptr); +} -- cgit v1.2.3-24-ge0c7