ブロッキング
スレッド実行中にI/Oなどシステム関係の操作で処理がブロックするときは、グローバルロックを解除します。YARVのスレッドモデルでは、そうしないと他のスレッドまで一斉に止まってしまうので。これは、ブロックする処理を実装した関数へのポインタを rb_thread_blocking_region @ thread.c 関数に渡すことで実現されるようになっています。
VALUE
rb_thread_blocking_region(
rb_blocking_function_t *func, void *data,
rb_unblock_function_t *ubf)
{
VALUE val;
rb_thread_t *th = GET_THREAD();
if (ubf == RB_UBF_DFL) {
ubf = ubf_select;
}
BLOCKING_REGION({
val = func(th, data);
}, ubf);
return val;
}
rb_thread_blocking_region の実体は BLOCKING_REGION マクロで、これの定義は
#define GVL_UNLOCK_BEGIN() do { \ rb_thread_t *_th_stored = GET_THREAD(); \ rb_gc_save_machine_context(_th_stored); \ native_mutex_unlock(&_th_stored->vm->global_interpreter_lock) #define GVL_UNLOCK_END() \ native_mutex_lock(&_th_stored->vm->global_interpreter_lock); \ rb_thread_set_current(_th_stored); \ } while(0) #define BLOCKING_REGION(exec, ubf) do { \ rb_thread_t *__th = GET_THREAD(); \ ...(略)... GVL_UNLOCK_BEGIN(); {\ exec; \ } \ GVL_UNLOCK_END(); \ ...(略)... } while(0)
rb_thread_scheduleとまったく同じです。
rb_thread_blocking_regionはprocess.cやfile.cなどのライブラリ部分で何カ所か使われているみたいですね。