Loading arch/arm64/kernel/perf_event.c +2 −2 Original line number Diff line number Diff line Loading @@ -707,8 +707,8 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; /* Ignore if we don't have an event. */ if (!event) /* Ignore if we don't have an event or if it's a zombie event */ if (!event || event->state == PERF_EVENT_STATE_ZOMBIE) continue; /* Loading drivers/perf/arm_pmu.c +9 −0 Original line number Diff line number Diff line Loading @@ -659,6 +659,15 @@ static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd) continue; event = hw_events->events[idx]; if (!event) continue; /* * Check if an attempt was made to free this event during * the CPU went offline. */ if (event->state == PERF_EVENT_STATE_ZOMBIE) continue; switch (cmd) { case CPU_PM_ENTER: Loading include/linux/perf_event.h +4 −1 Original line number Diff line number Diff line Loading @@ -490,7 +490,8 @@ struct perf_addr_filters_head { * enum perf_event_active_state - the states of a event */ enum perf_event_active_state { PERF_EVENT_STATE_DEAD = -4, PERF_EVENT_STATE_DEAD = -5, PERF_EVENT_STATE_ZOMBIE = -4, PERF_EVENT_STATE_EXIT = -3, PERF_EVENT_STATE_ERROR = -2, PERF_EVENT_STATE_OFF = -1, Loading Loading @@ -705,6 +706,8 @@ struct perf_event { #endif struct list_head sb_list; struct list_head zombie_entry; #endif /* CONFIG_PERF_EVENTS */ }; Loading kernel/events/core.c +57 −0 Original line number Diff line number Diff line Loading @@ -4357,6 +4357,14 @@ static void put_event(struct perf_event *event) _free_event(event); } /* * Maintain a zombie list to collect all the zombie events */ #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE static LIST_HEAD(zombie_list); static DEFINE_SPINLOCK(zombie_list_lock); #endif /* * Kill an event dead; while event:refcount will preserve the event * object, it will not preserve its functionality. Once the last 'user' Loading @@ -4367,6 +4375,26 @@ int perf_event_release_kernel(struct perf_event *event) struct perf_event_context *ctx = event->ctx; struct perf_event *child, *tmp; /* * If the cpu associated to this event is offline, set the event as a * zombie event. The cleanup of the cpu would be done if the CPU is * back online. */ #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE if (!cpu_online(event->cpu)) { if (event->state == PERF_EVENT_STATE_ZOMBIE) return 0; event->state = PERF_EVENT_STATE_ZOMBIE; spin_lock(&zombie_list_lock); list_add_tail(&event->zombie_entry, &zombie_list); spin_unlock(&zombie_list_lock); return 0; } #endif /* * If we got here through err_file: fput(event_file); we will not have * attached to a context yet. Loading Loading @@ -9559,6 +9587,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, INIT_LIST_HEAD(&event->rb_entry); INIT_LIST_HEAD(&event->active_entry); INIT_LIST_HEAD(&event->addr_filters.list); INIT_LIST_HEAD(&event->zombie_entry); INIT_HLIST_NODE(&event->hlist_entry); Loading Loading @@ -11307,6 +11336,32 @@ check_hotplug_start_event(struct perf_event *event) event->pmu->start(event, 0); } static void perf_event_zombie_cleanup(unsigned int cpu) { struct perf_event *event, *tmp; spin_lock(&zombie_list_lock); list_for_each_entry_safe(event, tmp, &zombie_list, zombie_entry) { if (event->cpu != cpu) continue; list_del(&event->zombie_entry); spin_unlock(&zombie_list_lock); /* * The detachment of the event with the * PMU expects it to be in an active state */ event->state = PERF_EVENT_STATE_ACTIVE; perf_event_release_kernel(event); spin_lock(&zombie_list_lock); } spin_unlock(&zombie_list_lock); } int perf_event_start_swevents(unsigned int cpu) { struct perf_event_context *ctx; Loading @@ -11314,6 +11369,8 @@ int perf_event_start_swevents(unsigned int cpu) struct perf_event *event; int idx; perf_event_zombie_cleanup(cpu); idx = srcu_read_lock(&pmus_srcu); list_for_each_entry_rcu(pmu, &pmus, entry) { ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx; Loading Loading
arch/arm64/kernel/perf_event.c +2 −2 Original line number Diff line number Diff line Loading @@ -707,8 +707,8 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; /* Ignore if we don't have an event. */ if (!event) /* Ignore if we don't have an event or if it's a zombie event */ if (!event || event->state == PERF_EVENT_STATE_ZOMBIE) continue; /* Loading
drivers/perf/arm_pmu.c +9 −0 Original line number Diff line number Diff line Loading @@ -659,6 +659,15 @@ static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd) continue; event = hw_events->events[idx]; if (!event) continue; /* * Check if an attempt was made to free this event during * the CPU went offline. */ if (event->state == PERF_EVENT_STATE_ZOMBIE) continue; switch (cmd) { case CPU_PM_ENTER: Loading
include/linux/perf_event.h +4 −1 Original line number Diff line number Diff line Loading @@ -490,7 +490,8 @@ struct perf_addr_filters_head { * enum perf_event_active_state - the states of a event */ enum perf_event_active_state { PERF_EVENT_STATE_DEAD = -4, PERF_EVENT_STATE_DEAD = -5, PERF_EVENT_STATE_ZOMBIE = -4, PERF_EVENT_STATE_EXIT = -3, PERF_EVENT_STATE_ERROR = -2, PERF_EVENT_STATE_OFF = -1, Loading Loading @@ -705,6 +706,8 @@ struct perf_event { #endif struct list_head sb_list; struct list_head zombie_entry; #endif /* CONFIG_PERF_EVENTS */ }; Loading
kernel/events/core.c +57 −0 Original line number Diff line number Diff line Loading @@ -4357,6 +4357,14 @@ static void put_event(struct perf_event *event) _free_event(event); } /* * Maintain a zombie list to collect all the zombie events */ #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE static LIST_HEAD(zombie_list); static DEFINE_SPINLOCK(zombie_list_lock); #endif /* * Kill an event dead; while event:refcount will preserve the event * object, it will not preserve its functionality. Once the last 'user' Loading @@ -4367,6 +4375,26 @@ int perf_event_release_kernel(struct perf_event *event) struct perf_event_context *ctx = event->ctx; struct perf_event *child, *tmp; /* * If the cpu associated to this event is offline, set the event as a * zombie event. The cleanup of the cpu would be done if the CPU is * back online. */ #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE if (!cpu_online(event->cpu)) { if (event->state == PERF_EVENT_STATE_ZOMBIE) return 0; event->state = PERF_EVENT_STATE_ZOMBIE; spin_lock(&zombie_list_lock); list_add_tail(&event->zombie_entry, &zombie_list); spin_unlock(&zombie_list_lock); return 0; } #endif /* * If we got here through err_file: fput(event_file); we will not have * attached to a context yet. Loading Loading @@ -9559,6 +9587,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, INIT_LIST_HEAD(&event->rb_entry); INIT_LIST_HEAD(&event->active_entry); INIT_LIST_HEAD(&event->addr_filters.list); INIT_LIST_HEAD(&event->zombie_entry); INIT_HLIST_NODE(&event->hlist_entry); Loading Loading @@ -11307,6 +11336,32 @@ check_hotplug_start_event(struct perf_event *event) event->pmu->start(event, 0); } static void perf_event_zombie_cleanup(unsigned int cpu) { struct perf_event *event, *tmp; spin_lock(&zombie_list_lock); list_for_each_entry_safe(event, tmp, &zombie_list, zombie_entry) { if (event->cpu != cpu) continue; list_del(&event->zombie_entry); spin_unlock(&zombie_list_lock); /* * The detachment of the event with the * PMU expects it to be in an active state */ event->state = PERF_EVENT_STATE_ACTIVE; perf_event_release_kernel(event); spin_lock(&zombie_list_lock); } spin_unlock(&zombie_list_lock); } int perf_event_start_swevents(unsigned int cpu) { struct perf_event_context *ctx; Loading @@ -11314,6 +11369,8 @@ int perf_event_start_swevents(unsigned int cpu) struct perf_event *event; int idx; perf_event_zombie_cleanup(cpu); idx = srcu_read_lock(&pmus_srcu); list_for_each_entry_rcu(pmu, &pmus, entry) { ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx; Loading