mirror of
https://github.com/ruby/ruby.git
synced 2025-09-15 16:44:01 +02: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
|
@ -73,6 +73,25 @@ module Fiddle
|
|||
assert_equal("123", str.to_s)
|
||||
end
|
||||
|
||||
def test_nogvl_poll
|
||||
begin
|
||||
poll = @libc['poll']
|
||||
rescue Fiddle::DLError
|
||||
skip 'poll(2) not available'
|
||||
end
|
||||
f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT)
|
||||
|
||||
msec = 200
|
||||
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
||||
th = Thread.new { f.call(nil, 0, msec) }
|
||||
n1 = f.call(nil, 0, msec)
|
||||
n2 = th.value
|
||||
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
||||
assert_in_delta(msec, t1 - t0, 100, 'slept correct amount of time')
|
||||
assert_equal(0, n1, 'poll(2) called correctly main-thread')
|
||||
assert_equal(0, n2, 'poll(2) called correctly in sub-thread')
|
||||
end
|
||||
|
||||
def test_no_memory_leak
|
||||
prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_tainted"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"'
|
||||
code = 'begin r.call(a); rescue TypeError; end'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue