diff --git a/[refs] b/[refs] index 0a4aeb5396be..6d2a70259298 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bb1693f89ae7f0b30c90d9b26a4f827faed1144a +refs/heads/master: f9d36996564f91c517b75b02942015f7e09a6574 diff --git a/trunk/arch/x86/kernel/dumpstack_64.c b/trunk/arch/x86/kernel/dumpstack_64.c index af7785ff5aa0..6d728d9284bd 100644 --- a/trunk/arch/x86/kernel/dumpstack_64.c +++ b/trunk/arch/x86/kernel/dumpstack_64.c @@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!stack) { if (regs) stack = (unsigned long *)regs->sp; - else if (task != current) + else if (task && task != current) stack = (unsigned long *)task->thread.sp; else stack = &dummy; diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 412b790f5da6..0b91db2522cc 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -589,7 +589,6 @@ struct hw_perf_event { u64 sample_period; u64 last_period; local64_t period_left; - u64 interrupts_seq; u64 interrupts; u64 freq_time_stamp; diff --git a/trunk/kernel/events/core.c b/trunk/kernel/events/core.c index 7c3b9de55f6b..de859fb4038f 100644 --- a/trunk/kernel/events/core.c +++ b/trunk/kernel/events/core.c @@ -2300,9 +2300,6 @@ do { \ return div64_u64(dividend, divisor); } -static DEFINE_PER_CPU(int, perf_throttled_count); -static DEFINE_PER_CPU(u64, perf_throttled_seq); - static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) { struct hw_perf_event *hwc = &event->hw; @@ -2328,29 +2325,16 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) } } -/* - * combine freq adjustment with unthrottling to avoid two passes over the - * events. At the same time, make sure, having freq events does not change - * the rate of unthrottling as that would introduce bias. - */ -static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, - int needs_unthr) +static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) { struct perf_event *event; struct hw_perf_event *hwc; - u64 now, period = TICK_NSEC; + u64 interrupts, now; s64 delta; - /* - * only need to iterate over all events iff: - * - context have events in frequency mode (needs freq adjust) - * - there are events to unthrottle on this cpu - */ - if (!(ctx->nr_freq || needs_unthr)) + if (!ctx->nr_freq) return; - raw_spin_lock(&ctx->lock); - list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { if (event->state != PERF_EVENT_STATE_ACTIVE) continue; @@ -2360,8 +2344,13 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, hwc = &event->hw; - if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) { - hwc->interrupts = 0; + interrupts = hwc->interrupts; + hwc->interrupts = 0; + + /* + * unthrottle events on the tick + */ + if (interrupts == MAX_INTERRUPTS) { perf_log_throttle(event, 1); event->pmu->start(event, 0); } @@ -2369,26 +2358,14 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, if (!event->attr.freq || !event->attr.sample_freq) continue; - /* - * stop the event and update event->count - */ - event->pmu->stop(event, PERF_EF_UPDATE); - + event->pmu->read(event); now = local64_read(&event->count); delta = now - hwc->freq_count_stamp; hwc->freq_count_stamp = now; - /* - * restart the event - * reload only if value has changed - */ if (delta > 0) perf_adjust_period(event, period, delta); - - event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0); } - - raw_spin_unlock(&ctx->lock); } /* @@ -2411,13 +2388,16 @@ static void rotate_ctx(struct perf_event_context *ctx) */ static void perf_rotate_context(struct perf_cpu_context *cpuctx) { + u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC; struct perf_event_context *ctx = NULL; - int rotate = 0, remove = 1; + int rotate = 0, remove = 1, freq = 0; if (cpuctx->ctx.nr_events) { remove = 0; if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) rotate = 1; + if (cpuctx->ctx.nr_freq) + freq = 1; } ctx = cpuctx->task_ctx; @@ -2425,26 +2405,37 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx) remove = 0; if (ctx->nr_events != ctx->nr_active) rotate = 1; + if (ctx->nr_freq) + freq = 1; } - if (!rotate) + if (!rotate && !freq) goto done; perf_ctx_lock(cpuctx, cpuctx->task_ctx); perf_pmu_disable(cpuctx->ctx.pmu); - cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); - if (ctx) - ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); + if (freq) { + perf_ctx_adjust_freq(&cpuctx->ctx, interval); + if (ctx) + perf_ctx_adjust_freq(ctx, interval); + } - rotate_ctx(&cpuctx->ctx); - if (ctx) - rotate_ctx(ctx); + if (rotate) { + cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); + if (ctx) + ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); - perf_event_sched_in(cpuctx, ctx, current); + rotate_ctx(&cpuctx->ctx); + if (ctx) + rotate_ctx(ctx); + + perf_event_sched_in(cpuctx, ctx, current); + } perf_pmu_enable(cpuctx->ctx.pmu); perf_ctx_unlock(cpuctx, cpuctx->task_ctx); + done: if (remove) list_del_init(&cpuctx->rotation_list); @@ -2454,22 +2445,10 @@ void perf_event_task_tick(void) { struct list_head *head = &__get_cpu_var(rotation_list); struct perf_cpu_context *cpuctx, *tmp; - struct perf_event_context *ctx; - int throttled; WARN_ON(!irqs_disabled()); - __this_cpu_inc(perf_throttled_seq); - throttled = __this_cpu_xchg(perf_throttled_count, 0); - list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) { - ctx = &cpuctx->ctx; - perf_adjust_freq_unthr_context(ctx, throttled); - - ctx = cpuctx->task_ctx; - if (ctx) - perf_adjust_freq_unthr_context(ctx, throttled); - if (cpuctx->jiffies_interval == 1 || !(jiffies % cpuctx->jiffies_interval)) perf_rotate_context(cpuctx); @@ -4535,7 +4514,6 @@ static int __perf_event_overflow(struct perf_event *event, { int events = atomic_read(&event->event_limit); struct hw_perf_event *hwc = &event->hw; - u64 seq; int ret = 0; /* @@ -4545,20 +4523,14 @@ static int __perf_event_overflow(struct perf_event *event, if (unlikely(!is_sampling_event(event))) return 0; - seq = __this_cpu_read(perf_throttled_seq); - if (seq != hwc->interrupts_seq) { - hwc->interrupts_seq = seq; - hwc->interrupts = 1; - } else { - hwc->interrupts++; - if (unlikely(throttle - && hwc->interrupts >= max_samples_per_tick)) { - __this_cpu_inc(perf_throttled_count); + if (unlikely(hwc->interrupts >= max_samples_per_tick)) { + if (throttle) { hwc->interrupts = MAX_INTERRUPTS; perf_log_throttle(event, 0); ret = 1; } - } + } else + hwc->interrupts++; if (event->attr.freq) { u64 now = perf_clock(); diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index d869b214ada2..e8b033c074f9 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -88,6 +88,8 @@ void get_term_dimensions(struct winsize *ws) static void perf_top__update_print_entries(struct perf_top *top) { + top->print_entries = top->winsize.ws_row; + if (top->print_entries > 9) top->print_entries -= 9; } @@ -97,13 +99,6 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar struct perf_top *top = arg; get_term_dimensions(&top->winsize); - if (!top->print_entries - || (top->print_entries+4) > top->winsize.ws_row) { - top->print_entries = top->winsize.ws_row; - } else { - top->print_entries += 4; - top->winsize.ws_row = top->print_entries; - } perf_top__update_print_entries(top); } @@ -457,10 +452,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) }; perf_top__sig_winch(SIGWINCH, NULL, top); sigaction(SIGWINCH, &act, NULL); - } else { - perf_top__sig_winch(SIGWINCH, NULL, top); + } else signal(SIGWINCH, SIG_DFL); - } break; case 'E': if (top->evlist->nr_entries > 1) { diff --git a/trunk/tools/perf/util/evsel.c b/trunk/tools/perf/util/evsel.c index 667f3b78bb2c..dcfefab53e00 100644 --- a/trunk/tools/perf/util/evsel.c +++ b/trunk/tools/perf/util/evsel.c @@ -535,7 +535,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, } if (type & PERF_SAMPLE_READ) { - fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n"); + fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n"); return -1; }