Skip to content

Commit

Permalink
ARM: oprofile: fix and simplify init/exit functions
Browse files Browse the repository at this point in the history
Now that oprofile_arch_exit is only called when the OProfile module
is unloaded, it can assume that init completed successfully and not
have to worry about double frees or releasing NULL perf events.

This patch ensures that oprofile_arch_init fails gracefully on ARM
and simplifies the exit code based on the above.

Cc: Robert Richter <robert.richter@amd.com>
Cc: Matt Fleming <matt@console-pimps.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Robert Richter <robert.richter@amd.com>
  • Loading branch information
Will Deacon authored and Robert Richter committed Aug 31, 2010
1 parent 979048e commit c7fd239
Showing 1 changed file with 25 additions and 22 deletions.
47 changes: 25 additions & 22 deletions arch/arm/oprofile/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ static int __init init_driverfs(void)
return ret;
}

static void exit_driverfs(void)
static void __exit exit_driverfs(void)
{
platform_device_unregister(oprofile_pdev);
platform_driver_unregister(&oprofile_driver);
Expand Down Expand Up @@ -359,24 +359,22 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
if (!counter_config) {
pr_info("oprofile: failed to allocate %d "
"counters\n", perf_num_counters);
return -ENOMEM;
ret = -ENOMEM;
goto out;
}

ret = init_driverfs();
if (ret) {
kfree(counter_config);
return ret;
}
if (ret)
goto out;

for_each_possible_cpu(cpu) {
perf_events[cpu] = kcalloc(perf_num_counters,
sizeof(struct perf_event *), GFP_KERNEL);
if (!perf_events[cpu]) {
pr_info("oprofile: failed to allocate %d perf events "
"for cpu %d\n", perf_num_counters, cpu);
while (--cpu >= 0)
kfree(perf_events[cpu]);
return -ENOMEM;
ret = -ENOMEM;
goto out;
}
}

Expand All @@ -393,34 +391,39 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
else
pr_info("oprofile: using %s\n", ops->cpu_type);

out:
if (ret) {
for_each_possible_cpu(cpu)
kfree(perf_events[cpu]);
kfree(counter_config);
}

return ret;
}

void oprofile_arch_exit(void)
void __exit oprofile_arch_exit(void)
{
int cpu, id;
struct perf_event *event;

if (*perf_events) {
exit_driverfs();
for_each_possible_cpu(cpu) {
for (id = 0; id < perf_num_counters; ++id) {
event = perf_events[cpu][id];
if (event != NULL)
perf_event_release_kernel(event);
}
kfree(perf_events[cpu]);
for_each_possible_cpu(cpu) {
for (id = 0; id < perf_num_counters; ++id) {
event = perf_events[cpu][id];
if (event)
perf_event_release_kernel(event);
}

kfree(perf_events[cpu]);
}

if (counter_config)
kfree(counter_config);
kfree(counter_config);
exit_driverfs();
}
#else
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
pr_info("oprofile: hardware counters not available\n");
return -ENODEV;
}
void oprofile_arch_exit(void) {}
void __exit oprofile_arch_exit(void) {}
#endif /* CONFIG_HW_PERF_EVENTS */

0 comments on commit c7fd239

Please sign in to comment.