- FPU context is stored only if conflict between 2 FPU users or while
  exporting context of a process to userspace while it is the active
  user of FPU

- FPU has its owner (fpu_owner) which points to the process whose
  state is currently loaded in FPU

- the FPU exception is only turned on when scheduling a process which
  is not the owner of FPU

- FPU state is restored for the process that generated the FPU
  exception. This process runs immediately without letting scheduler
  to pick a new process to resolve the FPU conflict asap, to minimize
  the FPU thrashing and FPU exception hadler execution

- faster all non-FPU-exception kernel entries as FPU state is not
  checked nor saved

- removed MF_USED_FPU flag, only MF_FPU_INITIALIZED remains to signal
  that a process has used FPU in the past
This commit is contained in:
Tomas Hruby
2010-06-07 07:43:17 +00:00
parent b641afc78a
commit cbc9586c13
14 changed files with 87 additions and 49 deletions

View File

@@ -70,6 +70,10 @@ PUBLIC int do_clear(struct proc * caller, message * m_ptr)
}
#endif
/* release FPU */
if (fpu_owner == rc)
release_fpu();
return OK;
}

View File

@@ -46,6 +46,9 @@ PUBLIC int do_exec(struct proc * caller, message * m_ptr)
/* Mark fpu_regs contents as not significant, so fpu
* will be initialized, when it's used next time. */
rp->p_misc_flags &= ~MF_FPU_INITIALIZED;
/* force reloading FPU if the current process is the owner */
if (rp == fpu_owner)
release_fpu();
return(OK);
}
#endif /* USE_EXEC */

View File

@@ -51,6 +51,11 @@ PUBLIC int do_fork(struct proc * caller, message * m_ptr)
map_ptr= (struct mem_map *) m_ptr->PR_MEM_PTR;
/* make sure that the FPU context is saved in parent before copy */
if (fpu_owner == rpp) {
disable_fpu_exception();
save_fpu(rpp);
}
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
gen = _ENDPOINT_G(rpc->p_endpoint);
#if (_MINIX_CHIP == _CHIP_INTEL)

View File

@@ -42,6 +42,11 @@ PUBLIC int do_getmcontext(struct proc * caller, message * m_ptr)
/* Copy FPU state */
mc.mc_fpu_flags = 0;
if (rp->p_misc_flags & MF_FPU_INITIALIZED) {
/* make sure that the FPU context is saved into proc structure first */
if (fpu_owner == rp) {
disable_fpu_exception();
save_fpu(rp);
}
mc.mc_fpu_flags = 0 | rp->p_misc_flags & MF_FPU_INITIALIZED;
memcpy(&(mc.mc_fpu_state), rp->p_fpu_state.fpu_save_area_p,
FPU_XFP_SIZE);
@@ -86,6 +91,9 @@ PUBLIC int do_setmcontext(struct proc * caller, message * m_ptr)
FPU_XFP_SIZE);
} else
rp->p_misc_flags &= ~MF_FPU_INITIALIZED;
/* force reloading FPU in either case */
if (fpu_owner == rp)
release_fpu();
#endif
return(OK);

View File

@@ -59,6 +59,9 @@ PUBLIC int do_sigreturn(struct proc * caller, message * m_ptr)
memcpy(rp->p_fpu_state.fpu_save_area_p, &sc.sc_fpu_state,
FPU_XFP_SIZE);
rp->p_misc_flags |= MF_FPU_INITIALIZED; /* Restore math usage flag. */
/* force reloading FPU */
if (fpu_owner == rp)
release_fpu();
}
#endif

View File

@@ -44,9 +44,15 @@ PUBLIC int do_sigsend(struct proc * caller, message * m_ptr)
/* Copy the registers to the sigcontext structure. */
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(sigregs));
#if (_MINIX_CHIP == _CHIP_INTEL)
if(rp->p_misc_flags & MF_FPU_INITIALIZED)
if(rp->p_misc_flags & MF_FPU_INITIALIZED) {
/* save the FPU context before saving it to the sig context */
if (fpu_owner == rp) {
disable_fpu_exception();
save_fpu(rp);
}
memcpy(&sc.sc_fpu_state, rp->p_fpu_state.fpu_save_area_p,
FPU_XFP_SIZE);
}
#endif
/* Finish the sigcontext initialization. */