simplerexx updated:
[AROS.git] / rom / exec / newcreatetaska.c
blobe8cbfb9680f22076ca948a0f0cae621ad6467195
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Create a new task, improved version
6 Lang: english
7 */
9 #include <proto/arossupport.h>
10 #include <exec/memory.h>
11 #include <exec/execbase.h>
13 #include <string.h>
15 #include "exec_debug.h"
16 #include "exec_util.h"
18 struct newMemList
20 struct Node nml_Node;
21 UWORD nml_NumEntries;
22 struct MemEntry nml_ME[4];
25 static const struct newMemList MemTemplate =
27 { 0, },
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 /*****************************************************************************
39 NAME */
40 #include <exec/tasks.h>
41 #include <proto/exec.h>
43 AROS_LH1(struct Task *, NewCreateTaskA,
45 /* SYNOPSIS */
46 AROS_LHA(struct TagItem *, tags, A0),
48 /* LOCATION */
49 struct ExecBase *, SysBase, 153, Exec)
51 /* FUNCTION
52 Create a new task.
54 INPUTS
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
60 failure.
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
65 value.
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.
69 TASKTAG_ARG1 ...
70 TASKTAG_ARG8 (IPTR) - Arguments (up to 8) which will be passed to task's
71 entry function. The arguments are supplied in
72 C-standard way.
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.
81 RESULT
82 A pointer to the new task or NULL on failure.
84 NOTES
86 EXAMPLE
88 BUGS
89 Value of TASKTAG_FLAGS is actually ignored.
90 There are some more tags which are currently not implemented.
92 SEE ALSO
94 INTERNALS
96 HISTORY
98 ******************************************************************************/
100 AROS_LIBFUNC_INIT
102 struct Task * newtask;
103 struct newMemList nml = MemTemplate;
104 struct MemList * ml;
105 struct TagItem *tag, *tstate = tags;
106 struct MsgPort **msgPortPtr = NULL;
107 ULONG *errPtr = NULL;
108 APTR initpc = NULL;
109 APTR finalpc = SysBase->TaskExitCode;
110 char *taskname = NULL;
111 APTR userdata = NULL;
112 ULONG pri = 0;
113 ULONG flags = 0;
115 while ((tag = LibNextTagItem(&tstate)))
117 switch (tag->ti_Tag)
119 case TASKTAG_ERROR:
120 errPtr = (ULONG *)tag->ti_Data;
121 break;
123 case TASKTAG_PC:
124 initpc = (APTR)tag->ti_Data;
125 break;
127 case TASKTAG_FINALPC:
128 finalpc = (APTR)tag->ti_Data;
129 break;
131 case TASKTAG_STACKSIZE:
132 nml.nml_ME[1].me_Length = AROS_ALIGN(tag->ti_Data);
133 break;
135 case TASKTAG_NAME:
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;
140 break;
142 case TASKTAG_USERDATA:
143 userdata = (APTR)tag->ti_Data;
144 break;
146 case TASKTAG_PRI:
147 pri = tag->ti_Data;
148 break;
150 case TASKTAG_TASKMSGPORT:
151 msgPortPtr = (struct MsgPort **)tag->ti_Data;
152 if (nml.nml_NumEntries < 4)
153 nml.nml_NumEntries = 4;
154 break;
156 case TASKTAG_FLAGS:
157 flags = tag->ti_Data;
158 break;
160 case TASKTAG_TCBEXTRASIZE:
161 nml.nml_ME[0].me_Length += tag->ti_Data;
162 break;
166 DADDTASK("NewCreateTaskA: name %s", taskname ? taskname : "<NULL>");
168 ml = NewAllocEntry((struct MemList *)&nml, NULL);
169 if (ml)
171 struct Task *task2 = NULL;
172 APTR name = ml->ml_ME[2].me_Addr;
174 if (taskname)
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
189 * GetTaskAttr().
191 struct MsgPort *mp = ml->ml_ME[3].me_Addr;
192 LONG sig;
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);
201 if (sig == -1)
203 DADDTASK("NewCreateTaskA: Failed to allocate a signal for MsgPort");
204 goto fail;
207 InitMsgPort(mp);
208 mp->mp_SigBit = sig;
209 mp->mp_SigTask = newtask;
211 /* Return port address */
212 if (msgPortPtr)
213 *msgPortPtr = mp;
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);
237 fail: if (!task2)
239 FreeEntry (ml);
240 newtask = NULL;
243 else
244 newtask=NULL;
246 /* Set secondary error code if requested */
247 if (errPtr)
248 *errPtr = newtask ? TASKERROR_OK : TASKERROR_NOMEMORY;
250 return newtask;
252 AROS_LIBFUNC_EXIT