comparison src/classes/java/lang/Thread.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
1 /*
2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
4 * All rights reserved.
5 *
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package java.lang;
19
20 import gov.nasa.jpf.annotation.NeverBreak;
21 import sun.nio.ch.Interruptible;
22
23 /**
24 * MJI model class for java.lang.Thread library abstraction
25 *
26 * <2do> this should not require the JPF ThreadList to retrieve corresponding ThreadInfos
27 * (the ThreadList might not store terminated threads)
28 */
29 public class Thread implements Runnable {
30
31 public interface UncaughtExceptionHandler {
32 // note this doesn't stop the thread from being terminated
33 void uncaughtException (Thread t, Throwable x);
34 }
35
36 static int nameThreadNum; // to construct the default thread name
37
38 public static final int MIN_PRIORITY = 1;
39 public static final int NORM_PRIORITY = 5;
40 public static final int MAX_PRIORITY = 10;
41
42 // don't rename this - it's used by ThreadGoup.uncaughtException()
43 private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler; // null by default
44
45 // initialized in init(), except of the main thread (which gets explicitly initialized by the VM)
46 ThreadGroup group;
47 Runnable target;
48 String name;
49 int priority;
50 boolean isDaemon;
51
52 // this is an explicit thread state that gets set on a call of interrupt(), but
53 // only if the thread is not blocked. If it is, we only change the status.
54 // this gets cleared by calling interrupted()
55 boolean interrupted;
56
57 // those are only accessed from peers since thread obects are per se shared
58 @NeverBreak
59 ThreadLocal.Entry<?>[] threadLocals;
60
61 // this is what we use for sun.misc.Unsafe.park()/unpark()
62 // this is accessed from the native peer, VM.createMainThread() and sun.misc.Unsafe
63 static class Permit {
64 boolean blockPark = true; // this is used to remember unpark() calls before park() (they don't accumulate)
65 }
66 Permit permit; // the object is used for wait/notify
67
68 // referenced by java.util.concurrent.locks.LockSupport via sun.misc.Unsafe
69 // DON'T CHANGE THIS NAME
70 volatile Object parkBlocker;
71
72 // used to store Thread.stop() exceptions
73 Throwable stopException;
74
75 private volatile UncaughtExceptionHandler uncaughtExceptionHandler; // null by default
76
77
78 public enum State { BLOCKED, NEW, RUNNABLE, TERMINATED, TIMED_WAITING, WAITING }
79
80
81 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler xh) {
82 defaultUncaughtExceptionHandler = xh;
83 }
84
85 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
86 return defaultUncaughtExceptionHandler;
87 }
88
89
90 public Thread () {
91 this(null, null, null, 0L);
92 }
93
94 public Thread (Runnable target) {
95 this(null, target, null, 0L);
96 }
97
98 public Thread (Runnable target, String name) {
99 this(null, target, name, 0L);
100 }
101
102 public Thread (String name) {
103 this(null, null, name, 0L);
104 }
105
106 public Thread (ThreadGroup group, String name) {
107 this(group, null, name, 0L);
108 }
109
110 public Thread (ThreadGroup group, Runnable target) {
111 this(group, target, null, 0L);
112 }
113
114 public Thread (ThreadGroup group, Runnable target, String name) {
115 this(group, target, name, 0L);
116 }
117
118 public Thread (ThreadGroup group, Runnable target, String name, long stackSize) {
119 Thread cur = currentThread();
120
121 if (group == null) {
122 this.group = cur.getThreadGroup();
123 } else {
124 this.group = group;
125 }
126
127 this.group.add(this);
128
129 if (name == null) {
130 this.name = "Thread-" + ++nameThreadNum;
131 } else {
132 this.name = name;
133 }
134
135 this.permit = new Permit();
136
137 // those are always inherited from the current thread
138 this.priority = cur.getPriority();
139 this.isDaemon = cur.isDaemon();
140
141 this.target = target;
142
143 // do our associated native init
144 init0(this.group, target, this.name, stackSize);
145
146 initThreadLocals(cur);
147 }
148
149 // this takes care of ThreadInfo initialization
150 native void init0 (ThreadGroup group, Runnable target, String name, long stackSize);
151
152 // this is here since InheritableThreadLocals would require childValue(parentVal) roundtrips.
153 // Unfortunately we can't defer this until the ThreadLocal is actually accessed since
154 // we have to capture the value at the point of child creation
155 // Note this executes in the parent thread
156 private void initThreadLocals (Thread parent){
157 ThreadLocal.Entry<?>[] tl = parent.threadLocals;
158 if (tl != null){
159 int len = tl.length;
160 ThreadLocal.Entry<?>[] inherited = null;
161 int j=0;
162
163 for (int i=0; i<len; i++){
164 ThreadLocal.Entry<?> e = tl[i];
165 ThreadLocal.Entry<?> ec = e.getChildEntry();
166 if (ec != null){
167 if (inherited == null){
168 inherited = new ThreadLocal.Entry<?>[len];
169 }
170 inherited[j++] = ec;
171 }
172 }
173
174 if (inherited != null){
175 ThreadLocal.Entry<?>[] a = new ThreadLocal.Entry<?>[j];
176 System.arraycopy(inherited,0,a,0,j);
177 threadLocals = a;
178 }
179 }
180 }
181
182 public static int activeCount () {
183 return 0;
184 }
185
186 public void setUncaughtExceptionHandler(UncaughtExceptionHandler xh) {
187 uncaughtExceptionHandler = xh;
188 }
189
190 public UncaughtExceptionHandler getUncaughtExceptionHandler(){
191 if (uncaughtExceptionHandler != null){
192 return uncaughtExceptionHandler;
193 } else {
194 return group;
195 }
196 }
197
198 public void setContextClassLoader (ClassLoader cl) {
199 }
200
201 public ClassLoader getContextClassLoader () {
202 // <NSY>
203 return null;
204 }
205
206 public synchronized void setDaemon (boolean isDaemon) {
207 this.isDaemon = isDaemon;
208 setDaemon0(isDaemon);
209 }
210
211 public boolean isDaemon () {
212 return isDaemon;
213 }
214
215 public native long getId();
216
217 public StackTraceElement[] getStackTrace() {
218 return null; // not yet implemented
219 }
220
221 public native int getState0();
222
223 public Thread.State getState() {
224 int i = getState0();
225 switch (i) {
226 case 0: return State.BLOCKED;
227 case 1: return State.NEW;
228 case 2: return State.RUNNABLE;
229 case 3: return State.TERMINATED;
230 case 4: return State.TIMED_WAITING;
231 case 5: return State.WAITING;
232 }
233
234 return null; // shoudl be intercepted by a getState0 assertion
235 }
236
237 public synchronized void setName (String name) {
238 if (name == null) {
239 throw new IllegalArgumentException("thread name can't be null");
240 }
241
242 this.name = name;
243 setName0(name);
244 }
245
246 public String getName () {
247 return name;
248 }
249
250 public void setPriority (int priority) {
251 if ((priority < MIN_PRIORITY) || (priority > MAX_PRIORITY)) {
252 throw new IllegalArgumentException("thread priority out of range");
253 }
254
255 this.priority = priority;
256 setPriority0(priority);
257 }
258
259 public int getPriority () {
260 return priority;
261 }
262
263 public ThreadGroup getThreadGroup () {
264 return group;
265 }
266
267 public void checkAccess () {
268 // <NSY>
269 }
270
271 public native int countStackFrames ();
272
273 public static native Thread currentThread ();
274
275 public void destroy () {
276 }
277
278 public static void dumpStack () {
279 }
280
281 public static int enumerate (Thread[] tarray) {
282 Thread cur = currentThread();
283
284 return cur.group.enumerate(tarray);
285 }
286
287 public static native boolean holdsLock (Object obj);
288
289 // this one needs to be native because it might change the thread status
290 public native void interrupt ();
291
292 // those don't have to be native, but we keep it symmetric
293 public static native boolean interrupted ();
294 public native boolean isInterrupted ();
295
296 public native boolean isAlive ();
297
298
299 /**
300 * note these are not synchronized anymore since they are intercepted by the
301 * native peer. The reason is that we don't want two CGs per join call (one for the
302 * sync call, and one for the wait) because this can cause serious
303 * performance degradation
304 */
305 public void join () throws InterruptedException {
306 synchronized(this){
307
308 if (interrupted()) {
309 throw new InterruptedException();
310 }
311
312 while (isAlive()) {
313 // apparently, the JDK doesn't throw InterruptedExceptions if
314 // we get interrupted after waiting in the join
315 wait();
316 }
317 }
318 }
319
320 public void join (long millis) throws InterruptedException {
321 join(millis, 0);
322 }
323
324 public void join (long millis, int nanos) throws InterruptedException {
325
326 if (millis < 0){
327 throw new java.lang.IllegalArgumentException("timeout value is negative");
328
329 } else if (millis == 0){
330 join();
331
332 } else {
333 synchronized(this){
334 if (interrupted()){
335 throw new InterruptedException();
336 }
337
338 wait(millis);
339 }
340 }
341 }
342
343
344
345 @Override
346 public void run () {
347 if (target != null) {
348 target.run();
349 }
350 }
351
352 public static void sleep (long millis) throws InterruptedException {
353 sleep(millis, 0);
354 }
355
356 public static native void sleep (long millis, int nanos)
357 throws InterruptedException;
358
359 public native void start();
360 public native void stop();
361 public native void stop(Throwable obj);
362
363 public native void suspend();
364 public native void resume();
365
366
367 @Override
368 public String toString () {
369 return ("Thread[" + name + ',' + priority + ',' + (group == null ? "" : group.getName()) + ']');
370 }
371
372 public static native void yield ();
373
374 native void setDaemon0 (boolean on);
375
376 native void setName0 (String name);
377
378 native void setPriority0 (int priority);
379
380
381
382 /**
383 * automatically called by system upon thread termination to clean up
384 * references.
385 *
386 * NOTE - we clean up atomically during ThreadInfo.finish(), to avoid any
387 * additional states. This is important since group per se is a shared object
388 * We only include this method here as a specification for ThreadInfo
389 */
390 private void exit () {
391 if (group != null){
392 group.threadTerminated(this);
393 group = null;
394 }
395
396 threadLocals = null;
397 parkBlocker = null;
398 uncaughtExceptionHandler = null;
399 }
400
401 // some Java 6 mojo
402 // <2do> not implemented yet
403 native void blockedOn (Interruptible b);
404
405
406 // we probably will remove these fields once we modeled java.util.concurrent.ThreadLocalRandom
407 // to make it deterministic
408 long threadLocalRandomSeed;
409 int threadLocalRandomProbe;
410 int threadLocalRandomSecondarySeed;
411 }