added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / ppc-sam440 / exec / newaddtask.c
blob57cdb8d01aca254b9a28c21392b960d226bd6ede
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"
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 /* if #define fills the unused stack with 0xE1 */
28 #define STACKSNOOP
30 void AROS_SLIB_ENTRY(TrapHandler,Exec)(void);
32 /*****************************************************************************
34 NAME */
36 AROS_LH4(APTR, NewAddTask,
38 /* SYNOPSIS */
39 AROS_LHA(struct Task *, task, A1),
40 AROS_LHA(APTR, initialPC, A2),
41 AROS_LHA(APTR, finalPC, A3),
42 AROS_LHA(struct TagItem *, tagList, A4),
44 /* LOCATION */
45 struct ExecBase *, SysBase, 152, Exec)
47 /* FUNCTION
48 Add a new task to the system. If the new task has the highest
49 priority of all and task switches are allowed it will be started
50 immediately.
51 Certain task fields should be intitialized and a stack must be
52 allocated before calling this function. tc_SPReg will be used as the
53 starting location for the stack pointer, i.e. a part of the stack can
54 be reserved to pass the task some initial arguments.
55 Memory can be added to the tc_MemEntry list and will be freed when the
56 task dies. The new task's registers are set to 0.
58 INPUTS
59 task - Pointer to task structure.
60 initialPC - Entry point for the new task.
61 finalPC - Routine that is called if the initialPC() function returns.
62 A NULL pointer installs the default finalizer.
64 RESULT
65 The address of the new task or NULL if the operation failed (can only
66 happen with TF_ETASK set - currenty not implemented).
68 NOTES
70 EXAMPLE
72 BUGS
74 SEE ALSO
75 RemTask()
77 INTERNALS
79 HISTORY
81 ******************************************************************************/
83 AROS_LIBFUNC_INIT
84 /* APTR sp; */
86 D(bug("[exec] Call NewAddTask (%012lx (\"%s\"), %012lx, %012lx)\n"
87 , task
88 , task->tc_Node.ln_Name
89 , initialPC
90 , finalPC
91 ));
92 ASSERT_VALID_PTR(task);
94 /* Set node type to NT_TASK if not set to something else. */
95 if(!task->tc_Node.ln_Type)
96 task->tc_Node.ln_Type=NT_TASK;
98 /* Sigh - you should provide a name for your task. */
99 if(task->tc_Node.ln_Name==NULL)
100 task->tc_Node.ln_Name="unknown task";
102 /* This is moved into SysBase at the tasks's startup */
103 task->tc_IDNestCnt=-1;
104 task->tc_TDNestCnt=-1;
106 task->tc_State = TS_ADDED;
107 task->tc_Flags = 0;
109 task->tc_SigWait = 0;
110 task->tc_SigRecvd = 0;
111 task->tc_SigExcept = 0;
113 /* Signals default to all system signals allocated. */
114 if(task->tc_SigAlloc==0)
115 task->tc_SigAlloc=SysBase->TaskSigAlloc;
117 /* Currently only used for segmentation violation */
118 if(task->tc_TrapCode==NULL)
119 task->tc_TrapCode=SysBase->TaskTrapCode;
121 if(task->tc_ExceptCode==NULL)
122 task->tc_ExceptCode=SysBase->TaskExceptCode;
124 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
126 If you can't to store the registers on the signal stack, you
127 must set this flag.
129 task->tc_Flags |= TF_ETASK;
130 #endif
132 /* Allocate the ETask structure if requested */
133 if (task->tc_Flags & TF_ETASK)
135 task->tc_UnionETask.tc_ETask = AllocTaskMem (task
136 , sizeof (struct IntETask)
137 , MEMF_ANY|MEMF_CLEAR
140 if (!task->tc_UnionETask.tc_ETask)
141 return NULL;
143 /* I'm the parent task */
144 GetETask(task)->et_Parent = FindTask(NULL);
147 /* Get new stackpointer. */
148 /* sp=task->tc_SPReg; */
149 if (task->tc_SPReg==NULL)
150 #if AROS_STACK_GROWS_DOWNWARDS
151 task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET;
152 #else
153 task->tc_SPReg = (UBYTE *)(task->tc_SPLower) - SP_OFFSET;
154 #endif
156 #ifdef STACKSNOOP
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 */