Create a new thread state to describe threads that would be ready to run

except for the fact tha they are presently swapped out. Also add a process
flag to indicate that the process has started the struggle to swap
back in. This will be  needed for the case where multiple threads
start the swapin action top a collision. Also add code to stop
a process fropm being swapped out if one of the threads in this
process is actually off running on another CPU.. that might hurt...

Submitted by:	Seigo Tanimura <tanimura@r.dl.itc.u-tokyo.ac.jp>
This commit is contained in:
Julian Elischer 2002-07-29 18:33:32 +00:00
parent 49545b3891
commit 1d7b9ed2e6
5 changed files with 80 additions and 21 deletions

View File

@ -144,7 +144,9 @@ procfs_control(struct thread *td, struct proc *p, int op)
* Stop the target.
*/
p->p_flag |= P_TRACED;
mtx_lock_spin(&sched_lock);
faultin(p);
mtx_unlock_spin(&sched_lock);
p->p_xstat = 0; /* XXX ? */
if (p->p_pptr != td->td_proc) {
p->p_oppid = p->p_pptr->p_pid;

View File

@ -533,6 +533,7 @@ cv_wakeup(struct cv *cvp)
setrunqueue(td);
maybe_resched(td);
} else {
td->td_state = TDS_SWAPPED;
td->td_proc->p_sflag |= PS_SWAPINREQ;
wakeup(&proc0); /* XXXKSE */
}

View File

@ -718,7 +718,7 @@ restart:
setrunqueue(td);
maybe_resched(td);
} else {
/* XXXKSE Wrong! */ td->td_state = TDS_RUNQ;
td->td_state = TDS_SWAPPED;
p->p_sflag |= PS_SWAPINREQ;
wakeup(&proc0);
}
@ -765,7 +765,7 @@ restart:
maybe_resched(td);
break;
} else {
/* XXXKSE Wrong */ td->td_state = TDS_RUNQ;
td->td_state = TDS_SWAPPED;
p->p_sflag |= PS_SWAPINREQ;
wakeup(&proc0);
}
@ -919,6 +919,7 @@ setrunnable(struct thread *td)
case 0:
case TDS_RUNNING:
case TDS_IWAIT:
case TDS_SWAPPED:
default:
printf("state is %d", td->td_state);
panic("setrunnable(2)");
@ -939,7 +940,7 @@ setrunnable(struct thread *td)
updatepri(td);
td->td_ksegrp->kg_slptime = 0;
if ((p->p_sflag & PS_INMEM) == 0) {
td->td_state = TDS_RUNQ; /* XXXKSE not a good idea */
td->td_state = TDS_SWAPPED;
p->p_sflag |= PS_SWAPINREQ;
wakeup(&proc0);
} else {

View File

@ -306,7 +306,8 @@ struct thread {
TDS_RUNNING,
TDS_SUSPENDED, /* would have liked to have run */
TDS_IWAIT,
TDS_SURPLUS
TDS_SURPLUS,
TDS_SWAPPED
} td_state;
struct callout td_slpcallout; /* (h) Callout for sleep. */
struct trapframe *td_frame; /* (k) */
@ -587,6 +588,7 @@ struct proc {
#define PS_SWAPINREQ 0x00100 /* Swapin request due to wakeup. */
#define PS_SWAPPING 0x00200 /* Process is being swapped. */
#define PS_NEEDSIGCHK 0x02000 /* Process may need signal delivery. */
#define PS_SWAPPINGIN 0x04000 /* Swapin in progress. */
/* used only in legacy conversion code */
#define SIDL 1 /* Process being created by fork. */
@ -711,8 +713,11 @@ sigonstack(size_t sp)
} while (0)
#define _PHOLD(p) do { \
PROC_LOCK_ASSERT((p), MA_OWNED); \
if ((p)->p_lock++ == 0) \
if ((p)->p_lock++ == 0) { \
mtx_lock_spin(&sched_lock); \
faultin((p)); \
mtx_unlock_spin(&sched_lock); \
} \
} while (0)
#define PRELE(p) do { \

View File

@ -480,7 +480,7 @@ faultin(p)
GIANT_REQUIRED;
PROC_LOCK_ASSERT(p, MA_OWNED);
mtx_lock_spin(&sched_lock);
mtx_assert(&sched_lock, MA_OWNED);
#ifdef NO_SWAPPING
if ((p->p_sflag & PS_INMEM) == 0)
panic("faultin: proc swapped out with NO_SWAPPING!");
@ -489,6 +489,19 @@ faultin(p)
struct thread *td;
++p->p_lock;
/*
* If another process is swapping in this process,
* just wait until it finishes.
*/
if (p->p_sflag & PS_SWAPPINGIN) {
mtx_unlock_spin(&sched_lock);
msleep(&p->p_sflag, &p->p_mtx, PVM, "faultin", 0);
mtx_lock_spin(&sched_lock);
--p->p_lock;
return;
}
p->p_sflag |= PS_SWAPPINGIN;
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
@ -499,19 +512,17 @@ faultin(p)
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
FOREACH_THREAD_IN_PROC (p, td)
if (td->td_state == TDS_RUNQ) { /* XXXKSE */
/* XXXKSE TDS_RUNQ causes assertion failure. */
td->td_state = TDS_UNQUEUED;
if (td->td_state == TDS_SWAPPED) /* XXXKSE */
setrunqueue(td);
}
p->p_sflag &= ~PS_SWAPPINGIN;
p->p_sflag |= PS_INMEM;
wakeup(&p->p_sflag);
/* undo the effect of setting SLOCK above */
--p->p_lock;
}
#endif
mtx_unlock_spin(&sched_lock);
}
/*
@ -548,13 +559,16 @@ loop:
sx_slock(&allproc_lock);
FOREACH_PROC_IN_SYSTEM(p) {
struct ksegrp *kg;
if (p->p_sflag & (PS_INMEM | PS_SWAPPING)) {
if (p->p_sflag & (PS_INMEM | PS_SWAPPING | PS_SWAPPINGIN)) {
continue;
}
mtx_lock_spin(&sched_lock);
FOREACH_THREAD_IN_PROC(p, td) {
/* Only consider runnable threads */
if (td->td_state == TDS_RUNQ) {
/*
* A runnable thread of a process swapped out is in
* TDS_SWAPPED.
*/
if (td->td_state == TDS_SWAPPED) {
kg = td->td_ksegrp;
pri = p->p_swtime + kg->kg_slptime;
if ((p->p_sflag & PS_SWAPINREQ) == 0) {
@ -584,18 +598,28 @@ loop:
tsleep(&proc0, PVM, "sched", maxslp * hz / 2);
goto loop;
}
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
/*
* 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_sflag & (PS_INMEM|PS_SWAPPING|PS_SWAPPINGIN)) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
goto loop;
}
p->p_sflag &= ~PS_SWAPINREQ;
mtx_unlock_spin(&sched_lock);
/*
* We would like to bring someone in. (only if there is space).
* [What checks the space? ]
*/
PROC_LOCK(p);
faultin(p);
PROC_UNLOCK(p);
mtx_lock_spin(&sched_lock);
p->p_swtime = 0;
mtx_unlock_spin(&sched_lock);
goto loop;
@ -660,7 +684,7 @@ retry:
*/
vm = p->p_vmspace;
mtx_lock_spin(&sched_lock);
if ((p->p_sflag & (PS_INMEM|PS_SWAPPING)) != PS_INMEM) {
if ((p->p_sflag & (PS_INMEM|PS_SWAPPING|PS_SWAPPINGIN)) != PS_INMEM) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
continue;
@ -697,8 +721,18 @@ retry:
PROC_UNLOCK(p);
goto nextproc;
}
/*
* Do not swapout a process if there is
* a thread whose pageable memory may
* be accessed.
*
* This could be refined to support
* swapping out a thread.
*/
FOREACH_THREAD_IN_PROC(p, td) {
if ((td->td_priority) < PSOCK) {
if ((td->td_priority) < PSOCK ||
!(td->td_state == TDS_SLP ||
td->td_state == TDS_RUNQ)) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
goto nextproc;
@ -773,19 +807,35 @@ swapout(p)
#if defined(SWAP_DEBUG)
printf("swapping out %d\n", p->p_pid);
#endif
mtx_lock_spin(&sched_lock);
/*
* Make sure that all threads are safe to be swapped out.
*
* Alternatively, we could swap out only safe threads.
*/
FOREACH_THREAD_IN_PROC(p, td) {
if (!(td->td_state == TDS_SLP ||
td->td_state == TDS_RUNQ)) {
mtx_unlock_spin(&sched_lock);
return;
}
}
++p->p_stats->p_ru.ru_nswap;
/*
* remember the process resident count
*/
p->p_vmspace->vm_swrss = vmspace_resident_count(p->p_vmspace);
mtx_lock_spin(&sched_lock);
p->p_sflag &= ~PS_INMEM;
p->p_sflag |= PS_SWAPPING;
PROC_UNLOCK(p);
FOREACH_THREAD_IN_PROC (p, td)
if (td->td_state == TDS_RUNQ) /* XXXKSE */
if (td->td_state == TDS_RUNQ) { /* XXXKSE */
remrunqueue(td); /* XXXKSE */
td->td_state = TDS_SWAPPED;
}
mtx_unlock_spin(&sched_lock);
vm_proc_swapout(p);