rseq fallback: use saturated reference counter
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 3 Nov 2016 16:40:14 +0000 (10:40 -0600)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 22 Nov 2016 20:20:02 +0000 (15:20 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
liblttng-ust/lttng-ring-buffer-client.h
libringbuffer/frontend_types.h

index f014f4e46158e9706873e9ae5bc7a74d67a72303..8a2155ef3e8501309948c49966fd37b9f41b8b52 100644 (file)
@@ -690,13 +690,36 @@ void lttng_channel_destroy(struct lttng_channel *chan)
        channel_destroy(chan->chan, chan->handle, 1);
 }
 
+static
+bool refcount_get_saturate(long *ref)
+{
+       long old, _new, res;
+
+       old = uatomic_read(ref);
+       for (;;) {
+               if (old == LONG_MAX) {
+                       return false;   /* Saturated. */
+               }
+               _new = old + 1;
+               res = uatomic_cmpxchg(ref, old, _new);
+               if (res == old) {
+                       if (_new == LONG_MAX) {
+                               return false; /* Saturation. */
+                       }
+                       return true;    /* Success. */
+               }
+               old = res;
+       }
+}
+
 static
 int lttng_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx,
                      uint32_t event_id)
 {
        struct lttng_channel *lttng_chan = channel_get_private(ctx->chan);
        struct lttng_rseq_state rseq_state;
-       int ret, cpu, fallback = 0;
+       int ret, cpu;
+       bool put_fallback_ref = false;
 
        if (lib_ring_buffer_begin(&client_config))
                return -EPERM;
@@ -739,9 +762,9 @@ fallback:
        ret = lib_ring_buffer_reserve(&client_config, ctx);
        if (caa_unlikely(ret)) {
                if (ret == -EAGAIN) {
-                       assert(!fallback);
-                       fallback = 1;
-                       uatomic_inc(&lttng_chan->chan->u.reserve_fallback_ref);
+                       assert(!put_fallback_ref);
+                       put_fallback_ref = refcount_get_saturate(
+                               &lttng_chan->chan->u.reserve_fallback_ref);
                        cpu = lib_ring_buffer_get_cpu(&client_config);
                        if (caa_unlikely(cpu < 0)) {
                                ret = -EPERM;
@@ -761,13 +784,13 @@ fallback:
        }
        lttng_write_event_header(&client_config, ctx, event_id);
 
-       if (caa_unlikely(fallback))
+       if (caa_unlikely(put_fallback_ref))
                uatomic_dec(&lttng_chan->chan->u.reserve_fallback_ref);
 
        return 0;
 end:
        lib_ring_buffer_end(&client_config);
-       if (fallback)
+       if (put_fallback_ref)
                uatomic_dec(&lttng_chan->chan->u.reserve_fallback_ref);
        return ret;
 }
index b99fb8cba204687da8e4900da80c01da4c533a51..6b023b7c3ba9c217c304f9f0e1431d03595860d1 100644 (file)
@@ -71,7 +71,7 @@ struct channel {
        unsigned int nr_streams;                /* Number of streams */
        struct lttng_ust_shm_handle *handle;
        union {
-               unsigned long reserve_fallback_ref;
+               long reserve_fallback_ref;
                char padding[RB_CHANNEL_PADDING];
        } u;
        /*
This page took 0.027321 seconds and 5 git commands to generate.