diff -ur linux-2.2.13/include/asm-i386/resource.h linux-2.2.13+cpumod/include/asm-i386/resource.h --- linux-2.2.13/include/asm-i386/resource.h Wed Aug 25 20:29:49 1999 +++ linux-2.2.13+cpumod/include/asm-i386/resource.h Sun Nov 21 22:39:43 1999 @@ -15,8 +15,9 @@ #define RLIMIT_NOFILE 7 /* max number of open files */ #define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ #define RLIMIT_AS 9 /* address space limit */ +#define RLIMIT_TCPU 10 /* temporary cpu limits */ -#define RLIM_NLIMITS 10 +#define RLIM_NLIMITS 11 #ifdef __KERNEL__ @@ -30,6 +31,7 @@ { LONG_MAX, LONG_MAX }, \ { MAX_TASKS_PER_USER, MAX_TASKS_PER_USER }, \ { INR_OPEN, INR_OPEN }, \ + { LONG_MAX, LONG_MAX }, \ { LONG_MAX, LONG_MAX }, \ { LONG_MAX, LONG_MAX }, \ } diff -ur linux-2.2.13/include/linux/sched.h linux-2.2.13+cpumod/include/linux/sched.h --- linux-2.2.13/include/linux/sched.h Tue Oct 19 20:14:02 1999 +++ linux-2.2.13+cpumod/include/linux/sched.h Sun Nov 21 23:12:28 1999 @@ -227,6 +227,13 @@ */ struct user_struct; +struct timepenalty_struct { + unsigned long waitjiffies; /* penalty time before allowing rescheduling */ + long last_time; /* last penalized cpu time */ +}; + +#define INIT_TIMEPENALTY {0, 0} + struct task_struct { /* these are hardcoded - don't touch */ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ @@ -300,6 +307,7 @@ struct user_struct *user; /* limits */ struct rlimit rlim[RLIM_NLIMITS]; + struct timepenalty_struct timepenalty; unsigned short used_math; char comm[16]; /* file system info */ @@ -385,6 +393,7 @@ /* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \ /* user */ NULL, \ /* rlimits */ INIT_RLIMITS, \ +/* penalties */ INIT_TIMEPENALTY, \ /* math */ 0, \ /* comm */ "swapper", \ /* fs info */ 0,NULL, \ diff -ur linux-2.2.13/kernel/sched.c linux-2.2.13+cpumod/kernel/sched.c --- linux-2.2.13/kernel/sched.c Tue Oct 19 20:14:02 1999 +++ linux-2.2.13+cpumod/kernel/sched.c Mon Nov 22 15:58:30 1999 @@ -115,12 +115,12 @@ #ifdef __SMP__ #define idle_task(cpu) (task[cpu_number_map[(cpu)]]) -#define can_schedule(p) (!(p)->has_cpu) +#define can_schedule(p) (!(p)->has_cpu && (jiffies > p->timepenalty.waitjiffies)) #else #define idle_task(cpu) (&init_task) -#define can_schedule(p) (1) +#define can_schedule(p) ((jiffies > p->timepenalty.waitjiffies)) #endif @@ -1409,9 +1409,18 @@ unsigned long user, unsigned long system) { long psecs; + static unsigned long abooga = 0; psecs = (p->times.tms_utime += user); psecs += (p->times.tms_stime += system); +#if 0 + if (p->pid > 100 && !(abooga++ % 500)) { + printk (KERN_INFO "pid %u: relevant call to do_process_times()\n", p->pid); + printk (KERN_INFO "psecs/HZ=%lu waitjiffies=%lu last_time=%ld jiffies=%lu\n", psecs/HZ, p->timepenalty.waitjiffies, p->timepenalty.last_time, jiffies); + printk (KERN_INFO "psecs=%lu HZ=%u p->rlim[RLIMIT_TCPU].rlim_cur/max=%ld/%ld\n", psecs, HZ, p->rlim[RLIMIT_TCPU].rlim_cur, p->rlim[RLIMIT_TCPU].rlim_max); + } +#endif + if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur) { /* Send SIGXCPU every second.. */ if (!(psecs % HZ)) @@ -1419,6 +1428,21 @@ /* and SIGKILL when we go over max.. */ if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_max) send_sig(SIGKILL, p, 1); + } + /* rlim_max is the amount of cpu time allowed to pass since the last + penalty, measured by 1/100th of a cpu second. + rlim_cur is the reverse number of jiffies to wait as penalty time + before allowing scheduling to continue (reverse so that the user + may increase his penalty time but not decrease it). */ + if (psecs - p->timepenalty.last_time >= p->rlim[RLIMIT_TCPU].rlim_max) { + unsigned long penalty = + LONG_MAX - p->rlim[RLIMIT_TCPU].rlim_cur; + p->timepenalty.last_time = psecs; + p->timepenalty.waitjiffies = jiffies + penalty; + if (penalty > 200) /* warn about penalties over 200 jiffies */ + printk(KERN_INFO + "pid %u: set penalty time of %lu jiffies\n", + p->pid, penalty); } }