* thread.c: fix comment (terminology: Global VM Lock).

* thread.c (blocking_region_begin, blocking_region_end):
  save and clear th->blocking_region_buffer.
* thread.c (rb_thread_call_with_gvl): check if it has GVL.
* thread.c (ruby_thread_has_gvl_p): added.
* vm_core.h: add decls.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21438 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2009-01-12 01:43:23 +00:00
Родитель af12cefe06
Коммит 6f09fc2efd
3 изменённых файлов: 56 добавлений и 6 удалений

Просмотреть файл

@ -1,3 +1,16 @@
Mon Jan 12 10:39:19 2009 Koichi Sasada <ko1@atdot.net>
* thread.c: fix comment (terminology: Global VM Lock).
* thread.c (blocking_region_begin, blocking_region_end):
save and clear th->blocking_region_buffer.
* thread.c (rb_thread_call_with_gvl): check if it has GVL.
* thread.c (ruby_thread_has_gvl_p): added.
* vm_core.h: add decls.
Mon Jan 12 10:21:11 2009 Koichi Sasada <ko1@atdot.net>
* eval.c: remove unused decl.

Просмотреть файл

@ -14,7 +14,7 @@
model 1: Userlevel Thread
Same as traditional ruby thread.
model 2: Native Thread with Giant VM lock
model 2: Native Thread with Global VM lock
Using pthread (or Windows thread) and Ruby threads run concurrent.
model 3: Native Thread with fine grain lock
@ -23,8 +23,8 @@
------------------------------------------------------------------------
model 2:
A thread has mutex (GVL: Global VM Lock) can run. When thread
scheduling, running thread release GVL. If running thread
A thread has mutex (GVL: Global VM Lock or Giant VM Lock) can run.
When thread scheduling, running thread release GVL. If running thread
try blocking operation, this thread must release GVL and another
thread can continue this flow. After blocking operation, thread
must check interrupt (RUBY_VM_CHECK_INTS).
@ -953,6 +953,7 @@ blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
rb_unblock_function_t *func, void *arg)
{
region->prev_status = th->status;
th->blocking_region_buffer = region;
set_unblock_function(th, func, arg, &region->oldubf);
th->status = THREAD_STOPPED;
thread_debug("enter blocking region (%p)\n", (void *)th);
@ -967,6 +968,7 @@ blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
rb_thread_set_current(th);
thread_debug("leave blocking region (%p)\n", (void *)th);
remove_signal_thread_list(th);
th->blocking_region_buffer = 0;
reset_unblock_function(th, &region->oldubf);
if (th->status == THREAD_STOPPED) {
th->status = region->prev_status;
@ -1014,8 +1016,7 @@ 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). Especially, ALLOC*() are
* forbidden because they are related to GC. If you need to do it,
* GVL (cause synchronization problem). 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
@ -1024,6 +1025,8 @@ rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region)
*
* Safe C API:
* * rb_thread_interrupted() - check interrupt flag
* * ruby_xalloc(), ruby_xrealloc(), ruby_xfree() -
* if they called without GVL, acquire GVL automatically.
*/
VALUE
rb_thread_blocking_region(
@ -1058,6 +1061,11 @@ rb_thread_call_without_gvl(
/*
* rb_thread_call_with_gvl - re-enter into Ruby world while releasing GVL.
*
***
*** This API is EXPERIMENTAL!
*** We do not guarantee that this API remains in ruby 1.9.2 or later.
***
*
* 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().
@ -1103,6 +1111,10 @@ rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
brb = (struct rb_blocking_region_buffer *)th->blocking_region_buffer;
prev_unblock = th->unblock;
if (brb == 0) {
rb_bug("rb_thread_call_with_gvl: called by a thread which has GVL.");
}
blocking_region_end(th, brb);
/* enter to Ruby world: You can access Ruby values, methods and so on. */
r = (*func)(data1);
@ -1111,6 +1123,28 @@ rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
return r;
}
/*
* ruby_thread_has_gvl_p - check if current native thread has GVL.
*
***
*** This API is EXPERIMENTAL!
*** We do not guarantee that this API remains in ruby 1.9.2 or later.
***
*/
int
ruby_thread_has_gvl_p(void)
{
rb_thread_t *th = ruby_thread_from_native();
if (th && th->blocking_region_buffer == 0) {
return 1;
}
else {
return 0;
}
}
/*
* call-seq:
* Thread.pass => nil
@ -3721,7 +3755,7 @@ Init_Thread(void)
{
/* main thread setting */
{
/* acquire global interpreter lock */
/* acquire global vm lock */
rb_thread_lock_t *lp = &GET_THREAD()->vm->global_vm_lock;
native_mutex_initialize(lp);
native_mutex_lock(lp);

Просмотреть файл

@ -588,6 +588,9 @@ VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
VALUE vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass);
VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
int ruby_thread_has_gvl_p(void);
NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]