update copyright
[AROS.git] / rom / exec / newaddtask.c
blobc1e652a4655927704c7a24d97ad51cfb3bac8e19
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 if (!InitETask(task))
126 return NULL;
128 /* Get new stackpointer. */
129 if (task->tc_SPReg==NULL)
130 task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET;
132 #ifdef AROS_STACKALIGN
133 if ((IPTR)task->tc_SPReg & (AROS_STACKALIGN - 1))
135 DADDTASK("NewAddTask with unaligned stack pointer (0x%p)! Fixing...", task->tc_SPReg);
136 task->tc_SPReg = (APTR)((IPTR)task->tc_SPReg & ~(AROS_STACKALIGN - 1));
138 #endif
139 DADDTASK("NewAddTask: SPLower: 0x%p SPUpper: 0x%p SP: 0x%p", task->tc_SPLower, task->tc_SPUpper, task->tc_SPReg);
141 if (task->tc_Flags & TF_STACKCHK)
143 UBYTE *startfill, *endfill;
145 startfill = (UBYTE *)task->tc_SPLower;
146 endfill = ((UBYTE *)task->tc_SPReg) - 16;
148 while(startfill <= endfill)
150 *startfill++ = 0xE1;
154 /* Default finalizer? */
155 if(finalPC==NULL)
156 finalPC=SysBase->TaskExitCode;
158 /* Init new context. */
159 if (!PrepareContext(task, initialPC, finalPC, tagList, SysBase))
161 CleanupETask(task);
162 return NULL;
165 /* Set the task flags for switch and launch. */
166 if(task->tc_Switch)
167 task->tc_Flags|=TF_SWITCH;
169 if(task->tc_Launch)
170 task->tc_Flags|=TF_LAUNCH;
173 Protect the task lists. This must be done with Disable() because
174 of Signal() which is usable from interrupts and may change those
175 lists.
177 Disable();
179 /* Add the new task to the ready list. */
180 task->tc_State=TS_READY;
181 Enqueue(&SysBase->TaskReady,&task->tc_Node);
184 Determine if a task switch is necessary. (If the new task has a
185 higher priority than the current one and the current one
186 is still active.) If the current task isn't of type TS_RUN it
187 is already gone.
190 if (task->tc_Node.ln_Pri > SysBase->ThisTask->tc_Node.ln_Pri &&
191 SysBase->ThisTask->tc_State == TS_RUN)
193 D(bug("[AddTask] Rescheduling...\n"));
195 /* Reschedule() will take care about disabled task switching automatically */
196 Reschedule();
199 Enable();
201 DADDTASK("Added task 0x%p", task);
202 return task;
204 AROS_LIBFUNC_EXIT
205 } /* NewAddTask */