From 1ed6aacf5cb3265191acc61449fe68abd7c8f503 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 9 Feb 2014 08:07:02 +0000 Subject: prepare for rb_thread_blocking_region removal 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/tdb/extconf.rb | 1 + ext/tdb/tdb.c | 103 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 60 insertions(+), 44 deletions(-) (limited to 'ext') 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 +# define WITHOUT_GVL(fn,a,ubf,b) \ + rb_thread_call_without_gvl((fn),(a),(ubf),(b)) +#else /* Ruby 1.8 */ # include -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; } -- cgit v1.2.3-24-ge0c7