I've made a draft version of the out-of-memory
killer (linux/mm/oom_kill.c) but it isn't complete
yet and could probably be better.
Especially the IOPL/IOPERM stuff is very important
but I haven't figured it out yet :(
Also, there's no code yet to trigger this routine,
so everybody should be safe for now :)
(I post this mainly because we've had several flamewars
over this issue and I want to prevent that this time)
Rik.
+-------------------------------------------+--------------------------+
| Linux: - LinuxHQ MM-patches page          | Scouting       webmaster |
|        - kswapd ask-him & complain-to guy | Vries    cubscout leader |
|     http://www.phys.uu.nl/~riel/          | <H.H.vanRiel@phys.uu.nl> |
+-------------------------------------------+--------------------------+
/*
 *  linux/mm/oom_kill.c
 * 
 *  Copyright (C)  1998  Rik van Riel
 *
 *  The routines in this file are used to kill a process when
 *  we're seriously out of memory. This gets called from kswapd()
 *  in linux/mm/vmscan.c when the pageout daemon gets stuck.
 *
 *  We hope to call this function as little as often, there are
 *  no critical code paths in here. Don't try to be smart, just
 *  leave it ultra-readable so we'll never mess up...
 */
#include <linux/sched.h>
#define DEBUG
/* Ugly helper function, we don't want to do without it because
 * the points variable might overflow if we just squared the
 * size instead. */
inline int int_sqrt(int x)
{
	int i,out;
	for (i = 10; i-- > 0;)
		out = x + out >> 1;
	if (out)
		return out;
	return 1;
}	
inline int badness(task_struct *p)
{
	int points = p->mm->total_vm;
	points /= int_sqrt((p->tms->tms_utime + p->tms->tms_stime) >> (SHIFT_HZ + 6))
	if (p->priority < DEF_PRIORITY)
		points <<= 1;
	if (p->uid == 0 || p->euid == 0)
		points >>= 1;
	/* FIXME: - strange assumption being made :) 
	 *        - not jiffie-overflow safe!  */
	if (p->start_time < jiffies >> 6)
		points >>= 1;
	/* FIXME: How can I test for IOPL or IOPERM permissions??? */		
	if (/* p->tss->	|| */ p->cap_effective & CAP_SYS_RAWIO)
		points = 0;
#ifdef DEBUG
	printk(KERN_DEBUG "OOMkill: task %d (%s) got %d points\n",
	p->pid, p->comm, points);
#endif
}
inline struct task_struct * select_bad_process(void)
{
	int points = 0;
	struct task_struct *p = NULL;
	struct task_struct *chosen = NULL;
	read_lock(&tasklist_lock);	/* We might need this on SMP */
	for_each_task(p)
		if (p->pid && badness(p) > points)
			chosen = p;
	read_unlock(&tasklist_lock);
	return chosen;
}
/*
 * The SCHED_FIFO magic is because we want the process to
 * be able to kill itself even when kswapd is running.
 */
void oom_kill(void)
{
	struct task_struct *p = select_bad_process();
	if (p == NULL)
		return;
	force_sig(SIGKILL, p);
	p->policy = SCHED_FIFO;
	p->rt_priority = 1000;
	current->policy |= SCHED_YIELD;
	schedule();
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu