1 /*
2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package nsk.share.jpda;
24 
25 import nsk.share.TestBug;
26 import nsk.share.locks.MonitorLockingThread;
27 
28 /*
29  *  StateTestThread sequentially switches its state in following order:
30  *  - thread not started
31  *  - thread is running
32  *  - thread is sleeping
33  *  - thread in Object.wait()
34  *  - thread wait on java monitor
35  *  - thread is finished
36  *
37  *  To use this class create new instance of StateTestThread and sequentially call method nextState().
38  */
39 public class StateTestThread extends Thread {
40     // thread states available through ThreadReference.state()
41     public static String stateTestThreadStates[] = { "UNKNOWN", "RUNNING", "SLEEPING", "WAIT", "MONITOR", "ZOMBIE" };
42 
43     private Object waitOnObject = new Object();
44 
StateTestThread(String name)45     public StateTestThread(String name) {
46         super(name);
47     }
48 
49     private volatile boolean isRunning;
50 
51     private volatile boolean waitState;
52 
getCurrentState()53     public int getCurrentState() {
54         return currentState;
55     }
56 
57     private MonitorLockingThread auxiliaryThread = new MonitorLockingThread(this);
58 
59     private boolean isExecutedWithErrors;
60 
61     private volatile boolean readyToBeBlocked;
62 
63     private String errorMessage;
64 
run()65     public void run() {
66         isRunning = true;
67 
68         // running state
69         while (isRunning)
70             ;
71 
72         try {
73             // sleeping state
74             sleep(Long.MAX_VALUE);
75         } catch (InterruptedException e) {
76             // expected exception
77         }
78 
79         synchronized (waitOnObject) {
80             try {
81                 // wait state
82                 while (waitState)
83                     waitOnObject.wait();
84             } catch (InterruptedException e) {
85                 isExecutedWithErrors = true;
86                 errorMessage = "StateTestThread was unexpected interrupted during waiting";
87             }
88         }
89 
90         // start auxiliary thread which should acquire 'this' lock
91         auxiliaryThread.acquireLock();
92 
93         readyToBeBlocked = true;
94 
95         // try acquire the same lock as auxiliaryThread, switch state to 'wait on monitor'
96         synchronized (this) {
97 
98         }
99     }
100 
101     private int currentState = 1;
102 
nextState()103     public void nextState() {
104         // check is thread states change as expected
105         if (isExecutedWithErrors)
106             throw new TestBug(errorMessage);
107 
108         switch (currentState++) {
109         case 1:
110             // start thread
111             start();
112 
113             while (!isRunning)
114                 yield();
115 
116             break;
117         case 2:
118             // stop running
119             isRunning = false;
120 
121             while (this.getState() != Thread.State.TIMED_WAITING)
122                 yield();
123 
124             break;
125         case 3:
126             waitState = true;
127 
128             // stop sleeping
129             interrupt();
130 
131             while (getState() != Thread.State.WAITING)
132                 yield();
133 
134             break;
135         case 4:
136             waitState = false;
137 
138             // stop wait
139             synchronized (waitOnObject) {
140                 waitOnObject.notify();
141             }
142 
143             while (!readyToBeBlocked || (getState() != Thread.State.BLOCKED))
144                 yield();
145 
146             break;
147         case 5:
148             // let StateTestThread thread acquire lock
149             auxiliaryThread.releaseLock();
150             try {
151                 join();
152             } catch (InterruptedException e) {
153                 throw new TestBug("Unexpected exception: " + e);
154             }
155             break;
156 
157         default:
158             throw new TestBug("Invalid thread state");
159         }
160     }
161 }
162