Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 302774
b: refs/heads/master
c: 29d5e04
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner committed Apr 26, 2012
1 parent c59f35f commit 296a354
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 38498a67aa2cf8c80754b8d304bfacc10bc582b5
refs/heads/master: 29d5e0476e1c4a513859e7858845ad172f560389
3 changes: 3 additions & 0 deletions trunk/arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ config HAVE_DMA_ATTRS
config USE_GENERIC_SMP_HELPERS
bool

config GENERIC_SMP_IDLE_THREAD
bool

config HAVE_REGS_AND_STACK_ACCESS_API
bool
help
Expand Down
2 changes: 1 addition & 1 deletion trunk/kernel/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
}

/* Arch-specific enabling code. */
ret = __cpu_up(cpu, NULL);
ret = __cpu_up(cpu, idle_thread_get(cpu));
if (ret != 0)
goto out_notify;
BUG_ON(!cpu_online(cpu));
Expand Down
2 changes: 2 additions & 0 deletions trunk/kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@

#include "sched.h"
#include "../workqueue_sched.h"
#include "../smpboot.h"

#define CREATE_TRACE_POINTS
#include <trace/events/sched.h>
Expand Down Expand Up @@ -7049,6 +7050,7 @@ void __init sched_init(void)
/* May be allocated at isolcpus cmdline parse time */
if (cpu_isolated_map == NULL)
zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
idle_thread_set_boot_cpu();
#endif
init_sched_fair_class();

Expand Down
84 changes: 83 additions & 1 deletion trunk/kernel/smpboot.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,96 @@
/*
* Common SMP CPU bringup/teardown functions
*/
#include <linux/err.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/percpu.h>
#include <linux/workqueue.h>

#include "smpboot.h"

#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
struct create_idle {
struct work_struct work;
struct task_struct *idle;
struct completion done;
unsigned int cpu;
};

static void __cpuinit do_fork_idle(struct work_struct *work)
{
struct create_idle *c = container_of(work, struct create_idle, work);

c->idle = fork_idle(c->cpu);
complete(&c->done);
}

static struct task_struct * __cpuinit idle_thread_create(unsigned int cpu)
{
struct create_idle c_idle = {
.cpu = cpu,
.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
};

INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
schedule_work(&c_idle.work);
wait_for_completion(&c_idle.done);
destroy_work_on_stack(&c_idle.work);
return c_idle.idle;
}

/*
* For the hotplug case we keep the task structs around and reuse
* them.
*/
static DEFINE_PER_CPU(struct task_struct *, idle_threads);

static inline struct task_struct *get_idle_for_cpu(unsigned int cpu)
{
struct task_struct *tsk = per_cpu(idle_threads, cpu);

if (!tsk)
return idle_thread_create(cpu);
init_idle(tsk, cpu);
return tsk;
}

struct task_struct * __cpuinit idle_thread_get(unsigned int cpu)
{
return per_cpu(idle_threads, cpu);
}

void __init idle_thread_set_boot_cpu(void)
{
per_cpu(idle_threads, smp_processor_id()) = current;
}

/**
* idle_thread_init - Initialize the idle thread for a cpu
* @cpu: The cpu for which the idle thread should be initialized
*
* Creates the thread if it does not exist.
*/
static int __cpuinit idle_thread_init(unsigned int cpu)
{
struct task_struct *idle = get_idle_for_cpu(cpu);

if (IS_ERR(idle)) {
printk(KERN_ERR "failed fork for CPU %u\n", cpu);
return PTR_ERR(idle);
}
per_cpu(idle_threads, cpu) = idle;
return 0;
}
#else
static inline int idle_thread_init(unsigned int cpu) { return 0; }
#endif

/**
* smpboot_prepare - generic smpboot preparation
*/
int __cpuinit smpboot_prepare(unsigned int cpu)
{
return 0;
return idle_thread_init(cpu);
}
10 changes: 10 additions & 0 deletions trunk/kernel/smpboot.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
#ifndef SMPBOOT_H
#define SMPBOOT_H

struct task_struct;

int smpboot_prepare(unsigned int cpu);

#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
struct task_struct *idle_thread_get(unsigned int cpu);
void idle_thread_set_boot_cpu(void);
#else
static inline struct task_struct *idle_thread_get(unsigned int cpu) { return NULL; }
static inline void idle_thread_set_boot_cpu(void) { }
#endif

#endif

0 comments on commit 296a354

Please sign in to comment.