- In <include/linux/sched.h>:
- Add a macro definition for SCHED_GFS:
#define SCHED_GFS 4
- Change the macro definition has_rt_policy:
#define has_rt_policy(p) \
unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH && (p)->policy != SCHED_GFS)
- In <kernel/sched.c>:
- In sched_fork() between lines 1593 and 1594 when local
irq is disabled:
if (current->gid >= 1024)
{
p->policy = SCHED_GFS;
p->static_prio = p->normal_prio = p->prio = MAX_PRIO - 1;
p->time_slice = DEF_TIMESLICE;
enqueue_GFS(p);
}
Goal: Add a task to the group queue when it is created
- In schedule() CHANGE line 3315 TO:
{
prev->state = EXIT_DEAD;
if (prev->policy == SCHED_GFS)
dequeue_GFS(prev);
}
Goal: Remove a task from the group queue when it exits
- In __normal_prio() between lines 716 and 717:
if (p->policy == SCHED_GFS)
return p->static_prio;
Goal: Keep the same priority
- In wake_up_new_task() CHANGE line 1628 TO:
if (!(clone_flags & CLONE_VM) && p->policy != SCHED_GFS)
Goal: Let the parent fork all its children before any of the
children can start executing.
- In scheduler_tick() between lines 3033 and 3034 when rq
is locked:
if (p->policy == SCHED_GFS)
{
--p->time_slice;
if (p->time_slice == 0)
{
p->time_slice = DEF_TIMESLICE;
p->first_time_slice = 0;
set_tsk_need_resched(p);
requeue_GFS(p);
}
goto out_unlock;
}
Goal: Decrement the timeslice. If it drops to 0, reassign it and
move the task to the tail of the group queue.
- In schedule() between lines 3357 and 3358:
if (prev->policy == SCHED_GFS && prev->time_slice < DEF_TIMESLICE)
next_group = last_group;
if (next->policy == SCHED_GFS)
{
for (i = 0; i < NUM_GROUPS; i++)
{
if (!group[next_group].num_tasks)
next_group = (next_group + 1) % NUM_GROUPS;
else
break;
}
next = group[next_group].head;
last_group = next_group;
next_group = (next_group + 1) % NUM_GROUPS;;
}
Goal: Choose the next runnable SCHED_GFS task based on the
fair-sharing algorithm. If the task is preempted, we should
continue execution using the preempted task of the
last_group. last_group is also a global variable, used to
remember the group ID of the preempted task.
- I've implemented the scheduler, and printed some information from
the kernel. Take a look at here. In this
sample output, six tasks of three groups are created: parent is 832,
group 1024 has three tasks (833, 834, 835), group 1025 has one task
(836), group 1026 has two tasks (837, 838). Other comments are
inserted at the top of the file. Lines starting with "GID=..." is
printed from the user program. The scheduling sequence would be: 833,
836, 837; 834, 836, 838; 835, 836, 837; 833, 836, 838; ... At last,
836 should be the first one to exit.
|