зеркало из https://github.com/github/ruby.git
* 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:
Родитель
af12cefe06
Коммит
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>
|
||||
|
||||
* eval.c: remove unused decl.
|
||||
|
|
46
thread.c
46
thread.c
|
@ -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, ®ion->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, ®ion->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]
|
||||
|
|
Загрузка…
Ссылка в новой задаче