| @@ -2217,6 +2217,33 @@ static int group_can_go_on(struct perf_event *event, · 2216 unmodified lines |
| 2217 | return can_add_hw; | 2217 | return can_add_hw; |
| 2218 | } | 2218 | } |
| 2219 | | 2219 | |
| | 2220 | /* |
| | 2221 | * Complement to update_event_times(). This computes the tstamp_* values to |
| | 2222 | * continue 'enabled' state from @now, and effectively discards the time |
| | 2223 | * between the prior tstamp_stopped and now (as we were in the OFF state, or |
| | 2224 | * just switched (context) time base). |
| | 2225 | * |
| | 2226 | * This further assumes '@event->state == INACTIVE' (we just came from OFF) and |
| | 2227 | * cannot have been scheduled in yet. And going into INACTIVE state means |
| | 2228 | * '@event->tstamp_stopped = @now'. |
| | 2229 | * |
| | 2230 | * Thus given the rules of update_event_times(): |
| | 2231 | * |
| | 2232 | * total_time_enabled = tstamp_stopped - tstamp_enabled |
| | 2233 | * total_time_running = tstamp_stopped - tstamp_running |
| | 2234 | * |
| | 2235 | * We can insert 'tstamp_stopped == now' and reverse them to compute new |
| | 2236 | * tstamp_* values. |
| | 2237 | */ |
| | 2238 | static void __perf_event_enable_time(struct perf_event *event, u64 now) |
| | 2239 | { |
| | 2240 | WARN_ON_ONCE(event->state != PERF_EVENT_STATE_INACTIVE); |
| | 2241 | |
| | 2242 | event->tstamp_stopped = now; |
| | 2243 | event->tstamp_enabled = now - event->total_time_enabled; |
| | 2244 | event->tstamp_running = now - event->total_time_running; |
| | 2245 | } |
| | 2246 | |
| 2220 | static void add_event_to_ctx(struct perf_event *event, | 2247 | static void add_event_to_ctx(struct perf_event *event, |
| 2221 | struct perf_event_context *ctx) | 2248 | struct perf_event_context *ctx) |
| 2222 | { | 2249 | { |
| @@ -2224,9 +2251,12 @@ static void add_event_to_ctx(struct perf_event *event, · 1 unmodified line |
| 2224 | | 2251 | |
| 2225 | list_add_event(event, ctx); | 2252 | list_add_event(event, ctx); |
| 2226 | perf_group_attach(event); | 2253 | perf_group_attach(event); |
| 2227 | event->tstamp_enabled = tstamp; | 2254 | /* |
| 2228 | event->tstamp_running = tstamp; | 2255 | * We can be called with event->state == STATE_OFF when we create with |
| 2229 | event->tstamp_stopped = tstamp; | 2256 | * .disabled = 1. In that case the IOC_ENABLE will call this function. |
| | 2257 | */ |
| | 2258 | if (event->state == PERF_EVENT_STATE_INACTIVE) |
| | 2259 | __perf_event_enable_time(event, tstamp); |
| 2230 | } | 2260 | } |
| 2231 | | 2261 | |
| 2232 | static void ctx_sched_out(struct perf_event_context *ctx, | 2262 | static void ctx_sched_out(struct perf_event_context *ctx, |
| @@ -2471,10 +2501,11 @@ static void __perf_event_mark_enabled(struct perf_event *event) · 238 unmodified lines |
| 2471 | u64 tstamp = perf_event_time(event); | 2501 | u64 tstamp = perf_event_time(event); |
| 2472 | | 2502 | |
| 2473 | event->state = PERF_EVENT_STATE_INACTIVE; | 2503 | event->state = PERF_EVENT_STATE_INACTIVE; |
| 2474 | event->tstamp_enabled = tstamp - event->total_time_enabled; | 2504 | __perf_event_enable_time(event, tstamp); |
| 2475 | list_for_each_entry(sub, &event->sibling_list, group_entry) { | 2505 | list_for_each_entry(sub, &event->sibling_list, group_entry) { |
| | 2506 | /* XXX should not be > INACTIVE if event isn't */ |
| 2476 | if (sub->state >= PERF_EVENT_STATE_INACTIVE) | 2507 | if (sub->state >= PERF_EVENT_STATE_INACTIVE) |
| 2477 | sub->tstamp_enabled = tstamp - sub->total_time_enabled; | 2508 | __perf_event_enable_time(sub, tstamp); |
| 2478 | } | 2509 | } |
| 2479 | } | 2510 | } |
| 2480 | | 2511 | |
| @@ -5090,7 +5121,7 @@ static void perf_mmap_open(struct vm_area_struct *vma) · 2609 unmodified lines |
| 5090 | atomic_inc(&event->rb->aux_mmap_count); | 5121 | atomic_inc(&event->rb->aux_mmap_count); |
| 5091 | | 5122 | |
| 5092 | if (event->pmu->event_mapped) | 5123 | if (event->pmu->event_mapped) |
| 5093 | event->pmu->event_mapped(event); | 5124 | event->pmu->event_mapped(event, vma->vm_mm); |
| 5094 | } | 5125 | } |
| 5095 | | 5126 | |
| 5096 | static void perf_pmu_output_stop(struct perf_event *event); | 5127 | static void perf_pmu_output_stop(struct perf_event *event); |
| @@ -5113,7 +5144,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) · 16 unmodified lines |
| 5113 | unsigned long size = perf_data_size(rb); | 5144 | unsigned long size = perf_data_size(rb); |
| 5114 | | 5145 | |
| 5115 | if (event->pmu->event_unmapped) | 5146 | if (event->pmu->event_unmapped) |
| 5116 | event->pmu->event_unmapped(event); | 5147 | event->pmu->event_unmapped(event, vma->vm_mm); |
| 5117 | | 5148 | |
| 5118 | /* | 5149 | /* |
| 5119 | * rb->aux_mmap_count will always drop before rb->mmap_count and | 5150 | * rb->aux_mmap_count will always drop before rb->mmap_count and |
| @@ -5411,7 +5442,7 @@ aux_unlock: · 291 unmodified lines |
| 5411 | vma->vm_ops = &perf_mmap_vmops; | 5442 | vma->vm_ops = &perf_mmap_vmops; |
| 5412 | | 5443 | |
| 5413 | if (event->pmu->event_mapped) | 5444 | if (event->pmu->event_mapped) |
| 5414 | event->pmu->event_mapped(event); | 5445 | event->pmu->event_mapped(event, vma->vm_mm); |
| 5415 | | 5446 | |
| 5416 | return ret; | 5447 | return ret; |
| 5417 | } | 5448 | } |