X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=lib%2Fringbuffer%2Fring_buffer_frontend.c;h=ecc72ab84f7e3143f930e77cac0bc6ad3de16a8e;hb=5c0552665e4d152e97edc995650711d4f6ac418d;hp=9a90997c278b4b49086a03d2e4c16e3e1ea743a0;hpb=97ca2c5484815a67b70fcf2b1772eb1b2c2e5633;p=lttng-modules.git diff --git a/lib/ringbuffer/ring_buffer_frontend.c b/lib/ringbuffer/ring_buffer_frontend.c index 9a90997c..ecc72ab8 100644 --- a/lib/ringbuffer/ring_buffer_frontend.c +++ b/lib/ringbuffer/ring_buffer_frontend.c @@ -410,6 +410,7 @@ int __cpuinit lib_ring_buffer_cpu_hp_callback(struct notifier_block *nb, case CPU_DOWN_FAILED_FROZEN: case CPU_ONLINE: case CPU_ONLINE_FROZEN: + wake_up_interruptible(&chan->hp_wait); lib_ring_buffer_start_switch_timer(buf); lib_ring_buffer_start_read_timer(buf); return NOTIFY_OK; @@ -624,7 +625,9 @@ struct channel *channel_create(const struct lib_ring_buffer_config *config, chan->commit_count_mask = (~0UL >> chan->backend.num_subbuf_order); chan->switch_timer_interval = usecs_to_jiffies(switch_timer_interval); chan->read_timer_interval = usecs_to_jiffies(read_timer_interval); + kref_init(&chan->ref); init_waitqueue_head(&chan->read_wait); + init_waitqueue_head(&chan->hp_wait); if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { #if defined(CONFIG_NO_HZ) && defined(CONFIG_LIB_RING_BUFFER) @@ -685,6 +688,13 @@ error: } EXPORT_SYMBOL_GPL(channel_create); +static +void channel_release(struct kref *kref) +{ + struct channel *chan = container_of(kref, struct channel, ref); + channel_free(chan); +} + /** * channel_destroy - Finalize, wait for q.s. and destroy channel. * @chan: channel to destroy @@ -740,14 +750,11 @@ void *channel_destroy(struct channel *chan) ACCESS_ONCE(buf->finalized) = 1; wake_up_interruptible(&buf->read_wait); } + ACCESS_ONCE(chan->finalized) = 1; + wake_up_interruptible(&chan->hp_wait); wake_up_interruptible(&chan->read_wait); - - while (atomic_long_read(&chan->read_ref) > 0) - msleep(100); - /* Finish waiting for refcount before free */ - smp_mb(); + kref_put(&chan->ref, channel_release); priv = chan->backend.priv; - channel_free(chan); return priv; } EXPORT_SYMBOL_GPL(channel_destroy); @@ -769,7 +776,7 @@ int lib_ring_buffer_open_read(struct lib_ring_buffer *buf) if (!atomic_long_add_unless(&buf->active_readers, 1, 1)) return -EBUSY; - atomic_long_inc(&chan->read_ref); + kref_get(&chan->ref); smp_mb__after_atomic_inc(); return 0; } @@ -781,8 +788,8 @@ void lib_ring_buffer_release_read(struct lib_ring_buffer *buf) CHAN_WARN_ON(chan, atomic_long_read(&buf->active_readers) != 1); smp_mb__before_atomic_dec(); - atomic_long_dec(&chan->read_ref); atomic_long_dec(&buf->active_readers); + kref_put(&chan->ref, channel_release); } EXPORT_SYMBOL_GPL(lib_ring_buffer_release_read); @@ -1507,16 +1514,15 @@ int lib_ring_buffer_try_reserve_slow(struct lib_ring_buffer *buf, return -EIO; if (last_tsc_overflow(config, buf, ctx->tsc)) - ctx->rflags = RING_BUFFER_RFLAG_FULL_TSC; + ctx->rflags |= RING_BUFFER_RFLAG_FULL_TSC; if (unlikely(subbuf_offset(offsets->begin, ctx->chan) == 0)) { offsets->switch_new_start = 1; /* For offsets->begin */ } else { offsets->size = config->cb.record_header_size(config, chan, offsets->begin, - ctx->data_size, &offsets->pre_header_padding, - ctx->rflags, ctx); + ctx); offsets->size += lib_ring_buffer_align(offsets->begin + offsets->size, ctx->largest_align) @@ -1579,9 +1585,8 @@ int lib_ring_buffer_try_reserve_slow(struct lib_ring_buffer *buf, offsets->size = config->cb.record_header_size(config, chan, offsets->begin, - ctx->data_size, &offsets->pre_header_padding, - ctx->rflags, ctx); + ctx); offsets->size += lib_ring_buffer_align(offsets->begin + offsets->size, ctx->largest_align) @@ -1632,6 +1637,7 @@ int lib_ring_buffer_reserve_slow(struct lib_ring_buffer_ctx *ctx) const struct lib_ring_buffer_config *config = chan->backend.config; struct lib_ring_buffer *buf; struct switch_offsets offsets; + int ret; if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) buf = per_cpu_ptr(chan->backend.buf, ctx->cpu);