+
+error_add_context:
+ free(field->event_field);
+error_alloc_event_field:
+ free(field);
+error_alloc_field:
+ return NULL;
+}
+
+/*
+ * Takes ownership of @f on success.
+ */
+int lttng_context_add_rcu(struct lttng_ust_ctx **ctx_p,
+ 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_ust_ctx));
+ if (!new_ctx)
+ return -ENOMEM;
+ new_ctx->struct_size = sizeof(struct lttng_ust_ctx);
+ *new_ctx = *old_ctx;
+ new_fields = zmalloc(new_ctx->allocated_fields * sizeof(*new_fields));
+ if (!new_fields) {
+ free(new_ctx);
+ return -ENOMEM;
+ }
+ /* Copy pointers */
+ memcpy(new_fields, old_ctx->fields,
+ sizeof(*old_ctx->fields) * old_ctx->nr_fields);
+ new_ctx->fields = new_fields;
+ }
+ ret = lttng_add_context(&new_ctx);
+ if (ret) {
+ free(new_fields);
+ free(new_ctx);
+ return ret;
+ }
+ /* Taking ownership of f. */
+ (*ctx_p)->fields[(*ctx_p)->nr_fields - 1] = f;
+ lttng_context_update(new_ctx);
+ lttng_ust_rcu_assign_pointer(*ctx_p, new_ctx);
+ lttng_ust_urcu_synchronize_rcu();
+ if (old_ctx) {
+ free(old_ctx->fields);
+ free(old_ctx);
+ }
+ return 0;
+}
+
+static size_t get_type_max_align(struct lttng_ust_type_common *type)
+{
+ 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;
+ 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;
+ }