vm: Remove kernel stack swapping support, part 3

- Modify PHOLD() to no longer fault in the process.
- Remove _PHOLD_LITE(), which is now the same as _PHOLD(), fix up
  consumers.
- Remove faultin() and its callees.

Tested by:	pho
Reviewed by:	imp, kib
Differential Revision:	https://reviews.freebsd.org/D46114
This commit is contained in:
Mark Johnston 2024-07-29 01:39:49 +00:00
parent 0dd7789512
commit 8370e9dfa1
7 changed files with 10 additions and 172 deletions

View File

@ -981,7 +981,7 @@ fasttrap_pid_probe(struct trapframe *tf)
sx_sunlock(&proctree_lock);
return (-1);
}
_PHOLD_LITE(pp);
_PHOLD(pp);
PROC_UNLOCK(pp);
}
sx_sunlock(&proctree_lock);

View File

@ -208,7 +208,7 @@ again:
continue;
}
vm = vmspace_acquire_ref(p);
_PHOLD_LITE(p);
_PHOLD(p);
PROC_UNLOCK(p);
if (vm == NULL) {
PRELE(p);

View File

@ -337,7 +337,7 @@ reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2)
PROC_UNLOCK(p2);
return;
}
_PHOLD_LITE(p2);
_PHOLD(p2);
PROC_UNLOCK(p2);
t = malloc(sizeof(struct reap_kill_tracker), M_TEMP, M_WAITOK);
t->parent = p2;
@ -463,7 +463,7 @@ reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc *reaper,
} else {
PROC_LOCK(p2);
if ((p2->p_flag2 & P2_WEXIT) == 0) {
_PHOLD_LITE(p2);
_PHOLD(p2);
p2->p_flag2 |= P2_REAPKILLED;
PROC_UNLOCK(p2);
w->target = p2;

View File

@ -704,7 +704,7 @@ struct proc {
struct vnode *p_textvp; /* (b) Vnode of executable. */
struct vnode *p_textdvp; /* (b) Dir containing textvp. */
char *p_binname; /* (b) Binary hardlink name. */
u_int p_lock; /* (c) Proclock (prevent swap) count. */
u_int p_lock; /* (c) Prevent exit. */
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
int p_sigparent; /* (c) Signal to parent on exit. */
int p_sig; /* (n) For core dump/debugger XXX. */
@ -986,18 +986,12 @@ extern pid_t pid_max;
#define SESS_LOCK_ASSERT(s, type) mtx_assert(&(s)->s_mtx, (type))
/*
* Non-zero p_lock ensures that:
* - exit1() is not performed until p_lock reaches zero;
* - the process' threads stack are not swapped out if they are currently
* not (P_INMEM).
* A non-zero p_lock prevents the process from exiting; it will sleep in exit1()
* until the count reaches zero.
*
* PHOLD() asserts that the process (except the current process) is
* not exiting, increments p_lock and swaps threads stacks into memory,
* if needed.
* not exiting and increments p_lock.
* _PHOLD() is same as PHOLD(), it takes the process locked.
* _PHOLD_LITE() also takes the process locked, but comparing with
* _PHOLD(), it only guarantees that exit1() is not executed,
* faultin() is not called.
*/
#define PHOLD(p) do { \
PROC_LOCK(p); \
@ -1009,14 +1003,6 @@ extern pid_t pid_max;
KASSERT(!((p)->p_flag & P_WEXIT) || (p) == curproc, \
("PHOLD of exiting process %p", p)); \
(p)->p_lock++; \
if (((p)->p_flag & P_INMEM) == 0) \
faultin((p)); \
} while (0)
#define _PHOLD_LITE(p) do { \
PROC_LOCK_ASSERT((p), MA_OWNED); \
KASSERT(!((p)->p_flag & P_WEXIT) || (p) == curproc, \
("PHOLD of exiting process %p", p)); \
(p)->p_lock++; \
} while (0)
#define PROC_ASSERT_HELD(p) do { \
KASSERT((p)->p_lock > 0, ("process %p not held", p)); \
@ -1174,7 +1160,6 @@ int cr_cansignal(struct ucred *cred, struct proc *proc, int signum);
int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
struct session *sess);
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
int fork1(struct thread *, struct fork_req *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);

View File

@ -1980,7 +1980,7 @@ vm_pageout_oom(int shortage)
PROC_UNLOCK(p);
continue;
}
_PHOLD_LITE(p);
_PHOLD(p);
PROC_UNLOCK(p);
sx_sunlock(&allproc_lock);
if (!vm_map_trylock_read(&vm->vm_map)) {

View File

@ -159,11 +159,6 @@ static struct mtx vm_daemon_mtx;
/* Allow for use by vm_pageout before vm_daemon is initialized. */
MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
static int swapped_cnt;
static int swap_inprogress; /* Pending swap-ins done outside swapper. */
static int last_swapin;
static void swapclear(struct proc *);
static void vm_swapout_map_deactivate_pages(vm_map_t, long);
static void vm_swapout_object_deactivate(pmap_t, vm_object_t, long);
@ -396,7 +391,7 @@ again:
if ((p->p_flag & P_INMEM) == 0)
limit = 0; /* XXX */
vm = vmspace_acquire_ref(p);
_PHOLD_LITE(p);
_PHOLD(p);
PROC_UNLOCK(p);
if (vm == NULL) {
PRELE(p);
@ -460,136 +455,3 @@ again:
}
}
}
/*
* Bring the kernel stack for a specified thread back in.
*/
static void
vm_thread_swapin(struct thread *td, int oom_alloc)
{
vm_page_t ma[KSTACK_MAX_PAGES];
vm_offset_t kaddr;
vm_object_t obj;
int a, count, i, j, pages, rv __diagused;
kaddr = td->td_kstack;
pages = td->td_kstack_pages;
obj = vm_thread_kstack_size_to_obj(pages);
while (vm_thread_stack_back(kaddr, ma, pages, oom_alloc,
td->td_kstack_domain) == ENOMEM)
;
for (i = 0; i < pages;) {
vm_page_assert_xbusied(ma[i]);
if (vm_page_all_valid(ma[i])) {
i++;
continue;
}
vm_object_pip_add(obj, 1);
for (j = i + 1; j < pages; j++)
if (vm_page_all_valid(ma[j]))
break;
VM_OBJECT_WLOCK(obj);
rv = vm_pager_has_page(obj, ma[i]->pindex, NULL, &a);
VM_OBJECT_WUNLOCK(obj);
KASSERT(rv == 1, ("%s: missing page %p", __func__, ma[i]));
count = min(a + 1, j - i);
rv = vm_pager_get_pages(obj, ma + i, count, NULL, NULL);
KASSERT(rv == VM_PAGER_OK, ("%s: cannot get kstack for proc %d",
__func__, td->td_proc->p_pid));
vm_object_pip_wakeup(obj);
i += count;
}
pmap_qenter(kaddr, ma, pages);
cpu_thread_swapin(td);
}
void
faultin(struct proc *p)
{
struct thread *td;
int oom_alloc;
PROC_LOCK_ASSERT(p, MA_OWNED);
/*
* If another process is swapping in this process,
* just wait until it finishes.
*/
if (p->p_flag & P_SWAPPINGIN) {
while (p->p_flag & P_SWAPPINGIN)
msleep(&p->p_flag, &p->p_mtx, PVM, "faultin", 0);
return;
}
if ((p->p_flag & P_INMEM) == 0) {
oom_alloc = (p->p_flag & P_WKILLED) != 0 ? VM_ALLOC_SYSTEM :
VM_ALLOC_NORMAL;
/*
* Don't let another thread swap process p out while we are
* busy swapping it in.
*/
++p->p_lock;
p->p_flag |= P_SWAPPINGIN;
PROC_UNLOCK(p);
sx_xlock(&allproc_lock);
MPASS(swapped_cnt > 0);
swapped_cnt--;
if (curthread != &thread0)
swap_inprogress++;
sx_xunlock(&allproc_lock);
/*
* We hold no lock here because the list of threads
* can not change while all threads in the process are
* swapped out.
*/
FOREACH_THREAD_IN_PROC(p, td)
vm_thread_swapin(td, oom_alloc);
if (curthread != &thread0) {
sx_xlock(&allproc_lock);
MPASS(swap_inprogress > 0);
swap_inprogress--;
last_swapin = ticks;
sx_xunlock(&allproc_lock);
}
PROC_LOCK(p);
swapclear(p);
p->p_swtick = ticks;
/* Allow other threads to swap p out now. */
wakeup(&p->p_flag);
--p->p_lock;
}
}
static void
swapclear(struct proc *p)
{
struct thread *td;
PROC_LOCK_ASSERT(p, MA_OWNED);
FOREACH_THREAD_IN_PROC(p, td) {
thread_lock(td);
td->td_flags |= TDF_INMEM;
td->td_flags &= ~TDF_SWAPINREQ;
TD_CLR_SWAPPED(td);
if (TD_CAN_RUN(td)) {
if (setrunnable(td, 0)) {
#ifdef INVARIANTS
/*
* XXX: We just cleared TDI_SWAPPED
* above and set TDF_INMEM, so this
* should never happen.
*/
panic("not waking up swapper");
#endif
}
} else
thread_unlock(td);
}
p->p_flag &= ~(P_SWAPPINGIN | P_SWAPPINGOUT);
p->p_flag |= P_INMEM;
}

View File

@ -90,12 +90,3 @@ static int vm_swap_idle_enabled = 0;
SYSCTL_INT(_vm, OID_AUTO, swap_idle_enabled, CTLFLAG_RD,
&vm_swap_idle_enabled, 0,
"Allow swapout on idle criteria");
void
faultin(struct proc *p)
{
PROC_LOCK_ASSERT(p, MA_OWNED);
if ((p->p_flag & P_INMEM) == 0)
panic("faultin: proc %p swapped out with NO_SWAPPING", p);
}