Mercurial > projects > dwt-addons
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(","); |