librelist archives

« back to archive

[PATCH] prepare for rb_thread_blocking_region removal

[PATCH] prepare for rb_thread_blocking_region removal

From:
Eric Wong
Date:
2014-02-08 @ 20:44
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/kgio/accept.c             |  8 ++++----
 ext/kgio/blocking_io_region.h |  2 +-
 ext/kgio/connect.c            |  4 ++--
 ext/kgio/kgio.h               | 15 ++++++++-------
 ext/kgio/poll.c               |  8 +++++---
 ext/kgio/tryopen.c            | 25 +++++++++++++------------
 ext/kgio/write.c              |  4 ++--
 7 files changed, 35 insertions(+), 31 deletions(-)

diff --git a/ext/kgio/accept.c b/ext/kgio/accept.c
index eb40f32..c847c92 100644
--- a/ext/kgio/accept.c
+++ b/ext/kgio/accept.c
@@ -13,7 +13,7 @@ static VALUE cKgio_Socket;
 static VALUE mSocketMethods;
 static VALUE iv_kgio_addr;
 
-#if defined(__linux__) && defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL)
+#if defined(__linux__) && defined(KGIO_WITHOUT_GVL)
 static int accept4_flags = SOCK_CLOEXEC;
 #else /* ! linux */
 static int accept4_flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
@@ -79,7 +79,7 @@ static VALUE xaccept(void *ptr)
 	return (VALUE)rv;
 }
 
-#ifdef KGIO_HAVE_THREAD_CALL_WITHOUT_GVL
+#ifdef KGIO_WITHOUT_GVL
 #  include <time.h>
 #  include "blocking_io_region.h"
 static int thread_accept(struct accept_args *a, int force_nonblock)
@@ -89,7 +89,7 @@ static int thread_accept(struct accept_args *a, int 
force_nonblock)
 	return (int)rb_thread_io_blocking_region(xaccept, a, a->fd);
 }
 
-#else /* ! KGIO_HAVE_THREAD_CALL_WITHOUT_GVL */
+#else /* ! KGIO_WITHOUT_GVL */
 #  include <rubysig.h>
 static int thread_accept(struct accept_args *a, int force_nonblock)
 {
@@ -106,7 +106,7 @@ static int thread_accept(struct accept_args *a, int 
force_nonblock)
 	TRAP_END;
 	return rv;
 }
-#endif /* ! KGIO_HAVE_THREAD_CALL_WITHOUT_GVL */
+#endif /* ! KGIO_WITHOUT_GVL */
 
 static void
 prepare_accept(struct accept_args *a, VALUE self, int argc, const VALUE *argv)
diff --git a/ext/kgio/blocking_io_region.h b/ext/kgio/blocking_io_region.h
index 10e7533..db76eac 100644
--- a/ext/kgio/blocking_io_region.h
+++ b/ext/kgio/blocking_io_region.h
@@ -1,4 +1,4 @@
-#ifdef KGIO_HAVE_THREAD_CALL_WITHOUT_GVL
+#ifdef KGIO_WITHOUT_GVL
 #  if   defined(HAVE_RB_THREAD_IO_BLOCKING_REGION)
 /* temporary API for Ruby 1.9.3 */
 VALUE rb_thread_io_blocking_region(rb_blocking_function_t *, void *, int);
diff --git a/ext/kgio/connect.c b/ext/kgio/connect.c
index 2261b10..19cfa8f 100644
--- a/ext/kgio/connect.c
+++ b/ext/kgio/connect.c
@@ -145,7 +145,7 @@ static const struct sockaddr *sockaddr_from(socklen_t 
*addrlen, VALUE addr)
 	return NULL;
 }
 
-#if defined(MSG_FASTOPEN) && defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL)
+#if defined(MSG_FASTOPEN) && defined(KGIO_WITHOUT_GVL)
 #ifndef HAVE_RB_STR_SUBSEQ
 #define rb_str_subseq rb_str_substr
 #endif
@@ -383,7 +383,7 @@ void init_kgio_connect(void)
 	rb_define_singleton_method(cKgio_Socket, "new", kgio_new, -1);
 	rb_define_singleton_method(cKgio_Socket, "connect", kgio_connect, 1);
 	rb_define_singleton_method(cKgio_Socket, "start", kgio_start, 1);
-#if defined(MSG_FASTOPEN) && defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL)
+#if defined(MSG_FASTOPEN) && defined(KGIO_WITHOUT_GVL)
 	rb_define_method(cKgio_Socket, "kgio_fastopen", fastopen, 2);
 #endif
 	/*
diff --git a/ext/kgio/kgio.h b/ext/kgio/kgio.h
index 6c5da5b..66a8705 100644
--- a/ext/kgio/kgio.h
+++ b/ext/kgio/kgio.h
@@ -39,16 +39,17 @@ void kgio_autopush_send(VALUE);
 
 VALUE kgio_call_wait_writable(VALUE io);
 VALUE kgio_call_wait_readable(VALUE io);
-#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
-#  define KGIO_HAVE_THREAD_CALL_WITHOUT_GVL 1
-typedef  void *(*kgio_blocking_fn_t)(void*);
-#  define rb_thread_blocking_region(fn,data1,ubf,data2) \
-          
rb_thread_call_without_gvl((kgio_blocking_fn_t)(fn),(data1),(ubf),(data2))
+#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && \
+    !defined(HAVE_RB_THREAD_BLOCKING_REGION)
+#  define KGIO_WITHOUT_GVL(fn,data1,ubf,data2) \
+      rb_thread_call_without_gvl((fn),(data1),(ubf),(data2))
 #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
-#  define KGIO_HAVE_THREAD_CALL_WITHOUT_GVL 1
+typedef  VALUE(*kgio_blocking_fn_t)(void*);
+#  define KGIO_WITHOUT_GVL(fn,data1,ubf,data2) \
+      rb_thread_blocking_region((kgio_blocking_fn_t)(fn),(data1),(ubf),(data2))
 #endif /* HAVE_RB_THREAD_CALL_WITHOUT_GVL || HAVE_RB_THREAD_BLOCKING_REGION */
 
-#if defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_POLL)
+#if defined(KGIO_WITHOUT_GVL) && defined(HAVE_POLL)
 #  define USE_KGIO_POLL
 #endif /* USE_KGIO_POLL */
 
diff --git a/ext/kgio/poll.c b/ext/kgio/poll.c
index ae8d235..41bebf6 100644
--- a/ext/kgio/poll.c
+++ b/ext/kgio/poll.c
@@ -107,14 +107,16 @@ static void hash2pollfds(struct poll_args *a)
 	rb_hash_foreach(a->ios, io_to_pollfd_i, (VALUE)a);
 }
 
-static VALUE nogvl_poll(void *ptr)
+static void * nogvl_poll(void *ptr)
 {
 	struct poll_args *a = ptr;
+	long n;
 
 	if (a->timeout > 0)
 		clock_gettime(hopefully_CLOCK_MONOTONIC, &a->start);
 
-	return (VALUE)poll(a->fds, a->nfds, a->timeout);
+	n = poll(a->fds, a->nfds, a->timeout);
+	return (void *)n;
 }
 
 static VALUE poll_result(int nr, struct poll_args *a)
@@ -145,7 +147,7 @@ static VALUE do_poll(VALUE args)
 
 retry:
 	hash2pollfds(a);
-	nr = (long)rb_thread_blocking_region(nogvl_poll, a, RUBY_UBF_IO, NULL);
+	nr = (long)KGIO_WITHOUT_GVL(nogvl_poll, a, RUBY_UBF_IO, NULL);
 	if (nr < 0) {
 		if (interrupted()) {
 			if (retryable(a)) {
diff --git a/ext/kgio/tryopen.c b/ext/kgio/tryopen.c
index 50bacf4..20f3f6d 100644
--- a/ext/kgio/tryopen.c
+++ b/ext/kgio/tryopen.c
@@ -33,23 +33,24 @@ struct open_args {
 #  define rb_cloexec_open(p,f,m) open((p),(f),(m))
 #endif
 
-static VALUE nogvl_open(void *ptr)
+static void * nogvl_open(void *ptr)
 {
 	struct open_args *o = ptr;
+        long fd = (long)rb_cloexec_open(o->pathname, o->flags, o->mode);
 
-	return (VALUE)rb_cloexec_open(o->pathname, o->flags, o->mode);
+	return (void *)fd;
 }
 
-#ifndef KGIO_HAVE_THREAD_CALL_WITHOUT_GVL
+#ifndef KGIO_WITHOUT_GVL
 #  define RUBY_UBF_IO ((void *)(-1))
 #  include "rubysig.h"
-typedef void rb_unblock_function_t(void *);
-typedef VALUE rb_blocking_function_t(void *);
-static VALUE my_thread_blocking_region(
-	rb_blocking_function_t *fn, void *data1,
-	rb_unblock_function_t *ubf, void *data2)
+typedef void my_unblock_function_t(void *);
+typedef void *my_blocking_function_t(void *);
+static void * my_thread_blocking_region(
+	my_blocking_function_t *fn, void *data1,
+	my_unblock_function_t *ubf, void *data2)
 {
-	VALUE rv;
+	void *rv;
 
 	TRAP_BEG; /* for FIFO */
 	rv = fn(data1);
@@ -57,9 +58,9 @@ static VALUE my_thread_blocking_region(
 
 	return rv;
 }
-#define rb_thread_blocking_region(fn,data1,ubf,data2) \
+#define KGIO_WITHOUT_GVL(fn,data1,ubf,data2) \
         my_thread_blocking_region((fn),(data1),(ubf),(data2))
-#endif /* ! KGIO_HAVE_THREAD_CALL_WITHOUT_GVL */
+#endif /* ! KGIO_WITHOUT_GVL */
 
 /*
  * call-seq:
@@ -107,7 +108,7 @@ static VALUE s_tryopen(int argc, VALUE *argv, VALUE klass)
 	}
 
 retry:
-	fd = (long)rb_thread_blocking_region(nogvl_open, &o, RUBY_UBF_IO, 0);
+	fd = (long)KGIO_WITHOUT_GVL(nogvl_open, &o, RUBY_UBF_IO, 0);
 	if (fd < 0) {
 		if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
 			rb_gc();
diff --git a/ext/kgio/write.c b/ext/kgio/write.c
index fa152d8..cdf97b1 100644
--- a/ext/kgio/write.c
+++ b/ext/kgio/write.c
@@ -155,7 +155,7 @@ static VALUE kgio_trysend(VALUE io, VALUE str)
 #  define kgio_trysend kgio_trywrite
 #endif /* ! USE_MSG_DONTWAIT */
 
-#if defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL)
+#if defined(KGIO_WITHOUT_GVL)
 #  include "blocking_io_region.h"
 #ifdef MSG_DONTWAIT /* Linux only */
 #  define MY_MSG_DONTWAIT (MSG_DONTWAIT)
@@ -256,7 +256,7 @@ void init_kgio_write(void)
 	rb_define_method(mSocketMethods, "kgio_write", kgio_send, 1);
 	rb_define_method(mSocketMethods, "kgio_trywrite", kgio_trysend, 1);
 
-#if defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL)
+#if defined(KGIO_WITHOUT_GVL)
 	rb_define_method(mSocketMethods, "kgio_syssend", kgio_syssend, 2);
 #endif
 }
-- 
Eric Wong