Merge branch 'perf/urgent' into perf/core, to avoid conflicts
authorIngo Molnar <mingo@kernel.org>
Wed, 7 May 2014 11:39:22 +0000 (13:39 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 7 May 2014 11:39:22 +0000 (13:39 +0200)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
1  2 
kernel/events/core.c
kernel/hrtimer.c

diff --combined kernel/events/core.c
index 5129b1201050d3f27c62fd54e1592dcf3e9c0776,71232844f235f45068b1f6f30c5842693cff9e54..09866a330af8d5c147019c32762c65c7ad8859c8
@@@ -39,7 -39,6 +39,7 @@@
  #include <linux/hw_breakpoint.h>
  #include <linux/mm_types.h>
  #include <linux/cgroup.h>
 +#include <linux/module.h>
  
  #include "internal.h"
  
@@@ -1444,6 -1443,11 +1444,11 @@@ group_sched_out(struct perf_event *grou
                cpuctx->exclusive = 0;
  }
  
+ struct remove_event {
+       struct perf_event *event;
+       bool detach_group;
+ };
  /*
   * Cross CPU call to remove a performance event
   *
   */
  static int __perf_remove_from_context(void *info)
  {
-       struct perf_event *event = info;
+       struct remove_event *re = info;
+       struct perf_event *event = re->event;
        struct perf_event_context *ctx = event->ctx;
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
  
        raw_spin_lock(&ctx->lock);
        event_sched_out(event, cpuctx, ctx);
+       if (re->detach_group)
+               perf_group_detach(event);
        list_del_event(event, ctx);
        if (!ctx->nr_events && cpuctx->task_ctx == ctx) {
                ctx->is_active = 0;
   * When called from perf_event_exit_task, it's OK because the
   * context has been detached from its task.
   */
- static void perf_remove_from_context(struct perf_event *event)
+ static void perf_remove_from_context(struct perf_event *event, bool detach_group)
  {
        struct perf_event_context *ctx = event->ctx;
        struct task_struct *task = ctx->task;
+       struct remove_event re = {
+               .event = event,
+               .detach_group = detach_group,
+       };
  
        lockdep_assert_held(&ctx->mutex);
  
                 * Per cpu events are removed via an smp call and
                 * the removal is always successful.
                 */
-               cpu_function_call(event->cpu, __perf_remove_from_context, event);
+               cpu_function_call(event->cpu, __perf_remove_from_context, &re);
                return;
        }
  
  retry:
-       if (!task_function_call(task, __perf_remove_from_context, event))
+       if (!task_function_call(task, __perf_remove_from_context, &re))
                return;
  
        raw_spin_lock_irq(&ctx->lock);
         * Since the task isn't running, its safe to remove the event, us
         * holding the ctx->lock ensures the task won't get scheduled in.
         */
+       if (detach_group)
+               perf_group_detach(event);
        list_del_event(event, ctx);
        raw_spin_unlock_irq(&ctx->lock);
  }
@@@ -3230,9 -3243,6 +3244,9 @@@ static void __free_event(struct perf_ev
        if (event->ctx)
                put_ctx(event->ctx);
  
 +      if (event->pmu)
 +              module_put(event->pmu->module);
 +
        call_rcu(&event->rcu_head, free_event_rcu);
  }
  static void free_event(struct perf_event *event)
@@@ -3285,10 -3295,7 +3299,7 @@@ int perf_event_release_kernel(struct pe
         *     to trigger the AB-BA case.
         */
        mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
-       raw_spin_lock_irq(&ctx->lock);
-       perf_group_detach(event);
-       raw_spin_unlock_irq(&ctx->lock);
-       perf_remove_from_context(event);
+       perf_remove_from_context(event, true);
        mutex_unlock(&ctx->mutex);
  
        free_event(event);
@@@ -6555,7 -6562,6 +6566,7 @@@ free_pdc
        free_percpu(pmu->pmu_disable_count);
        goto unlock;
  }
 +EXPORT_SYMBOL_GPL(perf_pmu_register);
  
  void perf_pmu_unregister(struct pmu *pmu)
  {
        put_device(pmu->dev);
        free_pmu_context(pmu);
  }
 +EXPORT_SYMBOL_GPL(perf_pmu_unregister);
  
  struct pmu *perf_init_event(struct perf_event *event)
  {
        pmu = idr_find(&pmu_idr, event->attr.type);
        rcu_read_unlock();
        if (pmu) {
 +              if (!try_module_get(pmu->module)) {
 +                      pmu = ERR_PTR(-ENODEV);
 +                      goto unlock;
 +              }
                event->pmu = pmu;
                ret = pmu->event_init(event);
                if (ret)
        }
  
        list_for_each_entry_rcu(pmu, &pmus, entry) {
 +              if (!try_module_get(pmu->module)) {
 +                      pmu = ERR_PTR(-ENODEV);
 +                      goto unlock;
 +              }
                event->pmu = pmu;
                ret = pmu->event_init(event);
                if (!ret)
@@@ -6785,7 -6782,6 +6796,7 @@@ perf_event_alloc(struct perf_event_att
  err_pmu:
        if (event->destroy)
                event->destroy(event);
 +      module_put(pmu->module);
  err_ns:
        if (event->ns)
                put_pid_ns(event->ns);
@@@ -7180,7 -7176,7 +7191,7 @@@ SYSCALL_DEFINE5(perf_event_open
                struct perf_event_context *gctx = group_leader->ctx;
  
                mutex_lock(&gctx->mutex);
-               perf_remove_from_context(group_leader);
+               perf_remove_from_context(group_leader, false);
  
                /*
                 * Removing from the context ends up with disabled
                perf_event__state_init(group_leader);
                list_for_each_entry(sibling, &group_leader->sibling_list,
                                    group_entry) {
-                       perf_remove_from_context(sibling);
+                       perf_remove_from_context(sibling, false);
                        perf_event__state_init(sibling);
                        put_ctx(gctx);
                }
@@@ -7320,7 -7316,7 +7331,7 @@@ void perf_pmu_migrate_context(struct pm
        mutex_lock(&src_ctx->mutex);
        list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
                                 event_entry) {
-               perf_remove_from_context(event);
+               perf_remove_from_context(event, false);
                unaccount_event_cpu(event, src_cpu);
                put_ctx(src_ctx);
                list_add(&event->migrate_entry, &events);
@@@ -7382,13 -7378,7 +7393,7 @@@ __perf_event_exit_task(struct perf_even
                         struct perf_event_context *child_ctx,
                         struct task_struct *child)
  {
-       if (child_event->parent) {
-               raw_spin_lock_irq(&child_ctx->lock);
-               perf_group_detach(child_event);
-               raw_spin_unlock_irq(&child_ctx->lock);
-       }
-       perf_remove_from_context(child_event);
+       perf_remove_from_context(child_event, !!child_event->parent);
  
        /*
         * It can happen that the parent exits first, and has events
@@@ -7739,6 -7729,8 +7744,8 @@@ int perf_event_init_context(struct task
         * swapped under us.
         */
        parent_ctx = perf_pin_task_context(parent, ctxn);
+       if (!parent_ctx)
+               return 0;
  
        /*
         * No need to check if parent_ctx != NULL here; since we saw
@@@ -7872,14 -7864,14 +7879,14 @@@ static void perf_pmu_rotate_stop(struc
  
  static void __perf_event_exit_context(void *__info)
  {
+       struct remove_event re = { .detach_group = false };
        struct perf_event_context *ctx = __info;
-       struct perf_event *event;
  
        perf_pmu_rotate_stop(ctx->pmu);
  
        rcu_read_lock();
-       list_for_each_entry_rcu(event, &ctx->event_list, event_entry)
-               __perf_remove_from_context(event);
+       list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry)
+               __perf_remove_from_context(&re);
        rcu_read_unlock();
  }
  
diff --combined kernel/hrtimer.c
index 53d26829cd4d3dd00a6ce305f54d0a45fe7b7589,6b715c0af1b117b5b61bd32629a00845f0313557..d10eba8089d164e376134bc54ab2d2f45818aab9
@@@ -234,6 -234,11 +234,11 @@@ again
                        goto again;
                }
                timer->base = new_base;
+       } else {
+               if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
+                       cpu = this_cpu;
+                       goto again;
+               }
        }
        return new_base;
  }
@@@ -569,6 -574,23 +574,23 @@@ hrtimer_force_reprogram(struct hrtimer_
  
        cpu_base->expires_next.tv64 = expires_next.tv64;
  
+       /*
+        * If a hang was detected in the last timer interrupt then we
+        * leave the hang delay active in the hardware. We want the
+        * system to make progress. That also prevents the following
+        * scenario:
+        * T1 expires 50ms from now
+        * T2 expires 5s from now
+        *
+        * T1 is removed, so this code is called and would reprogram
+        * the hardware to 5s from now. Any hrtimer_start after that
+        * will not reprogram the hardware due to hang_detected being
+        * set. So we'd effectivly block all timers until the T2 event
+        * fires.
+        */
+       if (cpu_base->hang_detected)
+               return;
        if (cpu_base->expires_next.tv64 != KTIME_MAX)
                tick_program_event(cpu_base->expires_next, 1);
  }
@@@ -1017,7 -1039,6 +1039,7 @@@ int __hrtimer_start_range_ns(struct hrt
  
        return ret;
  }
 +EXPORT_SYMBOL_GPL(__hrtimer_start_range_ns);
  
  /**
   * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU