| 894 | } |
| 895 | |
| 896 | static int |
| 897 | swapout(struct proc *p) |
| 898 | { |
| 899 | struct thread *td; |
| 900 | |
| 901 | PROC_LOCK_ASSERT(p, MA_OWNED); |
| 902 | |
| 903 | /* |
| 904 | * The states of this process and its threads may have changed |
| 905 | * by now. Assuming that there is only one pageout daemon thread, |
| 906 | * this process should still be in memory. |
| 907 | */ |
| 908 | KASSERT((p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) == |
| 909 | P_INMEM, ("swapout: lost a swapout race?")); |
| 910 | |
| 911 | /* |
| 912 | * Remember the resident count. |
| 913 | */ |
| 914 | p->p_vmspace->vm_swrss = vmspace_resident_count(p->p_vmspace); |
| 915 | |
| 916 | /* |
| 917 | * Check and mark all threads before we proceed. |
| 918 | */ |
| 919 | p->p_flag &= ~P_INMEM; |
| 920 | p->p_flag |= P_SWAPPINGOUT; |
| 921 | FOREACH_THREAD_IN_PROC(p, td) { |
| 922 | thread_lock(td); |
| 923 | if (!thread_safetoswapout(td)) { |
| 924 | thread_unlock(td); |
| 925 | swapclear(p); |
| 926 | return (EBUSY); |
| 927 | } |
| 928 | td->td_flags &= ~TDF_INMEM; |
| 929 | TD_SET_SWAPPED(td); |
| 930 | thread_unlock(td); |
| 931 | } |
| 932 | td = FIRST_THREAD_IN_PROC(p); |
| 933 | ++td->td_ru.ru_nswap; |
| 934 | PROC_UNLOCK(p); |
| 935 | |
| 936 | /* |
| 937 | * This list is stable because all threads are now prevented from |
| 938 | * running. The list is only modified in the context of a running |
| 939 | * thread in this process. |
| 940 | */ |
| 941 | FOREACH_THREAD_IN_PROC(p, td) |
| 942 | vm_thread_swapout(td); |
| 943 | |
| 944 | PROC_LOCK(p); |
| 945 | p->p_flag &= ~P_SWAPPINGOUT; |
| 946 | p->p_swtick = ticks; |
| 947 | return (0); |
| 948 | } |
no test coverage detected