* 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:
parent
af12cefe06
commit
6f09fc2efd
13
ChangeLog
13
ChangeLog
@ -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>
|
Mon Jan 12 10:21:11 2009 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* eval.c: remove unused decl.
|
* eval.c: remove unused decl.
|
||||||
|
46
thread.c
46
thread.c
@ -14,7 +14,7 @@
|
|||||||
model 1: Userlevel Thread
|
model 1: Userlevel Thread
|
||||||
Same as traditional ruby 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.
|
Using pthread (or Windows thread) and Ruby threads run concurrent.
|
||||||
|
|
||||||
model 3: Native Thread with fine grain lock
|
model 3: Native Thread with fine grain lock
|
||||||
@ -23,8 +23,8 @@
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
model 2:
|
model 2:
|
||||||
A thread has mutex (GVL: Global VM Lock) can run. When thread
|
A thread has mutex (GVL: Global VM Lock or Giant VM Lock) can run.
|
||||||
scheduling, running thread release GVL. If running thread
|
When thread scheduling, running thread release GVL. If running thread
|
||||||
try blocking operation, this thread must release GVL and another
|
try blocking operation, this thread must release GVL and another
|
||||||
thread can continue this flow. After blocking operation, thread
|
thread can continue this flow. After blocking operation, thread
|
||||||
must check interrupt (RUBY_VM_CHECK_INTS).
|
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)
|
rb_unblock_function_t *func, void *arg)
|
||||||
{
|
{
|
||||||
region->prev_status = th->status;
|
region->prev_status = th->status;
|
||||||
|
th->blocking_region_buffer = region;
|
||||||
set_unblock_function(th, func, arg, ®ion->oldubf);
|
set_unblock_function(th, func, arg, ®ion->oldubf);
|
||||||
th->status = THREAD_STOPPED;
|
th->status = THREAD_STOPPED;
|
||||||
thread_debug("enter blocking region (%p)\n", (void *)th);
|
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);
|
rb_thread_set_current(th);
|
||||||
thread_debug("leave blocking region (%p)\n", (void *)th);
|
thread_debug("leave blocking region (%p)\n", (void *)th);
|
||||||
remove_signal_thread_list(th);
|
remove_signal_thread_list(th);
|
||||||
|
th->blocking_region_buffer = 0;
|
||||||
reset_unblock_function(th, ®ion->oldubf);
|
reset_unblock_function(th, ®ion->oldubf);
|
||||||
if (th->status == THREAD_STOPPED) {
|
if (th->status == THREAD_STOPPED) {
|
||||||
th->status = region->prev_status;
|
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
|
* NOTE: You can not execute most of Ruby C API and touch Ruby objects
|
||||||
* in `func()' and `ubf()' because current thread doesn't acquire
|
* in `func()' and `ubf()' because current thread doesn't acquire
|
||||||
* GVL (cause synchronization problem). Especially, ALLOC*() are
|
* GVL (cause synchronization problem). If you need to do it,
|
||||||
* forbidden because they are related to GC. If you need to do it,
|
|
||||||
* read source code of C APIs and confirm by yourself.
|
* read source code of C APIs and confirm by yourself.
|
||||||
*
|
*
|
||||||
* NOTE: In short, this API is difficult to use safely. I recommend you
|
* 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:
|
* Safe C API:
|
||||||
* * rb_thread_interrupted() - check interrupt flag
|
* * rb_thread_interrupted() - check interrupt flag
|
||||||
|
* * ruby_xalloc(), ruby_xrealloc(), ruby_xfree() -
|
||||||
|
* if they called without GVL, acquire GVL automatically.
|
||||||
*/
|
*/
|
||||||
VALUE
|
VALUE
|
||||||
rb_thread_blocking_region(
|
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.
|
* 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
|
* While releasing GVL using rb_thread_blocking_region() or
|
||||||
* rb_thread_call_without_gvl(), you can not access Ruby values or invoke methods.
|
* 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().
|
* 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;
|
brb = (struct rb_blocking_region_buffer *)th->blocking_region_buffer;
|
||||||
prev_unblock = th->unblock;
|
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);
|
blocking_region_end(th, brb);
|
||||||
/* enter to Ruby world: You can access Ruby values, methods and so on. */
|
/* enter to Ruby world: You can access Ruby values, methods and so on. */
|
||||||
r = (*func)(data1);
|
r = (*func)(data1);
|
||||||
@ -1111,6 +1123,28 @@ rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
|
|||||||
return r;
|
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:
|
* call-seq:
|
||||||
* Thread.pass => nil
|
* Thread.pass => nil
|
||||||
@ -3721,7 +3755,7 @@ Init_Thread(void)
|
|||||||
{
|
{
|
||||||
/* main thread setting */
|
/* main thread setting */
|
||||||
{
|
{
|
||||||
/* acquire global interpreter lock */
|
/* acquire global vm lock */
|
||||||
rb_thread_lock_t *lp = &GET_THREAD()->vm->global_vm_lock;
|
rb_thread_lock_t *lp = &GET_THREAD()->vm->global_vm_lock;
|
||||||
native_mutex_initialize(lp);
|
native_mutex_initialize(lp);
|
||||||
native_mutex_lock(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_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);
|
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 *));
|
NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
|
||||||
|
|
||||||
#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
|
#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user