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    }