prepare for rb_thread_blocking_region removal
authorEric Wong <normalperson@yhbt.net>
Sun, 9 Feb 2014 00:50:03 +0000 (9 00:50 +0000)
committerEric Wong <normalperson@yhbt.net>
Sun, 9 Feb 2014 00:50:03 +0000 (9 00:50 +0000)
It'll be OK to use rb_thread_call_without_gvl when
rb_thread_blocking_region is not detectable at all.
We still use rb_thread_blocking_region for Ruby 2.0-2.1 because
rb_thread_call_without_gvl was detectable in 1.9.3, but not
usable as an internal symbol.

ref: https://bugs.ruby-lang.org/issues/9502

ext/io_splice/extconf.rb
ext/io_splice/io_splice_ext.c

index 52dab83..bfd655a 100644 (file)
@@ -5,6 +5,7 @@ have_func('splice', %w(fcntl.h)) or abort 'splice(2) not defined'
 have_func('tee', %w(fcntl.h)) or abort 'tee(2) not defined'
 have_func('pipe2', %w(fcntl.h unistd.h))
 have_func('rb_thread_blocking_region')
+have_func('rb_thread_call_without_gvl')
 have_macro('F_GETPIPE_SZ', %w(fcntl.h))
 have_macro('F_SETPIPE_SZ', %w(fcntl.h))
 
index 9a838df..cad5dd1 100644 (file)
@@ -79,23 +79,35 @@ static int check_fileno(VALUE io)
        errno = saved_errno;
        return fd;
 }
-#ifndef HAVE_RB_THREAD_BLOCKING_REGION
+
 /* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
+#if defined(HAVE_RB_THREAD_BLOCKING_REGION) && \
+    defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
+/*
+ * Ruby 1.9 - 2.1 (we use deprecated rb_thread_blocking_region in 2.0+
+ * because we can detect (but not use) rb_thread_blocking_region in 1.9.3
+ */
+typedef VALUE (*my_blocking_fn_t)(void*);
+#  define WITHOUT_GVL(fn,a,ubf,b) \
+       rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
+#elif defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) /* Ruby 2.2+ */
+#include <ruby/thread.h>
+#  define WITHOUT_GVL(fn,a,ubf,b) \
+       rb_thread_call_without_gvl((fn),(a),(ubf),(b))
+#else /* Ruby 1.8 */
 #  include <rubysig.h>
 #  define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
 typedef void rb_unblock_function_t(void *);
-typedef VALUE rb_blocking_function_t(void *);
-static VALUE
-rb_thread_blocking_region(
-       rb_blocking_function_t *fn, void *data1,
-       rb_unblock_function_t *ubf, void *data2)
+typedef void * rb_blocking_function_t(void *);
+static void * WITHOUT_GVL(rb_blocking_function_t *func, void *data1,
+                       rb_unblock_function_t *ubf, void *data2)
 {
-       VALUE rv;
+       void *rv;
 
        assert(RUBY_UBF_IO == ubf && "RUBY_UBF_IO required for emulation");
 
        TRAP_BEG;
-       rv = fn(data1);
+       rv = func(data1);
        TRAP_END;
 
        return rv;
@@ -112,10 +124,7 @@ rb_thread_blocking_region(
 #  define RARRAY_LEN(s) (RARRAY(s)->len)
 #endif
 
-static VALUE io_run(rb_blocking_function_t *fn, void *data)
-{
-       return rb_thread_blocking_region(fn, data, RUBY_UBF_IO, 0);
-}
+#define io_run(fn,data) WITHOUT_GVL((fn),(data),RUBY_UBF_IO,0)
 
 struct splice_args {
        int fd_in;
@@ -126,14 +135,14 @@ struct splice_args {
        unsigned flags;
 };
 
-static VALUE nogvl_splice(void *ptr)
+static void * nogvl_splice(void *ptr)
 {
        struct splice_args *a = ptr;
 
        if (a->len > MAX_AT_ONCE)
                a->len = MAX_AT_ONCE;
 
-       return (VALUE)splice(a->fd_in, a->off_in, a->fd_out, a->off_out,
+       return (void *)splice(a->fd_in, a->off_in, a->fd_out, a->off_out,
                             a->len, a->flags);
 }
 
@@ -275,14 +284,14 @@ struct tee_args {
 };
 
 /* runs without GVL */
-static VALUE nogvl_tee(void *ptr)
+static void * nogvl_tee(void *ptr)
 {
        struct tee_args *a = ptr;
 
        if (a->len > MAX_AT_ONCE)
                a->len = MAX_AT_ONCE;
 
-       return (VALUE)tee(a->fd_in, a->fd_out, a->len, a->flags);
+       return (void *)tee(a->fd_in, a->fd_out, a->len, a->flags);
 }
 
 static ssize_t do_tee(int argc, VALUE *argv, unsigned dflags)
@@ -403,11 +412,11 @@ struct vmsplice_args {
        unsigned flags;
 };
 
-static VALUE nogvl_vmsplice(void *ptr)
+static void * nogvl_vmsplice(void *ptr)
 {
        struct vmsplice_args *a = ptr;
 
-       return (VALUE)vmsplice(a->fd, a->iov, a->nr_segs, a->flags);
+       return (void *)vmsplice(a->fd, a->iov, a->nr_segs, a->flags);
 }
 
 /* this can't be a function since we use alloca() */