- /* Signal that a capability is available */
- signalCondition(&thread_ready_cond);
- startSchedulerTaskIfNecessary(); // if there is more work to be done,
- // we'll need a new thread
- IF_DEBUG(scheduler, sched_belch("worker: released capability"));
- }
+ // Check to see whether a worker thread can be given
+ // the go-ahead to return the result of an external call..
+ if (rts_n_waiting_workers > 0) {
+ // Decrement the counter here to avoid livelock where the
+ // thread that is yielding its capability will repeatedly
+ // signal returning_worker_cond.
+
+ rts_n_waiting_workers--;
+ signalCondition(&returning_worker_cond);
+ IF_DEBUG(scheduler, sched_belch("worker: released capability to returning worker"));
+ } else if (passingCapability) {
+ if (passTarget == NULL) {
+ signalCondition(&thread_ready_cond);
+ startSchedulerTaskIfNecessary();
+ } else {
+ signalCondition(passTarget);
+ }
+ rts_n_free_capabilities++;
+ IF_DEBUG(scheduler, sched_belch("worker: released capability, passing it"));
+
+ } else {
+ rts_n_free_capabilities++;
+ // Signal that a capability is available
+ if (rts_n_waiting_tasks > 0 && ANY_WORK_TO_DO()) {
+ signalCondition(&thread_ready_cond);
+ }
+ startSchedulerTaskIfNecessary();
+ IF_DEBUG(scheduler, sched_belch("worker: released capability"));
+ }