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 struct TagItem
*tag
, *tstate
= tags
;
106 struct MsgPort
**msgPortPtr
= NULL
;
107 ULONG
*errPtr
= NULL
;
109 APTR finalpc
= SysBase
->TaskExitCode
;
110 char *taskname
= NULL
;
111 APTR userdata
= NULL
;
115 while ((tag
= LibNextTagItem(&tstate
)))
120 errPtr
= (ULONG
*)tag
->ti_Data
;
124 initpc
= (APTR
)tag
->ti_Data
;
127 case TASKTAG_FINALPC
:
128 finalpc
= (APTR
)tag
->ti_Data
;
131 case TASKTAG_STACKSIZE
:
132 nml
.nml_ME
[1].me_Length
= AROS_ALIGN(tag
->ti_Data
);
136 taskname
= (char *)tag
->ti_Data
;
137 nml
.nml_ME
[2].me_Length
= strlen(taskname
) + 1;
138 if (nml
.nml_NumEntries
< 3)
139 nml
.nml_NumEntries
= 3;
142 case TASKTAG_USERDATA
:
143 userdata
= (APTR
)tag
->ti_Data
;
150 case TASKTAG_TASKMSGPORT
:
151 msgPortPtr
= (struct MsgPort
**)tag
->ti_Data
;
152 if (nml
.nml_NumEntries
< 4)
153 nml
.nml_NumEntries
= 4;
157 flags
= tag
->ti_Data
;
160 case TASKTAG_TCBEXTRASIZE
:
161 nml
.nml_ME
[0].me_Length
+= tag
->ti_Data
;
166 DADDTASK("NewCreateTaskA: name %s", taskname
? taskname
: "<NULL>");
168 ml
= NewAllocEntry((struct MemList
*)&nml
, NULL
);
171 struct Task
*task2
= NULL
;
172 APTR name
= ml
->ml_ME
[2].me_Addr
;
175 strcpy(name
, taskname
);
177 newtask
= ml
->ml_ME
[0].me_Addr
;
179 newtask
->tc_Node
.ln_Type
= NT_TASK
;
180 newtask
->tc_Node
.ln_Pri
= pri
;
181 newtask
->tc_Node
.ln_Name
= name
;
183 if (nml
.nml_NumEntries
== 4)
186 * The caller asked us to create an MsgPort for the task.
187 * We can't reuse ETask's one because it's used for notifications about child tasks.
188 * We don't check against msgPortPtr == NULL because in future we can have MorphOS-compatible
191 struct MsgPort
*mp
= ml
->ml_ME
[3].me_Addr
;
195 * Allocate a signal for the port.
196 * Set tc_SigAlloc early for AllocTaskSignal() to work.
198 newtask
->tc_SigAlloc
= SysBase
->TaskSigAlloc
;
199 sig
= AllocTaskSignal(newtask
, -1, SysBase
);
203 DADDTASK("NewCreateTaskA: Failed to allocate a signal for MsgPort");
209 mp
->mp_SigTask
= newtask
;
211 /* Return port address */
216 /* FIXME: NewAddTask() will reset flags to 0 */
217 newtask
->tc_Flags
= flags
;
218 newtask
->tc_UserData
= userdata
;
221 * On some architectures (PPC) stack frames must be preallocated.
222 * SP_OFFSET is subtracted in order to take care of this.
224 newtask
->tc_SPReg
= ml
->ml_ME
[1].me_Addr
+ nml
.nml_ME
[1].me_Length
- SP_OFFSET
;
225 newtask
->tc_SPLower
= ml
->ml_ME
[1].me_Addr
;
226 newtask
->tc_SPUpper
= newtask
->tc_SPReg
;
228 NEWLIST(&newtask
->tc_MemEntry
);
229 AddHead(&newtask
->tc_MemEntry
, &ml
->ml_Node
);
232 * TASKTAG_ARGx will be processed by PrepareContext()
233 * TODO: process initpc and finalpc there too after ABI v1 transition
235 task2
= NewAddTask (newtask
, initpc
, finalpc
, tags
);
246 /* Set secondary error code if requested */
248 *errPtr
= newtask
? TASKERROR_OK
: TASKERROR_NOMEMORY
;