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.jvm;
020:
021: /**
022: * MJI NativePeer class for java.lang.Thread library abstraction
023: */
024: public class JPF_java_lang_Thread {
025:
026: public static boolean isAlive(MJIEnv env, int objref) {
027: return getThreadInfo(env, objref).isAlive();
028: }
029:
030: public static void setDaemon0(MJIEnv env, int objref,
031: boolean isDaemon) {
032: ThreadInfo ti = getThreadInfo(env, objref);
033: ti.setDaemon(isDaemon);
034: }
035:
036: public static boolean isInterrupted(MJIEnv env, int objref,
037: boolean clearStatus) {
038: return getThreadInfo(env, objref).isInterrupted(clearStatus);
039: }
040:
041: public static void setName0(MJIEnv env, int objref, int nameRef) {
042: // it bails if you try to set a null name
043: if (nameRef == -1) {
044: env.throwException("java.lang.IllegalArgumentException");
045:
046: return;
047: }
048:
049: // we have to intercept this to cache the name as a Java object
050: // (to be stored in ThreadData)
051: // luckily enough, it's copied into the java.lang.Thread object
052: // as a char[], i.e. does not have to preserve identity
053: // Note the nastiness in here - the java.lang.Thread object is only used
054: // to get the initial values into ThreadData, and gets inconsistent
055: // if this method is called (just works because the 'name' field is only
056: // directly accessed from within the Thread ctors)
057: ThreadInfo ti = getThreadInfo(env, objref);
058: ti.setName(env.getStringObject(nameRef));
059: }
060:
061: public static void setPriority0(MJIEnv env, int objref, int prio) {
062: // again, we have to cache this in ThreadData for performance reasons
063: ThreadInfo ti = getThreadInfo(env, objref);
064: ti.setPriority(prio);
065: }
066:
067: public static int countStackFrames(MJIEnv env, int objref) {
068: return getThreadInfo(env, objref).countStackFrames();
069: }
070:
071: public static int currentThread(MJIEnv env, int clsObjRef) {
072: ThreadInfo ti = env.getThreadInfo();
073:
074: return ti.getObjectReference();
075: }
076:
077: public static boolean holdsLock(MJIEnv env, int clsObjRef,
078: int objref) {
079: ThreadInfo ti = env.getThreadInfo();
080: ElementInfo ei = env.getElementInfo(objref);
081:
082: return ei.isLockedBy(ti);
083: }
084:
085: /**
086: * This method is the common initializer for all Thread ctors, and the only
087: * single location where we can init our ThreadInfo, but it is PRIVATE
088: */
089:
090: //__Ljava_lang_ThreadGroup__2Ljava_lang_Runnable__2Ljava_lang_String__2JZ
091: public static void init0(MJIEnv env, int objref, int rGroup,
092: int rRunnable, int rName, long stackSize) {
093: ThreadInfo ti = getThreadInfo(env, objref);
094: ti.init(rGroup, rRunnable, rName, stackSize, true);
095: }
096:
097: public static void interrupt(MJIEnv env, int objref) {
098: env.getElementInfo(objref).interrupt();
099: }
100:
101: public static void registerNatives(MJIEnv env, int clsObjRef) {
102: // nothing
103: }
104:
105: public static void resume0(MJIEnv env, int objref) {
106: // very deprecated
107: }
108:
109: public static void sleep__J(MJIEnv env, int clsObjRef, long millis) {
110: // no time
111: }
112:
113: public static void sleep__JI(MJIEnv env, int clsObjRef,
114: long millis, int nanos) {
115: // no time
116: }
117:
118: // <2do> pcm - I don't think so, find out!
119: // it's synced, and if the real native impl doesn't do the
120: // MONITOREXIT trick, it wouldn't go unlocked
121:
122: /**
123: public static boolean $isExecutable_start (MJIEnv env, int objref) {
124: ThreadInfo newThread = getThreadInfo(env,objref);
125: int target = env.getIntField(objref,"target");
126:
127: if (target == -1) {
128: target = objref;
129: }
130:
131: // better late than never
132: newThread.setTarget(target);
133:
134: // bug fix, only grab lock if "isSynchronized" 3/1/2002
135: // <2do> pcm - I don't think that's right, start nowadays IS synced
136: ElementInfo ei = env.getElementInfo(target);
137: ClassInfo ci = ei.getClassInfo();
138: MethodInfo run = ci.getMethod("run()", true);
139:
140: if (run.isSynchronized()) {
141: return ei.canLock(newThread);
142: }
143:
144: return true;
145: }
146: **/
147: public static void start(MJIEnv env, int objref) {
148: ThreadInfo newThread = getThreadInfo(env, objref);
149:
150: // check if this thread was already started. If it's still running, this
151: // is a IllegalThreadStateException. If it already terminated, it just gets
152: // silently ignored in Java 1.4, but the 1.5 spec explicitly marks this
153: // as illegal, so we adopt this by throwing an IllegalThreadState, too
154: if (newThread.getStatus() != ThreadInfo.NEW) {
155: env.throwException("java.lang.IllegalThreadStateException");
156: return;
157: }
158:
159: // Outch - that's bad. we have to dig this out from the innards
160: // of the java.lang.Thread class
161: int target = newThread.getTarget();
162:
163: if (target == -1) {
164: // note that we don't set the 'target' field, since java.lang.Thread doesn't
165: target = objref;
166: }
167:
168: // better late than never
169: newThread.setTarget(target);
170:
171: ElementInfo ei = env.getElementInfo(target);
172: ClassInfo ci = ei.getClassInfo();
173: MethodInfo run = ci.getMethod("run()", true);
174:
175: newThread.pushFrame(new StackFrame(run, false, target));
176: newThread
177: .setStatus(run.isSynchronized ? ThreadInfo.SYNC_RUNNING
178: : ThreadInfo.RUNNING);
179:
180: // <2do> now that we have another runnable, we should re-compute
181: // reachability so that subsequent potential breaks work correctly
182: if (newThread.usePor()) { // means we use on-the-fly POR
183: //env.getSystemState().activateGC();
184: env.getDynamicArea().analyzeHeap(false); // sledgehammer mark
185: }
186: }
187:
188: public static void stop0(MJIEnv env, int objref,
189: int threadDeathExcptRef) {
190: // that's very very very deprecated. I know of almost no kernel
191: // thread system with user-stoppable threads
192: }
193:
194: public static void suspend0(MJIEnv env, int objref) {
195: // again, deprecated
196: }
197:
198: public static void yield(MJIEnv env, int clsObjRef) {
199: // do nothing, we are scheduling relevant, so we should get all
200: // possible scheduling combinations
201: }
202:
203: // it's synchronized
204: /*
205: public static void join__ (MJIEnv env, int objref) {
206: ThreadInfo ti = getThreadInfo(env,objref);
207:
208: if (ti.isAlive()) {
209: env.wait(objref);
210: }
211: }
212: */
213:
214: private static ThreadInfo getThreadInfo(MJIEnv env, int objref) {
215: KernelState ks = env.getKernelState();
216:
217: return ks.tl.locate(objref);
218: }
219: }
|