1
votes

I am currently working on a project involving modifying the way linux priorities are implemented.

To do so I have :

  • a custom syscall : That modifies the task_struct of a process to change its priority

  • modified kernel/sched/fair.c

  • modified the standard task_struct to add new fields

    While the custom syscall works : it gets correctly called and prints to dmesg the fair.c file doesn't seem to take into account the changes.

original fair.c

Changes to fair.c :

 /*
  * move_task - move a task from one runqueue to another runqueue.
  * Both runqueues must be locked.
  */
 static void move_task(struct task_struct *p, struct lb_env *env)
 {
         deactivate_task(env->src_rq, p, 0);
         if (p->prio_per_cpu)
         {            
            p->rt_priority = p->smp_prio[env->dst_cpu];
            printk(KERN_EMERG "We are in move_task function");
         }
         set_task_cpu(p, env->dst_cpu);
         activate_task(env->dst_rq, p, 0);
         check_preempt_curr(env->dst_rq, p, 0);
 }

p->prio_per_cpu is set to 1 in the syscall, but move_task function doesn't seem to see it.

The syscall :

/* system call to set the new field in 
 * task struct 'smp_prio' that allows 
 * one priority per processor on SMP machines
 */

asmlinkage long sys_set_smp_prio(pid_t pid, const char *smp_prio)
{
 struct pid *pid_struct;
 struct task_struct *p;

 pid_struct = find_get_pid(pid);
 p = pid_task(pid_struct,PIDTYPE_PID);
 p->prio_per_cpu = 1;
 p->smp_prio = (char*) smp_prio;
 printk(KERN_EMERG "SMP priorities are correctly set \n");
 return 1;
}

I get the syscall printk message.

The original task_struct

The modified task_struct :

#define INIT_TASK(tsk)  \
 {                                                                       \
     .state          = 0,                                            \
     .stack          = &init_thread_info,                            \
     .usage          = ATOMIC_INIT(2),                               \
     .flags          = PF_KTHREAD,                                   \
     .prio_per_cpu   = 0,                                            \
     .smp_prio       = NULL,                                         \
     .prio           = MAX_PRIO-20,                                  \
     .static_prio    = MAX_PRIO-20,                                  \
     .normal_prio    = MAX_PRIO-20,                                  \
     .policy         = SCHED_NORMAL,                                 \
     .cpus_allowed   = CPU_MASK_ALL,                                 \
     .nr_cpus_allowed= NR_CPUS,                                      \
     .mm             = NULL,                                         \
     .active_mm      = &init_mm,                                     \
     .se             = {                                             \
             .group_node     = LIST_HEAD_INIT(tsk.se.group_node),    \
     },                                                              \
     .rt             = {                                             \
             .run_list       = LIST_HEAD_INIT(tsk.rt.run_list),      \
             .time_slice     = RR_TIMESLICE,                         \
     },         
     [...]

When I modified move_task() to print a message unconditionally it did print that message.

I am sure move_task gets called with the task_struct argument of the thread modified by the syscall because I manually force thread migration by setting cpusets (bitmask) and move_task is the very bit of code that performs migration from one cpu to another.

Why aren't the changes done by the custom syscall not effective in the move_task() function ?

Thank you for any help!

2
First obvious question I think of is have you put a breakpoint at the line if (p->prio_per_cpu) to see what the value of p->prio_per_cpu is at the time of evaluation. If it is 0, it never gets to the print function.ryyker
What does deactivate_task(env->src_rq, p, 0); do to p?ryyker
Also, it looks like p is has local scope to sys_set_smp_prio() True?ryyker
deactivate_task removes the task represented by p from the runqueue it is actually inMSI
What are the changes made to task_struct ? Could you please post it ?Vivek S

2 Answers

1
votes

I found the solution a long time ago, but just for the record : I am testing this new kernel facilities with real-time threads. They aren't scheduled by the CFS scheduler (fair.c)

0
votes

The locally defined struct task_struct *p; in this function:

asmlinkage long sys_set_smp_prio(pid_t pid, const char *smp_prio)
{
 struct pid *pid_struct;
 struct task_struct *p;  //THIS COPY OF task_struct *p HAS NO CONNECTION...

 pid_struct = find_get_pid(pid);
 task = pid_task(pid_struct,PIDTYPE_PID);
 p->prio_per_cpu = 1;
 p->smp_prio = (char*) smp_prio;
 printk(KERN_EMERG "SMP priorities are correctly set \n");
 return 1;
}   

Has no visible relationship to the argument passed struct task_struct *p (at least in the provided code)

static void move_task(struct task_struct *p, struct lb_env *env) //TO THIS ONE
 {
         deactivate_task(env->src_rq, p, 0);
         if (p->prio_per_cpu)  //If this value is zero, printk will never be called.
         {            
            p->rt_priority = p->smp_prio[env->dst_cpu];
            printk(KERN_EMERG "We are in move_task function");
         }
         set_task_cpu(p, env->dst_cpu);
         activate_task(env->dst_rq, p, 0);
         check_preempt_curr(env->dst_rq, p, 0);
 }  

That is, I do not see where you are calling move_task() from within sys_set_smp_prio() with its updated value for p->prio_per_cpu = 1;. Could this be the problem?