In sched.h:
struct user_struct {
atomic_t __count;
atomic_t processes;
atomic_t files; */
/* Hash table maintenance information
*/
struct user_struct *next, **pprev;
uid_t uid;
//
// the following lines are new
//
long processesTickSum;
long counter;
long usernice;
};
In user.c:
struct user_struct * alloc_uid(uid_T uid) {
…
new->processesTickSum = 0;
new->counter = 0;
new->usernice = 0;
…
In timer.c:
struct task_struct *p;
…
if (p->pid && p->euid >=100) {
// user processes
if (--p->counter<=0) {
p->counter=0;
p->need_resched=1;
}
if
(--p->user->processesTickSum<=0) {
spin_unlock_irq(&runqueue_lock);
read_lock(&tasklist_lock);
for_each_task(p)
{
p->counter
= (p->counter >> 1) +
NICE_TO_TICKS(p->nice);
p->user->processesTickSum+=p->counter;
}
read_unlock(&tasklist_lock);
spin_lock_irq(&runqueue_lock);
p->need_resched=1;
}
if (--p->user->counter <=0) {
p->user->counter=0;
p->need_resched=1;
}
} else if (p->pid) {
// system
processes
…
In sched.c:
if (p->policy == SCHED_OTHER) {
weight=0;
if (p->user->counter>0) {
weight=((20-p->user->usernice)+p->user->counter)<<16;
weight+=((20-p->nice)+p->counter);
}
// add other bonuses
…
}
recalculate:
{
struct
task_struct *p;
spin_unlock_irq(&runqueue_lock);
read_lock(&tasklist_lock);
for_each_task(p)
p->user->counter=(20-p->user->usernice);
read_unlock(&tasklist_lock);
spin_lock_irq(&runqueue_lock);
}
goto repeat_schedule;
In sched.c:
asmlinkage long sys_usernice(int nice_level, uid_t uid)
{
struct user_struct *user;
struct user_struct **hashent;
int ret_val;
if (nice_level < 0) {
if
(!capable(CAP_SYS_NICE))
return
-EPERM;
if
(nice_level < -20) {
nice_level
= -20;
}
}
if (nice_level > 19) {
nice_level
= 19;
}
spin_lock (&uidhash_lock);
hashent = uidhashentry(uid);
user = uid_hash_find(uid, hashent);
if(user) {
user->usernice
= nice;
ret_val
= 0;
} else {
ret_val
= -1;
}
spin_unlock (&uidhash_lock);
return ret_val;
}