Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / exec / newcreatetaska.c
blob969438f1760c3caa7489c5ae43f9496e87e7527a
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 const struct TagItem *tstate = tags;
106 struct TagItem *tag;
107 struct MsgPort **msgPortPtr = NULL;
108 ULONG *errPtr = NULL;
109 APTR initpc = NULL;
110 APTR finalpc = SysBase->TaskExitCode;
111 char *taskname = NULL;
112 APTR userdata = NULL;
113 ULONG pri = 0;
114 ULONG flags = 0;
116 while ((tag = LibNextTagItem(&tstate)))
118 switch (tag->ti_Tag)
120 case TASKTAG_ERROR:
121 errPtr = (ULONG *)tag->ti_Data;
122 break;
124 case TASKTAG_PC:
125 initpc = (APTR)tag->ti_Data;
126 break;
128 case TASKTAG_FINALPC:
129 finalpc = (APTR)tag->ti_Data;
130 break;
132 case TASKTAG_STACKSIZE:
133 nml.nml_ME[1].me_Length = AROS_ALIGN(tag->ti_Data);
134 break;
136 case TASKTAG_NAME:
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;
141 break;
143 case TASKTAG_USERDATA:
144 userdata = (APTR)tag->ti_Data;
145 break;
147 case TASKTAG_PRI:
148 pri = tag->ti_Data;
149 break;
151 case TASKTAG_TASKMSGPORT:
152 msgPortPtr = (struct MsgPort **)tag->ti_Data;
153 if (nml.nml_NumEntries < 4)
154 nml.nml_NumEntries = 4;
155 break;
157 case TASKTAG_FLAGS:
158 flags = tag->ti_Data;
159 break;
161 case TASKTAG_TCBEXTRASIZE:
162 nml.nml_ME[0].me_Length += tag->ti_Data;
163 break;
167 DADDTASK("NewCreateTaskA: name %s", taskname ? taskname : "<NULL>");
169 ml = NewAllocEntry((struct MemList *)&nml, NULL);
170 if (ml)
172 struct Task *task2 = NULL;
173 APTR name = ml->ml_ME[2].me_Addr;
175 if (taskname)
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
190 * GetTaskAttr().
192 struct MsgPort *mp = ml->ml_ME[3].me_Addr;
193 LONG sig;
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);
202 if (sig == -1)
204 DADDTASK("NewCreateTaskA: Failed to allocate a signal for MsgPort");
205 goto fail;
208 InitMsgPort(mp);
209 mp->mp_SigBit = sig;
210 mp->mp_SigTask = newtask;
212 /* Return port address */
213 if (msgPortPtr)
214 *msgPortPtr = mp;
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);
238 fail: if (!task2)
240 FreeEntry (ml);
241 newtask = NULL;
244 else
245 newtask=NULL;
247 /* Set secondary error code if requested */
248 if (errPtr)
249 *errPtr = newtask ? TASKERROR_OK : TASKERROR_NOMEMORY;
251 return newtask;
253 AROS_LIBFUNC_EXIT