mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
fiddle: release GVL for ffi_call
Some external functions I wish to call may take a long time and unnecessarily block other threads. This may lead to performance regressions for fast functions as releasing/acquiring the GVL is not cheap, but can improve performance for long-running functions in multi-threaded applications. This also means we must reacquire the GVL when calling Ruby-defined callbacks for Fiddle::Closure, meaning we must detect whether the current thread has the GVL by exporting ruby_thread_has_gvl_p in internal.h * ext/fiddle/function.c (struct nogvl_ffi_call_args): new struct for GVL release (nogvl_ffi_call): new function (function_call): adjust for GVL release [ruby-core:71642] [Feature #11607] * ext/fiddle/closure.c (struct callback_args): new struct for GVL acquire (with_gvl_callback): adjusted original callback function (callback): wrapper for conditional GVL acquire * ext/fiddle/depend: add dependencies * ext/fiddle/extconf.rb: include top_srcdir for internal.h * internal.h (ruby_thread_has_gvl_p): expose for fiddle * vm_core.h (ruby_thread_has_gvl_p): moved to internal.h * test/fiddle/test_function.rb (test_nogvl_poll): new test git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52723 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6965964df6
commit
15476c695d
8 changed files with 124 additions and 36 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#include <fiddle.h>
|
||||
#include <ruby/thread.h>
|
||||
|
||||
#ifdef PRIsVALUE
|
||||
# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
|
||||
|
|
@ -128,13 +129,28 @@ initialize(int argc, VALUE argv[], VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
struct nogvl_ffi_call_args {
|
||||
ffi_cif *cif;
|
||||
void (*fn)(void);
|
||||
void **values;
|
||||
fiddle_generic retval;
|
||||
};
|
||||
|
||||
static void *
|
||||
nogvl_ffi_call(void *ptr)
|
||||
{
|
||||
struct nogvl_ffi_call_args *args = ptr;
|
||||
|
||||
ffi_call(args->cif, args->fn, &args->retval, args->values);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
function_call(int argc, VALUE argv[], VALUE self)
|
||||
{
|
||||
ffi_cif * cif;
|
||||
fiddle_generic retval;
|
||||
struct nogvl_ffi_call_args args = { 0 };
|
||||
fiddle_generic *generic_args;
|
||||
void **values;
|
||||
VALUE cfunc, types, cPointer;
|
||||
int i;
|
||||
VALUE alloc_buffer = 0;
|
||||
|
|
@ -148,7 +164,7 @@ function_call(int argc, VALUE argv[], VALUE self)
|
|||
rb_error_arity(argc, i, i);
|
||||
}
|
||||
|
||||
TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
|
||||
TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif);
|
||||
|
||||
if (rb_safe_level() >= 1) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
|
|
@ -161,7 +177,8 @@ function_call(int argc, VALUE argv[], VALUE self)
|
|||
|
||||
generic_args = ALLOCV(alloc_buffer,
|
||||
(size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic));
|
||||
values = (void **)((char *)generic_args + (size_t)argc * sizeof(fiddle_generic));
|
||||
args.values = (void **)((char *)generic_args +
|
||||
(size_t)argc * sizeof(fiddle_generic));
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
VALUE type = RARRAY_AREF(types, i);
|
||||
|
|
@ -177,11 +194,12 @@ function_call(int argc, VALUE argv[], VALUE self)
|
|||
}
|
||||
|
||||
VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
|
||||
values[i] = (void *)&generic_args[i];
|
||||
args.values[i] = (void *)&generic_args[i];
|
||||
}
|
||||
values[argc] = NULL;
|
||||
args.values[argc] = NULL;
|
||||
args.fn = NUM2PTR(rb_Integer(cfunc));
|
||||
|
||||
ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);
|
||||
(void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
|
||||
|
||||
rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
|
||||
#if defined(_WIN32)
|
||||
|
|
@ -190,7 +208,7 @@ function_call(int argc, VALUE argv[], VALUE self)
|
|||
|
||||
ALLOCV_END(alloc_buffer);
|
||||
|
||||
return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
|
||||
return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue