Fix: notifier: use store-release/load-acquire for error counter
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 9 Dec 2020 14:30:23 +0000 (09:30 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 9 Dec 2020 14:30:23 +0000 (09:30 -0500)
The "record_error" operation is executed concurrently with setting the
error counter in the notifier group without locking, so we need to
explicitly provide existance guarantees.

The only visible transition is from NULL -> !NULL, because the only
situation reverting the error counter back to NULL is on destruction of
the notification group, after an RCU synchronisation guarantees that no
record_error can observe this pointer anymore.

Use the stronger "cmm_smp_mb()" to provide store-release/load-acquire
semantics because the explicit store-release and load-acquire are not
implemented in the CMM model yet.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I3bbeecc00ff33c5d8ad1e3fd41c8a0dc866f1943

liblttng-ust/event-notifier-notification.c
liblttng-ust/lttng-ust-abi.c

index 5f7d9d58f24b67bf04fb4cf5fef6b2e8854f8895..ed2c8d28ae217823acace539b5d3e9c777d816c6 100644 (file)
@@ -284,17 +284,26 @@ static void record_error(struct lttng_event_notifier *event_notifier)
 {
        struct lttng_event_notifier_group *event_notifier_group =
                        event_notifier->group;
+       struct lttng_counter *error_counter;
        size_t dimension_index[1];
        int ret;
 
+       error_counter = CMM_LOAD_SHARED(event_notifier_group->error_counter);
+       /*
+        * load-acquire paired with store-release orders creation of the
+        * error counter and setting error_counter_len before the
+        * error_counter is used.
+        * Currently a full memory barrier is used, which could be
+        * turned into acquire-release barriers.
+        */
+       cmm_smp_mb();
        /* This group may not have an error counter attached to it. */
-       if (!event_notifier_group->error_counter)
+       if (!error_counter)
                return;
 
        dimension_index[0] = event_notifier->error_counter_index;
        ret = event_notifier_group->error_counter->ops->counter_add(
-                       event_notifier_group->error_counter->counter,
-                       dimension_index, 1);
+                       error_counter->counter, dimension_index, 1);
        if (ret)
                WARN_ON_ONCE(1);
 }
index a024b616fe5198be022ebe6858ae6653556327a6..aad64a6dd326dbd13b01332c07d0bde8326b837c 100644 (file)
@@ -846,8 +846,16 @@ int lttng_ust_event_notifier_group_create_error_counter(int event_notifier_group
                goto create_error;
        }
 
-       event_notifier_group->error_counter = counter;
        event_notifier_group->error_counter_len = counter_len;
+       /*
+        * store-release to publish error counter matches load-acquire
+        * in record_error. Ensures the counter is created and the
+        * error_counter_len is set before they are used.
+        * Currently a full memory barrier is used, which could be
+        * turned into acquire-release barriers.
+        */
+       cmm_smp_mb();
+       CMM_STORE_SHARED(event_notifier_group->error_counter, counter);
 
        counter->objd = counter_objd;
        counter->event_notifier_group = event_notifier_group;   /* owner */
This page took 0.026216 seconds and 4 git commands to generate.