#define EBADEPT (_SIGN 301) /* specified endpoint is bad */
#define EDEADEPT (_SIGN 302) /* specified endpoint is not alive */
+#define EBADCPU (_SIGN 1000) /* requested CPU does not work */
+
#endif /* _ERRNO_H */
extern u32_t busclock[CONFIG_MAX_CPUS];
extern int panicking;
-static int ap_cpu_ready;
-static int cpu_down;
+static int volatile ap_cpu_ready;
+static int volatile cpu_down;
/* there can be at most 255 local APIC ids, each fits in 8 bits */
PRIVATE unsigned char apicid2cpuid[255];
for (cpu = 0; cpu < ncpus; cpu++) {
if (cpu == cpuid)
continue;
+ if (!cpu_test_flag(cpu, CPU_IS_READY)) {
+ printf("CPU %d didn't boot\n", cpu);
+ continue;
+ }
+
cpu_down = -1;
barrier();
apic_send_ipi(APIC_SMP_CPU_HALT_VECTOR, cpu, APIC_IPI_DEST);
PUBLIC void wait_for_APs_to_finish_booting(void)
{
+ unsigned n = 0;
+ int i;
+
+ /* check how many cpus are actually alive */
+ for (i = 0 ; i < ncpus ; i++) {
+ if (cpu_test_flag(i, CPU_IS_READY))
+ n++;
+ }
+ if (n != ncpus)
+ printf("WARNING only %d out of %d cpus booted\n", n, ncpus);
+
/* we must let the other CPUs to run in kernel mode first */
BKL_UNLOCK();
- while (ap_cpus_booted != (ncpus - 1))
+ while (ap_cpus_booted != (n - 1))
arch_pause();
/* now we have to take the lock again as we continu execution */
BKL_LOCK();
#ifdef CONFIG_SMP
if ((cpu < 0 && cpu != -1) || (cpu > 0 && (unsigned) cpu >= ncpus))
return(EINVAL);
+ if (cpu != -1 && !(cpu_is_ready(cpu)))
+ return EBADCPU;
#endif
/* In some cases, we might be rescheduling a runnable process. In such
EXTERN struct machine machine; /* machine info */
#ifdef CONFIG_SMP
-EXTERN unsigned cpu_proc[CONFIG_MAX_CPUS];
+EXTERN int cpu_proc[CONFIG_MAX_CPUS];
#endif
#define schedule_process_migrate(p) \
schedule_process(p, SCHEDULE_CHANGE_CPU)
+#define CPU_DEAD -1
+
+#define cpu_is_available(c) (cpu_proc[c] >= 0)
+
#define DEFAULT_USER_TIME_SLICE 200
/* processes created by RS are sysytem processes */
return;
}
+ /* if no other cpu available, try BSP */
+ cpu = machine.bsp_id;
for (c = 0; c < machine.processors_count; c++) {
+ /* skip dead cpus */
+ if (!cpu_is_available(c))
+ continue;
if (c != machine.bsp_id && cpu_load > cpu_proc[c]) {
cpu_load = cpu_proc[c];
cpu = c;
/* Schedule the process, giving it some quantum */
pick_cpu(rmp);
- if ((rv = schedule_process(rmp, SCHEDULE_CHANGE_ALL)) != OK) {
+ while ((rv = schedule_process(rmp, SCHEDULE_CHANGE_ALL)) == EBADCPU) {
+ /* don't try this CPU ever again */
+ cpu_proc[rmp->cpu] = CPU_DEAD;
+ pick_cpu(rmp);
+ }
+
+ if (rv != OK) {
printf("Sched: Error while scheduling process, kernel replied %d\n",
rv);
return rv;