use new version of the macros - and add wip changes for newaddtask and remtask
[AROS.git] / rom / exec / newaddtask.c
blobb253aa4eecff2e61c64f025783d266d093e05f52
1 /*
2 Copyright © 1995-2015, 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.
178 #if defined(__AROSEXEC_SMP__)
179 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskReadySpinLock, SPINLOCK_MODE_WRITE);
180 #endif
181 Disable();
183 /* Add the new task to the ready list. */
184 task->tc_State=TS_READY;
185 Enqueue(&SysBase->TaskReady,&task->tc_Node);
186 #if defined(__AROSEXEC_SMP__)
187 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
188 #endif
191 Determine if a task switch is necessary. (If the new task has a
192 higher priority than the current one and the current one
193 is still active.) If the current task isn't of type TS_RUN it
194 is already gone.
197 if (task->tc_Node.ln_Pri > GET_THIS_TASK->tc_Node.ln_Pri &&
198 GET_THIS_TASK->tc_State == TS_RUN)
200 D(bug("[AddTask] Rescheduling...\n"));
202 /* Reschedule() will take care about disabled task switching automatically */
203 Reschedule();
206 Enable();
208 DADDTASK("Added task 0x%p", task);
209 return task;
211 AROS_LIBFUNC_EXIT
212 } /* NewAddTask */