2 Copyright © 2013, The AROS Development Team. All rights reserved.
8 #include <aros/debug.h>
10 #include <aros/kernel.h>
11 #include <aros/symbolsets.h>
12 #include <exec/memory.h>
13 #include <exec/tasks.h>
14 #include <exec/alerts.h>
15 #include <exec/execbase.h>
18 #include <proto/exec.h>
19 #include <proto/kernel.h>
24 #include "kernel_cpu.h"
25 #include "kernel_ipi.h"
27 #include "exec_intern.h"
28 #if defined(__AROSEXEC_SMP__)
32 /* Linked from kernel.resource,
33 * need to retrieve in a cleaner fashion .. */
36 extern void IdleTask(struct ExecBase
*);
38 int Exec_ARMCPUInit(struct ExecBase
*SysBase
)
40 struct Task
*BootTask
, *CPUIdleTask
;
41 #if defined(__AROSEXEC_SMP__)
42 int cpu
, cpunum
= KrnGetCPUCount();
46 D(bug("[Exec] %s()\n", __PRETTY_FUNCTION__
));
48 BootTask
= GET_THIS_TASK
;
50 D(bug("[Exec] %s: launched from %s @ 0x%p\n", __PRETTY_FUNCTION__
, BootTask
->tc_Node
.ln_Name
, BootTask
));
52 #if defined(__AROSEXEC_SMP__)
56 /* for our sanity we will tell exec about the correct stack for the boot task */
57 BootTask
->tc_SPLower
= stack
;
58 BootTask
->tc_SPUpper
= stack
+ AROS_STACKSIZE
;
59 #if defined(__AROSEXEC_SMP__)
62 for (cpu
= 0; cpu
< cpunum
; cpu
++)
64 taskName
= AllocVec(15, MEMF_CLEAR
);
65 sprintf( taskName
, "CPU #%02d Idle", cpu
);
67 taskName
= "System Idle";
69 CPUIdleTask
= NewCreateTask(TASKTAG_NAME
, taskName
,
70 #if defined(__AROSEXEC_SMP__)
71 TASKTAG_AFFINITY
, KrnGetCPUMask(cpu
),
74 TASKTAG_PC
, IdleTask
,
75 TASKTAG_ARG1
, SysBase
,
81 bug("[Exec] %s: %s Task created @ 0x%p\n", __PRETTY_FUNCTION__
, CPUIdleTask
->tc_Node
.ln_Name
, CPUIdleTask
);
82 #if defined(__AROSEXEC_SMP__)
83 bug("[Exec] %s: CPU Affinity : %08x\n", __PRETTY_FUNCTION__
, GetIntETask(CPUIdleTask
)->iet_CpuAffinity
);
87 #if defined(__AROSEXEC_SMP__)
94 #if defined(__AROSEXEC_SMP__)
95 struct Hook Exec_TaskSpinLockFailHook
;
97 AROS_UFH3(void, Exec_TaskSpinLockFailFunc
,
98 AROS_UFHA(struct Hook
*, h
, A0
),
99 AROS_UFHA(spinlock_t
*, thisLock
, A1
),
100 AROS_UFHA(void *, unused
, A2
))
104 struct Task
*thisTask
= GET_THIS_TASK
;
106 /* tell the schedular that the task is waiting on a spinlock */
107 thisTask
->tc_State
= TS_SPIN
;
108 GetIntETask(thisTask
)->iet_SpinLock
= thisLock
;
113 void Exec_TaskSpinUnlock(spinlock_t
*thisLock
)
115 struct Task
*curTask
, *nxtTask
;
117 Kernel_43_KrnSpinLock(&PrivExecBase(SysBase
)->TaskSpinningLock
, NULL
,
118 SPINLOCK_MODE_WRITE
, NULL
);
119 ForeachNodeSafe(&PrivExecBase(SysBase
)->TaskSpinning
, curTask
, nxtTask
)
121 if (GetIntETask(curTask
)->iet_SpinLock
== thisLock
)
123 Kernel_43_KrnSpinLock(&PrivExecBase(SysBase
)->TaskReadySpinLock
, NULL
,
124 SPINLOCK_MODE_WRITE
, NULL
);
126 Remove(&curTask
->tc_Node
);
127 Enqueue(&SysBase
->TaskReady
, &curTask
->tc_Node
);
128 Kernel_44_KrnSpinUnLock(&PrivExecBase(SysBase
)->TaskReadySpinLock
, NULL
);
132 Kernel_44_KrnSpinUnLock(&PrivExecBase(SysBase
)->TaskSpinningLock
, NULL
);
135 int Exec_ARMCPUSMPInit(struct ExecBase
*SysBase
)
137 int cpu
, thiscpu
= KrnGetCPUNumber();
139 /* setup the task spinning hook */
140 Exec_TaskSpinLockFailHook
.h_Entry
= (HOOKFUNC
)Exec_TaskSpinLockFailFunc
;
142 D(bug("[Exec] %s: Task SpinLock Fail hook @ 0x%p initialised (func @ 0x%p)\n", __PRETTY_FUNCTION__
, &Exec_TaskSpinLockFailHook
, Exec_TaskSpinLockFailHook
.h_Entry
));
144 for (cpu
= 1; cpu
< 4; cpu
++)
146 __arm_arosintern
.ARMI_SendIPI((IPI_SCHEDULE
& 0x0fffffff) | (thiscpu
<< 28), 0, KrnGetCPUMask(cpu
));
151 ADD2INITLIB(Exec_ARMCPUSMPInit
, -127)
154 ADD2INITLIB(Exec_ARMCPUInit
, 0)