Moved DisplayError() back to base code
[AROS.git] / rom / exec / newaddtask.c
blob854d88bbbadafa099a7ed2c065136c714689e2d2
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Add a task.
6 Lang: english
7 */
9 #include <exec/execbase.h>
10 #include <exec/memory.h>
11 #include <utility/tagitem.h>
12 #include <aros/debug.h>
13 #include <aros/libcall.h>
14 #include <proto/exec.h>
16 #include "etask.h"
17 #include "exec_util.h"
18 #include "exec_debug.h"
19 #include "taskstorage.h"
21 /*****************************************************************************
23 NAME */
25 AROS_LH4(APTR, NewAddTask,
27 /* SYNOPSIS */
28 AROS_LHA(struct Task *, task, A1),
29 AROS_LHA(APTR, initialPC, A2),
30 AROS_LHA(APTR, finalPC, A3),
31 AROS_LHA(struct TagItem *, tagList, A4),
33 /* LOCATION */
34 struct ExecBase *, SysBase, 176, Exec)
36 /* FUNCTION
37 Add a new task to the system. If the new task has the highest
38 priority of all and task switches are allowed it will be started
39 immediately.
40 Certain task fields should be intitialized and a stack must be
41 allocated before calling this function. tc_SPReg will be used as the
42 starting location for the stack pointer, i.e. a part of the stack can
43 be reserved to pass the task some initial arguments.
44 Memory can be added to the tc_MemEntry list and will be freed when the
45 task dies. The new task's registers are set to 0.
47 INPUTS
48 task - Pointer to task structure.
49 initialPC - Entry point for the new task.
50 finalPC - Routine that is called if the initialPC() function returns.
51 A NULL pointer installs the default finalizer.
53 RESULT
54 The address of the new task or NULL if the operation failed (can only
55 happen with TF_ETASK set - currenty not implemented).
57 NOTES
58 This function is private. Use MorphOS-compatible NewCreateTaskA()
59 in your applications.
61 EXAMPLE
63 BUGS
65 SEE ALSO
66 RemTask()
68 INTERNALS
70 HISTORY
72 ******************************************************************************/
74 AROS_LIBFUNC_INIT
76 ASSERT_VALID_PTR(task);
78 /* Sigh - you should provide a name for your task. */
79 if(task->tc_Node.ln_Name==NULL)
80 task->tc_Node.ln_Name="unknown task";
82 DADDTASK("NewAddTask (0x%p (\"%s\"), 0x%p, 0x%p)", task, task->tc_Node.ln_Name, initialPC, finalPC);
84 /* Initialize the memory entry list if the caller forgot */
85 if (!task->tc_MemEntry.lh_Head)
86 NEWLIST(&task->tc_MemEntry);
88 DADDTASK("NewAddTask MemEntry head: 0x%p", GetHead(&task->tc_MemEntry.lh_Head));
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 /* This is moved into SysBase at the tasks's startup */
95 task->tc_IDNestCnt=-1;
96 task->tc_TDNestCnt=-1;
98 task->tc_State = TS_ADDED;
99 task->tc_Flags = 0;
101 task->tc_SigWait = 0;
102 task->tc_SigRecvd = 0;
103 task->tc_SigExcept = 0;
105 /* Signals default to all system signals allocated. */
106 if(task->tc_SigAlloc==0)
107 task->tc_SigAlloc=SysBase->TaskSigAlloc;
109 /* Currently only used for segmentation violation */
110 if(task->tc_TrapCode==NULL)
111 task->tc_TrapCode=SysBase->TaskTrapCode;
113 if(task->tc_ExceptCode==NULL)
114 task->tc_ExceptCode=SysBase->TaskExceptCode;
117 * EXECF_StackSnoop can be set or reset at runtime.
118 * However task's stack is either snooped or not, it's problematic
119 * to turn it on at runtime. So we initialize it when the task starts up.
121 if (PrivExecBase(SysBase)->IntFlags & EXECF_StackSnoop)
122 task->tc_Flags |= TF_STACKCHK;
124 /* Initialize ETask */
125 InitETask(task);
126 if (!task->tc_UnionETask.tc_ETask)
127 return NULL;
129 /* Get new stackpointer. */
130 if (task->tc_SPReg==NULL)
131 task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET;
133 #ifdef AROS_STACKALIGN
134 if ((IPTR)task->tc_SPReg & (AROS_STACKALIGN - 1))
136 DADDTASK("NewAddTask with unaligned stack pointer (0x%p)! Fixing...", task->tc_SPReg);
137 task->tc_SPReg = (APTR)((IPTR)task->tc_SPReg & ~(AROS_STACKALIGN - 1));
139 #endif
140 DADDTASK("NewAddTask: SPLower: 0x%p SPUpper: 0x%p SP: 0x%p", task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
142 if (task->tc_Flags & TF_STACKCHK)
144 UBYTE *startfill, *endfill;
146 startfill = (UBYTE *)task->tc_SPLower;
147 endfill = ((UBYTE *)task->tc_SPReg) - 16;
149 while(startfill <= endfill)
151 *startfill++ = 0xE1;
155 /* Default finalizer? */
156 if(finalPC==NULL)
157 finalPC=SysBase->TaskExitCode;
159 /* Init new context. */
160 if (!PrepareContext(task, initialPC, finalPC, tagList, SysBase))
162 CleanupETask(task);
163 return NULL;
166 /* Set the task flags for switch and launch. */
167 if(task->tc_Switch)
168 task->tc_Flags|=TF_SWITCH;
170 if(task->tc_Launch)
171 task->tc_Flags|=TF_LAUNCH;
174 Protect the task lists. This must be done with Disable() because
175 of Signal() which is usable from interrupts and may change those
176 lists.
178 Disable();
180 /* Add the new task to the ready list. */
181 task->tc_State=TS_READY;
182 Enqueue(&SysBase->TaskReady,&task->tc_Node);
185 Determine if a task switch is necessary. (If the new task has a
186 higher priority than the current one and the current one
187 is still active.) If the current task isn't of type TS_RUN it
188 is already gone.
191 if (task->tc_Node.ln_Pri > SysBase->ThisTask->tc_Node.ln_Pri &&
192 SysBase->ThisTask->tc_State == TS_RUN)
194 D(bug("[AddTask] Rescheduling...\n"));
196 /* Reschedule() will take care about disabled task switching automatically */
197 Reschedule();
200 Enable();
202 DADDTASK("Added task 0x%p", task);
203 return task;
205 AROS_LIBFUNC_EXIT
206 } /* NewAddTask */