aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_counter.h2
-rw-r--r--kernel/perf_counter.c20
2 files changed, 21 insertions, 1 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index f9d5cf0bfbdd..8d5d11b8d011 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -238,6 +238,7 @@ enum perf_event_type {
238#include <linux/rcupdate.h> 238#include <linux/rcupdate.h>
239#include <linux/spinlock.h> 239#include <linux/spinlock.h>
240#include <linux/hrtimer.h> 240#include <linux/hrtimer.h>
241#include <linux/fs.h>
241#include <asm/atomic.h> 242#include <asm/atomic.h>
242 243
243struct task_struct; 244struct task_struct;
@@ -398,6 +399,7 @@ struct perf_counter {
398 399
399 /* poll related */ 400 /* poll related */
400 wait_queue_head_t waitq; 401 wait_queue_head_t waitq;
402 struct fasync_struct *fasync;
401 /* optional: for NMIs */ 403 /* optional: for NMIs */
402 struct perf_wakeup_entry wakeup; 404 struct perf_wakeup_entry wakeup;
403 405
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 727624db5078..c58cc64319e1 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1526,6 +1526,22 @@ out:
1526 return ret; 1526 return ret;
1527} 1527}
1528 1528
1529static int perf_fasync(int fd, struct file *filp, int on)
1530{
1531 struct perf_counter *counter = filp->private_data;
1532 struct inode *inode = filp->f_path.dentry->d_inode;
1533 int retval;
1534
1535 mutex_lock(&inode->i_mutex);
1536 retval = fasync_helper(fd, filp, on, &counter->fasync);
1537 mutex_unlock(&inode->i_mutex);
1538
1539 if (retval < 0)
1540 return retval;
1541
1542 return 0;
1543}
1544
1529static const struct file_operations perf_fops = { 1545static const struct file_operations perf_fops = {
1530 .release = perf_release, 1546 .release = perf_release,
1531 .read = perf_read, 1547 .read = perf_read,
@@ -1533,6 +1549,7 @@ static const struct file_operations perf_fops = {
1533 .unlocked_ioctl = perf_ioctl, 1549 .unlocked_ioctl = perf_ioctl,
1534 .compat_ioctl = perf_ioctl, 1550 .compat_ioctl = perf_ioctl,
1535 .mmap = perf_mmap, 1551 .mmap = perf_mmap,
1552 .fasync = perf_fasync,
1536}; 1553};
1537 1554
1538/* 1555/*
@@ -1549,7 +1566,7 @@ void perf_counter_wakeup(struct perf_counter *counter)
1549 rcu_read_lock(); 1566 rcu_read_lock();
1550 data = rcu_dereference(counter->data); 1567 data = rcu_dereference(counter->data);
1551 if (data) { 1568 if (data) {
1552 (void)atomic_xchg(&data->wakeup, POLL_IN); 1569 atomic_set(&data->wakeup, POLL_IN);
1553 /* 1570 /*
1554 * Ensure all data writes are issued before updating the 1571 * Ensure all data writes are issued before updating the
1555 * user-space data head information. The matching rmb() 1572 * user-space data head information. The matching rmb()
@@ -1561,6 +1578,7 @@ void perf_counter_wakeup(struct perf_counter *counter)
1561 rcu_read_unlock(); 1578 rcu_read_unlock();
1562 1579
1563 wake_up_all(&counter->waitq); 1580 wake_up_all(&counter->waitq);
1581 kill_fasync(&counter->fasync, SIGIO, POLL_IN);
1564} 1582}
1565 1583
1566/* 1584/*