aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/ring_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/events/ring_buffer.c')
-rw-r--r--kernel/events/ring_buffer.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 96472824a752..b2be01b1aa9d 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -221,6 +221,8 @@ void perf_output_end(struct perf_output_handle *handle)
221 rcu_read_unlock(); 221 rcu_read_unlock();
222} 222}
223 223
224static void rb_irq_work(struct irq_work *work);
225
224static void 226static void
225ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) 227ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
226{ 228{
@@ -241,6 +243,16 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
241 243
242 INIT_LIST_HEAD(&rb->event_list); 244 INIT_LIST_HEAD(&rb->event_list);
243 spin_lock_init(&rb->event_lock); 245 spin_lock_init(&rb->event_lock);
246 init_irq_work(&rb->irq_work, rb_irq_work);
247}
248
249static void ring_buffer_put_async(struct ring_buffer *rb)
250{
251 if (!atomic_dec_and_test(&rb->refcount))
252 return;
253
254 rb->rcu_head.next = (void *)rb;
255 irq_work_queue(&rb->irq_work);
244} 256}
245 257
246/* 258/*
@@ -319,7 +331,7 @@ err_put:
319 rb_free_aux(rb); 331 rb_free_aux(rb);
320 332
321err: 333err:
322 ring_buffer_put(rb); 334 ring_buffer_put_async(rb);
323 handle->event = NULL; 335 handle->event = NULL;
324 336
325 return NULL; 337 return NULL;
@@ -370,7 +382,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
370 382
371 local_set(&rb->aux_nest, 0); 383 local_set(&rb->aux_nest, 0);
372 rb_free_aux(rb); 384 rb_free_aux(rb);
373 ring_buffer_put(rb); 385 ring_buffer_put_async(rb);
374} 386}
375 387
376/* 388/*
@@ -557,7 +569,18 @@ static void __rb_free_aux(struct ring_buffer *rb)
557void rb_free_aux(struct ring_buffer *rb) 569void rb_free_aux(struct ring_buffer *rb)
558{ 570{
559 if (atomic_dec_and_test(&rb->aux_refcount)) 571 if (atomic_dec_and_test(&rb->aux_refcount))
572 irq_work_queue(&rb->irq_work);
573}
574
575static void rb_irq_work(struct irq_work *work)
576{
577 struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work);
578
579 if (!atomic_read(&rb->aux_refcount))
560 __rb_free_aux(rb); 580 __rb_free_aux(rb);
581
582 if (rb->rcu_head.next == (void *)rb)
583 call_rcu(&rb->rcu_head, rb_free_rcu);
561} 584}
562 585
563#ifndef CONFIG_PERF_USE_VMALLOC 586#ifndef CONFIG_PERF_USE_VMALLOC