Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / i386-pc / exec / newaddtask.c
blob78853691e5b398d6cfb0a34228fda3265a3a150b
1 /*
2 Copyright © 1995-2009, 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 void AROS_SLIB_ENTRY(TrapHandler,Exec)(void);
28 /*****************************************************************************
30 NAME */
32 AROS_LH4(APTR, NewAddTask,
34 /* SYNOPSIS */
35 AROS_LHA(struct Task *, task, A1),
36 AROS_LHA(APTR, initialPC, A2),
37 AROS_LHA(APTR, finalPC, A3),
38 AROS_LHA(struct TagItem *, tagList, A4),
40 /* LOCATION */
41 struct ExecBase *, SysBase, 152, Exec)
43 /* FUNCTION
44 Add a new task to the system. If the new task has the highest
45 priority of all and task switches are allowed it will be started
46 immediately.
47 Certain task fields should be intitialized and a stack must be
48 allocated before calling this function. tc_SPReg will be used as the
49 starting location for the stack pointer, i.e. a part of the stack can
50 be reserved to pass the task some initial arguments.
51 Memory can be added to the tc_MemEntry list and will be freed when the
52 task dies. The new task's registers are set to 0.
54 INPUTS
55 task - Pointer to task structure.
56 initialPC - Entry point for the new task.
57 finalPC - Routine that is called if the initialPC() function returns.
58 A NULL pointer installs the default finalizer.
60 RESULT
61 The address of the new task or NULL if the operation failed (can only
62 happen with TF_ETASK set - currenty not implemented).
64 NOTES
66 EXAMPLE
68 BUGS
70 SEE ALSO
71 RemTask()
73 INTERNALS
75 HISTORY
77 ******************************************************************************/
79 AROS_LIBFUNC_INIT
80 /* APTR sp; */
82 D(bug("Call NewAddTask (%08lx (\"%s\"), %08lx, %08lx)\n"
83 , task
84 , task->tc_Node.ln_Name
85 , initialPC
86 , finalPC
87 ));
88 ASSERT_VALID_PTR(task);
90 /* Set node type to NT_TASK if not set to something else. */
91 if(!task->tc_Node.ln_Type)
92 task->tc_Node.ln_Type=NT_TASK;
94 /* Sigh - you should provide a name for your task. */
95 if(task->tc_Node.ln_Name==NULL)
96 task->tc_Node.ln_Name="unknown task";
98 /* This is moved into SysBase at the tasks's startup */
99 task->tc_IDNestCnt=-1;
100 task->tc_TDNestCnt=-1;
102 task->tc_State = TS_ADDED;
103 task->tc_Flags = 0;
105 task->tc_SigWait = 0;
106 task->tc_SigRecvd = 0;
107 task->tc_SigExcept = 0;
109 /* Signals default to all system signals allocated. */
110 if(task->tc_SigAlloc==0)
111 task->tc_SigAlloc=SysBase->TaskSigAlloc;
113 /* Currently only used for segmentation violation */
114 if(task->tc_TrapCode==NULL)
115 task->tc_TrapCode=SysBase->TaskTrapCode;
117 if(task->tc_ExceptCode==NULL)
118 task->tc_ExceptCode=SysBase->TaskExceptCode;
120 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
122 If you can't to store the registers on the signal stack, you
123 must set this flag.
125 task->tc_Flags |= TF_ETASK;
126 #endif
128 /* Allocate the ETask structure if requested */
129 if (task->tc_Flags & TF_ETASK)
132 * We don't add this to the task memory, it isn't free'd by
133 * RemTask(), rather by somebody else calling ChildFree().
134 * Alternatively, an orphaned task will free its own ETask.
136 task->tc_UnionETask.tc_ETask = AllocVec
138 sizeof (struct IntETask),
139 MEMF_ANY|MEMF_CLEAR
142 if (!task->tc_UnionETask.tc_ETask)
143 return NULL;
145 InitETask(task, task->tc_UnionETask.tc_ETask);
148 /* Get new stackpointer. */
149 /* sp=task->tc_SPReg; */
150 if (task->tc_SPReg==NULL)
151 #if AROS_STACK_GROWS_DOWNWARDS
152 task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET;
153 #else
154 task->tc_SPReg = (UBYTE *)(task->tc_SPLower) - SP_OFFSET;
155 #endif
157 #if AROS_STACK_DEBUG
159 UBYTE *startfill, *endfill;
161 #if AROS_STACK_GROWS_DOWNWARDS
162 startfill = (UBYTE *)task->tc_SPLower;
163 endfill = ((UBYTE *)task->tc_SPReg) - 16;
164 #else
165 startfill = ((UBYTE *)task->tc_SPReg) + 16;
166 endfill = ((UBYTE *)task->tc_SPUpper) - 1; /* FIXME: -1 correct ?? */
167 #endif
169 while(startfill <= endfill)
171 *startfill++ = 0xE1;
175 #endif
177 /* Default finalizer? */
178 if(finalPC==NULL)
179 finalPC=SysBase->TaskExitCode;
181 /* Init new context. */
182 if (!PrepareContext (task, initialPC, finalPC, tagList))
184 FreeTaskMem (task, task->tc_UnionETask.tc_ETask);
185 return NULL;
188 /* store sp */
189 /* task->tc_SPReg=sp; */
191 /* Set the task flags for switch and launch. */
192 if(task->tc_Switch)
193 task->tc_Flags|=TF_SWITCH;
195 if(task->tc_Launch)
196 task->tc_Flags|=TF_LAUNCH;
198 /* tc_MemEntry _must_ already be set. */
201 Protect the task lists. This must be done with Disable() because
202 of Signal() which is usable from interrupts and may change those
203 lists.
205 Disable();
207 /* Add the new task to the ready list. */
208 task->tc_State=TS_READY;
209 Enqueue(&SysBase->TaskReady,&task->tc_Node);
212 Determine if a task switch is necessary. (If the new task has a
213 higher priority than the current one and the current one
214 is still active.) If the current task isn't of type TS_RUN it
215 is already gone.
218 if(task->tc_Node.ln_Pri>SysBase->ThisTask->tc_Node.ln_Pri&&
219 SysBase->ThisTask->tc_State==TS_RUN)
221 /* Are taskswitches allowed? (Don't count own Disable() here) */
222 if(SysBase->TDNestCnt>=0||SysBase->IDNestCnt>0)
223 /* No. Store it for later. */
224 SysBase->AttnResched|=0x80;
225 else
227 /* Switches are allowed. Move the current task away. */
228 //SysBase->ThisTask->tc_State=TS_READY;
229 //Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
231 /* And force a reschedule. */
232 Reschedule(task);
233 // Supervisor(Exec_Switch); //Switch();
237 /* if(SysBase->TaskReady.lh_Head->ln_Succ == task)
238 Reschedule(task);*/
239 Enable();
241 ReturnPtr ("NewAddTask", struct Task *, task);
242 AROS_LIBFUNC_EXIT
243 } /* NewAddTask */