Branch: Tag:

2010-10-11

2010-10-11 22:50:03 by Martin Stjernholm <mast@lysator.liu.se>

Drastically improved chances of actually switching threads when
yielding.

This solution still has two weaknesses though: A presumably mostly
theoretical one is that it might keep alternating between two threads
while starving a third. The other more pertinent one is that it still
doesn't handle threads waiting on condvars.

Adaption of patch suggested by Artur Skawina. Thanks.

365:   #endif   static int th_running = 0;   static MUTEX_T interpreter_lock; + static MUTEX_T interpreter_lock_wanted;   MUTEX_T thread_table_lock;   static MUTEX_T interleave_lock;   static struct program *mutex_key = 0;
411:      PMOD_EXPORT INLINE void pike_low_lock_interpreter (DLOC_DECL)   { +  /* The double locking here is to ensure that when a thread releases +  * the interpreter lock, a different thread gets it first. Thereby +  * we ensure a thread switch in check_threads, if there are other +  * threads waiting. */ +  mt_lock (&interpreter_lock_wanted);    mt_lock (&interpreter_lock); -  +  mt_unlock (&interpreter_lock_wanted); +     SET_LOCKING_THREAD;    THREADS_FPRINTF (1, (stderr, "Got iplock" DLOC_PF(" @ ",) "\n"    COMMA_DLOC_ARGS_OPT));
422:    THREADS_FPRINTF (1, (stderr,    "Waiting on cond %p without iplock" DLOC_PF(" @ ",) "\n",    cond COMMA_DLOC_ARGS_OPT)); +  +  /* FIXME: Should use interpreter_lock_wanted here as well. The +  * problem is that few (if any) thread libs lets us atomically +  * unlock a mutex and wait, and then lock a different mutex. */    co_wait (cond, &interpreter_lock); -  +     SET_LOCKING_THREAD;    THREADS_FPRINTF (1, (stderr,    "Got signal on cond %p with iplock" DLOC_PF(" @ ",) "\n",
437:    THREADS_FPRINTF (1, (stderr,    "Waiting on cond %p without iplock" DLOC_PF(" @ ",) "\n",    cond COMMA_DLOC_ARGS_OPT)); +  +  /* FIXME: Should use interpreter_lock_wanted here as well. The +  * problem is that few (if any) thread libs lets us atomically +  * unlock a mutex and wait, and then lock a different mutex. */    res = co_wait_timeout (cond, &interpreter_lock, sec, nsec); -  +     SET_LOCKING_THREAD;    THREADS_FPRINTF (1, (stderr,    "Got signal on cond %p with iplock" DLOC_PF(" @ ",) "\n",
2866:    really_low_th_init();       mt_init( & interpreter_lock); +  mt_init( & interpreter_lock_wanted);    low_mt_lock_interpreter();    mt_init( & thread_table_lock);    mt_init( & interleave_lock);