X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-context-perf-counters.c;h=72e920afbba137fa138caa4a1b5ae9e5bb6bbc28;hb=8a57ec025ffbe56153748fd69b60118862707182;hp=5784f75e30625e52693769902a578fa21ae13063;hpb=cfa6cc1d0f01c2cfcc1a679abf3a6572d411c309;p=lttng-modules.git diff --git a/src/lttng-context-perf-counters.c b/src/lttng-context-perf-counters.c index 5784f75e..72e920af 100644 --- a/src/lttng-context-perf-counters.c +++ b/src/lttng-context-perf-counters.c @@ -14,13 +14,14 @@ #include #include #include +#include #include #include #include #include static -size_t perf_counter_get_size(size_t offset) +size_t perf_counter_get_size(void *priv, struct lttng_kernel_probe_ctx *probe_ctx, size_t offset) { size_t size = 0; @@ -30,14 +31,15 @@ size_t perf_counter_get_size(size_t offset) } static -void perf_counter_record(struct lttng_ctx_field *field, - struct lib_ring_buffer_ctx *ctx, +void perf_counter_record(void *priv, struct lttng_kernel_probe_ctx *probe_ctx, + struct lttng_kernel_ring_buffer_ctx *ctx, struct lttng_channel *chan) { + struct lttng_perf_counter_field *perf_field = (struct lttng_perf_counter_field *) priv; struct perf_event *event; uint64_t value; - event = field->u.perf_counter->e[ctx->cpu]; + event = perf_field->e[ctx->priv.reserve_cpu]; if (likely(event)) { if (unlikely(event->state == PERF_EVENT_STATE_ERROR)) { value = 0; @@ -59,7 +61,7 @@ void perf_counter_record(struct lttng_ctx_field *field, chan->ops->event_write(ctx, &value, sizeof(value)); } -#if defined(CONFIG_PERF_EVENTS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,99)) +#if defined(CONFIG_PERF_EVENTS) && (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,1,0)) static void overflow_callback(struct perf_event *event, struct perf_sample_data *data, @@ -76,22 +78,23 @@ void overflow_callback(struct perf_event *event, int nmi, #endif static -void lttng_destroy_perf_counter_field(struct lttng_ctx_field *field) +void lttng_destroy_perf_counter_ctx_field(void *priv) { - struct perf_event **events = field->u.perf_counter->e; + struct lttng_perf_counter_field *perf_field = priv; + struct perf_event **events = perf_field->e; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) { int ret; ret = cpuhp_state_remove_instance(lttng_hp_online, - &field->u.perf_counter->cpuhp_online.node); + &perf_field->cpuhp_online.node); WARN_ON(ret); ret = cpuhp_state_remove_instance(lttng_hp_prepare, - &field->u.perf_counter->cpuhp_prepare.node); + &perf_field->cpuhp_prepare.node); WARN_ON(ret); } -#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ +#else /* #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ { int cpu; @@ -100,17 +103,18 @@ void lttng_destroy_perf_counter_field(struct lttng_ctx_field *field) perf_event_release_kernel(events[cpu]); put_online_cpus(); #ifdef CONFIG_HOTPLUG_CPU - unregister_cpu_notifier(&field->u.perf_counter->nb); + unregister_cpu_notifier(&perf_field->nb); #endif } -#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ - kfree(field->event_field.name); - kfree(field->u.perf_counter->attr); +#endif /* #else #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ + kfree(perf_field->name); + kfree(perf_field->attr); + kfree(perf_field->event_field); lttng_kvfree(events); - kfree(field->u.perf_counter); + kfree(perf_field); } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) int lttng_cpuhp_perf_counter_online(unsigned int cpu, struct lttng_cpuhp_node *node) @@ -151,7 +155,7 @@ int lttng_cpuhp_perf_counter_dead(unsigned int cpu, return 0; } -#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ +#else /* #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ #ifdef CONFIG_HOTPLUG_CPU @@ -210,23 +214,44 @@ int lttng_perf_counter_cpu_hp_callback(struct notifier_block *nb, #endif -#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ +#endif /* #else #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ + +static const struct lttng_kernel_type_common *field_type = + lttng_kernel_static_type_integer_from_type(uint64_t, __BYTE_ORDER, 10); int lttng_add_perf_counter_to_ctx(uint32_t type, uint64_t config, const char *name, - struct lttng_ctx **ctx) + struct lttng_kernel_ctx **ctx) { - struct lttng_ctx_field *field; + struct lttng_kernel_ctx_field ctx_field = { 0 }; + struct lttng_kernel_event_field *event_field; struct lttng_perf_counter_field *perf_field; struct perf_event **events; struct perf_event_attr *attr; int ret; char *name_alloc; + if (lttng_kernel_find_context(*ctx, name)) + return -EEXIST; + name_alloc = kstrdup(name, GFP_KERNEL); + if (!name_alloc) { + ret = -ENOMEM; + goto name_alloc_error; + } + event_field = kzalloc(sizeof(*event_field), GFP_KERNEL); + if (!event_field) { + ret = -ENOMEM; + goto event_field_alloc_error; + } + event_field->name = name_alloc; + event_field->type = field_type; + events = lttng_kvzalloc(num_possible_cpus() * sizeof(*events), GFP_KERNEL); - if (!events) - return -ENOMEM; + if (!events) { + ret = -ENOMEM; + goto event_alloc_error; + } attr = kzalloc(sizeof(struct perf_event_attr), GFP_KERNEL); if (!attr) { @@ -247,24 +272,16 @@ int lttng_add_perf_counter_to_ctx(uint32_t type, } perf_field->e = events; perf_field->attr = attr; + perf_field->name = name_alloc; + perf_field->event_field = event_field; - name_alloc = kstrdup(name, GFP_KERNEL); - if (!name_alloc) { - ret = -ENOMEM; - goto name_alloc_error; - } - - field = lttng_append_context(ctx); - if (!field) { - ret = -ENOMEM; - goto append_context_error; - } - if (lttng_find_context(*ctx, name_alloc)) { - ret = -EEXIST; - goto find_error; - } + ctx_field.event_field = event_field; + ctx_field.get_size = perf_counter_get_size; + ctx_field.record = perf_counter_record; + ctx_field.destroy = lttng_destroy_perf_counter_ctx_field; + ctx_field.priv = perf_field; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) perf_field->cpuhp_prepare.component = LTTNG_CONTEXT_PERF_COUNTERS; ret = cpuhp_state_add_instance(lttng_hp_prepare, @@ -278,7 +295,7 @@ int lttng_add_perf_counter_to_ctx(uint32_t type, if (ret) goto cpuhp_online_error; -#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ +#else /* #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ { int cpu; @@ -304,27 +321,18 @@ int lttng_add_perf_counter_to_ctx(uint32_t type, put_online_cpus(); perf_field->hp_enable = 1; } -#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ - - field->destroy = lttng_destroy_perf_counter_field; - - field->event_field.name = name_alloc; - field->event_field.type.atype = atype_integer; - field->event_field.type.u.integer.size = sizeof(uint64_t) * CHAR_BIT; - field->event_field.type.u.integer.alignment = lttng_alignof(uint64_t) * CHAR_BIT; - field->event_field.type.u.integer.signedness = lttng_is_signed_type(uint64_t); - field->event_field.type.u.integer.reverse_byte_order = 0; - field->event_field.type.u.integer.base = 10; - field->event_field.type.u.integer.encoding = lttng_encode_none; - field->get_size = perf_counter_get_size; - field->record = perf_counter_record; - field->u.perf_counter = perf_field; - lttng_context_update(*ctx); - - wrapper_vmalloc_sync_mappings(); +#endif /* #else #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ + + ret = lttng_kernel_context_append(ctx, &ctx_field); + if (ret) { + ret = -ENOMEM; + goto append_context_error; + } return 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) + /* Error handling. */ +append_context_error: +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) cpuhp_online_error: { int remove_ret; @@ -334,7 +342,7 @@ cpuhp_online_error: WARN_ON(remove_ret); } cpuhp_prepare_error: -#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ +#else /* #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ counter_busy: counter_error: { @@ -349,16 +357,16 @@ counter_error: unregister_cpu_notifier(&perf_field->nb); #endif } -#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ -find_error: - lttng_remove_context_field(ctx, field); -append_context_error: - kfree(name_alloc); -name_alloc_error: +#endif /* #else #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */ kfree(perf_field); error_alloc_perf_field: kfree(attr); error_attr: lttng_kvfree(events); +event_alloc_error: + kfree(event_field); +event_field_alloc_error: + kfree(name_alloc); +name_alloc_error: return ret; }