1 package gov.nasa.jpf.jvm; 20 21 import gov.nasa.jpf.JPFException; 22 import gov.nasa.jpf.util.Debug; 23 import gov.nasa.jpf.util.HashData; 24 25 28 public class Monitor { 29 32 private int lockingThread; 33 34 37 private int lockCount; 38 39 42 private int[] waitingThreads; 43 44 47 public Monitor () { 48 lockingThread = -1; 49 lockCount = 0; 50 waitingThreads = new int[0]; 51 } 52 53 56 public int getLockCount () { 57 return lockCount; 58 } 59 60 63 public int getLockingThread () { 64 return lockingThread; 65 } 66 67 70 public int[] getWaitingThreads () { 71 return waitingThreads; 72 } 73 74 77 public boolean canLock (ThreadInfo th) { 78 if (lockingThread == -1) { 79 return true; 80 } 81 82 return (lockingThread == th.index); 83 } 84 85 88 public Object clone () { 89 Monitor m = new Monitor(); 90 91 m.lockingThread = lockingThread; 92 m.lockCount = lockCount; 93 m.waitingThreads = new int[waitingThreads.length]; 94 System.arraycopy(waitingThreads, 0, m.waitingThreads, 0, 95 waitingThreads.length); 96 97 return m; 98 } 99 100 103 public boolean equals (Object o) { 104 if (o == null) { 105 return false; 106 } 107 108 if (!(o instanceof Monitor)) { 109 return false; 110 } 111 112 Monitor m = (Monitor) o; 113 114 if (lockingThread != m.getLockingThread()) { 115 return false; 116 } 117 118 if (lockCount != m.getLockCount()) { 119 return false; 120 } 121 122 int[] w = m.waitingThreads; 123 124 if (waitingThreads.length != w.length) { 125 return false; 126 } 127 128 for (int i = 0; i < waitingThreads.length; i++) { 129 if (waitingThreads[i] != w[i]) { 130 return false; 131 } 132 } 133 134 return true; 135 } 136 137 public void hash (HashData hd) { 138 hd.add(lockingThread); 139 hd.add(lockCount); 140 141 for (int i = 0, l = waitingThreads.length; i < l; i++) { 142 hd.add(waitingThreads[i]); 143 } 144 } 145 146 public int hashCode () { 147 HashData hd = new HashData(); 148 149 hash(hd); 150 151 return hd.getValue(); 152 } 153 154 157 public void interrupt (ThreadInfo th) { 158 remove(th.index); 159 th.setStatus(ThreadInfo.INTERRUPTED); 160 } 161 162 165 public void lock (ThreadInfo th, Ref ref) { 166 169 if (lockingThread == -1) { 170 lockingThread = th.index; 171 172 th.lock(ref); 173 } else if (lockingThread != th.index) { 174 throw new JPFException("lock operation failed"); 175 } 176 177 lockCount++; 178 } 179 180 183 public void lockNotified (ThreadInfo th, Ref ref) { 184 if (lockingThread != -1) { 185 throw new JPFException("lock operation failed"); 186 } 187 188 lockingThread = th.index; 189 lockCount = th.getLockCount(); 190 191 for (int i = 0; i < waitingThreads.length; i++) { 193 if (waitingThreads[i] == th.index) { 194 remove(i); 195 196 break; 197 } 198 } 199 200 th.setStatus(ThreadInfo.RUNNING); 201 th.setLockCount(0); 202 203 th.lock(ref); 204 } 205 206 public void log () { 207 Debug.println(Debug.MESSAGE, " $lockingThread$: " + lockingThread); 208 Debug.println(Debug.MESSAGE, " $lockCount$: " + lockCount); 209 Debug.print(Debug.MESSAGE, " $waitingThreads$: { "); 210 211 for (int i = 0, l = waitingThreads.length; i < l; i++) { 212 if (i != 0) { 213 Debug.print(Debug.MESSAGE, ", "); 214 } 215 216 Debug.print(Debug.MESSAGE, Integer.toString(waitingThreads[i])); 217 } 218 219 Debug.println(Debug.MESSAGE, " }"); 220 } 221 222 225 public void notify (SystemState ss) { 226 int length = waitingThreads.length; 227 228 if (length == 0) { 229 return; 230 } 231 232 int random = ss.random(length); 233 234 ss.ks.tl.get(remove(random)).setStatus(ThreadInfo.NOTIFIED); 235 } 236 237 240 public void notifyAll (SystemState ss) { 241 for (int i = 0, l = waitingThreads.length; i < l; i++) { 242 ThreadInfo th = ss.ks.tl.get(waitingThreads[i]); 243 th.setStatus(ThreadInfo.NOTIFIED); 244 } 245 246 waitingThreads = new int[0]; 247 } 248 249 public int objectHashCode () { 250 return super.hashCode(); 251 } 252 253 public String toString () { 254 StringBuffer sb = new StringBuffer (); 255 256 sb.append("Monitor("); 257 sb.append("lockingThread="); 258 sb.append(lockingThread); 259 sb.append(','); 260 sb.append("lockCount="); 261 sb.append(lockCount); 262 sb.append(','); 263 sb.append("waitingThreads="); 264 sb.append('['); 265 266 for (int i = 0; i < waitingThreads.length; i++) { 267 if (i != 0) { 268 sb.append(','); 269 } 270 271 sb.append(waitingThreads[i]); 272 } 273 274 sb.append(']'); 275 sb.append(')'); 276 277 return sb.toString(); 278 } 279 280 284 public void unlock (ThreadInfo th, Ref ref) { 285 289 lockCount--; 290 291 if (lockCount < 0) { 292 throw new JPFException("lock counter can't be negative"); 293 } 294 295 if (lockCount == 0) { 296 lockingThread = -1; 297 th.unlock(ref); 298 } 299 } 300 301 304 public void wait (ThreadInfo th, Ref ref) { 305 if (lockingThread != th.index) { 306 throw new JPFException("wait on an unlocked monitor"); 307 } 308 309 th.setStatus(ThreadInfo.WAITING); 310 th.setLockCount(lockCount); 311 312 int length = waitingThreads.length; 313 int[] n = new int[length + 1]; 314 System.arraycopy(waitingThreads, 0, n, 0, length); 315 waitingThreads = n; 316 waitingThreads[length] = th.index; 317 318 lockingThread = -1; 319 lockCount = 0; 320 321 th.unlock(ref); 322 } 323 324 private int remove (int index) { 325 int r = waitingThreads[index]; 326 int length = waitingThreads.length; 327 328 int[] n = new int[length - 1]; 329 System.arraycopy(waitingThreads, 0, n, 0, index); 330 System.arraycopy(waitingThreads, index + 1, n, index, length - index - 1); 331 waitingThreads = n; 332 333 return r; 334 } 335 } 336 | Popular Tags |