summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-30 07:57:53 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-30 07:57:53 +0000
commit9c04a0647fb99f7554cb2e04385ddbb970631e02 (patch)
tree48e3262b26982e893adcc36fd7722298d5ea03ce
parentf396a10e132aeb8e80023ee1a1515124dfa3b486 (diff)
* 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
-rw-r--r--ChangeLog12
-rw-r--r--thread.c73
-rw-r--r--vm_core.h1
3 files changed, 85 insertions, 1 deletions
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 <ko1@atdot.net>
+
+ * 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 <ko1@atdot.net>
* 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;