mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-23 07:31:31 +00:00
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:
parent
0dd7789512
commit
8370e9dfa1
@ -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);
|
||||
|
@ -208,7 +208,7 @@ tmpfs_all_rw_maps(struct mount *mp, bool (*cb)(struct mount *mp, vm_map_t,
|
||||
continue;
|
||||
}
|
||||
vm = vmspace_acquire_ref(p);
|
||||
_PHOLD_LITE(p);
|
||||
_PHOLD(p);
|
||||
PROC_UNLOCK(p);
|
||||
if (vm == NULL) {
|
||||
PRELE(p);
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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)) {
|
||||
|
@ -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 @@ vm_daemon(void)
|
||||
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 @@ vm_daemon(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user