lkml.org 
[lkml]   [2009]   [May]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 2/2] cpuhotplug: introduce try_get_online_cpus()
    Andrew Morton wrote:
    >
    >> ---
    >> diff --git a/include/linux/cpu.h b/include/linux/cpu.h
    >> index 2643d84..98f5c4b 100644
    >> --- a/include/linux/cpu.h
    >> +++ b/include/linux/cpu.h
    >> @@ -104,6 +104,7 @@ extern struct sysdev_class cpu_sysdev_class;
    >>
    >> extern void get_online_cpus(void);
    >> extern void put_online_cpus(void);
    >> +extern int try_get_online_cpus(void);
    >> #define hotcpu_notifier(fn, pri) { \
    >> static struct notifier_block fn##_nb __cpuinitdata = \
    >> { .notifier_call = fn, .priority = pri }; \
    >> @@ -117,6 +118,7 @@ int cpu_down(unsigned int cpu);
    >>
    >> #define get_online_cpus() do { } while (0)
    >> #define put_online_cpus() do { } while (0)
    >> +#define try_get_online_cpus() (1)
    >> #define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
    >> /* These aren't inline functions due to a GCC bug. */
    >> #define register_hotcpu_notifier(nb) ({ (void)(nb); 0; })
    >> diff --git a/kernel/cpu.c b/kernel/cpu.c
    >> index 62198ec..e948f19 100644
    >> --- a/kernel/cpu.c
    >> +++ b/kernel/cpu.c
    >> @@ -66,6 +66,15 @@ void put_online_cpus(void)
    >> }
    >> EXPORT_SYMBOL_GPL(put_online_cpus);
    >>
    >> +int try_get_online_cpus(void)
    >> +{
    >> + might_sleep();
    >> + if (cpu_hotplug.active_writer == current)
    >> + return 1;
    >> + return down_read_trylock(&cpu_hotplug.rwlock);
    >> +
    >> +}
    >> +EXPORT_SYMBOL_GPL(try_get_online_cpus);
    >
    > It's strange to add a might_sleep() to a function which doesn't sleep.

    It might sleep indeed. I prefer to add a might_sleep()/cond_sched()
    for a sleepable function.

    >
    > The patch adds no callers to this function. This is significant
    > because it would be quite interesting to find out which subsystem(s)
    > you've found to have this deadlock. I do think that we should look at
    > alternative (non-trylocky) ways of fixing them.
    >

    This problem exist in cgroup/cpuset. and Max Krasnyansky fix it:
    (non-trylocky way)
    *
    * The rebuild_sched_domains() and partition_sched_domains()
    * routines must nest cgroup_lock() inside get_online_cpus(),
    * but such cpuset changes as these must nest that locking the
    * other way, holding cgroup_lock() for much of the code.
    *
    * So in order to avoid an ABBA deadlock, the cpuset code handling
    * these user changes delegates the actual sched domain rebuilding
    * to a separate workqueue thread, which ends up processing the
    * above do_rebuild_sched_domains() function.
    */
    static void async_rebuild_sched_domains(void)
    {
    queue_work(cpuset_wq, &rebuild_sched_domains_work);
    }


    get_online_cpus() is so a coarsely granular lock, and
    try_get_online_cpus() fails rarely. The kernel indeed needs
    try_get_online_cpus().

    Paul will use it:
    http://lkml.org/lkml/2009/5/22/332

    Lai




    \
     
     \ /
      Last update: 2009-06-01 04:49    [W:0.059 / U:0.208 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site