Mercurial > hg > Members > kono > jpf-core
comparison src/main/gov/nasa/jpf/vm/AllRunnablesSyncPolicy.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 | 87e9c7544a06 |
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 | |
19 package gov.nasa.jpf.vm; | |
20 | |
21 import gov.nasa.jpf.Config; | |
22 import gov.nasa.jpf.vm.choice.ThreadChoiceFromSet; | |
23 | |
24 /** | |
25 * a Scheduler implementation base class that allows filtering of runnable threads and | |
26 * implements SyncPolicy without backtracking or empty transitions, i.e. choice sets that | |
27 * include all runnable threads | |
28 */ | |
29 public class AllRunnablesSyncPolicy implements SyncPolicy { | |
30 | |
31 protected VM vm; | |
32 protected boolean breakSingleChoice; | |
33 protected boolean breakLockRelease; | |
34 protected boolean breakNotify; | |
35 protected boolean breakSleep; | |
36 protected boolean breakYield; | |
37 protected boolean breakPriority; | |
38 | |
39 public AllRunnablesSyncPolicy (Config config){ | |
40 breakSingleChoice = config.getBoolean("cg.break_single_choice", false); | |
41 breakLockRelease = config.getBoolean("cg.break_lock_release", true); | |
42 breakNotify = config.getBoolean("cg.break_notify", true); | |
43 breakSleep = config.getBoolean("cg.break_sleep", true); | |
44 breakYield = config.getBoolean("cg.break_yield", true); | |
45 breakPriority = config.getBoolean("cg.break_priority", true); | |
46 } | |
47 | |
48 | |
49 //--- internal methods | |
50 | |
51 /** | |
52 * this is the main policy method that can be overridden by subclasses, e.g. by filtering | |
53 * out the highest priority runnables, or by ordering according to priority | |
54 * | |
55 * Default behavior is to first try to find runnables within the provided ApplicationContext, | |
56 * and fall back to any runnable if there are none in this context | |
57 * | |
58 * this includes threads that are in operations that can timeout | |
59 */ | |
60 protected ThreadInfo[] getTimeoutRunnables (ApplicationContext appCtx){ | |
61 ThreadList tlist = vm.getThreadList(); | |
62 | |
63 if (tlist.hasProcessTimeoutRunnables(appCtx)){ | |
64 return tlist.getProcessTimeoutRunnables(appCtx); | |
65 } else { | |
66 return tlist.getTimeoutRunnables(); | |
67 } | |
68 } | |
69 | |
70 | |
71 protected ChoiceGenerator<ThreadInfo> getRunnableCG (String id, ThreadInfo tiCurrent){ | |
72 ThreadInfo[] choices = getTimeoutRunnables(tiCurrent.getApplicationContext()); | |
73 | |
74 if (choices.length == 0){ | |
75 return null; | |
76 } | |
77 | |
78 if ((choices.length == 1) && (choices[0] == tiCurrent) && !tiCurrent.isTimeoutWaiting()){ // no context switch | |
79 if (!breakSingleChoice){ | |
80 return null; | |
81 } | |
82 } | |
83 | |
84 return new ThreadChoiceFromSet( id, choices, true); | |
85 } | |
86 | |
87 protected boolean setNextChoiceGenerator (ChoiceGenerator<ThreadInfo> cg){ | |
88 if (cg != null){ | |
89 return vm.getSystemState().setNextChoiceGenerator(cg); // listeners could still remove CGs | |
90 } else { | |
91 return false; | |
92 } | |
93 } | |
94 | |
95 /** | |
96 * set a runnable CG that is optional if we are in a atomic section | |
97 */ | |
98 protected boolean setNonBlockingCG (String id, ThreadInfo tiCurrent){ | |
99 if (!tiCurrent.isFirstStepInsn() || tiCurrent.isEmptyTransitionEnabled()) { | |
100 if (vm.getSystemState().isAtomic()) { | |
101 return false; | |
102 } else { | |
103 return setNextChoiceGenerator(getRunnableCG(id, tiCurrent)); | |
104 } | |
105 | |
106 } else { | |
107 return false; // no empty transitions | |
108 } | |
109 } | |
110 | |
111 protected static ChoiceGenerator<ThreadInfo> blockedWithoutChoice = | |
112 new ThreadChoiceFromSet("BLOCKED_NO_CHOICE", new ThreadInfo[0], true); | |
113 | |
114 /** | |
115 * set a runnable CG that would break a atomic section because it requires | |
116 * a context switch | |
117 */ | |
118 protected boolean setBlockingCG (String id, ThreadInfo tiCurrent){ | |
119 if (!tiCurrent.isFirstStepInsn() || tiCurrent.isEmptyTransitionEnabled()) { | |
120 if (vm.getSystemState().isAtomic()) { | |
121 vm.getSystemState().setBlockedInAtomicSection(); | |
122 } | |
123 | |
124 ChoiceGenerator<ThreadInfo> cg = getRunnableCG(id, tiCurrent); | |
125 if (cg == null){ // make sure we don't mask a deadlock | |
126 if (vm.getThreadList().hasLiveThreads()){ | |
127 cg = blockedWithoutChoice; | |
128 } | |
129 } | |
130 | |
131 return setNextChoiceGenerator(cg); | |
132 | |
133 } else { | |
134 return false; // no empty transitions | |
135 } | |
136 } | |
137 | |
138 /** | |
139 * set a runnable CG that only breaks a atomic section if the blocking thread | |
140 * is the currently executing one | |
141 */ | |
142 protected boolean setMaybeBlockingCG (String id, ThreadInfo tiCurrent, ThreadInfo tiBlock){ | |
143 if (tiCurrent == tiBlock){ | |
144 return setBlockingCG( id, tiCurrent); | |
145 } else { | |
146 return setNonBlockingCG( id, tiCurrent); | |
147 } | |
148 } | |
149 | |
150 | |
151 //--- SyncPolicy interface | |
152 | |
153 //--- initialization | |
154 @Override | |
155 public void initializeSyncPolicy (VM vm, ApplicationContext appCtx){ | |
156 this.vm = vm; | |
157 } | |
158 | |
159 @Override | |
160 public void initializeThreadSync (ThreadInfo tiCurrent, ThreadInfo tiNew){ | |
161 } | |
162 | |
163 //--- locks | |
164 @Override | |
165 public boolean setsBlockedThreadCG (ThreadInfo ti, ElementInfo ei){ | |
166 return setBlockingCG( BLOCK, ti); | |
167 } | |
168 | |
169 @Override | |
170 public boolean setsLockAcquisitionCG (ThreadInfo ti, ElementInfo ei){ | |
171 return setNonBlockingCG( LOCK, ti); | |
172 } | |
173 | |
174 @Override | |
175 public boolean setsLockReleaseCG (ThreadInfo ti, ElementInfo ei, boolean didUnblock){ | |
176 if (breakLockRelease){ | |
177 if (didUnblock){ | |
178 return setNonBlockingCG( RELEASE, ti); | |
179 } | |
180 } | |
181 | |
182 return false; | |
183 } | |
184 | |
185 //--- thread termination | |
186 @Override | |
187 public boolean setsTerminationCG (ThreadInfo ti){ | |
188 return setBlockingCG( TERMINATE, ti); | |
189 } | |
190 | |
191 //--- java.lang.Object APIs | |
192 @Override | |
193 public boolean setsWaitCG (ThreadInfo ti, long timeout){ | |
194 return setBlockingCG( WAIT, ti); | |
195 } | |
196 | |
197 @Override | |
198 public boolean setsNotifyCG (ThreadInfo ti, boolean didNotify){ | |
199 if (breakNotify){ | |
200 if (didNotify){ | |
201 return setNonBlockingCG( NOTIFY, ti); | |
202 } | |
203 } | |
204 | |
205 return false; | |
206 } | |
207 | |
208 @Override | |
209 public boolean setsNotifyAllCG (ThreadInfo ti, boolean didNotify){ | |
210 if (breakNotify){ | |
211 if (didNotify){ | |
212 return setNonBlockingCG( NOTIFYALL, ti); | |
213 } | |
214 } | |
215 | |
216 return false; | |
217 } | |
218 | |
219 | |
220 //--- the java.lang.Thread APIs | |
221 @Override | |
222 public boolean setsStartCG (ThreadInfo tiCurrent, ThreadInfo tiStarted){ | |
223 return setNonBlockingCG( START, tiCurrent); | |
224 } | |
225 | |
226 @Override | |
227 public boolean setsYieldCG (ThreadInfo ti){ | |
228 if (breakYield){ | |
229 return setNonBlockingCG( YIELD, ti); | |
230 } else { | |
231 return false; | |
232 } | |
233 } | |
234 | |
235 @Override | |
236 public boolean setsPriorityCG (ThreadInfo ti){ | |
237 if (breakPriority){ | |
238 return setNonBlockingCG( PRIORITY, ti); | |
239 } else { | |
240 return false; | |
241 } | |
242 } | |
243 | |
244 @Override | |
245 public boolean setsSleepCG (ThreadInfo ti, long millis, int nanos){ | |
246 if (breakSleep){ | |
247 return setNonBlockingCG( SLEEP, ti); | |
248 } else { | |
249 return false; | |
250 } | |
251 } | |
252 | |
253 @Override | |
254 public boolean setsSuspendCG (ThreadInfo tiCurrent, ThreadInfo tiSuspended){ | |
255 return setMaybeBlockingCG( SUSPEND, tiCurrent, tiSuspended); | |
256 } | |
257 | |
258 @Override | |
259 public boolean setsResumeCG (ThreadInfo tiCurrent, ThreadInfo tiResumed){ | |
260 return setNonBlockingCG( RESUME, tiCurrent); | |
261 } | |
262 | |
263 @Override | |
264 public boolean setsJoinCG (ThreadInfo tiCurrent, ThreadInfo tiJoin, long timeout){ | |
265 return setBlockingCG( JOIN, tiCurrent); | |
266 } | |
267 | |
268 @Override | |
269 public boolean setsStopCG (ThreadInfo tiCurrent, ThreadInfo tiStopped){ | |
270 return setMaybeBlockingCG( STOP, tiCurrent, tiStopped); | |
271 } | |
272 | |
273 @Override | |
274 public boolean setsInterruptCG (ThreadInfo tiCurrent, ThreadInfo tiInterrupted){ | |
275 if (tiInterrupted.isWaiting()){ | |
276 return setNonBlockingCG( INTERRUPT, tiCurrent); | |
277 } else { | |
278 return false; | |
279 } | |
280 } | |
281 | |
282 | |
283 //--- sun.misc.Unsafe | |
284 @Override | |
285 public boolean setsParkCG (ThreadInfo ti, boolean isAbsTime, long timeout){ | |
286 return setBlockingCG( PARK, ti); | |
287 } | |
288 | |
289 @Override | |
290 public boolean setsUnparkCG (ThreadInfo tiCurrent, ThreadInfo tiUnparked){ | |
291 // if the unparked thread is not blocked there is no point | |
292 if (tiUnparked.isBlocked()){ | |
293 return setNonBlockingCG( UNPARK, tiCurrent); | |
294 } else { | |
295 return false; | |
296 } | |
297 } | |
298 | |
299 | |
300 //--- system scheduling events | |
301 | |
302 /** | |
303 * this one has to be guaranteed to set a CG | |
304 */ | |
305 @Override | |
306 public void setRootCG (){ | |
307 ThreadInfo[] runnables = vm.getThreadList().getTimeoutRunnables(); | |
308 ChoiceGenerator<ThreadInfo> cg = new ThreadChoiceFromSet( ROOT, runnables, true); | |
309 vm.getSystemState().setMandatoryNextChoiceGenerator( cg, "no ROOT choice generator"); | |
310 } | |
311 | |
312 | |
313 //--- gov.nasa.jpf.vm.Verify | |
314 @Override | |
315 public boolean setsBeginAtomicCG (ThreadInfo ti){ | |
316 return setNonBlockingCG( BEGIN_ATOMIC, ti); | |
317 } | |
318 | |
319 @Override | |
320 public boolean setsEndAtomicCG (ThreadInfo ti){ | |
321 return setNonBlockingCG( END_ATOMIC, ti); | |
322 } | |
323 | |
324 //--- ThreadInfo reschedule request | |
325 @Override | |
326 public boolean setsRescheduleCG (ThreadInfo ti, String reason){ | |
327 return setNonBlockingCG( reason, ti); | |
328 } | |
329 | |
330 //--- FinalizerThread | |
331 @Override | |
332 public boolean setsPostFinalizeCG (ThreadInfo tiFinalizer){ | |
333 // the finalizer is already waiting at this point, i.e. it's not runnable anymore | |
334 return setBlockingCG( POST_FINALIZE, tiFinalizer); | |
335 } | |
336 | |
337 | |
338 } |