Avoid holding locks too long in imagereclaim,
and avoid rescheduling if it does happen.
[rsc] --rw-rw-r-- M 23749 glenda sys 28702 Jan 31 18:16 sys/src/9/port/proc.c
/n/sourcesdump/2006/0131/plan9/sys/src/9/port/proc.c:122,128 -
/n/sourcesdump/2006/0201/plan9/sys/src/9/port/proc.c:122,146
getcallerpc(&p+2));
if(up){
- if(up->nlocks.ref && up->state != Moribund && up->delaysched < 20){
+ /*
+ * Delay the sched until the process gives up the locks
+ * it is holding. This avoids dumb lock loops.
+ * Don't delay if the process is Moribund.
+ * It called sched to die.
+ * But do sched eventually. This avoids a missing unlock
+ * from hanging the entire kernel.
+ * But don't reschedule procs holding palloc or procalloc.
+ * Those are far too important to be holding while asleep.
+ *
+ * This test is not exact. There can still be a few instructions
+ * in the middle of taslock when a process holds a lock
+ * but Lock.p has not yet been initialized.
+ */
+ if(up->nlocks.ref)
+ if(up->state != Moribund)
+ if(up->delaysched < 20
+ || palloc.Lock.p == up
+ || procalloc.Lock.p == up){
up->delaysched++;
delayedscheds++;
return;
[rsc] --rw-rw-r-- M 23749 glenda sys 13939 Jan 31 18:16 sys/src/9/port/segment.c
/n/sourcesdump/2006/0131/plan9/sys/src/9/port/segment.c:320,325 -
/n/sourcesdump/2006/0201/plan9/sys/src/9/port/segment.c:320,326
static void
imagereclaim(void)
{
+ int n;
Page *p;
uvlong ticks;
/n/sourcesdump/2006/0131/plan9/sys/src/9/port/segment.c:330,339 -
/n/sourcesdump/2006/0201/plan9/sys/src/9/port/segment.c:331,348
lock(&palloc);
ticks = fastticks(nil);
- for(p = palloc.head; p; p = p->next) {
- if(p->ref == 0 && p->image && canlock(p)) {
- if(p->ref == 0)
+ n = 0;
+ /*
+ * All the pages with images backing them are at the
+ * end of the list (see putpage) so start there and work
+ * backward.
+ */
+ for(p = palloc.tail; p && p->image && n<1000; p = p->prev) {
+ if(p->ref == 0 && canlock(p)) {
+ if(p->ref == 0) {
+ n++;
uncachepage(p);
+ }
unlock(p);
}
}
|