PUBLIC void save_fpu(struct proc *pr) { #ifdef CONFIG_SMP if (cpuid == pr->p_cpu) { if (get_cpulocal_var(fpu_owner) == pr) { disable_fpu_exception(); save_local_fpu(pr); } } else { int stopped; /* remember if the process was already stopped */ stopped = RTS_ISSET(pr, RTS_PROC_STOP); /* stop the remote process and force it's context to be saved */ smp_schedule_stop_proc_save_ctx(pr); /* * If the process wasn't stopped let the process run again. The * process is kept block by the fact that the kernel cannot run * on its cpu */ if (!stopped) RTS_UNSET(pr, RTS_PROC_STOP); } #else if (get_cpulocal_var(fpu_owner) == pr) { disable_fpu_exception(); save_local_fpu(pr); } #endif }
void smp_sched_handler(void) { unsigned flgs; unsigned cpu = cpuid; flgs = sched_ipi_data[cpu].flags; if (flgs) { struct proc * p; p = (struct proc *)sched_ipi_data[cpu].data; if (flgs & SCHED_IPI_STOP_PROC) { RTS_SET(p, RTS_PROC_STOP); } if (flgs & SCHED_IPI_SAVE_CTX) { /* all context has been saved already, FPU remains */ if (proc_used_fpu(p) && get_cpulocal_var(fpu_owner) == p) { disable_fpu_exception(); save_local_fpu(p, FALSE /*retain*/); /* we're preparing to migrate somewhere else */ release_fpu(p); } } if (flgs & SCHED_IPI_VM_INHIBIT) { RTS_SET(p, RTS_VMINHIBIT); } } __insn_barrier(); sched_ipi_data[cpu].flags = 0; }