From 2dccf128a59b5353176277d01da4eabcc2086211 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 25 May 2011 17:20:30 -0400 Subject: [PATCH] Add context management infrastructure Signed-off-by: Mathieu Desnoyers --- Makefile | 2 +- ltt-context.c | 54 +++++++++++++++++++++++++++++++ ltt-events.h | 3 ++ probes/lttng-perf-counters.c | 62 ++++++++++++------------------------ 4 files changed, 79 insertions(+), 42 deletions(-) create mode 100644 ltt-context.c diff --git a/Makefile b/Makefile index d2d6cbab..169b7cdd 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ obj-m += ltt-ring-buffer-metadata-client.o obj-m += ltt-relay.o ltt-relay-objs := ltt-events.o ltt-debugfs-abi.o \ - ltt-probes.o ltt-core.o + ltt-probes.o ltt-core.o ltt-context.o obj-m += probes/ obj-m += lib/ diff --git a/ltt-context.c b/ltt-context.c new file mode 100644 index 00000000..cc9633ac --- /dev/null +++ b/ltt-context.c @@ -0,0 +1,54 @@ +/* + * ltt-context.c + * + * Copyright 2011 (c) - Mathieu Desnoyers + * + * LTTng trace/channel/event context management. + */ + +#include +#include +#include +#include +#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ +#include "ltt-events.h" +#include "ltt-tracer.h" + +struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p) +{ + struct lttng_ctx_field *field; + struct lttng_ctx *ctx; + + if (!*ctx_p) { + *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL); + if (!*ctx_p) + return NULL; + } + ctx = *ctx_p; + if (ctx->nr_fields + 1 > ctx->allocated_fields) { + struct lttng_ctx_field *new_fields; + + ctx->allocated_fields = min_t(size_t, 1, 2 * ctx->allocated_fields); + new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL); + if (!new_fields) + return NULL; + if (ctx->fields) + memcpy(new_fields, ctx->fields, ctx->nr_fields); + kfree(ctx->fields); + ctx->fields = new_fields; + } + field = &ctx->fields[ctx->nr_fields]; + ctx->nr_fields++; + return field; +} +EXPORT_SYMBOL_GPL(lttng_append_context); + +void lttng_destroy_context(struct lttng_ctx *ctx) +{ + int i; + + for (i = 0; i < ctx->nr_fields; i++) + ctx->fields[i].destroy(&ctx->fields[i]); + kfree(ctx->fields); + kfree(ctx); +} diff --git a/ltt-events.h b/ltt-events.h index ce030ae3..bacef0a8 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -125,6 +125,7 @@ struct lttng_ctx_field { struct perf_event_attr *attr; } perf_counter; } u; + void (*destroy)(struct lttng_ctx_field *field); }; struct lttng_ctx { @@ -261,6 +262,8 @@ const struct lttng_event_desc *ltt_event_get(const char *name); void ltt_event_put(const struct lttng_event_desc *desc); int ltt_probes_init(void); void ltt_probes_exit(void); +struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx); +void lttng_destroy_context(struct lttng_ctx *ctx); #ifdef CONFIG_KPROBES int lttng_kprobes_register(const char *name, diff --git a/probes/lttng-perf-counters.c b/probes/lttng-perf-counters.c index cdda4833..c6620713 100644 --- a/probes/lttng-perf-counters.c +++ b/probes/lttng-perf-counters.c @@ -46,9 +46,24 @@ void overflow_callback(struct perf_event *event, int nmi, { } +static +void lttng_destroy_perf_counter_field(struct lttng_ctx_field *field) +{ + struct perf_event **events = field->u.perf_counter.e; + int cpu; + + mutex_lock(&perf_counter_mutex); + list_del(&field->u.perf_counter.head); + for_each_online_cpu(cpu) + perf_event_release_kernel(events[cpu]); + mutex_unlock(&perf_counter_mutex); + kfree(field->u.perf_counter.attr); + kfree(events); +} + int lttng_add_perf_counter_to_ctx(uint32_t type, uint64_t config, - struct lttng_ctx *ctx) + struct lttng_ctx **ctx) { struct lttng_ctx_field *field; struct perf_event **events; @@ -83,22 +98,12 @@ int lttng_add_perf_counter_to_ctx(uint32_t type, } } - ctx->nr_fields++; - if (ctx->nr_fields > ctx->allocated_fields) { - struct lttng_ctx_field *new_fields; - - ctx->allocated_fields = min_t(size_t, 1, 2 * ctx->allocated_fields); - new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL); - if (!new_fields) { - ret = -ENOMEM; - goto error; - } - if (ctx->fields) - memcpy(new_fields, ctx->fields, ctx->nr_fields - 1); - kfree(ctx->fields); - ctx->fields = new_fields; + field = lttng_append_context(ctx); + if (!field) { + ret = -ENOMEM; + goto error; } - field = &ctx->fields[ctx->nr_fields - 1]; + field->destroy = lttng_destroy_perf_counter_field; field->name = "dummyname";//TODO: lookup_counter_name(type, config); field->type.atype = atype_integer; @@ -130,31 +135,6 @@ error_attr: return ret; } -struct lttng_ctx *lttng_create_perf_counter_ctx(void) -{ - return kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL); -} - -void lttng_destroy_perf_counter_ctx(struct lttng_ctx *ctx) -{ - int i; - - for (i = 0; i < ctx->nr_fields; i++) { - struct perf_event **events = ctx->fields[i].u.perf_counter.e; - int cpu; - - mutex_lock(&perf_counter_mutex); - list_del(&ctx->fields[i].u.perf_counter.head); - for_each_online_cpu(cpu) - perf_event_release_kernel(events[cpu]); - mutex_unlock(&perf_counter_mutex); - kfree(ctx->fields[i].u.perf_counter.attr); - kfree(events); - } - kfree(ctx->fields); - kfree(ctx); -} - MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Mathieu Desnoyers"); MODULE_DESCRIPTION("Linux Trace Toolkit Perf Support"); -- 2.34.1