comparison dwtx/core/internal/jobs/DeadlockDetector.d @ 167:862b05e0334a

Add a wrapper for Thread
author Frank Benoit <benoit@tionex.de>
date Tue, 09 Sep 2008 15:59:16 +0200
parents 9d0585bcb7aa
children
comparison
equal deleted inserted replaced
163:e5dd0081ccba 167:862b05e0334a
10 * Port to the D programming language: 10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de> 11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/ 12 *******************************************************************************/
13 module dwtx.core.internal.jobs.DeadlockDetector; 13 module dwtx.core.internal.jobs.DeadlockDetector;
14 14
15 import tango.core.Thread; 15 import dwtx.dwtxhelper.JThread;
16 import tango.io.Stdout; 16 import tango.io.Stdout;
17 import tango.text.convert.Format; 17 import tango.text.convert.Format;
18 18
19 import dwt.dwthelper.utils; 19 import dwt.dwthelper.utils;
20 import dwtx.dwtxhelper.Collection; 20 import dwtx.dwtxhelper.Collection;
99 /** 99 /**
100 * Recursively check if any of the threads that prevent the current thread from running 100 * Recursively check if any of the threads that prevent the current thread from running
101 * are actually deadlocked with the current thread. 101 * are actually deadlocked with the current thread.
102 * Add the threads that form deadlock to the deadlockedThreads list. 102 * Add the threads that form deadlock to the deadlockedThreads list.
103 */ 103 */
104 private bool addCycleThreads(ArrayList deadlockedThreads, Thread next) { 104 private bool addCycleThreads(ArrayList deadlockedThreads, JThread next) {
105 //get the thread that block the given thread from running 105 //get the thread that block the given thread from running
106 Thread[] blocking = blockingThreads(next); 106 JThread[] blocking = blockingThreads(next);
107 //if the thread is not blocked by other threads, then it is not part of a deadlock 107 //if the thread is not blocked by other threads, then it is not part of a deadlock
108 if (blocking.length is 0) 108 if (blocking.length is 0)
109 return false; 109 return false;
110 bool inCycle = false; 110 bool inCycle = false;
111 for (int i = 0; i < blocking.length; i++) { 111 for (int i = 0; i < blocking.length; i++) {
126 } 126 }
127 127
128 /** 128 /**
129 * Get the thread(s) that own the lock this thread is waiting for. 129 * Get the thread(s) that own the lock this thread is waiting for.
130 */ 130 */
131 private Thread[] blockingThreads(Thread current) { 131 private JThread[] blockingThreads(JThread current) {
132 //find the lock this thread is waiting for 132 //find the lock this thread is waiting for
133 ISchedulingRule lock = cast(ISchedulingRule) getWaitingLock(current); 133 ISchedulingRule lock = cast(ISchedulingRule) getWaitingLock(current);
134 return getThreadsOwningLock(lock); 134 return getThreadsOwningLock(lock);
135 } 135 }
136 136
165 165
166 /** 166 /**
167 * Returns true IFF the matrix contains a row for the given thread. 167 * Returns true IFF the matrix contains a row for the given thread.
168 * (meaning the given thread either owns locks or is waiting for locks) 168 * (meaning the given thread either owns locks or is waiting for locks)
169 */ 169 */
170 bool contains(Thread t) { 170 bool contains(JThread t) {
171 return lockThreads.contains(t); 171 return lockThreads.contains(t);
172 } 172 }
173 173
174 /** 174 /**
175 * A new rule was just added to the graph. 175 * A new rule was just added to the graph.
198 } 198 }
199 199
200 /** 200 /**
201 * Returns all the locks owned by the given thread 201 * Returns all the locks owned by the given thread
202 */ 202 */
203 private Object[] getOwnedLocks(Thread current) { 203 private Object[] getOwnedLocks(JThread current) {
204 ArrayList ownedLocks = new ArrayList(1); 204 ArrayList ownedLocks = new ArrayList(1);
205 int index = indexOf(current, false); 205 int index = indexOf(current, false);
206 206
207 for (int j = 0; j < graph[index].length; j++) { 207 for (int j = 0; j < graph[index].length; j++) {
208 if (graph[index][j] > NO_STATE) 208 if (graph[index][j] > NO_STATE)
214 } 214 }
215 215
216 /** 216 /**
217 * Returns an array of threads that form the deadlock (usually 2). 217 * Returns an array of threads that form the deadlock (usually 2).
218 */ 218 */
219 private Thread[] getThreadsInDeadlock(Thread cause) { 219 private JThread[] getThreadsInDeadlock(JThread cause) {
220 ArrayList deadlockedThreads = new ArrayList(2); 220 ArrayList deadlockedThreads = new ArrayList(2);
221 /** 221 /**
222 * if the thread that caused deadlock doesn't own any locks, then it is not part 222 * if the thread that caused deadlock doesn't own any locks, then it is not part
223 * of the deadlock (it just caused it because of a rule it tried to acquire) 223 * of the deadlock (it just caused it because of a rule it tried to acquire)
224 */ 224 */
225 if (ownsLocks(cause)) 225 if (ownsLocks(cause))
226 deadlockedThreads.add(cause); 226 deadlockedThreads.add(cause);
227 addCycleThreads(deadlockedThreads, cause); 227 addCycleThreads(deadlockedThreads, cause);
228 return arraycast!(Thread)( deadlockedThreads.toArray()); 228 return arraycast!(JThread)( deadlockedThreads.toArray());
229 } 229 }
230 230
231 /** 231 /**
232 * Returns the thread(s) that own the given lock. 232 * Returns the thread(s) that own the given lock.
233 */ 233 */
234 private Thread[] getThreadsOwningLock(ISchedulingRule rule) { 234 private JThread[] getThreadsOwningLock(ISchedulingRule rule) {
235 if (rule is null) 235 if (rule is null)
236 return new Thread[0]; 236 return new JThread[0];
237 int lockIndex = indexOf(rule, false); 237 int lockIndex = indexOf(rule, false);
238 ArrayList blocking = new ArrayList(1); 238 ArrayList blocking = new ArrayList(1);
239 for (int i = 0; i < graph.length; i++) { 239 for (int i = 0; i < graph.length; i++) {
240 if (graph[i][lockIndex] > NO_STATE) 240 if (graph[i][lockIndex] > NO_STATE)
241 blocking.add(lockThreads.get(i)); 241 blocking.add(lockThreads.get(i));
242 } 242 }
243 if ((blocking.size() is 0) && (JobManager.DEBUG_LOCKS)) 243 if ((blocking.size() is 0) && (JobManager.DEBUG_LOCKS))
244 Stdout.formatln(Format("Lock {} is involved in deadlock but is not owned by any thread.", rule )); //$NON-NLS-1$ //$NON-NLS-2$ 244 Stdout.formatln(Format("Lock {} is involved in deadlock but is not owned by any thread.", rule )); //$NON-NLS-1$ //$NON-NLS-2$
245 if ((blocking.size() > 1) && (cast(ILock)rule ) && (JobManager.DEBUG_LOCKS)) 245 if ((blocking.size() > 1) && (cast(ILock)rule ) && (JobManager.DEBUG_LOCKS))
246 Stdout.formatln(Format("Lock {} is owned by more than 1 thread, but it is not a rule.", rule )); //$NON-NLS-1$ //$NON-NLS-2$ 246 Stdout.formatln(Format("Lock {} is owned by more than 1 thread, but it is not a rule.", rule )); //$NON-NLS-1$ //$NON-NLS-2$
247 return arraycast!(Thread)( blocking.toArray()); 247 return arraycast!(JThread)( blocking.toArray());
248 } 248 }
249 249
250 /** 250 /**
251 * Returns the lock the given thread is waiting for. 251 * Returns the lock the given thread is waiting for.
252 */ 252 */
253 private Object getWaitingLock(Thread current) { 253 private Object getWaitingLock(JThread current) {
254 int index = indexOf(current, false); 254 int index = indexOf(current, false);
255 //find the lock that this thread is waiting for 255 //find the lock that this thread is waiting for
256 for (int j = 0; j < graph[index].length; j++) { 256 for (int j = 0; j < graph[index].length; j++) {
257 if (graph[index][j] is WAITING_FOR_LOCK) 257 if (graph[index][j] is WAITING_FOR_LOCK)
258 return locks.get(j); 258 return locks.get(j);
277 277
278 /** 278 /**
279 * Returns the index of the given thread in the thread array. If the thread 279 * Returns the index of the given thread in the thread array. If the thread
280 * is not present in the array, it is added to the end. 280 * is not present in the array, it is added to the end.
281 */ 281 */
282 private int indexOf(Thread owner, bool add) { 282 private int indexOf(JThread owner, bool add) {
283 int index = lockThreads.indexOf(owner); 283 int index = lockThreads.indexOf(owner);
284 if ((index < 0) && add) { 284 if ((index < 0) && add) {
285 lockThreads.add(owner); 285 lockThreads.add(owner);
286 resize = true; 286 resize = true;
287 index = lockThreads.size() - 1; 287 index = lockThreads.size() - 1;
297 } 297 }
298 298
299 /** 299 /**
300 * The given lock was acquired by the given thread. 300 * The given lock was acquired by the given thread.
301 */ 301 */
302 void lockAcquired(Thread owner, ISchedulingRule lock) { 302 void lockAcquired(JThread owner, ISchedulingRule lock) {
303 int lockIndex = indexOf(lock, true); 303 int lockIndex = indexOf(lock, true);
304 int threadIndex = indexOf(owner, true); 304 int threadIndex = indexOf(owner, true);
305 if (resize) 305 if (resize)
306 resizeGraph(); 306 resizeGraph();
307 if (graph[threadIndex][lockIndex] is WAITING_FOR_LOCK) 307 if (graph[threadIndex][lockIndex] is WAITING_FOR_LOCK)
331 } 331 }
332 332
333 /** 333 /**
334 * The given lock was released by the given thread. Update the graph. 334 * The given lock was released by the given thread. Update the graph.
335 */ 335 */
336 void lockReleased(Thread owner, ISchedulingRule lock) { 336 void lockReleased(JThread owner, ISchedulingRule lock) {
337 int lockIndex = indexOf(lock, false); 337 int lockIndex = indexOf(lock, false);
338 int threadIndex = indexOf(owner, false); 338 int threadIndex = indexOf(owner, false);
339 //make sure the lock and thread exist in the graph 339 //make sure the lock and thread exist in the graph
340 if (threadIndex < 0) { 340 if (threadIndex < 0) {
341 if (JobManager.DEBUG_LOCKS) 341 if (JobManager.DEBUG_LOCKS)
342 Stdout.formatln("[lockReleased] Lock {} was already released by thread {}", lock, owner.name()); //$NON-NLS-1$ //$NON-NLS-2$ 342 Stdout.formatln("[lockReleased] Lock {} was already released by thread {}", lock, owner.getName()); //$NON-NLS-1$ //$NON-NLS-2$
343 return; 343 return;
344 } 344 }
345 if (lockIndex < 0) { 345 if (lockIndex < 0) {
346 if (JobManager.DEBUG_LOCKS) 346 if (JobManager.DEBUG_LOCKS)
347 Stdout.formatln("[lockReleased] Thread {} already released lock {}", owner.name(), lock); //$NON-NLS-1$ //$NON-NLS-2$ 347 Stdout.formatln("[lockReleased] Thread {} already released lock {}", owner.getName(), lock); //$NON-NLS-1$ //$NON-NLS-2$
348 return; 348 return;
349 } 349 }
350 //if this lock was suspended, set it to NO_STATE 350 //if this lock was suspended, set it to NO_STATE
351 if ((cast(ILock)lock ) && (graph[threadIndex][lockIndex] is WAITING_FOR_LOCK)) { 351 if ((cast(ILock)lock ) && (graph[threadIndex][lockIndex] is WAITING_FOR_LOCK)) {
352 graph[threadIndex][lockIndex] = NO_STATE; 352 graph[threadIndex][lockIndex] = NO_STATE;
356 //or release all rules that are owned by the given thread, if we are releasing a rule 356 //or release all rules that are owned by the given thread, if we are releasing a rule
357 for (int j = 0; j < graph[threadIndex].length; j++) { 357 for (int j = 0; j < graph[threadIndex].length; j++) {
358 if ((lock.isConflicting(cast(ISchedulingRule) locks.get(j))) || (!(cast(ILock)lock ) && !(cast(ILock)locks.get(j)) && (graph[threadIndex][j] > NO_STATE))) { 358 if ((lock.isConflicting(cast(ISchedulingRule) locks.get(j))) || (!(cast(ILock)lock ) && !(cast(ILock)locks.get(j)) && (graph[threadIndex][j] > NO_STATE))) {
359 if (graph[threadIndex][j] is NO_STATE) { 359 if (graph[threadIndex][j] is NO_STATE) {
360 if (JobManager.DEBUG_LOCKS) 360 if (JobManager.DEBUG_LOCKS)
361 Stdout.formatln("[lockReleased] More releases than acquires for thread {} and lock {}", owner.name(), lock); //$NON-NLS-1$ //$NON-NLS-2$ 361 Stdout.formatln("[lockReleased] More releases than acquires for thread {} and lock {}", owner.getName(), lock); //$NON-NLS-1$ //$NON-NLS-2$
362 } else { 362 } else {
363 graph[threadIndex][j]--; 363 graph[threadIndex][j]--;
364 } 364 }
365 } 365 }
366 } 366 }
371 371
372 /** 372 /**
373 * The given scheduling rule is no longer used because the job that invoked it is done. 373 * The given scheduling rule is no longer used because the job that invoked it is done.
374 * Release this rule regardless of how many times it was acquired. 374 * Release this rule regardless of how many times it was acquired.
375 */ 375 */
376 void lockReleasedCompletely(Thread owner, ISchedulingRule rule) { 376 void lockReleasedCompletely(JThread owner, ISchedulingRule rule) {
377 int ruleIndex = indexOf(rule, false); 377 int ruleIndex = indexOf(rule, false);
378 int threadIndex = indexOf(owner, false); 378 int threadIndex = indexOf(owner, false);
379 //need to make sure that the given thread and rule were not already removed from the graph 379 //need to make sure that the given thread and rule were not already removed from the graph
380 if (threadIndex < 0) { 380 if (threadIndex < 0) {
381 if (JobManager.DEBUG_LOCKS) 381 if (JobManager.DEBUG_LOCKS)
382 Stdout.formatln("[lockReleasedCompletely] Lock {} was already released by thread {}", rule, owner.name()); //$NON-NLS-1$ //$NON-NLS-2$ 382 Stdout.formatln("[lockReleasedCompletely] Lock {} was already released by thread {}", rule, owner.getName()); //$NON-NLS-1$ //$NON-NLS-2$
383 return; 383 return;
384 } 384 }
385 if (ruleIndex < 0) { 385 if (ruleIndex < 0) {
386 if (JobManager.DEBUG_LOCKS) 386 if (JobManager.DEBUG_LOCKS)
387 Stdout.formatln("[lockReleasedCompletely] Thread {} already released lock {}", owner.name(), rule); //$NON-NLS-1$ //$NON-NLS-2$ 387 Stdout.formatln("[lockReleasedCompletely] Thread {} already released lock {}", owner.getName(), rule); //$NON-NLS-1$ //$NON-NLS-2$
388 return; 388 return;
389 } 389 }
390 /** 390 /**
391 * set all rules that are owned by the given thread to NO_STATE 391 * set all rules that are owned by the given thread to NO_STATE
392 * (not just rules that conflict with the rule we are releasing) 392 * (not just rules that conflict with the rule we are releasing)
401 401
402 /** 402 /**
403 * The given thread could not get the given lock and is waiting for it. 403 * The given thread could not get the given lock and is waiting for it.
404 * Update the graph. 404 * Update the graph.
405 */ 405 */
406 Deadlock lockWaitStart(Thread client, ISchedulingRule lock) { 406 Deadlock lockWaitStart(JThread client, ISchedulingRule lock) {
407 setToWait(client, lock, false); 407 setToWait(client, lock, false);
408 int lockIndex = indexOf(lock, false); 408 int lockIndex = indexOf(lock, false);
409 int[] temp = new int[lockThreads.size()]; 409 int[] temp = new int[lockThreads.size()];
410 //check if the addition of the waiting thread caused deadlock 410 //check if the addition of the waiting thread caused deadlock
411 if (!checkWaitCycles(temp, lockIndex)) 411 if (!checkWaitCycles(temp, lockIndex))
412 return null; 412 return null;
413 //there is a deadlock in the graph 413 //there is a deadlock in the graph
414 Thread[] threads = getThreadsInDeadlock(client); 414 JThread[] threads = getThreadsInDeadlock(client);
415 Thread candidate = resolutionCandidate(threads); 415 JThread candidate = resolutionCandidate(threads);
416 ISchedulingRule[] locksToSuspend = realLocksForThread(candidate); 416 ISchedulingRule[] locksToSuspend = realLocksForThread(candidate);
417 Deadlock deadlock = new Deadlock(threads, locksToSuspend, candidate); 417 Deadlock deadlock = new Deadlock(threads, locksToSuspend, candidate);
418 //find a thread whose locks can be suspended to resolve the deadlock 418 //find a thread whose locks can be suspended to resolve the deadlock
419 if (JobManager.DEBUG_LOCKS) 419 if (JobManager.DEBUG_LOCKS)
420 reportDeadlock(deadlock); 420 reportDeadlock(deadlock);
421 if (JobManager.DEBUG_DEADLOCK) 421 if (JobManager.DEBUG_DEADLOCK)
422 throw new IllegalStateException(Format("Deadlock detected. Caused by thread {}.", client.name())); //$NON-NLS-1$ 422 throw new IllegalStateException(Format("Deadlock detected. Caused by thread {}.", client.getName())); //$NON-NLS-1$
423 // Update the graph to indicate that the locks will now be suspended. 423 // Update the graph to indicate that the locks will now be suspended.
424 // To indicate that the lock will be suspended, we set the thread to wait for the lock. 424 // To indicate that the lock will be suspended, we set the thread to wait for the lock.
425 // When the lock is forced to be released, the entry will be cleared. 425 // When the lock is forced to be released, the entry will be cleared.
426 for (int i = 0; i < locksToSuspend.length; i++) 426 for (int i = 0; i < locksToSuspend.length; i++)
427 setToWait(deadlock.getCandidate(), locksToSuspend[i], true); 427 setToWait(deadlock.getCandidate(), locksToSuspend[i], true);
430 430
431 /** 431 /**
432 * The given thread has stopped waiting for the given lock. 432 * The given thread has stopped waiting for the given lock.
433 * Update the graph. 433 * Update the graph.
434 */ 434 */
435 void lockWaitStop(Thread owner, ISchedulingRule lock) { 435 void lockWaitStop(JThread owner, ISchedulingRule lock) {
436 int lockIndex = indexOf(lock, false); 436 int lockIndex = indexOf(lock, false);
437 int threadIndex = indexOf(owner, false); 437 int threadIndex = indexOf(owner, false);
438 //make sure the thread and lock exist in the graph 438 //make sure the thread and lock exist in the graph
439 if (threadIndex < 0) { 439 if (threadIndex < 0) {
440 if (JobManager.DEBUG_LOCKS) 440 if (JobManager.DEBUG_LOCKS)
441 Stdout.formatln("Thread {} was already removed.", owner.name() ); //$NON-NLS-1$ //$NON-NLS-2$ 441 Stdout.formatln("Thread {} was already removed.", owner.getName() ); //$NON-NLS-1$ //$NON-NLS-2$
442 return; 442 return;
443 } 443 }
444 if (lockIndex < 0) { 444 if (lockIndex < 0) {
445 if (JobManager.DEBUG_LOCKS) 445 if (JobManager.DEBUG_LOCKS)
446 Stdout.formatln("Lock {} was already removed.", lock ); //$NON-NLS-1$ //$NON-NLS-2$ 446 Stdout.formatln("Lock {} was already removed.", lock ); //$NON-NLS-1$ //$NON-NLS-2$
447 return; 447 return;
448 } 448 }
449 if (graph[threadIndex][lockIndex] !is WAITING_FOR_LOCK) 449 if (graph[threadIndex][lockIndex] !is WAITING_FOR_LOCK)
450 Assert.isTrue(false, Format("Thread {} was not waiting for lock {} so it could not time out.", owner.name(), (cast(Object)lock).toString())); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 450 Assert.isTrue(false, Format("Thread {} was not waiting for lock {} so it could not time out.", owner.getName(), (cast(Object)lock).toString())); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
451 graph[threadIndex][lockIndex] = NO_STATE; 451 graph[threadIndex][lockIndex] = NO_STATE;
452 reduceGraph(threadIndex, lock); 452 reduceGraph(threadIndex, lock);
453 } 453 }
454 454
455 /** 455 /**
456 * Returns true IFF the given thread owns a single lock 456 * Returns true IFF the given thread owns a single lock
457 */ 457 */
458 private bool ownsLocks(Thread cause) { 458 private bool ownsLocks(JThread cause) {
459 int threadIndex = indexOf(cause, false); 459 int threadIndex = indexOf(cause, false);
460 for (int j = 0; j < graph[threadIndex].length; j++) { 460 for (int j = 0; j < graph[threadIndex].length; j++) {
461 if (graph[threadIndex][j] > NO_STATE) 461 if (graph[threadIndex][j] > NO_STATE)
462 return true; 462 return true;
463 } 463 }
466 466
467 /** 467 /**
468 * Returns true IFF the given thread owns a single real lock. 468 * Returns true IFF the given thread owns a single real lock.
469 * A real lock is a lock that can be suspended. 469 * A real lock is a lock that can be suspended.
470 */ 470 */
471 private bool ownsRealLocks(Thread owner) { 471 private bool ownsRealLocks(JThread owner) {
472 int threadIndex = indexOf(owner, false); 472 int threadIndex = indexOf(owner, false);
473 for (int j = 0; j < graph[threadIndex].length; j++) { 473 for (int j = 0; j < graph[threadIndex].length; j++) {
474 if (graph[threadIndex][j] > NO_STATE) { 474 if (graph[threadIndex][j] > NO_STATE) {
475 Object lock = locks.get(j); 475 Object lock = locks.get(j);
476 if (cast(ILock)lock ) 476 if (cast(ILock)lock )
482 482
483 /** 483 /**
484 * Return true IFF this thread owns rule locks (i.e. implicit locks which 484 * Return true IFF this thread owns rule locks (i.e. implicit locks which
485 * cannot be suspended) 485 * cannot be suspended)
486 */ 486 */
487 private bool ownsRuleLocks(Thread owner) { 487 private bool ownsRuleLocks(JThread owner) {
488 int threadIndex = indexOf(owner, false); 488 int threadIndex = indexOf(owner, false);
489 for (int j = 0; j < graph[threadIndex].length; j++) { 489 for (int j = 0; j < graph[threadIndex].length; j++) {
490 if (graph[threadIndex][j] > NO_STATE) { 490 if (graph[threadIndex][j] > NO_STATE) {
491 Object lock = locks.get(j); 491 Object lock = locks.get(j);
492 if (!(cast(ILock)lock )) 492 if (!(cast(ILock)lock ))
498 498
499 /** 499 /**
500 * Returns an array of real locks that are owned by the given thread. 500 * Returns an array of real locks that are owned by the given thread.
501 * Real locks are locks that implement the ILock interface and can be suspended. 501 * Real locks are locks that implement the ILock interface and can be suspended.
502 */ 502 */
503 private ISchedulingRule[] realLocksForThread(Thread owner) { 503 private ISchedulingRule[] realLocksForThread(JThread owner) {
504 int threadIndex = indexOf(owner, false); 504 int threadIndex = indexOf(owner, false);
505 ArrayList ownedLocks = new ArrayList(1); 505 ArrayList ownedLocks = new ArrayList(1);
506 for (int j = 0; j < graph[threadIndex].length; j++) { 506 for (int j = 0; j < graph[threadIndex].length; j++) {
507 if ((graph[threadIndex][j] > NO_STATE) && (cast(ILock)locks.get(j) )) 507 if ((graph[threadIndex][j] > NO_STATE) && (cast(ILock)locks.get(j) ))
508 ownedLocks.add(locks.get(j)); 508 ownedLocks.add(locks.get(j));
605 605
606 /** 606 /**
607 * Adds a 'deadlock detected' message to the log with a stack trace. 607 * Adds a 'deadlock detected' message to the log with a stack trace.
608 */ 608 */
609 private void reportDeadlock(Deadlock deadlock) { 609 private void reportDeadlock(Deadlock deadlock) {
610 String msg = "Deadlock detected. All locks owned by thread " ~ deadlock.getCandidate().name() ~ " will be suspended."; //$NON-NLS-1$ //$NON-NLS-2$ 610 String msg = "Deadlock detected. All locks owned by thread " ~ deadlock.getCandidate().getName() ~ " will be suspended."; //$NON-NLS-1$ //$NON-NLS-2$
611 MultiStatus main = new MultiStatus(JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, new IllegalStateException()); 611 MultiStatus main = new MultiStatus(JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, new IllegalStateException());
612 Thread[] threads = deadlock.getThreads(); 612 JThread[] threads = deadlock.getThreads();
613 for (int i = 0; i < threads.length; i++) { 613 for (int i = 0; i < threads.length; i++) {
614 Object[] ownedLocks = getOwnedLocks(threads[i]); 614 Object[] ownedLocks = getOwnedLocks(threads[i]);
615 Object waitLock = getWaitingLock(threads[i]); 615 Object waitLock = getWaitingLock(threads[i]);
616 StringBuffer buf = new StringBuffer("Thread "); //$NON-NLS-1$ 616 StringBuffer buf = new StringBuffer("Thread "); //$NON-NLS-1$
617 buf.append(threads[i].name()); 617 buf.append(threads[i].getName());
618 buf.append(" has locks: "); //$NON-NLS-1$ 618 buf.append(" has locks: "); //$NON-NLS-1$
619 for (int j = 0; j < ownedLocks.length; j++) { 619 for (int j = 0; j < ownedLocks.length; j++) {
620 buf.append(Format("{}",ownedLocks[j])); 620 buf.append(Format("{}",ownedLocks[j]));
621 buf.append((j < ownedLocks.length - 1) ? ", " : " "); //$NON-NLS-1$ //$NON-NLS-2$ 621 buf.append((j < ownedLocks.length - 1) ? ", " : " "); //$NON-NLS-1$ //$NON-NLS-2$
622 } 622 }
652 652
653 /** 653 /**
654 * Get the thread whose locks can be suspended. (i.e. all locks it owns are 654 * Get the thread whose locks can be suspended. (i.e. all locks it owns are
655 * actual locks and not rules). Return the first thread in the array by default. 655 * actual locks and not rules). Return the first thread in the array by default.
656 */ 656 */
657 private Thread resolutionCandidate(Thread[] candidates) { 657 private JThread resolutionCandidate(JThread[] candidates) {
658 //first look for a candidate that has no scheduling rules 658 //first look for a candidate that has no scheduling rules
659 for (int i = 0; i < candidates.length; i++) { 659 for (int i = 0; i < candidates.length; i++) {
660 if (!ownsRuleLocks(candidates[i])) 660 if (!ownsRuleLocks(candidates[i]))
661 return candidates[i]; 661 return candidates[i];
662 } 662 }
670 } 670 }
671 671
672 /** 672 /**
673 * The given thread is waiting for the given lock. Update the graph. 673 * The given thread is waiting for the given lock. Update the graph.
674 */ 674 */
675 private void setToWait(Thread owner, ISchedulingRule lock, bool suspend) { 675 private void setToWait(JThread owner, ISchedulingRule lock, bool suspend) {
676 bool needTransfer = false; 676 bool needTransfer = false;
677 /** 677 /**
678 * if we are adding an entry where a thread is waiting on a scheduling rule, 678 * if we are adding an entry where a thread is waiting on a scheduling rule,
679 * then we need to transfer all positive entries for a conflicting rule to the 679 * then we need to transfer all positive entries for a conflicting rule to the
680 * newly added rule in order to synchronize the graph. 680 * newly added rule in order to synchronize the graph.
704 sb.append(","); 704 sb.append(",");
705 } 705 }
706 sb.append("\n"); 706 sb.append("\n");
707 for (int i = 0; i < graph.length; i++) { 707 for (int i = 0; i < graph.length; i++) {
708 sb.append(" "); 708 sb.append(" ");
709 sb.append( (cast(Thread) lockThreads.get(i)).name() ); 709 sb.append( (cast(JThread) lockThreads.get(i)).getName() );
710 sb.append(" : "); 710 sb.append(" : ");
711 for (int j = 0; j < graph[i].length; j++) { 711 for (int j = 0; j < graph[i].length; j++) {
712 sb.append(" "); 712 sb.append(" ");
713 sb.append(Integer.toString(graph[i][j])); //$NON-NLS-1$ 713 sb.append(Integer.toString(graph[i][j])); //$NON-NLS-1$
714 sb.append(","); 714 sb.append(",");