Re-enabled use of AROS.Boot file due to lack of general enthusiasm for
[tangerine.git] / arch / i386-pc / exec / newaddtask.c
blob08ae194676f02427d554cc9b6d4e3747a302c861
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Add a task.
6 Lang: english
7 */
8 #include <exec/execbase.h>
9 #include <exec/memory.h>
10 #include <utility/tagitem.h>
11 #include <aros/libcall.h>
12 #include <proto/exec.h>
13 #include "etask.h"
14 #include "exec_util.h"
16 #include "exec_debug.h"
17 #ifndef DEBUG_AddTask
18 # define DEBUG_AddTask 0
19 #endif
20 #undef DEBUG
21 #if DEBUG_AddTask
22 # define DEBUG 1
23 #endif
24 #include <aros/debug.h>
26 /* if #define fills the unused stack with 0xE1 */
27 #define STACKSNOOP
29 void AROS_SLIB_ENTRY(TrapHandler,Exec)(void);
31 /*****************************************************************************
33 NAME */
35 AROS_LH4(APTR, NewAddTask,
37 /* SYNOPSIS */
38 AROS_LHA(struct Task *, task, A1),
39 AROS_LHA(APTR, initialPC, A2),
40 AROS_LHA(APTR, finalPC, A3),
41 AROS_LHA(struct TagItem *, tagList, A4),
43 /* LOCATION */
44 struct ExecBase *, SysBase, 152, Exec)
46 /* FUNCTION
47 Add a new task to the system. If the new task has the highest
48 priority of all and task switches are allowed it will be started
49 immediately.
50 Certain task fields should be intitialized and a stack must be
51 allocated before calling this function. tc_SPReg will be used as the
52 starting location for the stack pointer, i.e. a part of the stack can
53 be reserved to pass the task some initial arguments.
54 Memory can be added to the tc_MemEntry list and will be freed when the
55 task dies. The new task's registers are set to 0.
57 INPUTS
58 task - Pointer to task structure.
59 initialPC - Entry point for the new task.
60 finalPC - Routine that is called if the initialPC() function returns.
61 A NULL pointer installs the default finalizer.
63 RESULT
64 The address of the new task or NULL if the operation failed (can only
65 happen with TF_ETASK set - currenty not implemented).
67 NOTES
69 EXAMPLE
71 BUGS
73 SEE ALSO
74 RemTask()
76 INTERNALS
78 HISTORY
80 ******************************************************************************/
82 AROS_LIBFUNC_INIT
83 /* APTR sp; */
85 D(bug("Call NewAddTask (%08lx (\"%s\"), %08lx, %08lx)\n"
86 , task
87 , task->tc_Node.ln_Name
88 , initialPC
89 , finalPC
90 ));
91 ASSERT_VALID_PTR(task);
93 /* Set node type to NT_TASK if not set to something else. */
94 if(!task->tc_Node.ln_Type)
95 task->tc_Node.ln_Type=NT_TASK;
97 /* Sigh - you should provide a name for your task. */
98 if(task->tc_Node.ln_Name==NULL)
99 task->tc_Node.ln_Name="unknown task";
101 /* This is moved into SysBase at the tasks's startup */
102 task->tc_IDNestCnt=-1;
103 task->tc_TDNestCnt=-1;
105 task->tc_State = TS_ADDED;
106 task->tc_Flags = 0;
108 task->tc_SigWait = 0;
109 task->tc_SigRecvd = 0;
110 task->tc_SigExcept = 0;
112 /* Signals default to all system signals allocated. */
113 if(task->tc_SigAlloc==0)
114 task->tc_SigAlloc=SysBase->TaskSigAlloc;
116 /* Currently only used for segmentation violation */
117 if(task->tc_TrapCode==NULL)
118 task->tc_TrapCode=SysBase->TaskTrapCode;
120 if(task->tc_ExceptCode==NULL)
121 task->tc_ExceptCode=SysBase->TaskExceptCode;
123 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
125 If you can't to store the registers on the signal stack, you
126 must set this flag.
128 task->tc_Flags |= TF_ETASK;
129 #endif
131 /* Allocate the ETask structure if requested */
132 if (task->tc_Flags & TF_ETASK)
135 * We don't add this to the task memory, it isn't free'd by
136 * RemTask(), rather by somebody else calling ChildFree().
137 * Alternatively, an orphaned task will free its own ETask.
139 task->tc_UnionETask.tc_ETask = AllocVec
141 sizeof (struct IntETask),
142 MEMF_ANY|MEMF_CLEAR
145 if (!task->tc_UnionETask.tc_ETask)
146 return NULL;
148 InitETask(task, task->tc_UnionETask.tc_ETask);
151 /* Get new stackpointer. */
152 /* sp=task->tc_SPReg; */
153 if (task->tc_SPReg==NULL)
154 #if AROS_STACK_GROWS_DOWNWARDS
155 task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET;
156 #else
157 task->tc_SPReg = (UBYTE *)(task->tc_SPLower) - SP_OFFSET;
158 #endif
160 #ifdef STACKSNOOP
162 UBYTE *startfill, *endfill;
164 #if AROS_STACK_GROWS_DOWNWARDS
165 startfill = (UBYTE *)task->tc_SPLower;
166 endfill = ((UBYTE *)task->tc_SPReg) - 16;
167 #else
168 startfill = ((UBYTE *)task->tc_SPReg) + 16;
169 endfill = ((UBYTE *)task->tc_SPUpper) - 1; /* FIXME: -1 correct ?? */
170 #endif
172 while(startfill <= endfill)
174 *startfill++ = 0xE1;
178 #endif
180 /* Default finalizer? */
181 if(finalPC==NULL)
182 finalPC=SysBase->TaskExitCode;
184 /* Init new context. */
185 if (!PrepareContext (task, initialPC, finalPC, tagList))
187 FreeTaskMem (task, task->tc_UnionETask.tc_ETask);
188 return NULL;
191 /* store sp */
192 /* task->tc_SPReg=sp; */
194 /* Set the task flags for switch and launch. */
195 if(task->tc_Switch)
196 task->tc_Flags|=TF_SWITCH;
198 if(task->tc_Launch)
199 task->tc_Flags|=TF_LAUNCH;
201 /* tc_MemEntry _must_ already be set. */
204 Protect the task lists. This must be done with Disable() because
205 of Signal() which is usable from interrupts and may change those
206 lists.
208 Disable();
210 /* Add the new task to the ready list. */
211 task->tc_State=TS_READY;
212 Enqueue(&SysBase->TaskReady,&task->tc_Node);
215 Determine if a task switch is necessary. (If the new task has a
216 higher priority than the current one and the current one
217 is still active.) If the current task isn't of type TS_RUN it
218 is already gone.
221 if(task->tc_Node.ln_Pri>SysBase->ThisTask->tc_Node.ln_Pri&&
222 SysBase->ThisTask->tc_State==TS_RUN)
224 /* Are taskswitches allowed? (Don't count own Disable() here) */
225 if(SysBase->TDNestCnt>=0||SysBase->IDNestCnt>0)
226 /* No. Store it for later. */
227 SysBase->AttnResched|=0x80;
228 else
230 /* Switches are allowed. Move the current task away. */
231 //SysBase->ThisTask->tc_State=TS_READY;
232 //Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
234 /* And force a reschedule. */
235 Reschedule(task);
236 // Supervisor(Exec_Switch); //Switch();
240 /* if(SysBase->TaskReady.lh_Head->ln_Succ == task)
241 Reschedule(task);*/
242 Enable();
244 ReturnPtr ("NewAddTask", struct Task *, task);
245 AROS_LIBFUNC_EXIT
246 } /* NewAddTask */