Bug 82146 [jobs] Reentrent schedule during aboutToRun doesn't wake worker
diff --git a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/jobs/WorkerPool.java b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/jobs/WorkerPool.java index 01c0d9b..bada4b6 100644 --- a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/jobs/WorkerPool.java +++ b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/jobs/WorkerPool.java
@@ -162,6 +162,7 @@ */ private synchronized void sleep(long duration) { sleepingThreads++; + decrementBusyThreads(); if (JobManager.DEBUG) JobManager.debug("worker sleeping for: " + duration + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ try { @@ -171,6 +172,7 @@ JobManager.debug("worker interrupted while waiting... :-|"); //$NON-NLS-1$ } finally { sleepingThreads--; + incrementBusyThreads(); } } @@ -186,35 +188,43 @@ return null; } } - Job job = manager.startJob(); - //spin until a job is found or until we have been idle for too long - long idleStart = System.currentTimeMillis(); - while (manager.isActive() && job == null) { - long hint = manager.sleepHint(); - if (hint > 0) - sleep(Math.min(hint, BEST_BEFORE)); + //set the thread to be busy now in case of reentrant scheduling + incrementBusyThreads(); + Job job = null; + try { job = manager.startJob(); - //if we were already idle, and there are still no new jobs, then - // the thread can expire - synchronized (this) { - if (job == null && (System.currentTimeMillis() - idleStart > BEST_BEFORE) && (numThreads - busyThreads) > MIN_THREADS) { - //must remove the worker immediately to prevent all threads from expiring - endWorker(worker); - return null; + //spin until a job is found or until we have been idle for too long + long idleStart = System.currentTimeMillis(); + while (manager.isActive() && job == null) { + long hint = manager.sleepHint(); + if (hint > 0) + sleep(Math.min(hint, BEST_BEFORE)); + job = manager.startJob(); + //if we were already idle, and there are still no new jobs, then + // the thread can expire + synchronized (this) { + if (job == null && (System.currentTimeMillis() - idleStart > BEST_BEFORE) && (numThreads - busyThreads) > MIN_THREADS) { + //must remove the worker immediately to prevent all threads from expiring + endWorker(worker); + return null; + } } } - } - if (job != null) { - incrementBusyThreads(); - //if this job has a rule, then we are essentially acquiring a lock - if ((job.getRule() != null) && !(job instanceof ThreadJob)) { - //don't need to reaquire locks because it was not recorded in the graph - //that this thread waited to get this rule - manager.getLockManager().addLockThread(Thread.currentThread(), job.getRule()); + if (job != null) { + //if this job has a rule, then we are essentially acquiring a lock + if ((job.getRule() != null) && !(job instanceof ThreadJob)) { + //don't need to reaquire locks because it was not recorded in the graph + //that this thread waited to get this rule + manager.getLockManager().addLockThread(Thread.currentThread(), job.getRule()); + } + //see if we need to wake another worker + if (manager.sleepHint() <= 0) + jobQueued(null); } - //see if we need to wake another worker - if (manager.sleepHint() <= 0) - jobQueued(null); + } finally { + //decrement busy thread count if we're not running a job + if (job == null) + decrementBusyThreads(); } return job; }