/* * Gets called when softcall queue is not moving forward. We choose * a CPU and poke except the ones which are already poked. */ static int softcall_choose_cpu() { cpu_t *cplist = CPU; cpu_t *cp; int intr_load = INT_MAX; int cpuid = -1; cpuset_t poke; int s; ASSERT(getpil() >= DISP_LEVEL); ASSERT(ncpus > 1); ASSERT(MUTEX_HELD(&softcall_lock)); CPUSET_ZERO(poke); /* * The hint is to start from current CPU. */ cp = cplist; do { if (CPU_IN_SET(*softcall_cpuset, cp->cpu_id) || (cp->cpu_flags & CPU_ENABLE) == 0) continue; /* if CPU is not busy */ if (cp->cpu_intrload == 0) { cpuid = cp->cpu_id; break; } if (cp->cpu_intrload < intr_load) { cpuid = cp->cpu_id; intr_load = cp->cpu_intrload; } else if (cp->cpu_intrload == intr_load) { /* * We want to poke CPUs having similar * load because we don't know which CPU is * can acknowledge level1 interrupt. The * list of such CPUs should not be large. */ if (cpuid != -1) { /* * Put the last CPU chosen because * it also has same interrupt load. */ CPUSET_ADD(poke, cpuid); cpuid = -1; } CPUSET_ADD(poke, cp->cpu_id); } } while ((cp = cp->cpu_next_onln) != cplist); /* if we found a CPU which suits best to poke */ if (cpuid != -1) { CPUSET_ZERO(poke); CPUSET_ADD(poke, cpuid); } if (CPUSET_ISNULL(poke)) { mutex_exit(&softcall_lock); return (0); } /* * We first set the bit in cpuset and then poke. */ CPUSET_XOR(*softcall_cpuset, poke); mutex_exit(&softcall_lock); /* * If softcall() was called at low pil then we may * get preempted before we raise PIL. It should be okay * because we are just going to poke CPUs now or at most * another thread may start choosing CPUs in this routine. */ s = splhigh(); siron_poke_cpu(poke); splx(s); return (1); }
/* * Gets called when softcall queue is not moving forward. We choose * a CPU and poke except the ones which are already poked. */ static int softcall_choose_cpu() { cpu_t *cplist = CPU; cpu_t *cp; int intr_load = INT_MAX; int cpuid = -1; cpuset_t poke; int s; ASSERT(getpil() >= DISP_LEVEL); ASSERT(ncpus > 1); ASSERT(MUTEX_HELD(&softcall_lock)); CPUSET_ZERO(poke); /* * The hint is to start from current CPU. */ cp = cplist; do { /* * Don't select this CPU if : * - in cpuset already * - CPU is not accepting interrupts * - CPU is being offlined */ if (CPU_IN_SET(*softcall_cpuset, cp->cpu_id) || (cp->cpu_flags & CPU_ENABLE) == 0 || (cp == cpu_inmotion)) continue; #if defined(__x86) /* * Don't select this CPU if a hypervisor indicates it * isn't currently scheduled onto a physical cpu. We are * looking for a cpu that can respond quickly and the time * to get the virtual cpu scheduled and switched to running * state is likely to be relatively lengthy. */ if (vcpu_on_pcpu(cp->cpu_id) == VCPU_NOT_ON_PCPU) continue; #endif /* __x86 */ /* if CPU is not busy */ if (cp->cpu_intrload == 0) { cpuid = cp->cpu_id; break; } if (cp->cpu_intrload < intr_load) { cpuid = cp->cpu_id; intr_load = cp->cpu_intrload; } else if (cp->cpu_intrload == intr_load) { /* * We want to poke CPUs having similar * load because we don't know which CPU is * can acknowledge level1 interrupt. The * list of such CPUs should not be large. */ if (cpuid != -1) { /* * Put the last CPU chosen because * it also has same interrupt load. */ CPUSET_ADD(poke, cpuid); cpuid = -1; } CPUSET_ADD(poke, cp->cpu_id); } } while ((cp = cp->cpu_next_onln) != cplist); /* if we found a CPU which suits best to poke */ if (cpuid != -1) { CPUSET_ZERO(poke); CPUSET_ADD(poke, cpuid); } if (CPUSET_ISNULL(poke)) { mutex_exit(&softcall_lock); return (0); } /* * We first set the bit in cpuset and then poke. */ CPUSET_XOR(*softcall_cpuset, poke); mutex_exit(&softcall_lock); /* * If softcall() was called at low pil then we may * get preempted before we raise PIL. It should be okay * because we are just going to poke CPUs now or at most * another thread may start choosing CPUs in this routine. */ s = splhigh(); siron_poke_cpu(poke); splx(s); return (1); }