Init RCU, add empty side callback
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 27 Oct 2022 20:19:11 +0000 (16:19 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 27 Oct 2022 20:19:11 +0000 (16:19 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/trace.h
src/rcu.c
src/rcu.h
src/side.c

index 9a0f6b573c2ff3cfbc7799a8b49ecadf72f3173b..51acc7035dd8be54a31fb8bfcd6950a4b3cd9138 100644 (file)
@@ -289,13 +289,13 @@ struct side_event_description {
        uint32_t loglevel;      /* enum side_loglevel */
        uint32_t nr_fields;
        uint32_t nr_attr;
-       uint32_t nr_cb;
+       uint32_t _unused;
        uint64_t flags;
        const char *provider_name;
        const char *event_name;
        const struct side_event_field *fields;
        const struct side_attr *attr;
-       struct side_callback *callbacks;
+       const struct side_callback *callbacks;
 };
 
 struct side_arg_dynamic_vec {
@@ -1062,13 +1062,13 @@ struct side_tracer_dynamic_vla_visitor_ctx {
                .loglevel = _loglevel, \
                .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
                .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
-               .nr_cb = 0, \
+               ._unused = 0, \
                .flags = (_flags), \
                .provider_name = _provider, \
                .event_name = _event, \
                .fields = _fields, \
                .attr = _attr, \
-               .callbacks = NULL, \
+               .callbacks = &side_empty_callback, \
        }; \
        static const struct side_event_description *side_event_ptr__##_identifier \
                __attribute__((section("side_event_description_ptr"), used)) = &(_identifier);
@@ -1107,4 +1107,6 @@ void side_call_variadic(const struct side_event_description *desc,
        const struct side_arg_vec_description *sav_desc,
        const struct side_arg_dynamic_event_struct *var_struct);
 
+extern const struct side_callback side_empty_callback;
+
 #endif /* _SIDE_TRACE_H */
index d4551c2c80343bc783006ac478f420cf046ddaa7..bd6059cc3cacfa6b43cede802c6bd6154d0b1624 100644 (file)
--- a/src/rcu.c
+++ b/src/rcu.c
@@ -4,12 +4,15 @@
  */
 
 #include <sched.h>
+#include <string.h>
 #include <stdint.h>
 #include <pthread.h>
 #include <stdbool.h>
 #include <poll.h>
+#include <stdlib.h>
 
 #include "rcu.h"
+#include "smp.h"
 
 /* active_readers is an input/output parameter. */
 static
@@ -149,3 +152,15 @@ end:
         */
        __atomic_thread_fence(__ATOMIC_SEQ_CST);
 }
+
+void side_rcu_gp_init(struct side_rcu_gp_state *rcu_gp)
+{
+       memset(rcu_gp, 0, sizeof(*rcu_gp));
+       rcu_gp->nr_cpus = get_possible_cpus_array_len();
+       if (!rcu_gp->nr_cpus)
+               abort();
+       pthread_mutex_init(&rcu_gp->gp_lock, NULL);
+       rcu_gp->percpu_state = calloc(rcu_gp->nr_cpus, sizeof(struct side_rcu_cpu_gp_state));
+       if (!rcu_gp->percpu_state)
+               abort();
+}
index 1a93365b0d0f80fab4b0695a171ec65e862461f6..dfd2227b86e16e26f3144e5e1e7c5306a4675753 100644 (file)
--- a/src/rcu.h
+++ b/src/rcu.h
@@ -85,5 +85,6 @@ void side_rcu_read_end(struct side_rcu_gp_state *gp_state, unsigned int period)
 #define side_rcu_assign_pointer(p, v)  __atomic_store_n(&(p), v, __ATOMIC_RELEASE); \
 
 void side_rcu_wait_grace_period(struct side_rcu_gp_state *gp_state) __attribute__((visibility("hidden")));
+void side_rcu_gp_init(struct side_rcu_gp_state *rcu_gp) __attribute__((visibility("hidden")));
 
 #endif /* _SIDE_RCU_H */
index 72424ee59d46ee246ae69ce14222e8651dd77107..0715c74eab1ba01d39cc03841b013beabdf2aff4 100644 (file)
@@ -6,16 +6,15 @@
 #include <side/trace.h>
 #include "tracer.h"
 #include "rcu.h"
-#include "smp.h"
 
+/* Top 8 bits reserved for kernel tracer use. */
+#define SIDE_EVENT_ENABLED_KERNEL_MASK                 0xFF000000
 #define SIDE_EVENT_ENABLED_KERNEL_USER_EVENT_MASK      0x80000000
 
-struct side_rcu_gp_state rcu_gp = {
-       .percpu_state = NULL,
-       .nr_cpus = 0,
-       .period = 0,
-       .gp_lock = PTHREAD_MUTEX_INITIALIZER,
-};
+/* Allow 2^24 tracers to be registered on an event. */
+#define SIDE_EVENT_ENABLED_USER_MASK                   0x00FFFFFF
+
+struct side_rcu_gp_state rcu_gp;
 
 /*
  * Lazy initialization for early use within library constructors.
@@ -26,8 +25,13 @@ static
 void side_init(void)
        __attribute__((constructor));
 
+const struct side_callback side_empty_callback;
+
 void side_call(const struct side_event_description *desc, const struct side_arg_vec_description *sav_desc)
 {
+       const struct side_callback *side_cb;
+       unsigned int rcu_period;
+
        if (side_unlikely(!initialized))
                side_init();
        if (side_unlikely(desc->flags & SIDE_EVENT_FLAG_VARIADIC)) {
@@ -37,29 +41,46 @@ void side_call(const struct side_event_description *desc, const struct side_arg_
        if (side_unlikely(*desc->enabled & SIDE_EVENT_ENABLED_KERNEL_USER_EVENT_MASK)) {
                // TODO: call kernel write.
        }
+       if (side_unlikely(!(*desc->enabled & SIDE_EVENT_ENABLED_USER_MASK)))
+               return;
+
        //TODO: replace tracer_call by rcu iteration on list of registered callbacks
        tracer_call(desc, sav_desc, NULL);
+
+       rcu_period = side_rcu_read_begin(&rcu_gp);
+       for (side_cb = side_rcu_dereference(desc->callbacks); side_cb->u.call != NULL; side_cb++)
+               side_cb->u.call(desc, sav_desc, side_cb->priv);
+       side_rcu_read_end(&rcu_gp, rcu_period);
 }
 
 void side_call_variadic(const struct side_event_description *desc,
        const struct side_arg_vec_description *sav_desc,
        const struct side_arg_dynamic_event_struct *var_struct)
 {
+       const struct side_callback *side_cb;
+       unsigned int rcu_period;
+
        if (side_unlikely(!initialized))
                side_init();
        if (side_unlikely(*desc->enabled & SIDE_EVENT_ENABLED_KERNEL_USER_EVENT_MASK)) {
                // TODO: call kernel write.
        }
+       if (side_unlikely(!(*desc->enabled & SIDE_EVENT_ENABLED_USER_MASK)))
+               return;
+
        //TODO: replace tracer_call by rcu iteration on list of registered callbacks
        tracer_call_variadic(desc, sav_desc, var_struct, NULL);
+
+       rcu_period = side_rcu_read_begin(&rcu_gp);
+       for (side_cb = side_rcu_dereference(desc->callbacks); side_cb->u.call_variadic != NULL; side_cb++)
+               side_cb->u.call_variadic(desc, sav_desc, var_struct, side_cb->priv);
+       side_rcu_read_end(&rcu_gp, rcu_period);
 }
 
 void side_init(void)
 {
        if (initialized)
                return;
-       rcu_gp.nr_cpus = get_possible_cpus_array_len();
-       if (!rcu_gp.nr_cpus)
-               abort();
+       side_rcu_gp_init(&rcu_gp);
        initialized = true;
 }
This page took 0.026827 seconds and 4 git commands to generate.