001: //
002: // Copyright (C) 2005 United States Government as represented by the
003: // Administrator of the National Aeronautics and Space Administration
004: // (NASA). All Rights Reserved.
005: //
006: // This software is distributed under the NASA Open Source Agreement
007: // (NOSA), version 1.3. The NOSA has been approved by the Open Source
008: // Initiative. See the file NOSA-1.3-JPF at the top of the distribution
009: // directory tree for the complete NOSA document.
010: //
011: // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
012: // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
013: // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
014: // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
015: // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
016: // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
017: // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
018: //
019: package gov.nasa.jpf.mc;
020:
021: abstract class SyncRunnable implements Runnable {
022: SyncRunnable other;
023:
024: public void setOther(SyncRunnable other) {
025: this .other = other;
026: }
027:
028: public abstract void doSomething();
029:
030: public abstract void doSomethingElse();
031:
032: public abstract void run();
033: }
034:
035: /**
036: * deadlock detection test
037: */
038: public class TestVMDeadlock {
039: public static void main(String[] args) {
040: TestVMDeadlock t = new TestVMDeadlock();
041:
042: if (args.length > 0) {
043: // just run the specified tests
044: for (int i = 0; i < args.length; i++) {
045: String func = args[i];
046:
047: // note that we don't use reflection here because this would
048: // blow up execution/test scope under JPF
049: if ("testSyncMthDeadlock".equals(func)) {
050: t.testSyncMthDeadlock();
051: } else if ("testSyncBlockDeadlock".equals(func)) {
052: t.testSyncBlockDeadlock();
053: } else if ("testMixedDeadlock".equals(func)) {
054: t.testMixedDeadlock();
055: } else if ("testMissedSignalDeadlock".equals(func)) {
056: t.testMissedSignalDeadlock();
057: } else {
058: throw new IllegalArgumentException(
059: "unknown test function");
060: }
061: }
062: } else {
063: // quite useless to call the others, it locks up
064: t.testSyncMthDeadlock();
065: }
066: }
067:
068: /**
069: * Testing for deadlocks resulting from missed signal. This is the original
070: * oldclassic example which has been turned into a test case.
071: */
072: public void testMissedSignalDeadlock() {
073: Event new_event1 = new Event();
074: Event new_event2 = new Event();
075:
076: FirstTask task1 = new FirstTask(new_event1, new_event2);
077: SecondTask task2 = new SecondTask(new_event1, new_event2);
078:
079: task1.start();
080: task2.start();
081: }
082:
083: /**
084: * the test which mixes synchronized method attr with MONITORENTER/EXIT
085: */
086: public void testMixedDeadlock() {
087: SyncRunnable r1 = new SyncMthRunnable();
088: SyncRunnable r2 = new SyncBlockRunnable();
089: r1.setOther(r2);
090: r2.setOther(r1);
091:
092: Thread t1 = new Thread(r1);
093: Thread t2 = new Thread(r2);
094:
095: t1.start();
096: t2.start();
097: }
098:
099: /**
100: * the test which checks MONITORENTER / MONITOREXIT
101: */
102: public void testSyncBlockDeadlock() {
103: SyncRunnable r1 = new SyncBlockRunnable();
104: SyncRunnable r2 = new SyncBlockRunnable();
105: r1.setOther(r2);
106: r2.setOther(r1);
107:
108: Thread t1 = new Thread(r1);
109: Thread t2 = new Thread(r2);
110:
111: t1.start();
112: t2.start();
113: }
114:
115: /**
116: * the test which checks the synchronized method attribute
117: */
118: public void testSyncMthDeadlock() {
119: SyncRunnable r1 = new SyncMthRunnable();
120: SyncRunnable r2 = new SyncMthRunnable();
121: r1.setOther(r2);
122: r2.setOther(r1);
123:
124: Thread t1 = new Thread(r1);
125: Thread t2 = new Thread(r2);
126:
127: t1.start();
128: t2.start();
129: }
130:
131: /**
132: * Required by the testMissedSignalDeadlock().
133: */
134: class Event {
135: int count = 0;
136:
137: public synchronized void signal_event() {
138: count = (count + 1) % 3;
139: notifyAll();
140: }
141:
142: public synchronized void wait_for_event() {
143: try {
144: wait();
145: } catch (InterruptedException e) {
146: }
147: }
148: }
149:
150: /**
151: * Required by the testMissedSignalDeadlock().
152: */
153: class FirstTask extends java.lang.Thread {
154: Event event1;
155: Event event2;
156: int count = 0;
157:
158: public FirstTask(Event e1, Event e2) {
159: event1 = e1;
160: event2 = e2;
161: }
162:
163: public void run() {
164: count = event1.count;
165:
166: while (true) {
167: if (count == event1.count) {
168: event1.wait_for_event();
169: }
170:
171: count = event1.count;
172: event2.signal_event();
173: }
174: }
175: }
176:
177: /**
178: * Required by the testMissedSignalDeadlock().
179: */
180: class SecondTask extends java.lang.Thread {
181: Event event1;
182: Event event2;
183: int count = 0;
184:
185: public SecondTask(Event e1, Event e2) {
186: event1 = e1;
187: event2 = e2;
188: }
189:
190: public void run() {
191: count = event2.count;
192:
193: while (true) {
194: event1.signal_event();
195:
196: if (count == event2.count) {
197: event2.wait_for_event();
198: }
199:
200: count = event2.count;
201: }
202: }
203: }
204:
205: /**
206: * DOCUMENT ME!
207: */
208: class SyncBlockRunnable extends SyncRunnable {
209: public void doSomething() {
210: synchronized (this ) {
211: other.doSomethingElse();
212: }
213: }
214:
215: public void doSomethingElse() {
216: synchronized (this ) {
217: }
218: }
219:
220: public void run() {
221: while (true) {
222: synchronized (this ) {
223: other.doSomething();
224: }
225: }
226: }
227: }
228:
229: /**
230: * DOCUMENT ME!
231: */
232: class SyncMthRunnable extends SyncRunnable {
233: public synchronized void doSomething() {
234: other.doSomethingElse();
235: }
236:
237: public synchronized void doSomethingElse() {
238: }
239:
240: public synchronized void run() {
241: while (true) {
242: other.doSomething();
243: }
244: }
245: }
246: }
|