fix bogus deadlocks from interrupts and GCs
authorNikodemus Siivola <nikodemus@sb-studio.net>
Mon, 15 Aug 2011 11:33:49 +0000 (14:33 +0300)
committerNikodemus Siivola <nikodemus@sb-studio.net>
Mon, 15 Aug 2011 13:32:14 +0000 (16:32 +0300)
commit5abf3b4b94c8c2315777e63729293395dc54992c
tree62486b0b80cd864f7972c8afa914c814b2ccdb6c
parent86d50ba6266c823eedd444c4e1c5a55e9dc7f46a
fix bogus deadlocks from interrupts and GCs

 lp#807475

 Going in despite the freeze since this is a regression that can
 semi-randomly break correct code. *ouch*

 Thanks to Bart Bortta and #sbcl for the analysis.

 Problem 1:

   T1 holds L1

   T2 is waiting for L1

   T2 is interrupted, interrupt handler grabs L2

   T1 starts waiting on L2

   Prior to this patch, when GET-MUTEX in T2's interrupt handler grabbed
   L2 is marked T2 as still waiting for L1 -- which is not true until
   the interrupt handler returns.

 Problem 2:

   T1 holds L1

   T2 is waiting for L1

   GC is triggered in T2 inside GET-MUTEX

   T2 grabs *ALREADY-IN-GC* lock

   GC is triggered in T1, T1 tries to get *ALREADY-IN-GC* lock.

   Prior to this patch, when T1 detects a bogus deadlock as T2 has
   been marked as waiting for L1 -- which is not true until the GC is
   finished and normal execution resumes.

 Problem 3:

   T1 holds L1

   T2 is waiting for L1

   GC is triggered in T2 inside GET-MUTEX

   T2 grabs lock L2 due to a finalizer or an after-gc-hook

   GC is triggered in T1

   T1 tries to grab L2 due to a finalizer, etc.

   Same as problem 2, but with a user-lock and POST-GC instead of
   *ALREADY-IN-GC* and SUB-GC.

 This patch fixes the issue by saving, clearing, and restoring
 the waiting-for mark in

  1) interrupt handlers

  2) SUB-GC

  3) POST-GC
NEWS
src/code/gc.lisp
src/code/target-signal.lisp
src/code/target-thread.lisp
src/code/thread.lisp
tests/threads.impure.lisp