00001 package gov.nasa.arc.ase.jpf.jvm;
00002
00003 import gov.nasa.arc.ase.jpf.*;
00004 import gov.nasa.arc.ase.util.Debug;
00005 import gov.nasa.arc.ase.util.HashData;
00006 import java.io.*;
00007 import java.util.*;
00008
00009 import gov.nasa.arc.ase.jpf.jvm.runtime.*;
00010
00011
00012 public class Monitor implements Cloneable {
00013 int locking_thread = -1;
00014 int lock_count = 0;
00015 List waiting_threads = new ArrayList();
00016
00017 public Monitor() {
00018 }
00019 public Monitor(int lt, int lc, List wt) {
00020 locking_thread = lt;
00021 lock_count = lc;
00022 waiting_threads = wt;
00023 }
00024
00025 private void ANALYZE_lock(ThreadInfo th, Ref ref) {
00026 if (Analyze.on()) {
00027 th.getLockSet().addLock(ref);
00028 if (Analyze.debug_on()) {
00029 Analyze.println("--- LOCK ------------");
00030 Analyze.println("Thread " + th.getThreadReference()
00031 + " locks object [" + ref + "]");
00032 th.getLockSet().print();
00033 }
00034 }
00035 }
00036 private void ANALYZE_unlock(ThreadInfo th, Ref ref) {
00037 if (Analyze.on()) {
00038 th.getLockSet().deleteLock(ref);
00039 if (Analyze.debug_on()) {
00040 Analyze.println("--- UNLOCK ----------");
00041 Analyze.println("Thread " + th.getThreadReference()
00042 + " releases object [" + ref + "]");
00043 th.getLockSet().print();
00044 }
00045 }
00046 }
00047 private void ANALYZE_wait(ThreadInfo th, Ref ref) {
00048 if (Analyze.on()) {
00049 th.getLockSet().deleteLock(ref);
00050 if (Analyze.debug_on()) {
00051 Analyze.println("--- WAIT ------------");
00052 Analyze.println("Thread " + th.getThreadReference()
00053 + " waits on object [" + ref + "]");
00054 th.getLockSet().print();
00055 }
00056 }
00057 }
00058 public boolean checkLock(ThreadInfo th) {
00059 if (locking_thread == -1)
00060 return true;
00061 return (locking_thread == th.getThreadReference());
00062 }
00063 public boolean checkLockAfterNotified(ThreadInfo th) {
00064 return checkLock(th);
00065 }
00066
00067
00068 public Object clone() {
00069 try {
00070 Monitor m = (Monitor)super.clone();
00071 m.locking_thread = locking_thread;
00072 m.lock_count = lock_count;
00073 m.waiting_threads = new ArrayList();
00074 for(int i = 0; i < waiting_threads.size(); i++)
00075 m.waiting_threads.add(waiting_threads.get(i));
00076 return m;
00077 } catch(CloneNotSupportedException e) {
00078 throw new InternalError(e.toString());
00079 }
00080 }
00081 public boolean equals(Object obj) {
00082 Monitor m = (Monitor)obj;
00083
00084 if (locking_thread != m.getLockingThread()) return false;
00085 if (lock_count != m.getLockCount()) return false;
00086
00087 List waiting = m.waiting_threads;
00088
00089 if (waiting_threads.size() != waiting.size()) return false;
00090
00091 for(int i = 0; i < waiting_threads.size(); i++)
00092 if (((Integer)waiting_threads.get(i)).compareTo(waiting.get(i)) != 0) return false;
00093
00094 return true;
00095 }
00096 public int getLockCount() {
00097 return lock_count;
00098 }
00099 public int getLockingThread() {
00100 return locking_thread;
00101 }
00102 public List getWaitingThreads() {
00103 return waiting_threads;
00104 }
00105 public void hash(HashData hd) {
00106 hd.add(lock_count);
00107
00108 for(int i = 0, l = waiting_threads.size(); i < l; i++)
00109 hd.add(((Integer)waiting_threads.get(i)).intValue());
00110 }
00111 public int hashCode() {
00112 HashData hd = new HashData();
00113
00114 hd.add(lock_count);
00115
00116 for(int i = 0, l = waiting_threads.size(); i < l; i++)
00117 hd.add(((Integer)waiting_threads.get(i)).intValue());
00118
00119 return hd.getValue();
00120 }
00121 public boolean lock(ThreadInfo th, Ref ref) {
00122 if (locking_thread == -1) {
00123 locking_thread = th.getThreadReference();
00124
00125 ANALYZE_lock(th,ref);
00126 LOCKORDER_lock(th,ref);
00127
00128 }
00129 if (locking_thread == th.getThreadReference()) {
00130 lock_count++;
00131
00132
00133
00134 return true;
00135 } else {
00136
00137
00138
00139
00140 return false;
00141 }
00142 }
00143 public boolean lockAfterNotified(ThreadInfo th, Ref ref) {
00144 if (lock(th,ref)) {
00145 th.setStatus(STATUS.RUNNING);
00146 lock_count = th.getLockCount();
00147 return true;
00148 }
00149 else
00150 return false;
00151 }
00152 private void LOCKORDER_lock(ThreadInfo th, Ref ref) {
00153 if (LockOrder.on()) {
00154 VirtualMachine vm = (VirtualMachine)Engine.vm;
00155 KernelState ks = (KernelState)vm.getKernelState();
00156 String className;
00157 if(ref.isClass)
00158 className = ks.static_area.getClass(ref.reference).getClassName();
00159 else
00160 className = ks.dynamic_area.getClass(ref.reference).getClassName();
00161 th.getLockTree().lock(LockPool.get(new Lock(ref,className)));
00162 }
00163 }
00164 private void LOCKORDER_unlock(ThreadInfo th) {
00165 if (LockOrder.on()) {
00166 th.getLockTree().unlock();
00167 }
00168 }
00169 private void LOCKORDER_wait(ThreadInfo th) {
00170 if (LockOrder.on()) {
00171 th.getLockTree().unlock();
00172 }
00173 }
00174 public void notify(KernelState ks, Scheduler sch) {
00175 int notify_index = sch.getCurrentNotify();
00176
00177 if (notify_index < waiting_threads.size()) {
00178 if ((notify_index + 1) < waiting_threads.size()) {
00179
00180
00181
00182
00183 TransitionResult.setNotified();
00184 }
00185 else {
00186
00187
00188
00189 TransitionResult.clearNotified();
00190 }
00191 int thread_index =
00192 ((Integer)waiting_threads.remove(notify_index)).intValue();
00193 ThreadInfo th = (ThreadInfo)ks.getThreadInfo(thread_index);
00194 th.setStatus(STATUS.NOTIFIED);
00195 }
00196 }
00197 public void notifyAll(KernelState ks) {
00198 while (!waiting_threads.isEmpty()) {
00199 int thread_index = ((Integer)waiting_threads.remove(0)).intValue();
00200 ThreadInfo th = (ThreadInfo)ks.getThreadInfo(thread_index);
00201 th.setStatus(STATUS.NOTIFIED);
00202 }
00203 }
00204 public void unlock(ThreadInfo th, Ref ref) {
00205
00206
00207
00208 lock_count--;
00209 if (lock_count < 0) {
00210 Debug.println(Debug.WARNING,"Illegal Monitor Operation");
00211 }
00212 if (lock_count == 0) {
00213 locking_thread = -1;
00214
00215 ANALYZE_unlock(th,ref);
00216 LOCKORDER_unlock(th);
00217
00218 }
00219 }
00220 public void wait(ThreadInfo th, Ref ref) {
00221 th.setStatus(STATUS.WAITING);
00222 th.setLockCount(lock_count);
00223 waiting_threads.add(new Integer(th.getThreadReference()));
00224 locking_thread = -1;
00225 lock_count = 0;
00226
00227 ANALYZE_wait(th,ref);
00228 LOCKORDER_wait(th);
00229
00230 }
00231 }