ブロッキング
スレッド実行中に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などのライブラリ部分で何カ所か使われているみたいですね。