From 9c04a0647fb99f7554cb2e04385ddbb970631e02 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 30 Dec 2008 07:57:53 +0000 Subject: * thread.c (rb_thread_blocking_region): add a comment. * thread.c (rb_thread_call_without_gvl): added as a alias of rb_thread_blocking_region(). * thread.c (rb_thread_call_with_gvl): added. * vm_core.h (rb_thread_t#blocking_region_buffer): added for rb_thread_call_with_gvl(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21185 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 +++++++++++ thread.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- vm_core.h | 1 + 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 587bba8cb2..7485975bc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Tue Dec 30 16:56:09 2008 Koichi Sasada + + * thread.c (rb_thread_blocking_region): add a comment. + + * thread.c (rb_thread_call_without_gvl): added as a alias of + rb_thread_blocking_region(). + + * thread.c (rb_thread_call_with_gvl): added. + + * vm_core.h (rb_thread_t#blocking_region_buffer): added for + rb_thread_call_with_gvl(). + Mon Dec 29 23:41:42 2008 Koichi Sasada * ext/dl/test/test_base.rb: add libc search logic. diff --git a/thread.c b/thread.c index 4f5f150650..16c7d0212c 100644 --- a/thread.c +++ b/thread.c @@ -1014,9 +1014,14 @@ rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region) * * NOTE: You can not execute most of Ruby C API and touch Ruby objects * in `func()' and `ubf()' because current thread doesn't acquire - * GVL (cause synchronization problem). If you need to do it, + * GVL (cause synchronization problem). Especially, ALLOC*() are + * forbidden because they are related to GC. If you need to do it, * read source code of C APIs and confirm by yourself. * + * NOTE: In short, this API is difficult to use safely. I recommend you + * use other ways if you have. We lack experiences to use this API. + * Please report your problem related on it. + * * Safe C API: * * rb_thread_interrupted() - check interrupt flag */ @@ -1040,6 +1045,72 @@ rb_thread_blocking_region( return val; } +/* alias of rb_thread_blocking_region() */ + +VALUE +rb_thread_call_without_gvl( + rb_blocking_function_t *func, void *data1, + rb_unblock_function_t *ubf, void *data2) +{ + return rb_thread_blocking_region(func, data1, ubf, data2); +} + +/* + * rb_thread_call_with_gvl - re-enter into Ruby world while releasing GVL. + * + * While releasing GVL using rb_thread_blocking_region() or + * rb_thread_call_without_gvl(), you can not access Ruby values or invoke methods. + * If you need to access it, you must use this function rb_thread_call_with_gvl(). + * + * This function rb_thread_call_with_gvl() does: + * (1) acquire GVL. + * (2) call passed function `func'. + * (3) release GVL. + * (4) return a value which is returned at (2). + * + * NOTE: You should not return Ruby object at (2) because such Object + * will not marked. + * + * NOTE: If an exception is raised in `func', this function "DOES NOT" + * protect (catch) the exception. If you have any resources + * which should free before throwing exception, you need use + * rb_protect() in `func' and return a value which represents + * exception is raised. + * + * NOTE: This functions should not be called by a thread which + * is not created as Ruby thread (created by Thread.new or so). + * In other words, this function *DOES NOT* associate + * NON-Ruby thread to Ruby thread. + */ +void * +rb_thread_call_with_gvl(void *(*func)(void *), void *data1) +{ + rb_thread_t *th = ruby_thread_from_native(); + struct rb_blocking_region_buffer *brb; + struct rb_unblock_callback prev_unblock; + void *r; + + if (th == 0) { + /* Error is occurred, but we can't use rb_bug() + * because this thread is not Ruby's thread. + * What should we do? + */ + + fprintf(stderr, "[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n"); + exit(1); + } + + brb = (struct rb_blocking_region_buffer *)th->blocking_region_buffer; + prev_unblock = th->unblock; + + blocking_region_end(th, brb); + /* enter to Ruby world: You can access Ruby values, methods and so on. */ + r = (*func)(data1); + /* levae from Ruby world: You can not access Ruby values, etc. */ + blocking_region_begin(th, brb, prev_unblock.func, prev_unblock.arg); + return r; +} + /* * call-seq: * Thread.pass => nil diff --git a/vm_core.h b/vm_core.h index 1fa5662686..fea803986f 100644 --- a/vm_core.h +++ b/vm_core.h @@ -363,6 +363,7 @@ typedef struct rb_thread_struct int slice; native_thread_data_t native_thread_data; + void *blocking_region_buffer; VALUE thgroup; VALUE value; -- cgit v1.2.3