From: Hidetoshi NAGAI Date: 2003-11-14T11:53:12+09:00 Subject: [ruby-dev:21922] Re: pthread trouble on tcltklib 永井@知能.九工大です. From: nobu.nakada@nifty.ne.jp Subject: [ruby-dev:21916] Re: pthread trouble on tcltklib Date: Wed, 12 Nov 2003 15:56:54 +0900 Message-ID: <200311120656.hAC6ur64023336@sharui.nakada.kanuma.tochigi.jp> > > # 当面は Tietew さんの patch を適用していただくだけで > > # きっと十分なんでしょうね. > 当面は足りるのではないかと思います。 え〜っと,誰が commit すべきなのかわかりませんでしたので そのままにしていましたが,commit の気配がないので とりあえず patch にしてみました. 元の Tietew さんの patch だと,eval.c の rb_thread_check() と 衝突するので rb_nativethread_check() (および NATIVETHREAD_CHECK) に 名前を変えています. また,ruby_thid の宣言で (rb_nativethread_t)0 で初期化するように 加えています. configure.in では相変わらず --with-pthread-ext が付与されたときだけ HAVE_LIBPTHREAD のチェックをする (FreeBSD を除く) ようになってますが, このチェックはデフォルトで行っても問題はないようにも見えます. ところで Tietew さんの patch では,rb_nativethread_check で ruby の native thread 以外から rb_thread_schedule() や rb_gc() が 呼ばれた時点で rb_bug で落ちるようになってますよね. これ,もう少し救ってあげれないかと考えていたのですが ( 例えば,rb_gc なりを呼び出しを pending してその native thread を wait させ,ruby の native thread で rb_gc なりが終了した時点で 起こして return する等 ),GC 中に別の native thread でオブジェクトを いじってしまう危険がある (ですよね?) 点が消えずに残るということで あきらめました. Index: ruby.h =================================================================== RCS file: /src/ruby/ruby.h,v retrieving revision 1.90 diff -u -r1.90 ruby.h --- ruby.h 14 Oct 2003 02:53:53 -0000 1.90 +++ ruby.h 14 Nov 2003 02:28:13 -0000 @@ -671,6 +671,22 @@ static char *dln_libs_to_be_linked[] = { EXTLIB, 0 }; #endif +#if defined(HAVE_LIBPTHREAD) +typedef pthread_t rb_nativethread_t; +# define NATIVETHREAD_CURRENT() pthread_self() +# define HAVE_NATIVETHREAD +#elif defined(_WIN32) || defined(__CYGWIN__) +typedef DWORD rb_nativethread_t; +# define NATIVETHREAD_CURRENT() GetCurrentThreadId() +# define HAVE_NATIVETHREAD +#endif +#ifdef HAVE_NATIVETHREAD +extern void rb_nativethread_check _(()); +# define NATIVETHREAD_CHECK rb_nativethread_check() +#else +# define NATIVETHREAD_CHECK +#endif + #if defined(__cplusplus) } /* extern "C" { */ #endif Index: eval.c =================================================================== RCS file: /src/ruby/eval.c,v retrieving revision 1.586 diff -u -r1.586 eval.c --- eval.c 6 Nov 2003 16:08:26 -0000 1.586 +++ eval.c 14 Nov 2003 02:28:15 -0000 @@ -33,10 +33,6 @@ #include "st.h" #include "dln.h" -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) -#include -#endif - #ifdef __APPLE__ #include #endif @@ -8610,11 +8606,6 @@ return test; } -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) -static pthread_t thid; -static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; -#endif - void rb_thread_schedule() { @@ -8631,10 +8622,8 @@ int n, max; int need_select = 0; int select_timeout = 0; -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) - int st; -#endif + NATIVETHREAD_CHECK; rb_thread_pending = 0; if (curr_thread == curr_thread->next && curr_thread->status == THREAD_RUNNABLE) @@ -8643,16 +8632,6 @@ next = 0; curr = curr_thread; /* starting thread */ -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) - if ((st = pthread_mutex_trylock(&mtx)) == EBUSY) { - if (pthread_self() != thid) { - return; - } - } else { - thid = pthread_self(); - } -#endif - while (curr->status == THREAD_KILLED) { curr = curr->prev; } @@ -8850,22 +8829,12 @@ } next->wait_for = 0; if (next->status == THREAD_RUNNABLE && next == curr_thread) { -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) - if (st != EBUSY) { - pthread_mutex_unlock(& mtx); - } -#endif return; } /* context switch */ if (curr == curr_thread) { if (THREAD_SAVE_CONTEXT(curr)) { -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) - if (st != EBUSY) { - pthread_mutex_unlock(& mtx); - } -#endif return; } } @@ -8875,19 +8844,9 @@ if (!(next->flags & THREAD_TERMINATING)) { next->flags |= THREAD_TERMINATING; /* terminate; execute ensure-clause if any */ -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) - if (st != EBUSY) { - pthread_mutex_unlock(& mtx); - } -#endif rb_thread_restore_context(next, RESTORE_FATAL); } } -#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB) - if (st != EBUSY) { - pthread_mutex_unlock(& mtx); - } -#endif rb_thread_restore_context(next, RESTORE_NORMAL); } Index: gc.c =================================================================== RCS file: /src/ruby/gc.c,v retrieving revision 1.160 diff -u -r1.160 gc.c --- gc.c 20 Oct 2003 02:06:39 -0000 1.160 +++ gc.c 14 Nov 2003 02:28:15 -0000 @@ -1216,6 +1216,7 @@ jmp_buf save_regs_gc_mark; SET_STACK_END; + NATIVETHREAD_CHECK; if (dont_gc || during_gc) { if (!freelist) { add_heap(); @@ -1316,6 +1317,16 @@ return Qnil; } +#ifdef HAVE_NATIVETHREAD +static rb_nativethread_t ruby_thid = (rb_nativethread_t)0; +void +rb_nativethread_check() +{ + if (!ruby_thid || ruby_thid != NATIVETHREAD_CURRENT()) + rb_bug("cross-thread violation."); +} +#endif + void Init_stack(addr) VALUE *addr; @@ -1353,6 +1364,10 @@ if (STACK_LEVEL_MAX > IA64_MAGIC_STACK_LIMIT) STACK_LEVEL_MAX = IA64_MAGIC_STACK_LIMIT; #endif +#endif +#ifdef HAVE_NATIVETHREAD + if (ruby_thid) rb_nativethread_check(); + else ruby_thid = NATIVETHREAD_CURRENT(); #endif } Index: configure.in =================================================================== RCS file: /src/ruby/configure.in,v retrieving revision 1.191 diff -u -r1.191 configure.in --- configure.in 8 Nov 2003 04:53:14 -0000 1.191 +++ configure.in 14 Nov 2003 02:28:16 -0000 @@ -662,9 +662,6 @@ ], rb_cv_stack_grow_dir=-1, rb_cv_stack_grow_dir=+1, rb_cv_stack_grow_dir=0)]) AC_DEFINE_UNQUOTED(STACK_GROW_DIRECTION, $rb_cv_stack_grow_dir) -dnl default value for $KANJI -DEFAULT_KCODE="KCODE_NONE" - AC_ARG_WITH(pthread-ext, [ --with-pthread-ext use pthread library on external modules ], [AC_DEFINE(USE_PTHREAD_EXTLIB) @@ -688,26 +685,39 @@ AC_DEFINE(_THREAD_SAFE) AC_DEFINE(HAVE_LIBPTHREAD) else - AC_CHECK_LIB(c_r, pthread_mutex_init, + AC_CHECK_LIB(c, pthread_mutex_init, rb_use_pthread_ext=yes, rb_use_pthread_ext=no) if test "$rb_use_pthread_ext" = "yes"; then - if test "$with_libc_r" = "yes"; then - if test "$rb_cv_supplementary_lib_c_r" = "yes"; then + AC_DEFINE(_REENTRANT) + AC_DEFINE(_THREAD_SAFE) + AC_DEFINE(HAVE_LIBPTHREAD) + else + AC_CHECK_LIB(c_r, pthread_mutex_init, + rb_use_pthread_ext=yes, rb_use_pthread_ext=no) + if test "$rb_use_pthread_ext" = "yes"; then + if test "$with_libc_r" = "yes"; then + if test "$rb_cv_supplementary_lib_c_r" = "yes"; then + AC_DEFINE(_REENTRANT) + AC_DEFINE(_THREAD_SAFE) + AC_DEFINE(HAVE_LIBPTHREAD) + MAINLIBS="-pthread $MAINLIBS" + fi + else + MAINLIBS="-pthread $MAINLIBS" AC_DEFINE(_REENTRANT) AC_DEFINE(_THREAD_SAFE) AC_DEFINE(HAVE_LIBPTHREAD) - MAINLIBS="-pthread $MAINLIBS" fi else - MAINLIBS="-pthread $MAINLIBS" - AC_DEFINE(_REENTRANT) - AC_DEFINE(_THREAD_SAFE) - AC_DEFINE(HAVE_LIBPTHREAD) + AC_MSG_WARN("Don't know how to find pthread library on your system -- thread support disabled") fi fi fi fi ]) + +dnl default value for $KANJI +DEFAULT_KCODE="KCODE_NONE" AC_ARG_WITH(default-kcode, [ --with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)], -- 永井 秀利 (九工大 知能情報) nagai@ai.kyutech.ac.jp