side: explicit statedump request key
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 23 Apr 2024 15:46:54 +0000 (11:46 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 23 Apr 2024 16:10:24 +0000 (12:10 -0400)
Make the statedump request key explicit rather than hiding it as a
Thread-Local Storage variable within libside. It's type is still opaque
to the application (void *), but this allows schemes where the statedump
callbacks are not required to emit statedump events from the same
thread: it can pass the statedump_request_key to another thread
responsible for emitting those events.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/instrumentation-c-api.h
include/side/trace.h
src/side.c
tests/unit/statedump.c

index 99a5acc2c544e6129c02de21ade8f62465ea045f..6b4b4592d65bfb5fc599e9974f7630cd8ca96e2c 100644 (file)
        side_event_cond(_identifier) \
                side_event_call_variadic(_identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
-#define side_statedump_event_call(_identifier, _sav) \
-       _side_event_call(side_statedump_call, _identifier, SIDE_PARAM(_sav))
+#define _side_statedump_event_call(_call, _identifier, _key, _sav) \
+       { \
+               const struct side_arg side_sav[] = { _sav }; \
+               const struct side_arg_vec side_arg_vec = { \
+                       .sav = SIDE_PTR_INIT(side_sav), \
+                       .len = SIDE_ARRAY_SIZE(side_sav), \
+               }; \
+               _call(&(side_event_state__##_identifier).parent, &side_arg_vec, _key); \
+       }
+
+#define side_statedump_event_call(_identifier, _key, _sav) \
+       _side_statedump_event_call(side_statedump_call, _identifier, _key, SIDE_PARAM(_sav))
+
+#define _side_statedump_event_call_variadic(_call, _identifier, _key, _sav, _var_fields, _attr...) \
+       { \
+               const struct side_arg side_sav[] = { _sav }; \
+               const struct side_arg_vec side_arg_vec = { \
+                       .sav = side_ptr_init(side_sav), \
+                       .len = side_array_size(side_sav), \
+               }; \
+               const struct side_arg_dynamic_field side_fields[] = { _var_fields }; \
+               const struct side_arg_dynamic_struct var_struct = { \
+                       .fields = side_ptr_init(side_fields), \
+                       .attr = side_ptr_init(_attr), \
+                       .len = side_array_size(side_fields), \
+                       .nr_attr = side_array_size(_attr), \
+               }; \
+               _call(&(side_event_state__##_identifier.parent), &side_arg_vec, &var_struct, _key); \
+       }
 
-#define side_statedump_event_call_variadic(_identifier, _sav, _var_fields, _attr...) \
-       _side_event_call_variadic(side_statedump_call_variadic, _identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var_fields), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
+#define side_statedump_event_call_variadic(_identifier, _key, _sav, _var_fields, _attr...) \
+       _side_statedump_event_call_variadic(side_statedump_call_variadic, _identifier, _key, SIDE_PARAM(_sav), SIDE_PARAM(_var_fields), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
 #define _side_define_event(_linkage, _identifier, _provider, _event, _loglevel, _fields, _flags, _attr...) \
        _linkage struct side_event_description __attribute__((section("side_event_description"))) \
index 647748e95b83279477b9fca94355df2bb55cacfd..662c7c788a33d6be12d357c5339d7d7a10677f03 100644 (file)
@@ -143,10 +143,12 @@ void side_tracer_event_notification_unregister(struct side_tracer_handle *handle
  * notification register/unregister APIs.
  */
 void side_statedump_call(const struct side_event_state *state,
-       const struct side_arg_vec *side_arg_vec);
+               const struct side_arg_vec *side_arg_vec,
+               void *statedump_request_key);
 void side_statedump_call_variadic(const struct side_event_state *state,
-       const struct side_arg_vec *side_arg_vec,
-       const struct side_arg_dynamic_struct *var_struct);
+               const struct side_arg_vec *side_arg_vec,
+               const struct side_arg_dynamic_struct *var_struct,
+               void *statedump_request_key);
 
 /*
  * If side_statedump_request_notification_register is invoked from
@@ -175,6 +177,9 @@ void side_statedump_call_variadic(const struct side_event_state *state,
  * their statedump callbacks registered with the agent thread. This
  * could result in deadlocks when pthread_atfork handler waits for
  * agent thread quiescence.
+ *
+ * The statedump_request_key received by the statedump_cb is only
+ * valid until the statedump_cb returns.
  */
 enum side_statedump_mode {
        SIDE_STATEDUMP_MODE_POLLING,
@@ -184,7 +189,7 @@ enum side_statedump_mode {
 struct side_statedump_request_handle *
        side_statedump_request_notification_register(
                const char *state_name,
-               void (*statedump_cb)(void),
+               void (*statedump_cb)(void *statedump_request_key),
                enum side_statedump_mode mode);
 void side_statedump_request_notification_unregister(
                struct side_statedump_request_handle *handle);
index 349b2df971e4d3b3d662aacaef5acbdf3d6625c1..f758102ec34b5237018a208a4f17c1052a5e97c0 100644 (file)
@@ -65,7 +65,7 @@ struct side_statedump_notification {
 struct side_statedump_request_handle {
        struct side_list_node node;                     /* Statedump request RCU list node. */
        struct side_list_head notification_queue;       /* Queue of struct side_statedump_notification */
-       void (*cb)(void);
+       void (*cb)(void *statedump_request_key);
        char *name;
        enum side_statedump_mode mode;
 };
@@ -140,11 +140,6 @@ static DEFINE_SIDE_LIST_HEAD(side_tracer_list);
  */
 static DEFINE_SIDE_LIST_HEAD(side_statedump_list);
 
-/*
- * Callback filter key for state dump.
- */
-static __thread uint64_t filter_key = SIDE_KEY_MATCH_ALL;
-
 /*
  * The empty callback has a NULL function callback pointer, which stops
  * iteration on the array of callbacks immediately.
@@ -210,9 +205,11 @@ void side_call(const struct side_event_state *event_state, const struct side_arg
        _side_call(event_state, side_arg_vec, SIDE_KEY_MATCH_ALL);
 }
 
-void side_statedump_call(const struct side_event_state *event_state, const struct side_arg_vec *side_arg_vec)
+void side_statedump_call(const struct side_event_state *event_state,
+               const struct side_arg_vec *side_arg_vec,
+               void *statedump_request_key)
 {
-       _side_call(event_state, side_arg_vec, filter_key);
+       _side_call(event_state, side_arg_vec, *(const uint64_t *) statedump_request_key);
 }
 
 static
@@ -261,10 +258,11 @@ void side_call_variadic(const struct side_event_state *event_state,
 }
 
 void side_statedump_call_variadic(const struct side_event_state *event_state,
-       const struct side_arg_vec *side_arg_vec,
-       const struct side_arg_dynamic_struct *var_struct)
+               const struct side_arg_vec *side_arg_vec,
+               const struct side_arg_dynamic_struct *var_struct,
+               void *statedump_request_key)
 {
-       _side_call_variadic(event_state, side_arg_vec, var_struct, filter_key);
+       _side_call_variadic(event_state, side_arg_vec, var_struct, *(const uint64_t *) statedump_request_key);
 }
 
 static
@@ -613,14 +611,12 @@ static
 void side_statedump_run(struct side_statedump_request_handle *handle,
                struct side_statedump_notification *notif)
 {
-       /* Invoke the state dump callback specifically for the tracer key. */
-       filter_key = notif->key;
-       side_statedump_event_call(side_statedump_begin,
+       side_statedump_event_call(side_statedump_begin, &notif->key,
                side_arg_list(side_arg_string(handle->name)));
-       handle->cb();
-       side_statedump_event_call(side_statedump_end,
+       /* Invoke the state dump callback specifically for the tracer key. */
+       handle->cb(&notif->key);
+       side_statedump_event_call(side_statedump_end, &notif->key,
                side_arg_list(side_arg_string(handle->name)));
-       filter_key = SIDE_KEY_MATCH_ALL;
 }
 
 static
@@ -756,7 +752,7 @@ void statedump_agent_thread_join(void)
 
 struct side_statedump_request_handle *
        side_statedump_request_notification_register(const char *state_name,
-               void (*statedump_cb)(void),
+               void (*statedump_cb)(void *statedump_request_key),
                enum side_statedump_mode mode)
 {
        struct side_statedump_request_handle *handle;
@@ -766,11 +762,6 @@ struct side_statedump_request_handle *
                return NULL;
        if (!initialized)
                side_init();
-       /*
-        * The statedump request notification should not be registered
-        * from a notification callback.
-        */
-       assert(!filter_key);
        handle = (struct side_statedump_request_handle *)
                                calloc(1, sizeof(struct side_statedump_request_handle));
        if (!handle)
@@ -817,7 +808,6 @@ void side_statedump_request_notification_unregister(struct side_statedump_reques
                return;
        if (!initialized)
                side_init();
-       assert(!filter_key);
 
        if (handle->mode == SIDE_STATEDUMP_MODE_AGENT_THREAD)
                pthread_mutex_lock(&side_agent_thread_lock);
index c33e8a6703ce77d8318c95e65995ab14bbc5acf7..a2d6f67104ed55f304e98aaf6942006c2b193c5a 100644 (file)
@@ -27,7 +27,7 @@ side_static_event(my_provider_event, "myprovider", "myevent", SIDE_LOGLEVEL_DEBU
 static struct side_statedump_request_handle *statedump_request_handle;
 
 static
-void statedump_cb(void)
+void statedump_cb(void *statedump_request_key)
 {
        size_t i;
 
@@ -35,12 +35,14 @@ void statedump_cb(void)
        side_event_cond(my_provider_event_dump1) {
                for (i = 0; i < SIDE_ARRAY_SIZE(mystr); i++) {
                        side_statedump_event_call(my_provider_event_dump1,
+                               statedump_request_key,
                                side_arg_list(side_arg_string(mystr[i])));
                }
        }
        side_event_cond(my_provider_event_dump2) {
                for (i = 0; i < SIDE_ARRAY_SIZE(myint); i++) {
                        side_statedump_event_call(my_provider_event_dump2,
+                               statedump_request_key,
                                side_arg_list(side_arg_s32(myint[i])));
                }
        }
This page took 0.027479 seconds and 4 git commands to generate.