X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-context.c;h=7e558067542877f846bc7f46dee9e5e9989318c5;hb=4e48b5d;hp=59bc082b6e353e43b7152bc2e2f245fb3d77d269;hpb=864a1eda22ed99266509ac76451c6f27f91aa17e;p=lttng-ust.git diff --git a/liblttng-ust/lttng-context.c b/liblttng-ust/lttng-context.c index 59bc082b..7e558067 100644 --- a/liblttng-ust/lttng-context.c +++ b/liblttng-ust/lttng-context.c @@ -11,11 +11,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "tracepoint-internal.h" #include "context-internal.h" @@ -25,11 +27,13 @@ * same context performed by the same thread return the same result. */ -int lttng_find_context(struct lttng_ctx *ctx, const char *name) +int lttng_find_context(struct lttng_ust_ctx *ctx, const char *name) { unsigned int i; const char *subname; + if (!ctx) + return 0; if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) { subname = name + strlen("$ctx."); } else { @@ -37,15 +41,15 @@ int lttng_find_context(struct lttng_ctx *ctx, const char *name) } for (i = 0; i < ctx->nr_fields; i++) { /* Skip allocated (but non-initialized) contexts */ - if (!ctx->fields[i].event_field.name) + if (!ctx->fields[i].event_field->name) continue; - if (!strcmp(ctx->fields[i].event_field.name, subname)) + if (!strcmp(ctx->fields[i].event_field->name, subname)) return 1; } return 0; } -int lttng_get_context_index(struct lttng_ctx *ctx, const char *name) +int lttng_get_context_index(struct lttng_ust_ctx *ctx, const char *name) { unsigned int i; const char *subname; @@ -59,23 +63,23 @@ int lttng_get_context_index(struct lttng_ctx *ctx, const char *name) } for (i = 0; i < ctx->nr_fields; i++) { /* Skip allocated (but non-initialized) contexts */ - if (!ctx->fields[i].event_field.name) + if (!ctx->fields[i].event_field->name) continue; - if (!strcmp(ctx->fields[i].event_field.name, subname)) + if (!strcmp(ctx->fields[i].event_field->name, subname)) return i; } return -1; } -static int lttng_find_context_provider(struct lttng_ctx *ctx, const char *name) +static int lttng_find_context_provider(struct lttng_ust_ctx *ctx, const char *name) { unsigned int i; for (i = 0; i < ctx->nr_fields; i++) { /* Skip allocated (but non-initialized) contexts */ - if (!ctx->fields[i].event_field.name) + if (!ctx->fields[i].event_field->name) continue; - if (!strncmp(ctx->fields[i].event_field.name, name, + if (!strncmp(ctx->fields[i].event_field->name, name, strlen(name))) return 1; } @@ -84,68 +88,125 @@ static int lttng_find_context_provider(struct lttng_ctx *ctx, const char *name) /* * Note: as we append context information, the pointer location may change. + * lttng_ust_context_add_field leaves the new last context initialized to NULL. */ -struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p) +static +int lttng_ust_context_add_field(struct lttng_ust_ctx **ctx_p) { - struct lttng_ctx_field *field; - struct lttng_ctx *ctx; + struct lttng_ust_ctx *ctx; if (!*ctx_p) { - *ctx_p = zmalloc(sizeof(struct lttng_ctx)); + *ctx_p = zmalloc(sizeof(struct lttng_ust_ctx)); if (!*ctx_p) - return NULL; + return -ENOMEM; (*ctx_p)->largest_align = 1; } ctx = *ctx_p; if (ctx->nr_fields + 1 > ctx->allocated_fields) { - struct lttng_ctx_field *new_fields; + struct lttng_ust_ctx_field *new_fields; ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields); - new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field)); + new_fields = zmalloc(ctx->allocated_fields * sizeof(*new_fields)); if (!new_fields) - return NULL; + return -ENOMEM; + /* Copy elements */ if (ctx->fields) memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields); free(ctx->fields); ctx->fields = new_fields; } - field = &ctx->fields[ctx->nr_fields]; ctx->nr_fields++; - return field; + return 0; } -int lttng_context_add_rcu(struct lttng_ctx **ctx_p, - const struct lttng_ctx_field *f) +static size_t get_type_max_align(const struct lttng_ust_type_common *type) { - struct lttng_ctx *old_ctx = *ctx_p, *new_ctx = NULL; - struct lttng_ctx_field *new_fields = NULL; - struct lttng_ctx_field *nf; + switch (type->type) { + case lttng_ust_type_integer: + return lttng_ust_get_type_integer(type)->alignment; + case lttng_ust_type_string: + return CHAR_BIT; + case lttng_ust_type_dynamic: + return 0; + case lttng_ust_type_enum: + return get_type_max_align(lttng_ust_get_type_enum(type)->container_type); + case lttng_ust_type_array: + return max_t(size_t, get_type_max_align(lttng_ust_get_type_array(type)->elem_type), + lttng_ust_get_type_array(type)->alignment); + case lttng_ust_type_sequence: + return max_t(size_t, get_type_max_align(lttng_ust_get_type_sequence(type)->elem_type), + lttng_ust_get_type_sequence(type)->alignment); + case lttng_ust_type_struct: + { + unsigned int i; + size_t field_align = 0; + const struct lttng_ust_type_struct *struct_type = lttng_ust_get_type_struct(type); + + for (i = 0; i < struct_type->nr_fields; i++) { + field_align = max_t(size_t, + get_type_max_align(struct_type->fields[i]->type), + field_align); + } + return field_align; + } + default: + WARN_ON_ONCE(1); + return 0; + } +} + +/* + * lttng_context_update() should be called at least once between context + * modification and trace start. + */ +static +void lttng_context_update(struct lttng_ust_ctx *ctx) +{ + int i; + size_t largest_align = 8; /* in bits */ + + for (i = 0; i < ctx->nr_fields; i++) { + size_t field_align = 8; + + field_align = get_type_max_align(ctx->fields[i].event_field->type); + largest_align = max_t(size_t, largest_align, field_align); + } + ctx->largest_align = largest_align >> 3; /* bits to bytes */ +} + +int lttng_ust_context_append_rcu(struct lttng_ust_ctx **ctx_p, + const struct lttng_ust_ctx_field *f) +{ + struct lttng_ust_ctx *old_ctx = *ctx_p, *new_ctx = NULL; + struct lttng_ust_ctx_field *new_fields = NULL; + int ret; if (old_ctx) { - new_ctx = zmalloc(sizeof(struct lttng_ctx)); + new_ctx = zmalloc(sizeof(struct lttng_ust_ctx)); if (!new_ctx) return -ENOMEM; *new_ctx = *old_ctx; - new_fields = zmalloc(new_ctx->allocated_fields - * sizeof(struct lttng_ctx_field)); + new_fields = zmalloc(new_ctx->allocated_fields * sizeof(*new_fields)); if (!new_fields) { free(new_ctx); return -ENOMEM; } + /* Copy elements */ memcpy(new_fields, old_ctx->fields, sizeof(*old_ctx->fields) * old_ctx->nr_fields); new_ctx->fields = new_fields; } - nf = lttng_append_context(&new_ctx); - if (!nf) { + ret = lttng_ust_context_add_field(&new_ctx); + if (ret) { free(new_fields); free(new_ctx); - return -ENOMEM; + return ret; } - *nf = *f; + /* Taking ownership of f. */ + new_ctx->fields[new_ctx->nr_fields - 1] = *f; lttng_context_update(new_ctx); lttng_ust_rcu_assign_pointer(*ctx_p, new_ctx); - lttng_ust_synchronize_trace(); + lttng_ust_urcu_synchronize_rcu(); if (old_ctx) { free(old_ctx->fields); free(old_ctx); @@ -153,167 +214,20 @@ int lttng_context_add_rcu(struct lttng_ctx **ctx_p, return 0; } -/* - * lttng_context_update() should be called at least once between context - * modification and trace start. - */ -void lttng_context_update(struct lttng_ctx *ctx) -{ - int i; - size_t largest_align = 8; /* in bits */ - - for (i = 0; i < ctx->nr_fields; i++) { - struct lttng_type *type; - size_t field_align = 8; - - type = &ctx->fields[i].event_field.type; - switch (type->atype) { - case atype_integer: - field_align = type->u.integer.alignment; - break; - case atype_array: - { - struct lttng_basic_type *btype; - - btype = &type->u.legacy.array.elem_type; - switch (btype->atype) { - case atype_integer: - field_align = btype->u.basic.integer.alignment; - break; - case atype_string: - break; - - case atype_array: - case atype_array_nestable: - case atype_sequence: - case atype_sequence_nestable: - default: - WARN_ON_ONCE(1); - break; - } - break; - } - case atype_array_nestable: - { - const struct lttng_type *nested_type; - - nested_type = type->u.array_nestable.elem_type; - switch (nested_type->atype) { - case atype_integer: - field_align = nested_type->u.integer.alignment; - break; - case atype_string: - break; - - case atype_array: - case atype_array_nestable: - case atype_sequence: - case atype_sequence_nestable: - default: - WARN_ON_ONCE(1); - break; - } - field_align = max_t(size_t, field_align, - type->u.array_nestable.alignment); - break; - } - case atype_sequence: - { - struct lttng_basic_type *btype; - - btype = &type->u.legacy.sequence.length_type; - switch (btype->atype) { - case atype_integer: - field_align = btype->u.basic.integer.alignment; - break; - - case atype_string: - case atype_array: - case atype_array_nestable: - case atype_sequence: - case atype_sequence_nestable: - default: - WARN_ON_ONCE(1); - break; - } - - btype = &type->u.legacy.sequence.elem_type; - switch (btype->atype) { - case atype_integer: - field_align = max_t(size_t, - field_align, - btype->u.basic.integer.alignment); - break; - - case atype_string: - break; - - case atype_array: - case atype_array_nestable: - case atype_sequence: - case atype_sequence_nestable: - default: - WARN_ON_ONCE(1); - break; - } - break; - } - case atype_sequence_nestable: - { - const struct lttng_type *nested_type; - - nested_type = type->u.sequence_nestable.elem_type; - switch (nested_type->atype) { - case atype_integer: - field_align = nested_type->u.integer.alignment; - break; - - case atype_string: - break; - - case atype_array: - case atype_array_nestable: - case atype_sequence: - case atype_sequence_nestable: - default: - WARN_ON_ONCE(1); - break; - } - field_align = max_t(size_t, field_align, - type->u.sequence_nestable.alignment); - break; - } - case atype_string: - break; - case atype_dynamic: - break; - case atype_enum: - case atype_enum_nestable: - default: - WARN_ON_ONCE(1); - break; - } - largest_align = max_t(size_t, largest_align, field_align); - } - ctx->largest_align = largest_align >> 3; /* bits to bytes */ -} - -/* - * Remove last context field. - */ -void lttng_remove_context_field(struct lttng_ctx **ctx_p, - struct lttng_ctx_field *field) +int lttng_ust_context_append(struct lttng_ust_ctx **ctx_p, + const struct lttng_ust_ctx_field *f) { - struct lttng_ctx *ctx; + int ret; - ctx = *ctx_p; - ctx->nr_fields--; - assert(&ctx->fields[ctx->nr_fields] == field); - assert(field->field_name == NULL); - memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field)); + ret = lttng_ust_context_add_field(ctx_p); + if (ret) + return ret; + (*ctx_p)->fields[(*ctx_p)->nr_fields - 1] = *f; + lttng_context_update(*ctx_p); + return 0; } -void lttng_destroy_context(struct lttng_ctx *ctx) +void lttng_destroy_context(struct lttng_ust_ctx *ctx) { int i; @@ -322,7 +236,6 @@ void lttng_destroy_context(struct lttng_ctx *ctx) for (i = 0; i < ctx->nr_fields; i++) { if (ctx->fields[i].destroy) ctx->fields[i].destroy(&ctx->fields[i]); - free(ctx->fields[i].field_name); } free(ctx->fields); free(ctx); @@ -340,18 +253,17 @@ void lttng_destroy_context(struct lttng_ctx *ctx) * a single RCU read-side critical section see either all old, or all * new handlers. */ -int lttng_ust_context_set_provider_rcu(struct lttng_ctx **_ctx, +int lttng_ust_context_set_provider_rcu(struct lttng_ust_ctx **_ctx, const char *name, - size_t (*get_size)(struct lttng_ctx_field *field, size_t offset), - void (*record)(struct lttng_ctx_field *field, - struct lttng_ust_lib_ring_buffer_ctx *ctx, - struct lttng_channel *chan), - void (*get_value)(struct lttng_ctx_field *field, - struct lttng_ctx_value *value)) + size_t (*get_size)(void *priv, size_t offset), + void (*record)(void *priv, struct lttng_ust_lib_ring_buffer_ctx *ctx, + struct lttng_ust_channel_buffer *chan), + void (*get_value)(void *priv, struct lttng_ust_ctx_value *value), + void *priv) { int i, ret; - struct lttng_ctx *ctx = *_ctx, *new_ctx; - struct lttng_ctx_field *new_fields; + struct lttng_ust_ctx *ctx = *_ctx, *new_ctx; + struct lttng_ust_ctx_field *new_fields; if (!ctx || !lttng_find_context_provider(ctx, name)) return 0; @@ -367,19 +279,21 @@ int lttng_ust_context_set_provider_rcu(struct lttng_ctx **_ctx, ret = -ENOMEM; goto field_error; } + /* Copy elements */ memcpy(new_fields, ctx->fields, sizeof(*new_fields) * ctx->allocated_fields); for (i = 0; i < ctx->nr_fields; i++) { - if (strncmp(new_fields[i].event_field.name, + if (strncmp(new_fields[i].event_field->name, name, strlen(name)) != 0) continue; new_fields[i].get_size = get_size; new_fields[i].record = record; new_fields[i].get_value = get_value; + new_fields[i].priv = priv; } new_ctx->fields = new_fields; lttng_ust_rcu_assign_pointer(*_ctx, new_ctx); - lttng_ust_synchronize_trace(); + lttng_ust_urcu_synchronize_rcu(); free(ctx->fields); free(ctx); return 0; @@ -389,7 +303,7 @@ field_error: return ret; } -int lttng_context_init_all(struct lttng_ctx **ctx) +int lttng_context_init_all(struct lttng_ust_ctx **ctx) { int ret;