try to make sure compiler/include/mmakefile is always refreshed correctly.
[AROS.git] / rom / exec / prepareexecbase.c
bloba009d35bc610cd0c24d7c372d48323573befcd4e
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Sets up the ExecBase a bit. (Mostly clearing).
6 Lang:
7 */
9 #define DEBUG 0
11 #include <aros/asmcall.h>
12 #include <aros/debug.h>
13 #include <aros/kernel.h>
14 #include <clib/macros.h>
15 #include <exec/types.h>
16 #include <exec/lists.h>
17 #include <exec/memory.h>
18 #include <exec/memheaderext.h>
19 #include <exec/resident.h>
20 #include <exec/execbase.h>
21 #include <exec/libraries.h>
22 #include <aros/arossupportbase.h>
24 #include <string.h>
26 #include <proto/alib.h>
27 #include <proto/exec.h>
29 #include LC_LIBDEFS_FILE
30 #include "etask.h"
31 #include "memory.h"
32 #include "exec_util.h"
33 #include "exec_debug.h"
34 #include "exec_intern.h"
36 #undef kprintf /* This can't be used in the code here */
38 #if defined(__AROSEXEC_SMP__)
39 extern struct Library *ExecLock__PrepareBase(struct MemHeader *);
40 #endif
42 extern void *LIBFUNCTABLE[];
44 extern struct Resident Exec_resident; /* Need this for lib_IdString */
46 extern void Exec_TrapHandler(ULONG trapNum, struct ExceptionContext *ctx);
47 AROS_LD3(ULONG, MakeFunctions,
48 AROS_LDA(APTR, target, A0),
49 AROS_LDA(CONST_APTR, functionArray, A1),
50 AROS_LDA(CONST_APTR, funcDispBase, A2),
51 struct ExecBase *, SysBase, 15, Exec);
53 /* Default finaliser. */
54 static void Exec_TaskFinaliser(void)
56 /* Get rid of current task. */
57 RemTask(GET_THIS_TASK);
60 #undef kprintf
61 #undef rkprintf
62 #undef vkprintf
64 void _aros_not_implemented(char *X)
66 kprintf("Unsupported function at offset -0x%h in %s\n",
67 ABS(*(WORD *)((&X)[-1]-2)),
68 ((struct Library *)(&X)[-2])->lib_Node.ln_Name);
71 struct Library *PrepareAROSSupportBase (struct MemHeader *mh)
73 struct AROSSupportBase *AROSSupportBase;
75 AROSSupportBase = Allocate(mh, sizeof(struct AROSSupportBase));
77 AROSSupportBase->kprintf = (void *)kprintf;
78 AROSSupportBase->rkprintf = (void *)rkprintf;
79 AROSSupportBase->vkprintf = (void *)vkprintf;
81 AROSSupportBase->StdOut = NULL;
82 AROSSupportBase->DebugConfig = NULL;
84 return (struct Library *)AROSSupportBase;
87 BOOL IsSysBaseValid(struct ExecBase *sysbase)
89 if (sysbase == NULL)
90 return FALSE;
91 #ifdef __mc68000
92 if (((IPTR)sysbase) & 0x80000001)
93 return FALSE;
94 #endif
95 if (sysbase->ChkBase != ~(IPTR)sysbase)
96 return FALSE;
97 if (sysbase->SoftVer != VERSION_NUMBER)
98 return FALSE;
99 /* more tests? */
100 return GetSysBaseChkSum(sysbase) == 0xffff;
103 UWORD GetSysBaseChkSum(struct ExecBase *sysbase)
105 UWORD sum = 0;
106 UWORD *p = (UWORD*)&sysbase->SoftVer;
107 while (p <= &sysbase->ChkSum)
108 sum += *p++;
109 return sum;
112 void SetSysBaseChkSum(void)
114 SysBase->ChkBase=~(IPTR)SysBase;
115 SysBase->ChkSum = 0;
116 SysBase->ChkSum = GetSysBaseChkSum(SysBase) ^ 0xffff;
119 static APTR allocmem(struct MemHeader *mh, ULONG size, ULONG attributes)
121 APTR ret;
123 if (IsManagedMem(mh))
125 struct MemHeaderExt *mhe = (struct MemHeaderExt *)mh;
127 if (mhe->mhe_Alloc)
128 ret = mhe->mhe_Alloc(mhe, size, &attributes);
129 else
130 ret = 0;
132 else
134 ret = stdAlloc(mh, NULL, size, attributes, NULL, NULL);
137 return ret;
141 * PrepareExecBase() will initialize the ExecBase to default values.
142 * MemHeader and ExecBase itself will already be added to appropriate
143 * lists. You don't need to do this yourself.
145 * WARNING: this routine intentionally sets up global SysBase.
146 * This is done because:
147 * 1. PrepareAROSSupportBase() calls Allocate() which relies on functional SysBase
148 * 2. After PrepareAROSSupportBase() it is possible to call debug output functions
149 * (kprintf() etc). Yes, KernelBase is not set up yet, but remember that kernel.resource
150 * may have patched functions in AROSSupportBase so that KernelBase is not needed there.
151 * 3. Existing ports (at least UNIX-hosted and Windows-hosted) rely on the fact that SysBase is
152 * set up here.
154 * Resume: please be extremely careful, study existing code, and think five times if you decide to
155 * change this. You WILL break existing ports if you do not modify their code accordingly. There's
156 * nothing really bad in the fact that global SysBase is touched here and changing this does not
157 * really win something.
158 * Pavel Fedin <pavel_fedin@mail.ru>
160 struct ExecBase *PrepareExecBase(struct MemHeader *mh, struct TagItem *msg)
162 ULONG negsize = 0;
163 VOID **fp = LIBFUNCTABLE;
164 APTR ColdCapture = NULL, CoolCapture = NULL, WarmCapture = NULL;
165 APTR KickMemPtr = NULL, KickTagPtr = NULL, KickCheckSum = NULL;
166 APTR mem;
167 ULONG i;
168 char *args;
170 D(bug("[Exec] %s()\n", __func__));
173 * Copy reset proof pointers if old SysBase is valid.
174 * Additional platform-specific code is needed in order to test
175 * address validity. This routine should zero out SysBase if it is invalid.
177 if (IsSysBaseValid(SysBase))
179 ColdCapture = SysBase->ColdCapture;
180 CoolCapture = SysBase->CoolCapture;
181 WarmCapture = SysBase->WarmCapture;
182 KickMemPtr = SysBase->KickMemPtr;
183 KickTagPtr = SysBase->KickTagPtr;
184 KickCheckSum = SysBase->KickCheckSum;
187 /* Calculate the size of the vector table */
188 while (*fp++ != (VOID *) -1) negsize += LIB_VECTSIZE;
190 /* Align library base */
191 negsize = AROS_ALIGN(negsize);
193 /* Allocate memory for library base */
194 mem = allocmem(mh, negsize + sizeof(struct IntExecBase), MEMF_CLEAR);
195 if (!mem)
196 return NULL;
198 SysBase = mem + negsize;
200 #ifdef HAVE_PREPAREPLATFORM
201 /* Setup platform-specific data */
202 if (!Exec_PreparePlatform(&PD(SysBase), msg))
203 return NULL;
204 #endif
206 /* Setup function vectors */
207 AROS_CALL3(ULONG, AROS_SLIB_ENTRY(MakeFunctions, Exec, 15),
208 AROS_UFCA(APTR, SysBase, A0),
209 AROS_UFCA(CONST_APTR, LIBFUNCTABLE, A1),
210 AROS_UFCA(CONST_APTR, NULL, A2),
211 struct ExecBase *, SysBase);
213 /* Set default values */
214 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
215 SysBase->LibNode.lib_Node.ln_Pri = -100;
216 SysBase->LibNode.lib_Node.ln_Name = (char *)Exec_resident.rt_Name;
217 SysBase->LibNode.lib_IdString = (char *)Exec_resident.rt_IdString;
218 SysBase->LibNode.lib_Version = VERSION_NUMBER;
219 SysBase->LibNode.lib_Revision = REVISION_NUMBER;
220 SysBase->LibNode.lib_OpenCnt = 1;
221 SysBase->LibNode.lib_NegSize = negsize;
222 SysBase->LibNode.lib_PosSize = sizeof(struct IntExecBase);
223 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
225 #if defined(__AROSEXEC_SMP__)
226 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->MemListSpinLock);
227 #endif
228 NEWLIST(&SysBase->MemList);
229 SysBase->MemList.lh_Type = NT_MEMORY;
231 #if defined(__AROSEXEC_SMP__)
232 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->ResourceListSpinLock);
233 #endif
234 NEWLIST(&SysBase->ResourceList);
235 SysBase->ResourceList.lh_Type = NT_RESOURCE;
237 #if defined(__AROSEXEC_SMP__)
238 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->DeviceListSpinLock);
239 #endif
240 NEWLIST(&SysBase->DeviceList);
241 SysBase->DeviceList.lh_Type = NT_DEVICE;
243 #if defined(__AROSEXEC_SMP__)
244 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->IntrListSpinLock);
245 #endif
246 NEWLIST(&SysBase->IntrList);
247 SysBase->IntrList.lh_Type = NT_INTERRUPT;
249 #if defined(__AROSEXEC_SMP__)
250 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->LibListSpinLock);
251 #endif
252 NEWLIST(&SysBase->LibList);
253 SysBase->LibList.lh_Type = NT_LIBRARY;
255 /* Add exec.library to system library list */
256 ADDHEAD(&SysBase->LibList, &SysBase->LibNode.lib_Node);
258 #if defined(__AROSEXEC_SMP__)
259 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->PortListSpinLock);
260 #endif
261 NEWLIST(&SysBase->PortList);
262 SysBase->PortList.lh_Type = NT_MSGPORT;
264 #if defined(__AROSEXEC_SMP__)
265 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskRunningSpinLock);
266 NEWLIST(&PrivExecBase(SysBase)->TaskRunning);
267 PrivExecBase(SysBase)->TaskRunning.lh_Type = NT_TASK;
269 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskSpinningLock);
270 NEWLIST(&PrivExecBase(SysBase)->TaskSpinning);
271 PrivExecBase(SysBase)->TaskSpinning.lh_Type = NT_TASK;
273 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskReadySpinLock);
274 #endif
275 NEWLIST(&SysBase->TaskReady);
276 SysBase->TaskReady.lh_Type = NT_TASK;
278 #if defined(__AROSEXEC_SMP__)
279 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskWaitSpinLock);
280 #endif
281 NEWLIST(&SysBase->TaskWait);
282 SysBase->TaskWait.lh_Type = NT_TASK;
284 #if defined(__AROSEXEC_SMP__)
285 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->SemListSpinLock);
286 #endif
287 NEWLIST(&SysBase->SemaphoreList);
288 SysBase->SemaphoreList.lh_Type = NT_SEMAPHORE;
290 NEWLIST(&SysBase->ex_MemHandlers);
292 for (i = 0; i < 5; i++)
294 NEWLIST(&SysBase->SoftInts[i].sh_List);
295 SysBase->SoftInts[i].sh_List.lh_Type = NT_INTERRUPT;
298 NEWLIST(&PrivExecBase(SysBase)->ResetHandlers);
299 NEWLIST(&PrivExecBase(SysBase)->AllocMemList);
300 NEWLIST(&PrivExecBase(SysBase)->AllocatorCtxList);
302 #if defined(__AROSEXEC_BROKENMEMLOCK__)
303 InitSemaphore(&PrivExecBase(SysBase)->MemListSem);
304 #endif
305 InitSemaphore(&PrivExecBase(SysBase)->LowMemSem);
307 SysBase->SoftVer = VERSION_NUMBER;
308 #if !defined(__AROSEXEC_SMP__)
309 SCHEDQUANTUM_SET(SCHEDQUANTUM_VALUE);
310 #endif
311 SysBase->TaskTrapCode = Exec_TrapHandler;
312 SysBase->TaskExceptCode = NULL;
313 SysBase->TaskExitCode = Exec_TaskFinaliser;
314 SysBase->TaskSigAlloc = 0xFFFF;
315 SysBase->TaskTrapAlloc = 0;
317 /* Parse some arguments from command line */
318 args = (char *)LibGetTagData(KRN_CmdLine, 0, msg);
319 if (args)
321 char *opts;
324 * Enable mungwall before the first AllocMem().
325 * Yes, we have actually already called stdAlloc() once
326 * in order to allocate memory for SysBase itself, however
327 * this is not a real problem because it is never going
328 * to be freed.
330 * We store mungwall setting in private flags because it must not be
331 * switched at runtime (or hard crash will happen).
333 opts = strcasestr(args, "mungwall");
334 if (opts)
335 PrivExecBase(SysBase)->IntFlags = EXECF_MungWall;
337 opts = strcasestr(args, "stacksnoop");
338 if (opts)
339 PrivExecBase(SysBase)->IntFlags = EXECF_StackSnoop;
342 * Parse system runtime debug flags.
343 * These are public. In future they will be editable by prefs program.
344 * However in order to be able to turn them on during early startup,
345 * we apply them also here.
347 opts = strcasestr(args, "sysdebug=");
348 if (opts)
349 SysBase->ex_DebugFlags = ParseFlags(&opts[9], ExecFlagNames);
352 NEWLIST(&PrivExecBase(SysBase)->TaskStorageSlots);
354 SetSysBaseChkSum();
356 /* Add our initial MemHeader */
357 ADDHEAD(&SysBase->MemList, &mh->mh_Node);
359 /* Bring back saved values (or NULLs) */
360 SysBase->ColdCapture = ColdCapture;
361 SysBase->CoolCapture = CoolCapture;
362 SysBase->WarmCapture = WarmCapture;
363 SysBase->KickMemPtr = KickMemPtr;
364 SysBase->KickTagPtr = KickTagPtr;
365 SysBase->KickCheckSum = KickCheckSum;
367 SysBase->DebugAROSBase = PrepareAROSSupportBase(mh);
368 #if defined(__AROSEXEC_SMP__)
369 PrivExecBase(SysBase)->ExecLockBase = NULL;
370 PrivExecBase(SysBase)->ExecLockBase = ExecLock__PrepareBase(mh);
371 #endif
373 D(bug("[Exec] %s: Preperation complete.\n"));
375 return SysBase;