summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2014-02-09 08:07:02 +0000
committerEric Wong <normalperson@yhbt.net>2014-02-09 09:24:31 +0000
commit1ed6aacf5cb3265191acc61449fe68abd7c8f503 (patch)
treed9c1332f8fe9211bcad47a12acc0d972d5205023
parent39b72b9bf756f67d070e33d64e1b37b589914e62 (diff)
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
-rw-r--r--ext/tdb/extconf.rb1
-rw-r--r--ext/tdb/tdb.c103
2 files changed, 60 insertions, 44 deletions
diff --git a/ext/tdb/extconf.rb b/ext/tdb/extconf.rb
index f7bb223..b309b2a 100644
--- a/ext/tdb/extconf.rb
+++ b/ext/tdb/extconf.rb
@@ -2,6 +2,7 @@ require 'mkmf'
 
 have_func('rb_thread_blocking_region')
 have_func('rb_thread_call_with_gvl')
+have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
 
 dir_config('tdb')
 have_header('tdb.h') or abort 'tdb.h missing'
diff --git a/ext/tdb/tdb.c b/ext/tdb/tdb.c
index 0a0adf2..754d712 100644
--- a/ext/tdb/tdb.c
+++ b/ext/tdb/tdb.c
@@ -96,26 +96,39 @@ rb_hash_aset(hashes,ID2SYM(rb_intern(#x)),ULONG2NUM((unsigned long)rbtdb_##x))
         HF(default);
 }
 
-#ifndef HAVE_RB_THREAD_BLOCKING_REGION
-/* (very) partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
+/* 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>
-typedef VALUE rb_blocking_function_t(void *);
-static VALUE my_tbr(rb_blocking_function_t *fn, void *data)
+#  define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
+typedef void rb_unblock_function_t(void *);
+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;
 
         TRAP_BEG;
-        rv = fn(data);
+        rv = func(data1);
         TRAP_END;
 
         return rv;
 }
-#else
-static VALUE my_tbr(rb_blocking_function_t *fn, void *data)
-{
-        return rb_thread_blocking_region(fn, data, RUBY_UBF_IO, 0);
-}
-#endif /* HAVE_RUBY_THREAD_BLOCKING_REGION */
+#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
+
+#define my_tbr(fn,data) WITHOUT_GVL((void *)(fn),(data),RUBY_UBF_IO,0)
 
 static void gcfree(void *ptr)
 {
@@ -156,7 +169,7 @@ struct open_args {
         tdb_hash_func hash_fn;
 };
 
-static VALUE nogvl_open(void *ptr)
+static void * nogvl_open(void *ptr)
 {
         struct open_args *o = ptr;
         struct tdb_context *tdb;
@@ -166,7 +179,7 @@ static VALUE nogvl_open(void *ptr)
                           o->open_flags, o->mode, o->log_ctx, o->hash_fn);
         pthread_mutex_unlock(&big_lock);
 
-        return (VALUE)tdb;
+        return (void *)tdb;
 }
 
 static void set_args(VALUE self, struct open_args *o, VALUE opts)
@@ -282,16 +295,16 @@ static VALUE init(int argc, VALUE *argv, VALUE self)
 }
 
 /* tdb_close can do a lot, including cancel transactions an munmap */
-static VALUE nogvl_close(void *ptr)
+static void * nogvl_close(void *ptr)
 {
         struct tdb_context *tdb = ptr;
-        VALUE rv;
+        long rv;
 
         pthread_mutex_lock(&big_lock);
-        rv = (VALUE)tdb_close(tdb);
+        rv = tdb_close(tdb);
         pthread_mutex_unlock(&big_lock);
 
-        return rv;
+        return (void *)rv;
 }
 
 static VALUE tdbclose(VALUE self)
@@ -300,7 +313,7 @@ static VALUE tdbclose(VALUE self)
 
         DATA_PTR(self) = NULL;
 
-        if ((int)my_tbr(nogvl_close, tdb) == -1)
+        if ((long)my_tbr(nogvl_close, tdb) == -1)
                 rb_sys_fail("tdb_close");
 
         return Qnil;
@@ -367,14 +380,14 @@ static int fetch_parse(TDB_DATA key, TDB_DATA val, void *data)
         return 0;
 }
 
-static VALUE nogvl_parse_record(void *ptr)
+static void * nogvl_parse_record(void *ptr)
 {
         struct fetch_parse_args *f = ptr;
 
         if (tdb_parse_record(f->tdb, f->as.key, fetch_parse, ptr) == -1)
-                return Qnil;
+                return (void *)Qnil;
 
-        return f->value == f->as.value ? f->value : Qnil;
+        return (void *)(f->value == f->as.value ? f->value : Qnil);
 }
 
 static VALUE fetch(int argc, VALUE *argv, VALUE self)
@@ -393,7 +406,7 @@ static VALUE fetch(int argc, VALUE *argv, VALUE self)
         f.tdb = db(self, 1);
         TO_TDB_DATA(f.as.key, key);
 
-        return my_tbr(nogvl_parse_record, &f);
+        return (VALUE)my_tbr(nogvl_parse_record, &f);
 }
 
 struct store_args {
@@ -403,11 +416,12 @@ struct store_args {
         int flag;
 };
 
-static VALUE nogvl_store(void *ptr)
+static void * nogvl_store(void *ptr)
 {
         struct store_args *s = ptr;
+        long rc = tdb_store(s->tdb, s->key, s->val, s->flag);
 
-        return (VALUE)tdb_store(s->tdb, s->key, s->val, s->flag);
+        return (void *)rc;
 }
 
 static VALUE rbtdb_store(VALUE self, VALUE key, VALUE val, int flag, int soft)
@@ -419,7 +433,7 @@ static VALUE rbtdb_store(VALUE self, VALUE key, VALUE val, int flag, int soft)
         TO_TDB_DATA(s.val, val);
         s.flag = flag;
 
-        if ((int)my_tbr(nogvl_store, &s) == -1) {
+        if ((long)my_tbr(nogvl_store, &s) == -1) {
                 if (soft) {
                         int ecode = tdb_error(s.tdb);
 
@@ -464,11 +478,11 @@ struct exists_args {
         TDB_DATA key;
 };
 
-static VALUE nogvl_exists(void *ptr)
+static void * nogvl_exists(void *ptr)
 {
         struct exists_args *e = ptr;
 
-        return tdb_exists(e->tdb, e->key) == 0 ? Qfalse : Qtrue;
+        return (void *)(tdb_exists(e->tdb, e->key) == 0 ? Qfalse : Qtrue);
 }
 
 static VALUE has_key(VALUE self, VALUE key)
@@ -478,7 +492,7 @@ static VALUE has_key(VALUE self, VALUE key)
         e.tdb = db(self, 1);
         TO_TDB_DATA(e.key, key);
 
-        return my_tbr(nogvl_exists, &e);
+        return (VALUE)my_tbr(nogvl_exists, &e);
 }
 
 struct traverse_args {
@@ -520,13 +534,13 @@ traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, void *data)
         return t->state;
 }
 
-static VALUE nogvl_traverse(void *ptr)
+static void * nogvl_traverse(void *ptr)
 {
         struct traverse_args *t = ptr;
 
         (void)tdb_traverse(t->tdb, traverse_fn, t);
 
-        return Qfalse;
+        return (void *)Qfalse;
 }
 
 static VALUE each(VALUE self)
@@ -547,11 +561,11 @@ struct delete_args {
         TDB_DATA key;
 };
 
-static VALUE nogvl_delete(void *ptr)
+static void * nogvl_delete(void *ptr)
 {
         struct delete_args *d = ptr;
 
-        return tdb_delete(d->tdb, d->key) == 0 ? Qtrue : Qfalse;
+        return (void *)(tdb_delete(d->tdb, d->key) == 0 ? Qtrue : Qfalse);
 }
 
 static VALUE nuke(VALUE self, VALUE key)
@@ -561,7 +575,7 @@ static VALUE nuke(VALUE self, VALUE key)
         d.tdb = db(self, 1);
         TO_TDB_DATA(d.key, key);
 
-        return my_tbr(nogvl_delete, &d);
+        return (VALUE)my_tbr(nogvl_delete, &d);
 }
 
 static VALUE aref(VALUE self, VALUE key)
@@ -582,7 +596,7 @@ static VALUE delete(int argc, VALUE *argv, VALUE self)
 static VALUE lockall(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_lockall, tdb))
+        if (my_tbr(tdb_lockall, tdb))
                 my_raise(tdb);
 
         return Qtrue;
@@ -593,7 +607,7 @@ static VALUE trylockall(VALUE self)
         struct tdb_context *tdb = db(self, 1);
         void *fn = tdb_lockall_nonblock;
 
-        if ((int)my_tbr((rb_blocking_function_t *)fn, tdb)) {
+        if (my_tbr(fn, tdb)) {
                 if (tdb_error(tdb) == TDB_ERR_LOCK)
                         return Qfalse;
                 my_raise(tdb);
@@ -604,7 +618,7 @@ static VALUE trylockall(VALUE self)
 static VALUE unlockall(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_unlockall, tdb))
+        if (my_tbr(tdb_unlockall, tdb))
                 my_raise(tdb);
         return Qtrue;
 }
@@ -612,7 +626,7 @@ static VALUE unlockall(VALUE self)
 static VALUE lockall_read(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_lockall_read, tdb))
+        if (my_tbr(tdb_lockall_read, tdb))
                 my_raise(tdb);
         return Qtrue;
 }
@@ -621,7 +635,7 @@ static VALUE trylockall_read(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
         void *fn = tdb_lockall_read_nonblock;
-        if ((int)my_tbr((rb_blocking_function_t *)fn, tdb)) {
+        if (my_tbr(fn, tdb)) {
                 if (tdb_error(tdb) == TDB_ERR_LOCK)
                         return Qfalse;
                 my_raise(tdb);
@@ -632,7 +646,7 @@ static VALUE trylockall_read(VALUE self)
 static VALUE unlockall_read(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_unlockall_read, tdb))
+        if (my_tbr(tdb_unlockall_read, tdb))
                 my_raise(tdb);
         return Qtrue;
 }
@@ -640,7 +654,7 @@ static VALUE unlockall_read(VALUE self)
 static VALUE lockall_mark(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_lockall_mark, tdb))
+        if (my_tbr(tdb_lockall_mark, tdb))
                 my_raise(tdb);
         return Qtrue;
 }
@@ -648,7 +662,8 @@ static VALUE lockall_mark(VALUE self)
 static VALUE lockall_unmark(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_lockall_unmark, tdb))
+
+        if (my_tbr(tdb_lockall_unmark, tdb))
                 my_raise(tdb);
         return Qtrue;
 }
@@ -659,7 +674,7 @@ static VALUE lockall_unmark(VALUE self)
 static VALUE clear(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_wipe_all, tdb))
+        if (my_tbr(tdb_wipe_all, tdb))
                 my_raise(tdb);
         return self;
 }
@@ -669,7 +684,7 @@ static VALUE clear(VALUE self)
 static VALUE repack(VALUE self)
 {
         struct tdb_context *tdb = db(self, 1);
-        if ((int)my_tbr((rb_blocking_function_t *)tdb_repack, tdb))
+        if (my_tbr(tdb_repack, tdb))
                 my_raise(tdb);
         return self;
 }