SMP boot finally works. Unknown behavior of worker threads due to
authorJens Krieg <jkrieg@mailbox.tu-berlin.de>
Mon, 30 Sep 2013 13:29:37 +0000 (15:29 +0200)
committerJens Krieg <jkrieg@mailbox.tu-berlin.de>
Mon, 30 Sep 2013 13:29:37 +0000 (15:29 +0200)
uninitialized migration. Inserting function migration_init solved all
problems.

arch/x86/kernel/process.c
kernel/kthread.c
kernel/sched.new/core.c
kernel/sched/core.c
kernel/workqueue.c

index ba584b2..0d657cb 100644 (file)
@@ -355,8 +355,6 @@ void cpu_idle(void)
                           has already called exit_idle. But some idle
                           loops can be woken up without interrupt. */
                        __exit_idle();
-//                     break;
-
                }
                tick_nohz_idle_exit();
                preempt_enable_no_resched();
index bda7fa4..f09fb12 100644 (file)
@@ -265,9 +265,6 @@ static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state)
                return;
        }
 
-//     if (cpu == 1)
-//             printk("Tsk(%d) bound to CPU 1\n", p->pid);
-
        /* It's safe because the task is inactive. */
        do_set_cpus_allowed(p, cpumask_of(cpu));
        p->flags |= PF_THREAD_BOUND;
index 3bc89f6..d852444 100644 (file)
@@ -1539,8 +1539,6 @@ context_switch(struct rq *rq, struct task_struct *prev,
  *          - return from syscall or exception to user-space
  *          - return from interrupt-handler to user-space
  */
-volatile struct rq *rq1, *rq2;
-volatile struct task_struct test_tsk;
 static void __sched __schedule(void)
 {
        struct task_struct *prev, *next;
@@ -1555,14 +1553,6 @@ need_resched:
        rcu_note_context_switch(cpu);
        prev = rq->curr;
 
-
-       if (cpu == 0)
-                       rq1 = rq;
-               else if (cpu == 1)
-                       rq2 = rq;
-               else
-                       printk("WTF!!!\n");
-
 //     schedule_debug(prev);
 
 //     if (sched_feat(HRTICK))
@@ -1570,15 +1560,12 @@ need_resched:
 
        raw_spin_lock_irq(&rq->lock);
 
-//     printk("Schedule on CPU %i\n", cpu);
-
 //     switch_count = &prev->nivcsw;
        if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
                if (unlikely(signal_pending_state(prev->state, prev))) {
                        prev->state = TASK_RUNNING;
                } else {
 //                     deactivate_task(rq, prev, DEQUEUE_SLEEP);
-//                     list_del_init(&prev->rq_tasks);
                        prev->on_rq = 0;
 
                        /*
@@ -1625,15 +1612,6 @@ need_resched:
        clear_tsk_need_resched(prev);
        rq->skip_clock_update = 0;
 
-
-//     if ((next->pid == 12) ||
-//             (next->pid == 13) ||
-//             (next->pid == 14))
-//             printk("tolle wurst!");
-//
-//     if (task_cpu(next) == 1)
-//             printk("Task (%i) on CPU 1\n", next->pid);
-
        if (likely(prev != next)) {
                rq->nr_switches++;
                rq->curr = next;
@@ -2307,6 +2285,128 @@ static int migration_cpu_stop(void *data)
        return 0;
 }
 
+
+static void set_rq_online(struct rq *rq)
+{
+       if (!rq->online)
+               rq->online = 1;
+}
+
+static void set_rq_offline(struct rq *rq)
+{
+       if (rq->online)
+               rq->online = 0;
+}
+
+/*
+ * migration_call - callback that gets triggered when a CPU is added.
+ * Here we can start up the necessary migration thread for the new CPU.
+ */
+static int __cpuinit
+migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+       int cpu = (long)hcpu;
+       unsigned long flags;
+       struct rq *rq = cpu_rq(cpu);
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+
+       case CPU_UP_PREPARE:
+//             rq->calc_load_update = calc_load_update;
+               break;
+
+       case CPU_ONLINE:
+               /* Update our root-domain */
+               raw_spin_lock_irqsave(&rq->lock, flags);
+//             if (rq->rd) {
+//                     BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
+//
+                       set_rq_online(rq);
+//             }
+               raw_spin_unlock_irqrestore(&rq->lock, flags);
+               break;
+
+#ifdef CONFIG_HOTPLUG_CPU
+       case CPU_DYING:
+               sched_ttwu_pending();
+               /* Update our root-domain */
+               raw_spin_lock_irqsave(&rq->lock, flags);
+//             if (rq->rd) {
+//                     BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
+                       set_rq_offline(rq);
+//             }
+               migrate_tasks(cpu);
+               BUG_ON(rq->nr_running != 1); /* the migration thread */
+               raw_spin_unlock_irqrestore(&rq->lock, flags);
+               break;
+
+       case CPU_DEAD:
+//             calc_load_migrate(rq);
+               break;
+#endif
+       }
+
+//     update_max_interval();
+
+       return NOTIFY_OK;
+}
+
+/*
+ * Register at high priority so that task migration (migrate_all_tasks)
+ * happens before everything else.  This has to be lower priority than
+ * the notifier in the perf_event subsystem, though.
+ */
+static struct notifier_block __cpuinitdata migration_notifier = {
+       .notifier_call = migration_call,
+       .priority = CPU_PRI_MIGRATION,
+};
+
+static int __cpuinit sched_cpu_active(struct notifier_block *nfb,
+                                     unsigned long action, void *hcpu)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+       case CPU_DOWN_FAILED:
+               set_cpu_active((long)hcpu, true);
+               return NOTIFY_OK;
+       default:
+               return NOTIFY_DONE;
+       }
+}
+
+static int __cpuinit sched_cpu_inactive(struct notifier_block *nfb,
+                                       unsigned long action, void *hcpu)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_PREPARE:
+               set_cpu_active((long)hcpu, false);
+               return NOTIFY_OK;
+       default:
+               return NOTIFY_DONE;
+       }
+}
+
+static int __init migration_init(void)
+{
+       void *cpu = (void *)(long)smp_processor_id();
+       int err;
+
+       /* Initialize migration for the boot CPU */
+       err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
+       BUG_ON(err == NOTIFY_BAD);
+       migration_call(&migration_notifier, CPU_ONLINE, cpu);
+       register_cpu_notifier(&migration_notifier);
+
+       /* Register cpu active notifiers */
+       cpu_notifier(sched_cpu_active, CPU_PRI_SCHED_ACTIVE);
+       cpu_notifier(sched_cpu_inactive, CPU_PRI_SCHED_INACTIVE);
+
+       return 0;
+}
+early_initcall(migration_init);
+
+
+
 void do_set_cpus_allowed(struct task_struct *p,
                               const struct cpumask *new_mask)
 {
@@ -2583,50 +2683,6 @@ unlock:
        raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 }
 
-///*
-// * kernel/sched/core.c:5512
-// */
-//static int init_rootdomain(struct root_domain *rd)
-//{
-//     memset(rd, 0, sizeof(*rd));
-//
-//     if (!alloc_cpumask_var(&rd->span, GFP_KERNEL))
-//             goto out;
-//     if (!alloc_cpumask_var(&rd->online, GFP_KERNEL))
-//             goto free_span;
-//     if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
-//             goto free_online;
-//
-//     if (cpupri_init(&rd->cpupri) != 0)
-//             goto free_rto_mask;
-//     return 0;
-//
-//free_rto_mask:
-//     free_cpumask_var(rd->rto_mask);
-//free_online:
-//     free_cpumask_var(rd->online);
-//free_span:
-//     free_cpumask_var(rd->span);
-//out:
-//     return -ENOMEM;
-//}
-//
-///*
-// * By default the system creates a single root-domain with all cpus as
-// * members (mimicking the global state we have today).
-// */
-//struct root_domain def_root_domain;
-//
-///*
-// * kernel/sched/core.c:5543
-// */
-//static void init_defrootdomain(void)
-//{
-//     init_rootdomain(&def_root_domain);
-//
-//     atomic_set(&def_root_domain.refcount, 1);
-//}
-
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
 #ifdef CONFIG_SCHED_DEBUG
@@ -2653,7 +2709,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 #endif
 #endif
 
-       // TODO: SMP, needs to implemented while using migration/load balancing
+       // TODO: SMP, needs to implemented while using load balancing
 //     trace_sched_migrate_task(p, new_cpu);
 //
 //     if (task_cpu(p) != new_cpu) {
index 634e887..0899b6b 100644 (file)
@@ -2878,13 +2878,25 @@ pick_next_task(struct rq *rq)
  *          - return from syscall or exception to user-space
  *          - return from interrupt-handler to user-space
  */
-volatile struct rq *rq1, *rq2;
+//void print_rb_nodes(struct rq *rq) {
+//     struct task_struct *p;
+//
+//     if (!rq->cfs.rb_leftmost)
+//             return;
+//
+//     p = pick_next_task(rq);
+//     if (rq->cfs.rb_leftmost)
+//             print_rb_nodes(rq);
+//     put_prev_task(rq, p);
+//
+//     printk("%i ", p->pid);
+//}
 static void __sched __schedule(void)
 {
        struct task_struct *prev, *next;
        unsigned long *switch_count;
        struct rq *rq;
-       int cpu;
+       int i, cpu;
 
 need_resched:
        preempt_disable();
@@ -2893,13 +2905,6 @@ need_resched:
        rcu_note_context_switch(cpu);
        prev = rq->curr;
 
-       if (cpu == 0)
-               rq1 = rq;
-       else if (cpu == 1)
-               rq2 = rq;
-       else
-               printk("WTF!!!\n");
-
        schedule_debug(prev);
 
        if (sched_feat(HRTICK))
@@ -2941,14 +2946,6 @@ need_resched:
        clear_tsk_need_resched(prev);
        rq->skip_clock_update = 0;
 
-       if ((next->pid == 12) ||
-               (next->pid == 13) ||
-               (next->pid == 14))
-               printk("tolle wurst!");
-
-       if (task_cpu(next) == 1)
-               printk("Task (%i) on CPU 1\n", next->pid);
-
        if (likely(prev != next)) {
                rq->nr_switches++;
                rq->curr = next;
@@ -2971,7 +2968,6 @@ need_resched:
        sched_preempt_enable_no_resched();
        if (need_resched())
                goto need_resched;
-
 }
 
 static inline void sched_submit_work(struct task_struct *tsk)
index b48cd59..6816746 100644 (file)
@@ -1557,6 +1557,7 @@ __acquires(&pool->lock)
                    cpumask_equal(&current->cpus_allowed,
                                  get_cpu_mask(pool->cpu)))
                        return true;
+
                spin_unlock_irq(&pool->lock);
 
                /*
@@ -1567,6 +1568,9 @@ __acquires(&pool->lock)
                 */
                cpu_relax();
                cond_resched();
+
+//             printk("worker_maybe_bind_and_lock: in loop: Worker(%i) on CPU(%i,%i) with masks equal?(%i) and poolsdis?(%i)\n", task->pid, pool->cpu, task_cpu(task),
+//                         cpumask_equal(&current->cpus_allowed, get_cpu_mask(pool->cpu)),(pool->flags & POOL_DISASSOCIATED));
        }
 }
 
@@ -1730,6 +1734,8 @@ static struct worker *create_worker(struct worker_pool *pool)
        else
                worker->task = kthread_create(worker_thread, worker,
                                              "kworker/u:%d%s", id, pri);
+
+
        if (IS_ERR(worker->task))
                goto fail;
 
@@ -2054,6 +2060,7 @@ static bool manage_workers(struct worker *worker)
         * Destroy and then create so that may_start_working() is true
         * on return.
         */
+
        ret |= maybe_destroy_workers(pool);
        ret |= maybe_create_worker(pool);