if (t == tso) {
if (prev) {
setTSOLink(cap,prev,t->_link);
+ t->_link = END_TSO_QUEUE;
return rtsFalse;
} else {
*queue = t->_link;
+ t->_link = END_TSO_QUEUE;
return rtsTrue;
}
}
*head = t->_link;
flag = rtsTrue;
}
- if (*tail == tso) {
+ t->_link = END_TSO_QUEUE;
+ if (*tail == tso) {
if (prev) {
*tail = prev;
} else {
// we'll block again.
tso->why_blocked = NotBlocked;
appendToRunQueue(cap,tso);
+
+ // We used to set the context switch flag here, which would
+ // trigger a context switch a short time in the future (at the end
+ // of the current nursery block). The idea is that we have just
+ // woken up a thread, so we may need to load-balance and migrate
+ // threads to other CPUs. On the other hand, setting the context
+ // switch flag here unfairly penalises the current thread by
+ // yielding its time slice too early.
+ //
+ // The synthetic benchmark nofib/smp/chan can be used to show the
+ // difference quite clearly.
+
+ // cap->context_switch = 1;
}
/* ----------------------------------------------------------------------------
i = thunk->header.info;
if (i != &stg_BLACKHOLE_info &&
i != &stg_CAF_BLACKHOLE_info &&
+ i != &__stg_EAGER_BLACKHOLE_info &&
i != &stg_WHITEHOLE_info) {
updateWithIndirection(cap, thunk, val);
return;
case BlockedOnCCall:
debugBelch("is blocked on an external call");
break;
- case BlockedOnCCall_NoUnblockExc:
- debugBelch("is blocked on an external call (exceptions were already blocked)");
+ case BlockedOnCCall_Interruptible:
+ debugBelch("is blocked on an external call (but may be interrupted)");
break;
case BlockedOnSTM:
debugBelch("is blocked on an STM operation");