2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
9 #include <aros/config.h>
10 #include <exec/execbase.h>
11 #include <exec/memory.h>
12 #include <utility/tagitem.h>
13 #include <aros/libcall.h>
14 #include <proto/exec.h>
16 #include "exec_util.h"
18 #include "exec_debug.h"
20 # define DEBUG_AddTask 0
26 #include <aros/debug.h>
28 /*****************************************************************************
32 AROS_LH4(APTR
, NewAddTask
,
35 AROS_LHA(struct Task
*, task
, A1
),
36 AROS_LHA(APTR
, initialPC
, A2
),
37 AROS_LHA(APTR
, finalPC
, A3
),
38 AROS_LHA(struct TagItem
*, tagList
, A4
),
41 struct ExecBase
*, SysBase
, 176, Exec
)
44 Add a new task to the system. If the new task has the highest
45 priority of all and task switches are allowed it will be started
47 Certain task fields should be intitialized and a stack must be
48 allocated before calling this function. tc_SPReg will be used as the
49 starting location for the stack pointer, i.e. a part of the stack can
50 be reserved to pass the task some initial arguments.
51 Memory can be added to the tc_MemEntry list and will be freed when the
52 task dies. The new task's registers are set to 0.
55 task - Pointer to task structure.
56 initialPC - Entry point for the new task.
57 finalPC - Routine that is called if the initialPC() function returns.
58 A NULL pointer installs the default finalizer.
61 The address of the new task or NULL if the operation failed (can only
62 happen with TF_ETASK set - currenty not implemented).
77 ******************************************************************************/
82 D(bug("Call NewAddTask (%08lx (\"%s\"), %08lx, %08lx)\n"
84 , task
->tc_Node
.ln_Name
88 ASSERT_VALID_PTR(task
);
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 /* Sigh - you should provide a name for your task. */
95 if(task
->tc_Node
.ln_Name
==NULL
)
96 task
->tc_Node
.ln_Name
="unknown task";
98 /* This is moved into SysBase at the tasks's startup */
99 task
->tc_IDNestCnt
=-1;
100 task
->tc_TDNestCnt
=-1;
102 task
->tc_State
= TS_ADDED
;
105 task
->tc_SigWait
= 0;
106 task
->tc_SigRecvd
= 0;
107 task
->tc_SigExcept
= 0;
109 /* Signals default to all system signals allocated. */
110 if(task
->tc_SigAlloc
==0)
111 task
->tc_SigAlloc
=SysBase
->TaskSigAlloc
;
113 /* Use default exception handler if unset by caller */
114 if(task
->tc_TrapCode
==NULL
)
115 task
->tc_TrapCode
=SysBase
->TaskTrapCode
;
117 if(task
->tc_ExceptCode
==NULL
)
118 task
->tc_ExceptCode
=SysBase
->TaskExceptCode
;
120 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
122 If you can't store the registers on the signal stack, you
125 task
->tc_Flags
|= TF_ETASK
;
128 /* Allocate the ETask structure if requested */
129 if (task
->tc_Flags
& TF_ETASK
)
132 * We don't add this to the task memory, it isn't free'd by
133 * RemTask(), rather by somebody else calling ChildFree().
134 * Alternatively, an orphaned task will free its own ETask.
136 task
->tc_UnionETask
.tc_ETask
= AllocVec
138 sizeof (struct IntETask
),
142 if (!task
->tc_UnionETask
.tc_ETask
)
145 InitETask(task
, task
->tc_UnionETask
.tc_ETask
);
148 /* Get new stackpointer. */
149 /* sp=task->tc_SPReg; */
150 if (task
->tc_SPReg
==NULL
)
151 task
->tc_SPReg
= (UBYTE
*)(task
->tc_SPUpper
) - SP_OFFSET
;
155 UBYTE
*startfill
, *endfill
;
157 startfill
= (UBYTE
*)task
->tc_SPLower
;
158 endfill
= ((UBYTE
*)task
->tc_SPReg
) - 16;
160 while(startfill
<= endfill
)
168 /* Default finalizer? */
170 finalPC
=SysBase
->TaskExitCode
;
172 /* Init new context. */
173 if (!PrepareContext (task
, initialPC
, finalPC
, tagList
))
175 FreeTaskMem (task
, task
->tc_UnionETask
.tc_ETask
);
180 /* task->tc_SPReg=sp; */
182 /* Set the task flags for switch and launch. */
184 task
->tc_Flags
|=TF_SWITCH
;
187 task
->tc_Flags
|=TF_LAUNCH
;
189 /* tc_MemEntry _must_ already be set. */
192 Protect the task lists. This must be done with Disable() because
193 of Signal() which is usable from interrupts and may change those
198 /* Add the new task to the ready list. */
199 task
->tc_State
=TS_READY
;
200 Enqueue(&SysBase
->TaskReady
,&task
->tc_Node
);
203 Determine if a task switch is necessary. (If the new task has a
204 higher priority than the current one and the current one
205 is still active.) If the current task isn't of type TS_RUN it
209 if(task
->tc_Node
.ln_Pri
>SysBase
->ThisTask
->tc_Node
.ln_Pri
&&
210 SysBase
->ThisTask
->tc_State
==TS_RUN
)
212 /* Are taskswitches allowed? (Don't count own Disable() here) */
213 if(SysBase
->TDNestCnt
>=0||SysBase
->IDNestCnt
>0)
214 /* No. Store it for later. */
215 SysBase
->AttnResched
|=0x80;
218 /* Switches are allowed. Move the current task away. */
219 //SysBase->ThisTask->tc_State=TS_READY;
220 //Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
222 /* And force a reschedule. */
224 // Supervisor(Exec_Switch); //Switch();
228 /* if(SysBase->TaskReady.lh_Head->ln_Succ == task)
232 ReturnPtr ("NewAddTask", struct Task
*, task
);