2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Create a new task, improved version
9 #include <proto/arossupport.h>
10 #include <exec/memory.h>
11 #include <exec/execbase.h>
15 #include "exec_debug.h"
16 #include "exec_util.h"
22 struct MemEntry nml_ME
[4];
25 static const struct newMemList MemTemplate
=
30 {{MEMF_CLEAR
|MEMF_PUBLIC
}, sizeof(struct Task
) }, /* Task descriptor itself */
31 {{MEMF_CLEAR
}, AROS_STACKSIZE
}, /* Task's stack */
32 {{MEMF_CLEAR
|MEMF_PUBLIC
}, 0 }, /* Task name */
33 {{MEMF_PUBLIC
}, sizeof(struct MsgPort
)} /* Task's MsgPort */
37 /*****************************************************************************
40 #include <exec/tasks.h>
41 #include <proto/exec.h>
43 AROS_LH1(struct Task
*, NewCreateTaskA
,
46 AROS_LHA(struct TagItem
*, tags
, A0
),
49 struct ExecBase
*, SysBase
, 153, Exec
)
55 tags - TagList which may contain the following tags:
57 TASKTAG_ERROR (ULONG *) - a pointer to an optional location for secondary
58 return code. The code itself will be set to
59 TASKERROR_OK on success or TASKERROR_NOMEMORY on
61 TASKTAG_PC (APTR) - Start address of the task's code.
62 TAGKTAG_FINALPC (APTR) - Address of the finalization routine. Defaults to
63 SysBase->TaskExitCode.
64 TASKTAG_STACKSIZE (ULONG) - Size of task's stack. Defaults to CPU-dependent
66 TASKTAG_NAME (STRPTR) - A pointer to task name. The name will be copied.
67 TASKTAG_USERDATA (APTR) - Anything. Will be written into tc_UserData.
68 TASKTAG_PRI (BYTE) - Task's priority. Defaults to 0.
70 TASKTAG_ARG8 (IPTR) - Arguments (up to 8) which will be passed to task's
71 entry function. The arguments are supplied in
73 TASKTAG_FLAGS (ULONG) - Initial value for tc_Flags.
74 TASKTAG_TASKMSGPORT (struct MsgPort **)
75 - Create a message port for the task and place its
76 address into the location specified by ti_Data.
77 TASKTAG_TCBEXTRASIZE (ULONG) - Value which will be added to sizeof(struct Task)
78 in order to determine final size of task structure.
79 Can be used for appending user data to task structure.
82 A pointer to the new task or NULL on failure.
89 Value of TASKTAG_FLAGS is actually ignored.
90 There are some more tags which are currently not implemented.
98 ******************************************************************************/
102 struct Task
* newtask
;
103 struct newMemList nml
= MemTemplate
;
105 const struct TagItem
*tstate
= tags
;
107 struct MsgPort
**msgPortPtr
= NULL
;
108 ULONG
*errPtr
= NULL
;
110 APTR finalpc
= SysBase
->TaskExitCode
;
111 char *taskname
= NULL
;
112 APTR userdata
= NULL
;
116 while ((tag
= LibNextTagItem(&tstate
)))
121 errPtr
= (ULONG
*)tag
->ti_Data
;
125 initpc
= (APTR
)tag
->ti_Data
;
128 case TASKTAG_FINALPC
:
129 finalpc
= (APTR
)tag
->ti_Data
;
132 case TASKTAG_STACKSIZE
:
133 nml
.nml_ME
[1].me_Length
= AROS_ALIGN(tag
->ti_Data
);
137 taskname
= (char *)tag
->ti_Data
;
138 nml
.nml_ME
[2].me_Length
= strlen(taskname
) + 1;
139 if (nml
.nml_NumEntries
< 3)
140 nml
.nml_NumEntries
= 3;
143 case TASKTAG_USERDATA
:
144 userdata
= (APTR
)tag
->ti_Data
;
151 case TASKTAG_TASKMSGPORT
:
152 msgPortPtr
= (struct MsgPort
**)tag
->ti_Data
;
153 if (nml
.nml_NumEntries
< 4)
154 nml
.nml_NumEntries
= 4;
158 flags
= tag
->ti_Data
;
161 case TASKTAG_TCBEXTRASIZE
:
162 nml
.nml_ME
[0].me_Length
+= tag
->ti_Data
;
167 DADDTASK("NewCreateTaskA: name %s", taskname
? taskname
: "<NULL>");
169 ml
= NewAllocEntry((struct MemList
*)&nml
, NULL
);
172 struct Task
*task2
= NULL
;
173 APTR name
= ml
->ml_ME
[2].me_Addr
;
176 strcpy(name
, taskname
);
178 newtask
= ml
->ml_ME
[0].me_Addr
;
180 newtask
->tc_Node
.ln_Type
= NT_TASK
;
181 newtask
->tc_Node
.ln_Pri
= pri
;
182 newtask
->tc_Node
.ln_Name
= name
;
184 if (nml
.nml_NumEntries
== 4)
187 * The caller asked us to create an MsgPort for the task.
188 * We can't reuse ETask's one because it's used for notifications about child tasks.
189 * We don't check against msgPortPtr == NULL because in future we can have MorphOS-compatible
192 struct MsgPort
*mp
= ml
->ml_ME
[3].me_Addr
;
196 * Allocate a signal for the port.
197 * Set tc_SigAlloc early for AllocTaskSignal() to work.
199 newtask
->tc_SigAlloc
= SysBase
->TaskSigAlloc
;
200 sig
= AllocTaskSignal(newtask
, -1, SysBase
);
204 DADDTASK("NewCreateTaskA: Failed to allocate a signal for MsgPort");
210 mp
->mp_SigTask
= newtask
;
212 /* Return port address */
217 /* FIXME: NewAddTask() will reset flags to 0 */
218 newtask
->tc_Flags
= flags
;
219 newtask
->tc_UserData
= userdata
;
222 * On some architectures (PPC) stack frames must be preallocated.
223 * SP_OFFSET is subtracted in order to take care of this.
225 newtask
->tc_SPReg
= ml
->ml_ME
[1].me_Addr
+ nml
.nml_ME
[1].me_Length
- SP_OFFSET
;
226 newtask
->tc_SPLower
= ml
->ml_ME
[1].me_Addr
;
227 newtask
->tc_SPUpper
= newtask
->tc_SPReg
;
229 NEWLIST(&newtask
->tc_MemEntry
);
230 AddHead(&newtask
->tc_MemEntry
, &ml
->ml_Node
);
233 * TASKTAG_ARGx will be processed by PrepareContext()
234 * TODO: process initpc and finalpc there too after ABI v1 transition
236 task2
= NewAddTask (newtask
, initpc
, finalpc
, tags
);
247 /* Set secondary error code if requested */
249 *errPtr
= newtask
? TASKERROR_OK
: TASKERROR_NOMEMORY
;