only bring in as many sdl things as are strictly necessary
[tangerine.git] / arch / ppc-sam440 / exec / newaddtask.c
blobdbbefa8f92b46b090149308444382d0c66305e9b
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"
18 #ifndef DEBUG_AddTask
19 # define DEBUG_AddTask 0
20 #endif
21 #undef DEBUG
22 #if DEBUG_AddTask
23 # define DEBUG 1
24 #endif
25 #include <aros/debug.h>
27 void AROS_SLIB_ENTRY(TrapHandler,Exec)(void);
29 /*****************************************************************************
31 NAME */
33 AROS_LH4(APTR, NewAddTask,
35 /* SYNOPSIS */
36 AROS_LHA(struct Task *, task, A1),
37 AROS_LHA(APTR, initialPC, A2),
38 AROS_LHA(APTR, finalPC, A3),
39 AROS_LHA(struct TagItem *, tagList, A4),
41 /* LOCATION */
42 struct ExecBase *, SysBase, 152, Exec)
44 /* FUNCTION
45 Add a new task to the system. If the new task has the highest
46 priority of all and task switches are allowed it will be started
47 immediately.
48 Certain task fields should be intitialized and a stack must be
49 allocated before calling this function. tc_SPReg will be used as the
50 starting location for the stack pointer, i.e. a part of the stack can
51 be reserved to pass the task some initial arguments.
52 Memory can be added to the tc_MemEntry list and will be freed when the
53 task dies. The new task's registers are set to 0.
55 INPUTS
56 task - Pointer to task structure.
57 initialPC - Entry point for the new task.
58 finalPC - Routine that is called if the initialPC() function returns.
59 A NULL pointer installs the default finalizer.
61 RESULT
62 The address of the new task or NULL if the operation failed (can only
63 happen with TF_ETASK set - currenty not implemented).
65 NOTES
67 EXAMPLE
69 BUGS
71 SEE ALSO
72 RemTask()
74 INTERNALS
76 HISTORY
78 ******************************************************************************/
80 AROS_LIBFUNC_INIT
81 /* APTR sp; */
83 D(bug("[exec] Call NewAddTask (%012lx (\"%s\"), %012lx, %012lx)\n"
84 , task
85 , task->tc_Node.ln_Name
86 , initialPC
87 , finalPC
88 ));
89 ASSERT_VALID_PTR(task);
91 /* Set node type to NT_TASK if not set to something else. */
92 if(!task->tc_Node.ln_Type)
93 task->tc_Node.ln_Type=NT_TASK;
95 /* Sigh - you should provide a name for your task. */
96 if(task->tc_Node.ln_Name==NULL)
97 task->tc_Node.ln_Name="unknown task";
99 /* This is moved into SysBase at the tasks's startup */
100 task->tc_IDNestCnt=-1;
101 task->tc_TDNestCnt=-1;
103 task->tc_State = TS_ADDED;
104 task->tc_Flags = 0;
106 task->tc_SigWait = 0;
107 task->tc_SigRecvd = 0;
108 task->tc_SigExcept = 0;
110 /* Signals default to all system signals allocated. */
111 if(task->tc_SigAlloc==0)
112 task->tc_SigAlloc=SysBase->TaskSigAlloc;
114 /* Currently only used for segmentation violation */
115 if(task->tc_TrapCode==NULL)
116 task->tc_TrapCode=SysBase->TaskTrapCode;
118 if(task->tc_ExceptCode==NULL)
119 task->tc_ExceptCode=SysBase->TaskExceptCode;
121 task->tc_Flags |= TF_ETASK;
124 * We don't add this to the task memory, it isn't free'd by
125 * RemTask(), rather by somebody else calling ChildFree().
126 * Alternatively, an orphaned task will free its own ETask.
128 task->tc_UnionETask.tc_ETask = AllocVec
130 sizeof (struct IntETask),
131 MEMF_ANY|MEMF_CLEAR
134 if (!task->tc_UnionETask.tc_ETask)
135 return NULL;
137 InitETask(task, task->tc_UnionETask.tc_ETask);
139 /* Get new stackpointer. */
140 /* sp=task->tc_SPReg; */
141 if (task->tc_SPReg==NULL)
142 #if AROS_STACK_GROWS_DOWNWARDS
143 task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET;
144 #else
145 task->tc_SPReg = (UBYTE *)(task->tc_SPLower) - SP_OFFSET;
146 #endif
148 if ((IPTR)task->tc_SPReg & 0xf)
150 bug("[exec] NewAddTask with unaligned stack pointer! fixing %08x->%08x\n",
151 task->tc_SPReg, (IPTR)task->tc_SPReg & 0xfffffff0);
153 task->tc_SPReg = (APTR)((IPTR)task->tc_SPReg & 0xfffffff0);
156 #if AROS_STACK_DEBUG
158 UBYTE *startfill, *endfill;
160 #if AROS_STACK_GROWS_DOWNWARDS
161 startfill = (UBYTE *)task->tc_SPLower;
162 endfill = ((UBYTE *)task->tc_SPReg) - 16;
163 #else
164 startfill = ((UBYTE *)task->tc_SPReg) + 16;
165 endfill = ((UBYTE *)task->tc_SPUpper) - 1; /* FIXME: -1 correct ?? */
166 #endif
168 while(startfill <= endfill)
170 *startfill++ = 0xE1;
174 #endif
176 /* Default finalizer? */
177 if(finalPC==NULL)
178 finalPC=SysBase->TaskExitCode;
180 /* Init new context. */
181 if (!PrepareContext (task, initialPC, finalPC, tagList))
183 FreeTaskMem (task, task->tc_UnionETask.tc_ETask);
184 return NULL;
187 /* store sp */
188 /* task->tc_SPReg=sp; */
190 /* Set the task flags for switch and launch. */
191 if(task->tc_Switch)
192 task->tc_Flags|=TF_SWITCH;
194 if(task->tc_Launch)
195 task->tc_Flags|=TF_LAUNCH;
197 /* tc_MemEntry _must_ already be set. */
200 Protect the task lists. This must be done with Disable() because
201 of Signal() which is usable from interrupts and may change those
202 lists.
204 Disable();
206 /* Add the new task to the ready list. */
207 task->tc_State=TS_READY;
208 Enqueue(&SysBase->TaskReady,&task->tc_Node);
211 Determine if a task switch is necessary. (If the new task has a
212 higher priority than the current one and the current one
213 is still active.) If the current task isn't of type TS_RUN it
214 is already gone.
217 if(task->tc_Node.ln_Pri>SysBase->ThisTask->tc_Node.ln_Pri&&
218 SysBase->ThisTask->tc_State==TS_RUN)
220 /* Are taskswitches allowed? (Don't count own Disable() here) */
221 if(SysBase->TDNestCnt>=0||SysBase->IDNestCnt>0)
222 /* No. Store it for later. */
223 SysBase->AttnResched|=0x80;
224 else
226 /* Force a reschedule. */
227 Reschedule(task);
231 Enable();
233 ReturnPtr ("NewAddTask", struct Task *, task);
234 AROS_LIBFUNC_EXIT
235 } /* NewAddTask */