diff options
| author | Soeren Sandmann Pedersen <sandmann@redhat.com> | 2008-05-12 15:20:49 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-23 14:55:43 -0400 |
| commit | 2a2cc8f7c4d0dfd75720867f7dc58d24f075edfc (patch) | |
| tree | 58bccce0675debd5619757a45b5aba770bf32d0e | |
| parent | aeaee8a2c9cb4489f166ca0e39c568e8254faaa6 (diff) | |
ftrace: allow the event pipe to be polled
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | kernel/trace/trace.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 958c4d77a67b..d041578affd0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
| 25 | #include <linux/ctype.h> | 25 | #include <linux/ctype.h> |
| 26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
| 27 | #include <linux/poll.h> | ||
| 27 | #include <linux/gfp.h> | 28 | #include <linux/gfp.h> |
| 28 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
| 29 | 30 | ||
| @@ -63,6 +64,7 @@ static struct tracer *current_trace __read_mostly; | |||
| 63 | static int max_tracer_type_len; | 64 | static int max_tracer_type_len; |
| 64 | 65 | ||
| 65 | static DEFINE_MUTEX(trace_types_lock); | 66 | static DEFINE_MUTEX(trace_types_lock); |
| 67 | static DECLARE_WAIT_QUEUE_HEAD (trace_wait); | ||
| 66 | 68 | ||
| 67 | #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry)) | 69 | #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry)) |
| 68 | 70 | ||
| @@ -105,6 +107,7 @@ enum trace_iterator_flags { | |||
| 105 | TRACE_ITER_RAW = 0x10, | 107 | TRACE_ITER_RAW = 0x10, |
| 106 | TRACE_ITER_HEX = 0x20, | 108 | TRACE_ITER_HEX = 0x20, |
| 107 | TRACE_ITER_BIN = 0x40, | 109 | TRACE_ITER_BIN = 0x40, |
| 110 | TRACE_ITER_BLOCK = 0x80, | ||
| 108 | }; | 111 | }; |
| 109 | 112 | ||
| 110 | #define TRACE_ITER_SYM_MASK \ | 113 | #define TRACE_ITER_SYM_MASK \ |
| @@ -119,6 +122,7 @@ static const char *trace_options[] = { | |||
| 119 | "raw", | 122 | "raw", |
| 120 | "hex", | 123 | "hex", |
| 121 | "bin", | 124 | "bin", |
| 125 | "block", | ||
| 122 | NULL | 126 | NULL |
| 123 | }; | 127 | }; |
| 124 | 128 | ||
| @@ -650,6 +654,9 @@ __ftrace(struct trace_array *tr, struct trace_array_cpu *data, | |||
| 650 | entry->fn.ip = ip; | 654 | entry->fn.ip = ip; |
| 651 | entry->fn.parent_ip = parent_ip; | 655 | entry->fn.parent_ip = parent_ip; |
| 652 | spin_unlock_irqrestore(&data->lock, irq_flags); | 656 | spin_unlock_irqrestore(&data->lock, irq_flags); |
| 657 | |||
| 658 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
| 659 | wake_up (&trace_wait); | ||
| 653 | } | 660 | } |
| 654 | 661 | ||
| 655 | notrace void | 662 | notrace void |
| @@ -675,6 +682,9 @@ trace_special(struct trace_array *tr, struct trace_array_cpu *data, | |||
| 675 | entry->special.arg2 = arg2; | 682 | entry->special.arg2 = arg2; |
| 676 | entry->special.arg3 = arg3; | 683 | entry->special.arg3 = arg3; |
| 677 | spin_unlock_irqrestore(&data->lock, irq_flags); | 684 | spin_unlock_irqrestore(&data->lock, irq_flags); |
| 685 | |||
| 686 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
| 687 | wake_up (&trace_wait); | ||
| 678 | } | 688 | } |
| 679 | 689 | ||
| 680 | notrace void | 690 | notrace void |
| @@ -696,6 +706,9 @@ tracing_sched_switch_trace(struct trace_array *tr, | |||
| 696 | entry->ctx.next_pid = next->pid; | 706 | entry->ctx.next_pid = next->pid; |
| 697 | entry->ctx.next_prio = next->prio; | 707 | entry->ctx.next_prio = next->prio; |
| 698 | spin_unlock_irqrestore(&data->lock, irq_flags); | 708 | spin_unlock_irqrestore(&data->lock, irq_flags); |
| 709 | |||
| 710 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
| 711 | wake_up (&trace_wait); | ||
| 699 | } | 712 | } |
| 700 | 713 | ||
| 701 | #ifdef CONFIG_FTRACE | 714 | #ifdef CONFIG_FTRACE |
| @@ -1765,7 +1778,6 @@ static struct file_operations tracing_readme_fops = { | |||
| 1765 | .read = tracing_readme_read, | 1778 | .read = tracing_readme_read, |
| 1766 | }; | 1779 | }; |
| 1767 | 1780 | ||
| 1768 | |||
| 1769 | static ssize_t | 1781 | static ssize_t |
| 1770 | tracing_ctrl_read(struct file *filp, char __user *ubuf, | 1782 | tracing_ctrl_read(struct file *filp, char __user *ubuf, |
| 1771 | size_t cnt, loff_t *ppos) | 1783 | size_t cnt, loff_t *ppos) |
| @@ -1953,6 +1965,28 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) | |||
| 1953 | return 0; | 1965 | return 0; |
| 1954 | } | 1966 | } |
| 1955 | 1967 | ||
| 1968 | static unsigned int | ||
| 1969 | tracing_poll_pipe(struct file *filp, poll_table *poll_table) | ||
| 1970 | { | ||
| 1971 | struct trace_iterator *iter = filp->private_data; | ||
| 1972 | |||
| 1973 | if (trace_flags & TRACE_ITER_BLOCK) { | ||
| 1974 | /* | ||
| 1975 | * Always select as readable when in blocking mode | ||
| 1976 | */ | ||
| 1977 | return POLLIN | POLLRDNORM; | ||
| 1978 | } | ||
| 1979 | else { | ||
| 1980 | if (!trace_empty(iter)) | ||
| 1981 | return POLLIN | POLLRDNORM; | ||
| 1982 | poll_wait(filp, &trace_wait, poll_table); | ||
| 1983 | if (!trace_empty(iter)) | ||
| 1984 | return POLLIN | POLLRDNORM; | ||
| 1985 | |||
| 1986 | return 0; | ||
| 1987 | } | ||
| 1988 | } | ||
| 1989 | |||
| 1956 | /* | 1990 | /* |
| 1957 | * Consumer reader. | 1991 | * Consumer reader. |
| 1958 | */ | 1992 | */ |
| @@ -1991,6 +2025,8 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
| 1991 | start = 0; | 2025 | start = 0; |
| 1992 | 2026 | ||
| 1993 | while (trace_empty(iter)) { | 2027 | while (trace_empty(iter)) { |
| 2028 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
| 2029 | return -EWOULDBLOCK; | ||
| 1994 | /* | 2030 | /* |
| 1995 | * This is a make-shift waitqueue. The reason we don't use | 2031 | * This is a make-shift waitqueue. The reason we don't use |
| 1996 | * an actual wait queue is because: | 2032 | * an actual wait queue is because: |
| @@ -2134,6 +2170,7 @@ static struct file_operations set_tracer_fops = { | |||
| 2134 | 2170 | ||
| 2135 | static struct file_operations tracing_pipe_fops = { | 2171 | static struct file_operations tracing_pipe_fops = { |
| 2136 | .open = tracing_open_pipe, | 2172 | .open = tracing_open_pipe, |
| 2173 | .poll = tracing_poll_pipe, | ||
| 2137 | .read = tracing_read_pipe, | 2174 | .read = tracing_read_pipe, |
| 2138 | .release = tracing_release_pipe, | 2175 | .release = tracing_release_pipe, |
| 2139 | }; | 2176 | }; |
