001 // This file is part of the program FRYSK.
002 //
003 // Copyright 2005, 2006, 2007, 2008 Red Hat Inc.
004 //
005 // FRYSK is free software; you can redistribute it and/or modify it
006 // under the terms of the GNU General Public License as published by
007 // the Free Software Foundation; version 2 of the License.
008 //
009 // FRYSK is distributed in the hope that it will be useful, but
010 // WITHOUT ANY WARRANTY; without even the implied warranty of
011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 // General Public License for more details.
013 //
014 // You should have received a copy of the GNU General Public License
015 // along with FRYSK; if not, write to the Free Software Foundation,
016 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
017 //
018 // In addition, as a special exception, Red Hat, Inc. gives You the
019 // additional right to link the code of FRYSK with code not covered
020 // under the GNU General Public License ("Non-GPL Code") and to
021 // distribute linked combinations including the two, subject to the
022 // limitations in this paragraph. Non-GPL Code permitted under this
023 // exception must only link to the code of FRYSK through those well
024 // defined interfaces identified in the file named EXCEPTION found in
025 // the source code files (the "Approved Interfaces"). The files of
026 // Non-GPL Code may instantiate templates or use macros or inline
027 // functions from the Approved Interfaces without causing the
028 // resulting work to be covered by the GNU General Public
029 // License. Only Red Hat, Inc. may make changes or additions to the
030 // list of Approved Interfaces. You must obey the GNU General Public
031 // License in all respects for all of the FRYSK code and other code
032 // used in conjunction with FRYSK except the Non-GPL Code covered by
033 // this exception. If you modify this file, you may extend this
034 // exception to your version of the file, but you are not obligated to
035 // do so. If you do not wish to provide this exception without
036 // modification, you must delete this exception statement from your
037 // version and license this file solely under the GPL without
038 // exception.
039
040 package frysk.proc;
041
042 import frysk.proc.TaskObserver.Terminating;
043 import frysk.isa.syscalls.SyscallTable;
044 import frysk.isa.syscalls.SyscallTableFactory;
045 import inua.eio.ByteBuffer;
046 import java.util.Set;
047 import java.util.HashSet;
048 import frysk.isa.registers.Register;
049 import frysk.isa.ISA;
050 import frysk.isa.banks.RegisterBanks;
051 import frysk.isa.signals.SignalTable;
052 import frysk.isa.signals.SignalTableFactory;
053 import frysk.rsl.Log;
054
055 public abstract class Task {
056 private static final Log fine = Log.fine(Task.class);
057
058 /**
059 * Create a new Task skeleton.
060 */
061 private Task(int pid, Proc proc) {
062 this.proc = proc;
063 this.tid = pid;
064 this.id = new TaskId(pid);
065 proc.add(this);
066 }
067
068 /**
069 * Create a new unattached Task.
070 */
071 protected Task(Proc proc, int pid) {
072 this(pid, proc);
073 fine.log("new -- create unattached");
074 }
075
076 /**
077 * Create a new attached CLONE of TASK.
078 */
079 protected Task(Task cloningTask, int clone) {
080 this(clone, cloningTask.getProc());
081 fine.log(this, "new -- create attached clone");
082 }
083
084 /**
085 * Create a newly created and attached main Task of Proc that is
086 * the result of a fork.
087 */
088 protected Task(Proc proc) {
089 this(proc.getPid(), proc);
090 }
091
092 /**
093 * Return the task's corresponding TaskId.
094 */
095 TaskId getTaskId() {
096 return id;
097 }
098 private final TaskId id;
099 private final int tid;
100
101 /**
102 * Return the task's process id.
103 */
104 public final int getTid() {
105 return tid;
106 }
107
108 /**
109 * Return the task's (derived) name
110 */
111 public final String getName() {
112 return "Task " + tid;
113 }
114
115 /**
116 * Return the state as a string; do not use!!!!
117 */
118 protected abstract String getStateFIXME();
119
120 /**
121 * Return's this Task's Instruction Set Architecture; or throw a
122 * NullPointerException if the ISA is not available.
123 *
124 * The isa is only available while the task is under observation
125 * (attached) as an un-observed task can switch isa's (using
126 * exec(2)) undetected.
127 */
128 public abstract ISA getISA();
129
130 private SyscallTable syscallTable;
131 public final SyscallTable getSyscallTable() {
132 if (syscallTable == null)
133 syscallTable = SyscallTableFactory.getSyscallTable(getISA());
134 return syscallTable;
135 }
136
137 /**
138 * Return the containing Proc.
139 */
140 public Proc getProc() {
141 return proc;
142 }
143 private final Proc proc;
144
145 public class TaskEventObservable extends java.util.Observable {
146 protected void notify(Object o) {
147 setChanged();
148 notifyObservers(o);
149 }
150 }
151
152 /**
153 * Return a summary of the task's state.
154 */
155 public String toString() {
156 return ("{" + super.toString()
157 + ",pid=" + proc.getPid()
158 + ",tid=" + getTid()
159 + ",state=" + getStateFIXME()
160 + "}");
161 }
162
163 /**
164 * XXX: Code using this needs a re-think.
165 */
166 public Set bogusUseOfInternalBlockersVariableFIXME() {
167 return new HashSet();
168 }
169
170 /**
171 * Request that the observer be removed from this tasks set of
172 * blockers; once there are no blocking observers, this task
173 * resumes.
174 */
175 public abstract void requestUnblock(final TaskObserver observerArg);
176
177 /**
178 * Add a TaskObserver.Cloned observer.
179 */
180 public abstract void requestAddClonedObserver(TaskObserver.Cloned o);
181 /**
182 * Delete a TaskObserver.Cloned observer.
183 */
184 public abstract void requestDeleteClonedObserver(TaskObserver.Cloned o);
185
186 /**
187 * Add a TaskAttachedObserverXXX observer.
188 */
189 public abstract void requestAddAttachedObserver(TaskAttachedObserverXXX o);
190 /**
191 * Delete a TaskAttachedObserverXXX observer.
192 */
193 public abstract void requestDeleteAttachedObserver(TaskAttachedObserverXXX o);
194
195 /**
196 * Add a TaskObserver.Forked observer.
197 */
198 public abstract void requestAddForkedObserver(TaskObserver.Forked o);
199 /**
200 * Delete a TaskObserver.Forked observer.
201 */
202 public abstract void requestDeleteForkedObserver(TaskObserver.Forked o);
203
204 /**
205 * Add a TaskObserver.Terminated observer.
206 */
207 public abstract void requestAddTerminatedObserver(TaskObserver.Terminated o);
208 /**
209 * Delete a TaskObserver.Terminated observer.
210 */
211 public abstract void requestDeleteTerminatedObserver(TaskObserver.Terminated o);
212
213 /**
214 * Add the Terminating observer to the TaskObserver pool.
215 */
216 public abstract void requestAddTerminatingObserver(Terminating o);
217 /**
218 * Delete the Terminating observer.
219 */
220 public abstract void requestDeleteTerminatingObserver(Terminating o);
221
222 /**
223 * Add TaskObserver.Execed to the TaskObserver pool.
224 */
225 public abstract void requestAddExecedObserver(TaskObserver.Execed o);
226 /**
227 * Delete TaskObserver.Execed.
228 */
229 public abstract void requestDeleteExecedObserver(TaskObserver.Execed o);
230
231 /**
232 * Add TaskObserver.Syscalls to the TaskObserver pool.
233 */
234 public abstract void requestAddSyscallsObserver(TaskObserver.Syscalls o);
235 /**
236 * Delete TaskObserver.Syscall.
237 */
238 public abstract void requestDeleteSyscallsObserver(TaskObserver.Syscalls o);
239
240 /**
241 * Add TaskObserver.Signaled to the TaskObserver pool.
242 */
243 public abstract void requestAddSignaledObserver(TaskObserver.Signaled o);
244 /**
245 * Delete TaskObserver.Signaled.
246 */
247 public abstract void requestDeleteSignaledObserver(TaskObserver.Signaled o);
248
249 /**
250 * Return the Task's memory.
251 */
252 public abstract ByteBuffer getMemory();
253
254 /**
255 * Add TaskObserver.Code to the TaskObserver pool.
256 */
257 public abstract void requestAddCodeObserver(TaskObserver.Code o, long a);
258 /**
259 * Delete TaskObserver.Code for the TaskObserver pool.
260 */
261 public abstract void requestDeleteCodeObserver(TaskObserver.Code o, long a);
262
263 /**
264 * Add TaskObserver.Watch to the TaskObserver pool.
265 */
266 public abstract void requestAddWatchObserver(TaskObserver.Watch o, long address,
267 int length, boolean writeOnly);
268
269 /**
270 * Delete TaskObserver.Watchfor the TaskObserver pool.
271 */
272 public abstract void requestDeleteWatchObserver(TaskObserver.Watch o, long address,
273 int length, boolean writeOnly);
274
275
276
277 /**
278 * Request the addition of a Instruction observer that will be
279 * notified as soon as the task executes an instruction.
280 * <code>o.updateExecuted</code> is called as soon as the Task
281 * starts running again (is not blocked or stopped) and executes
282 * the next instruction.
283 */
284 public abstract void requestAddInstructionObserver(TaskObserver.Instruction o);
285 /**
286 * Delete TaskObserver.Instruction from the TaskObserver pool.
287 */
288 public abstract void requestDeleteInstructionObserver(TaskObserver.Instruction o);
289 /**
290 * Returns true if the observer has been added to task's
291 * instruction observer list.
292 */
293 public abstract boolean isInstructionObserverAdded (TaskObserver.Instruction o);
294 /**
295 * Return the address of the instruction that this task will
296 * execute next.
297 */
298 public abstract long getPC();
299 /**
300 * Set the address of the instruction that this task will execute
301 * next.
302 */
303 public abstract void setPC(long addr);
304
305 /**
306 * Return the Task's Register as a long.
307 */
308 public long getRegister(Register register) {
309 return getRegisterBanks().get(register);
310 }
311 /**
312 * Store the long value in the Task's register.
313 */
314 public void setRegister(Register register, long value) {
315 getRegisterBanks().set(register, value);
316 }
317 /**
318 * Access bytes OFFSET:LENGTH of the Task's register read/writing
319 * it into the byte buffer from START.
320 */
321 public void access(Register register, int offset, int length,
322 byte[] bytes, int start, boolean write) {
323 getRegisterBanks().access(register, offset, length, bytes,
324 start, write);
325 }
326
327 /**
328 * Return this task's register banks.
329 */
330 protected abstract RegisterBanks getRegisterBanks();
331
332 /**
333 * Return the machine's register banks as an array of ByteBuffers.
334 *
335 * XXX: This is wrong. Clients cannot assume internal register
336 * layout.
337 */
338 public ByteBuffer[] getRegisterBuffersFIXME() {
339 return getRegisterBanks().getBanksFIXME();
340 }
341
342 /**
343 * Use a counter rather than a boolean because multiple caches may
344 * depend on this count and no cache should be able to clear it.
345 */
346 public abstract int getMod();
347
348 protected void clearIsa() {
349 syscallTable = null;
350 signalTable = null;
351 }
352
353
354 /**
355 * Return a table of known (and unknown) signals for this ISA.
356 */
357 public SignalTable getSignalTable() {
358 if (signalTable == null) {
359 signalTable = SignalTableFactory.getSignalTable(getISA());
360 }
361 return signalTable;
362 }
363 private SignalTable signalTable;
364
365 public int compareTo(Object o) {
366 Task other = (Task)o;
367 int comp = getProc().compareTo(other.getProc());
368 if (comp == 0)
369 comp = getTid() - other.getTid();
370 return comp;
371 }
372 }