PUBLIC void save_fpu(struct proc *pr)
{
+ int r;
+
#ifdef CONFIG_SMP
- if (cpuid == pr->p_cpu) {
- if (get_cpulocal_var(fpu_owner) == pr) {
- disable_fpu_exception();
- save_local_fpu(pr);
- }
- }
- else {
+ if (cpuid != pr->p_cpu) {
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 */
+ /* stop the remote process and force its context to be saved */
smp_schedule_stop_proc_save_ctx(pr);
/*
*/
if (!stopped)
RTS_UNSET(pr, RTS_PROC_STOP);
+
+ return;
}
-#else
+#endif
+
if (get_cpulocal_var(fpu_owner) == pr) {
disable_fpu_exception();
save_local_fpu(pr);
+
+ /* The state may now be reset, and the caller does not expect
+ * this. Immediately restore the saved state.
+ */
+ r = restore_fpu(pr);
+ assert(r == OK);
}
-#endif
}
PUBLIC int restore_fpu(struct proc *pr)
void do_parent(void)
{
+ ucontext_t dummy;
int s;
s = 1;
between context swaps. */
if (fesetround(FE_UPWARD) != 0) err(10, 2);
+ /* Quick check to make sure that getcontext does not reset the FPU state. */
+ getcontext(&dummy);
+
+ if (fegetround() != FE_UPWARD) err(10, 3);
+
while(s < SWAPS) {
do_calcs();
- if (fegetround() != FE_UPWARD) err(10, 3);
+ if (fegetround() != FE_UPWARD) err(10, 4);
s++;
- if (swapcontext(&ctx[1], &ctx[2]) == -1) err(10, 4);
+ if (swapcontext(&ctx[1], &ctx[2]) == -1) err(10, 5);
}
/* Returning to main thread through uc_link */
}