patch-2.1.52 linux/mm/vmscan.c
Next file: linux/net/bridge/br.c
Previous file: linux/mm/swapfile.c
Back to the patch index
Back to the overall index
- Lines: 195
- Date:
Wed Sep 3 11:44:50 1997
- Orig file:
v2.1.51/linux/mm/vmscan.c
- Orig date:
Sun Jul 27 12:11:01 1997
diff -u --recursive --new-file v2.1.51/linux/mm/vmscan.c linux/mm/vmscan.c
@@ -269,74 +269,78 @@
return 0;
}
+/*
+ * Select the task with maximal swap_cnt and try to swap out a page.
+ * N.B. This function returns only 0 or 1. Return values != 1 from
+ * the lower level routines result in continued processing.
+ */
static int swap_out(unsigned int priority, int dma, int wait)
{
- static int skip_factor = 0;
- int limit = nr_tasks - 1;
- int loop, counter, i;
- struct task_struct *p;
+ struct task_struct * p, * pbest;
+ int counter, assign, max_cnt;
+ /*
+ * We make one or two passes through the task list, indexed by
+ * assign = {0, 1}:
+ * Pass 1: select the swappable task with maximal swap_cnt.
+ * Pass 2: assign new swap_cnt values, then select as above.
+ * With this approach, there's no need to remember the last task
+ * swapped out. If the swap-out fails, we clear swap_cnt so the
+ * task won't be selected again until all others have been tried.
+ */
counter = ((PAGEOUT_WEIGHT * nr_tasks) >> 10) >> priority;
- if(skip_factor > nr_tasks)
- skip_factor = 0;
-
- read_lock(&tasklist_lock);
- p = init_task.next_task;
- i = skip_factor;
- while(i--)
- p = p->next_task;
- for(; counter >= 0; counter--) {
- /* Check if task is suitable for swapping. */
- loop = 0;
- while(1) {
- if(!--limit) {
- limit = nr_tasks - 1;
- /* See if all processes are unswappable or
- * already swapped out.
+ for (; counter >= 0; counter--) {
+ assign = 0;
+ max_cnt = 0;
+ pbest = NULL;
+ select:
+ read_lock(&tasklist_lock);
+ p = init_task.next_task;
+ for (; p != &init_task; p = p->next_task) {
+ if (!p->swappable)
+ continue;
+ if (p->mm->rss <= 0)
+ continue;
+ if (assign) {
+ /*
+ * If we didn't select a task on pass 1,
+ * assign each task a new swap_cnt.
+ * Normalise the number of pages swapped
+ * by multiplying by (RSS / 1MB)
*/
- if (loop)
- goto out;
- loop = 1;
+ p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss);
+ }
+ if (p->swap_cnt > max_cnt) {
+ max_cnt = p->swap_cnt;
+ pbest = p;
}
- if (p->swappable && p->mm->rss)
- break;
- if((p = p->next_task) == &init_task)
- p = p->next_task;
- }
- skip_factor++;
-
- /* Determine the number of pages to swap from this process. */
- if (!p->swap_cnt) {
- /* Normalise the number of pages swapped by
- multiplying by (RSS / 1MB) */
- p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss);
}
- if (!--p->swap_cnt)
- skip_factor++;
read_unlock(&tasklist_lock);
+ if (!pbest) {
+ if (!assign) {
+ assign = 1;
+ goto select;
+ }
+ goto out;
+ }
+ pbest->swap_cnt--;
- switch (swap_out_process(p, dma, wait)) {
+ switch (swap_out_process(pbest, dma, wait)) {
case 0:
- if (p->swap_cnt)
- skip_factor++;
+ /*
+ * Clear swap_cnt so we don't look at this task
+ * again until we've tried all of the others.
+ * (We didn't block, so the task is still here.)
+ */
+ pbest->swap_cnt = 0;
break;
case 1:
return 1;
default:
break;
};
-
- /* Whoever we swapped may not even exist now, in fact we cannot
- * assume anything about the list we were searching previously.
- */
- read_lock(&tasklist_lock);
- p = init_task.next_task;
- i = skip_factor;
- while(i--)
- p = p->next_task;
}
out:
- read_unlock(&tasklist_lock);
return 0;
}
@@ -362,9 +366,6 @@
return 1;
state = 1;
case 1:
- shrink_dcache();
- state = 2;
- case 2:
/*
* We shouldn't have a priority here:
* If we're low on memory we should
@@ -373,11 +374,11 @@
*/
if (kmem_cache_reap(0, dma, wait))
return 1;
- state = 3;
- case 3:
+ state = 2;
+ case 2:
if (shm_swap(i, dma))
return 1;
- state = 4;
+ state = 3;
default:
if (swap_out(i, dma, wait))
return 1;
@@ -477,31 +478,23 @@
void swap_tick(void)
{
- int want_wakeup = 0;
- static int last_wakeup_low = 0;
+ int want_wakeup = 0, memory_low = 0;
+ int pages = nr_free_pages + atomic_read(&nr_async_pages);
- if ((nr_free_pages + atomic_read(&nr_async_pages)) < free_pages_low) {
- if (last_wakeup_low)
- want_wakeup = jiffies >= next_swap_jiffies;
- else
- last_wakeup_low = want_wakeup = 1;
- }
- else if (((nr_free_pages + atomic_read(&nr_async_pages)) < free_pages_high) &&
- jiffies >= next_swap_jiffies) {
- last_wakeup_low = 0;
+ if (pages < free_pages_low)
+ memory_low = want_wakeup = 1;
+ else if (pages < free_pages_high && jiffies >= next_swap_jiffies)
want_wakeup = 1;
- }
if (want_wakeup) {
if (!kswapd_awake) {
wake_up(&kswapd_wait);
need_resched = 1;
}
- /* low on memory, we need to start swapping soon */
- if(last_wakeup_low)
- next_swap_jiffies = jiffies;
- else
- next_swap_jiffies = jiffies + swapout_interval;
+ /* Set the next wake-up time */
+ next_swap_jiffies = jiffies;
+ if (!memory_low)
+ next_swap_jiffies += swapout_interval;
}
timer_active |= (1<<SWAP_TIMER);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov