| 315 | } |
| 316 | |
| 317 | int |
| 318 | fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx) |
| 319 | { |
| 320 | struct pcb *pcb; |
| 321 | |
| 322 | pcb = td->td_pcb; |
| 323 | |
| 324 | if ((pcb->pcb_fpflags & PCB_FP_NOSAVE) != 0) { |
| 325 | KASSERT(ctx == NULL, ("non-null ctx after FPU_KERN_NOCTX")); |
| 326 | KASSERT(PCPU_GET(fpcurthread) == NULL, |
| 327 | ("non-NULL fpcurthread for PCB_FP_NOSAVE")); |
| 328 | CRITICAL_ASSERT(td); |
| 329 | |
| 330 | vfp_disable(); |
| 331 | pcb->pcb_fpflags &= ~(PCB_FP_NOSAVE | PCB_FP_STARTED); |
| 332 | critical_exit(); |
| 333 | } else { |
| 334 | KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0, |
| 335 | ("FPU context not inuse")); |
| 336 | ctx->flags &= ~FPU_KERN_CTX_INUSE; |
| 337 | |
| 338 | if (is_fpu_kern_thread(0) && |
| 339 | (ctx->flags & FPU_KERN_CTX_DUMMY) != 0) |
| 340 | return (0); |
| 341 | KASSERT((ctx->flags & FPU_KERN_CTX_DUMMY) == 0, ("dummy ctx")); |
| 342 | critical_enter(); |
| 343 | vfp_discard(td); |
| 344 | critical_exit(); |
| 345 | pcb->pcb_fpflags &= ~PCB_FP_STARTED; |
| 346 | pcb->pcb_fpusaved = ctx->prev; |
| 347 | } |
| 348 | |
| 349 | if (pcb->pcb_fpusaved == &pcb->pcb_fpustate) { |
| 350 | pcb->pcb_fpflags &= ~PCB_FP_KERN; |
| 351 | } else { |
| 352 | KASSERT((pcb->pcb_fpflags & PCB_FP_KERN) != 0, |
| 353 | ("unpaired fpu_kern_leave")); |
| 354 | } |
| 355 | |
| 356 | return (0); |
| 357 | } |
| 358 | |
| 359 | int |
| 360 | fpu_kern_thread(u_int flags) |
nothing calls this directly
no test coverage detected