Support "interruptible operations": threads which are blocked on
MVars, exceptions, I/O, or sleeping are fair game for raiseInThread.
/* -----------------------------------------------------------------------------
/* -----------------------------------------------------------------------------
- * $Id: Exception.h,v 1.1 1999/12/01 14:34:38 simonmar Exp $
+ * $Id: Exception.h,v 1.2 2000/03/17 10:24:44 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
*
* (c) The GHC Team, 1998-1999
*
extern const StgInfoTable blockAsyncExceptionszh_ret_info;
extern const StgInfoTable unblockAsyncExceptionszh_ret_info;
extern const StgInfoTable blockAsyncExceptionszh_ret_info;
extern const StgInfoTable unblockAsyncExceptionszh_ret_info;
+
+/* Determine whether a thread is interruptible (ie. blocked
+ * indefinitely). Interruptible threads can be sent an exception with
+ * killThread# even if they have async exceptions blocked.
+ */
+static __inline__ int
+interruptible(StgTSO *t)
+{
+ switch (t->why_blocked) {
+ case BlockedOnMVar:
+ case BlockedOnException:
+ case BlockedOnRead:
+ case BlockedOnWrite:
+ case BlockedOnDelay:
+ return 1;
+ default:
+ return 0;
+ }
+}
/* -----------------------------------------------------------------------------
/* -----------------------------------------------------------------------------
- * $Id: Exception.hc,v 1.8 2000/02/24 17:20:46 simonmar Exp $
+ * $Id: Exception.hc,v 1.9 2000/03/17 10:24:44 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
*
* (c) The GHC Team, 1998-1999
*
FN_(killThreadzh_fast)
{
FB_
FN_(killThreadzh_fast)
{
FB_
}
/* If the target thread is currently blocking async exceptions,
}
/* If the target thread is currently blocking async exceptions,
- * we'll have to block until it's ready to accept them.
+ * we'll have to block until it's ready to accept them. The
+ * exception is interruptible threads - ie. those that are blocked
+ * on some resource.
- if (R1.t->blocked_exceptions != NULL) {
-
- /* ToDo (SMP): locking if destination thread is currently
- * running...
- */
- CurrentTSO->link = R1.t->blocked_exceptions;
- R1.t->blocked_exceptions = CurrentTSO;
-
- CurrentTSO->why_blocked = BlockedOnException;
- CurrentTSO->block_info.tso = R1.t;
+ if (R1.t->blocked_exceptions != NULL && !interruptible(R1.t) ) {
+
+ /* ToDo (SMP): locking if destination thread is currently
+ * running...
+ */
+ CurrentTSO->link = R1.t->blocked_exceptions;
+ R1.t->blocked_exceptions = CurrentTSO;
- BLOCK( R1_PTR | R2_PTR, killThreadzh_fast );
+ CurrentTSO->why_blocked = BlockedOnException;
+ CurrentTSO->block_info.tso = R1.t;
+
+ BLOCK( R1_PTR | R2_PTR, killThreadzh_fast );
}
/* Killed threads turn into zombies, which might be garbage
}
/* Killed threads turn into zombies, which might be garbage