| 411 | } |
| 412 | |
| 413 | void |
| 414 | vmspace_exit(struct thread *td) |
| 415 | { |
| 416 | struct vmspace *vm; |
| 417 | struct proc *p; |
| 418 | bool released; |
| 419 | |
| 420 | p = td->td_proc; |
| 421 | vm = p->p_vmspace; |
| 422 | |
| 423 | /* |
| 424 | * Prepare to release the vmspace reference. The thread that releases |
| 425 | * the last reference is responsible for tearing down the vmspace. |
| 426 | * However, threads not releasing the final reference must switch to the |
| 427 | * kernel's vmspace0 before the decrement so that the subsequent pmap |
| 428 | * deactivation does not modify a freed vmspace. |
| 429 | */ |
| 430 | refcount_acquire(&vmspace0.vm_refcnt); |
| 431 | if (!(released = refcount_release_if_last(&vm->vm_refcnt))) { |
| 432 | if (p->p_vmspace != &vmspace0) { |
| 433 | PROC_VMSPACE_LOCK(p); |
| 434 | p->p_vmspace = &vmspace0; |
| 435 | PROC_VMSPACE_UNLOCK(p); |
| 436 | pmap_activate(td); |
| 437 | } |
| 438 | released = refcount_release(&vm->vm_refcnt); |
| 439 | } |
| 440 | if (released) { |
| 441 | /* |
| 442 | * pmap_remove_pages() expects the pmap to be active, so switch |
| 443 | * back first if necessary. |
| 444 | */ |
| 445 | if (p->p_vmspace != vm) { |
| 446 | PROC_VMSPACE_LOCK(p); |
| 447 | p->p_vmspace = vm; |
| 448 | PROC_VMSPACE_UNLOCK(p); |
| 449 | pmap_activate(td); |
| 450 | } |
| 451 | pmap_remove_pages(vmspace_pmap(vm)); |
| 452 | PROC_VMSPACE_LOCK(p); |
| 453 | p->p_vmspace = &vmspace0; |
| 454 | PROC_VMSPACE_UNLOCK(p); |
| 455 | pmap_activate(td); |
| 456 | vmspace_dofree(vm); |
| 457 | } |
| 458 | #ifdef RACCT |
| 459 | if (racct_enable) |
| 460 | vmspace_container_reset(p); |
| 461 | #endif |
| 462 | } |
| 463 | |
| 464 | /* Acquire reference to vmspace owned by another process. */ |
| 465 |
no test coverage detected