Page MenuHomeFreeBSD

D16489.id46028.diff
No OneTemporary

D16489.id46028.diff

Index: sys/kern/kern_sig.c
===================================================================
--- sys/kern/kern_sig.c
+++ sys/kern/kern_sig.c
@@ -3066,6 +3066,22 @@
return (1);
}
+void
+proc_wkilled(struct proc *p)
+{
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ if ((p->p_flag & P_WKILLED) == 0) {
+ p->p_flag |= P_WKILLED;
+ /*
+ * Notify swapper that there is a process to swap in.
+ * The notification is racy, at worst it would take 10
+ * seconds for the swapper process to notice.
+ */
+ wakeup(&proc0);
+ }
+}
+
/*
* Kill the current process for stated reason.
*/
@@ -3078,7 +3094,7 @@
p->p_comm);
log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid,
p->p_comm, p->p_ucred ? p->p_ucred->cr_uid : -1, why);
- p->p_flag |= P_WKILLED;
+ proc_wkilled(p);
kern_psignal(p, SIGKILL);
}
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -1170,7 +1170,7 @@
* queue cannot accommodate any new signals.
*/
if (data == SIGKILL)
- p->p_flag |= P_WKILLED;
+ proc_wkilled(p);
/*
* Unsuspend all threads. To leave a thread
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -1050,6 +1050,7 @@
void proc_reap(struct thread *td, struct proc *p, int *status, int options);
void proc_reparent(struct proc *child, struct proc *newparent);
void proc_set_traced(struct proc *p, bool stop);
+void proc_wkilled(struct proc *p);
struct pstats *pstats_alloc(void);
void pstats_fork(struct pstats *src, struct pstats *dst);
void pstats_free(struct pstats *ps);
Index: sys/vm/vm_swapout.c
===================================================================
--- sys/vm/vm_swapout.c
+++ sys/vm/vm_swapout.c
@@ -158,13 +158,15 @@
/* 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 void swapclear(struct proc *);
static int swapout(struct proc *);
static void vm_swapout_map_deactivate_pages(vm_map_t, long);
static void vm_swapout_object_deactivate_pages(pmap_t, vm_object_t, long);
static void swapout_procs(int action);
static void vm_req_vmdaemon(int req);
-static void vm_thread_swapin(struct thread *td);
+static void vm_thread_swapin(struct thread *td, bool oom_swapin);
static void vm_thread_swapout(struct thread *td);
/*
@@ -563,7 +565,7 @@
* Bring the kernel stack for a specified thread back in.
*/
static void
-vm_thread_swapin(struct thread *td)
+vm_thread_swapin(struct thread *td, bool oom_swapin)
{
vm_object_t ksobj;
vm_page_t ma[KSTACK_MAX_PAGES];
@@ -572,8 +574,8 @@
pages = td->td_kstack_pages;
ksobj = td->td_kstack_obj;
VM_OBJECT_WLOCK(ksobj);
- (void)vm_page_grab_pages(ksobj, 0, VM_ALLOC_NORMAL | VM_ALLOC_WIRED, ma,
- pages);
+ (void)vm_page_grab_pages(ksobj, 0, (oom_swapin ? VM_ALLOC_SYSTEM :
+ VM_ALLOC_NORMAL) | VM_ALLOC_WIRED, ma, pages);
for (i = 0; i < pages;) {
vm_page_assert_xbusied(ma[i]);
if (ma[i]->valid == VM_PAGE_BITS_ALL) {
@@ -601,8 +603,8 @@
cpu_thread_swapin(td);
}
-void
-faultin(struct proc *p)
+static void
+faultin1(struct proc *p, bool oom_swapin)
{
struct thread *td;
@@ -624,6 +626,10 @@
++p->p_lock;
p->p_flag |= P_SWAPPINGIN;
PROC_UNLOCK(p);
+ sx_xlock(&allproc_lock);
+ MPASS(swapped_cnt > 0);
+ swapped_cnt--;
+ sx_xunlock(&allproc_lock);
/*
* We hold no lock here because the list of threads
@@ -631,43 +637,63 @@
* swapped out.
*/
FOREACH_THREAD_IN_PROC(p, td)
- vm_thread_swapin(td);
+ vm_thread_swapin(td, oom_swapin);
+
PROC_LOCK(p);
swapclear(p);
p->p_swtick = ticks;
- wakeup(&p->p_flag);
-
/* Allow other threads to swap p out now. */
+ wakeup(&p->p_flag);
--p->p_lock;
}
}
+void
+faultin(struct proc *p)
+{
+
+ faultin1(p, false);
+}
+
/*
* This swapin algorithm attempts to swap-in processes only if there
* is enough space for them. Of course, if a process waits for a long
* time, it will be swapped in anyway.
*/
-void
-swapper(void)
+
+static bool
+swapper_selector(struct proc **pp)
{
- struct proc *p, *pp;
+ struct proc *p, *res;
struct thread *td;
- int ppri, pri, slptime, swtime;
-
-loop:
- if (vm_page_count_min()) {
- vm_wait_min();
- goto loop;
- }
+ int min_flag, ppri, pri, slptime, swtime;
- pp = NULL;
+ sx_assert(&allproc_lock, SA_SLOCKED);
+ res = NULL;
ppri = INT_MIN;
- sx_slock(&allproc_lock);
+ min_flag = vm_page_count_min();
FOREACH_PROC_IN_SYSTEM(p) {
PROC_LOCK(p);
- if (p->p_state == PRS_NEW ||
- p->p_flag & (P_SWAPPINGOUT | P_SWAPPINGIN | P_INMEM)) {
+ if (p->p_state == PRS_NEW || (p->p_flag & (P_SWAPPINGOUT |
+ P_SWAPPINGIN | P_INMEM)) != 0) {
+ PROC_UNLOCK(p);
+ continue;
+ }
+ if (p->p_state == PRS_NORMAL && (p->p_flag & P_WKILLED) != 0) {
+ /*
+ * A swapped-out process might have mapped a
+ * large portion of the system's pages as
+ * anonymous memory. There is no other way to
+ * release the memory other than to kill the
+ * process, for which we need to swap it in.
+ */
+ sx_sunlock(&allproc_lock);
+ faultin1(p, true);
+ PROC_UNLOCK(p);
+ return (false);
+ }
+ if (min_flag) {
PROC_UNLOCK(p);
continue;
}
@@ -690,7 +716,7 @@
* selection.
*/
if (pri > ppri) {
- pp = p;
+ res = p;
ppri = pri;
}
}
@@ -698,33 +724,44 @@
}
PROC_UNLOCK(p);
}
- sx_sunlock(&allproc_lock);
+ *pp = res;
+ return (true);
+}
- /*
- * Nothing to do, back to sleep.
- */
- if ((p = pp) == NULL) {
- tsleep(&proc0, PVM, "swapin", MAXSLP * hz / 2);
- goto loop;
- }
- PROC_LOCK(p);
+void
+swapper(void)
+{
+ struct proc *p;
+ bool selected;
- /*
- * Another process may be bringing or may have already
- * brought this process in while we traverse all threads.
- * Or, this process may even be being swapped out again.
- */
- if (p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) {
- PROC_UNLOCK(p);
- goto loop;
- }
+ for (;;) {
+ sx_slock(&allproc_lock);
+ if (swapped_cnt > 0) {
+ selected = swapper_selector(&p);
+ if (!selected)
+ continue;
+ }
+ sx_sunlock(&allproc_lock);
- /*
- * We would like to bring someone in.
- */
- faultin(p);
- PROC_UNLOCK(p);
- goto loop;
+ if (p == NULL) {
+ tsleep(&proc0, PVM, "swapin", MAXSLP * hz / 2);
+ } else {
+ PROC_LOCK(p);
+
+ /*
+ * Another process may be bringing or may have
+ * already brought this process in while we
+ * traverse all threads. Or, this process may
+ * have exited or even being swapped out
+ * again.
+ */
+ if (p->p_state == PRS_NORMAL && (p->p_flag & (P_INMEM |
+ P_SWAPPINGOUT | P_SWAPPINGIN)) == 0) {
+ faultin(p);
+ }
+ PROC_UNLOCK(p);
+ }
+ }
}
/*
@@ -803,7 +840,12 @@
didswap = true;
PROC_UNLOCK(p);
- sx_slock(&allproc_lock);
+ if (didswap) {
+ sx_xlock(&allproc_lock);
+ swapped_cnt++;
+ sx_downgrade(&allproc_lock);
+ } else
+ sx_slock(&allproc_lock);
PRELE(p);
}
sx_sunlock(&allproc_lock);

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 20, 4:02 AM (5 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29997073
Default Alt Text
D16489.id46028.diff (6 KB)

Event Timeline