diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-11-16 22:47:36 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-11-16 23:50:40 -0500 |
commit | 6f862cab27e52856628807d2eccc01d42838e31b (patch) | |
tree | 599757a731c67e6f7aeecbe1b35c47d0b539c158 | |
parent | dc664ee12621ad7d146ae9bcce92f17bad4c59e8 (diff) |
Add trace-seq
The trace-seq is a nice utility I wrote for Linux. It makes a page size
buffer that that can be written to with a printf,puts,putc interface.
This is perfect for having the same routine write the same type of
output, and used separately.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | trace-seq.c | 160 | ||||
-rw-r--r-- | trace-seq.h | 40 |
3 files changed, 202 insertions, 1 deletions
@@ -13,8 +13,9 @@ all: $(TARGETS) | |||
13 | parse-events.o:: parse-events.h | 13 | parse-events.o:: parse-events.h |
14 | trace-read.o:: parse-events.h | 14 | trace-read.o:: parse-events.h |
15 | trace-cmd.o:: parse-events.h | 15 | trace-cmd.o:: parse-events.h |
16 | trace-seq.o:: parse-events.h trace-seq.h | ||
16 | 17 | ||
17 | trace-cmd: trace-cmd.o trace-read.o parse-events.o | 18 | trace-cmd: trace-cmd.o trace-read.o parse-events.o trace-seq.o |
18 | $(CC) $^ -o $@ | 19 | $(CC) $^ -o $@ |
19 | 20 | ||
20 | clean: | 21 | clean: |
diff --git a/trace-seq.c b/trace-seq.c new file mode 100644 index 0000000..0201582 --- /dev/null +++ b/trace-seq.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * trace_seq.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
5 | * | ||
6 | */ | ||
7 | #include <stdio.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <string.h> | ||
10 | #include <stdarg.h> | ||
11 | |||
12 | #include "parse-events.h" | ||
13 | #include "trace-seq.h" | ||
14 | |||
15 | /** | ||
16 | * trace_seq_printf - sequence printing of trace information | ||
17 | * @s: trace sequence descriptor | ||
18 | * @fmt: printf format string | ||
19 | * | ||
20 | * It returns 0 if the trace oversizes the buffer's free | ||
21 | * space, 1 otherwise. | ||
22 | * | ||
23 | * The tracer may use either sequence operations or its own | ||
24 | * copy to user routines. To simplify formating of a trace | ||
25 | * trace_seq_printf is used to store strings into a special | ||
26 | * buffer (@s). Then the output may be either used by | ||
27 | * the sequencer or pulled into another buffer. | ||
28 | */ | ||
29 | int | ||
30 | trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | ||
31 | { | ||
32 | int len = (PAGE_SIZE - 1) - s->len; | ||
33 | va_list ap; | ||
34 | int ret; | ||
35 | |||
36 | if (!len) | ||
37 | return 0; | ||
38 | |||
39 | va_start(ap, fmt); | ||
40 | ret = vsnprintf(s->buffer + s->len, len, fmt, ap); | ||
41 | va_end(ap); | ||
42 | |||
43 | /* If we can't write it all, don't bother writing anything */ | ||
44 | if (ret >= len) | ||
45 | return 0; | ||
46 | |||
47 | s->len += ret; | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * trace_seq_vprintf - sequence printing of trace information | ||
54 | * @s: trace sequence descriptor | ||
55 | * @fmt: printf format string | ||
56 | * | ||
57 | * The tracer may use either sequence operations or its own | ||
58 | * copy to user routines. To simplify formating of a trace | ||
59 | * trace_seq_printf is used to store strings into a special | ||
60 | * buffer (@s). Then the output may be either used by | ||
61 | * the sequencer or pulled into another buffer. | ||
62 | */ | ||
63 | int | ||
64 | trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) | ||
65 | { | ||
66 | int len = (PAGE_SIZE - 1) - s->len; | ||
67 | int ret; | ||
68 | |||
69 | if (!len) | ||
70 | return 0; | ||
71 | |||
72 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); | ||
73 | |||
74 | /* If we can't write it all, don't bother writing anything */ | ||
75 | if (ret >= len) | ||
76 | return 0; | ||
77 | |||
78 | s->len += ret; | ||
79 | |||
80 | return len; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * trace_seq_puts - trace sequence printing of simple string | ||
85 | * @s: trace sequence descriptor | ||
86 | * @str: simple string to record | ||
87 | * | ||
88 | * The tracer may use either the sequence operations or its own | ||
89 | * copy to user routines. This function records a simple string | ||
90 | * into a special buffer (@s) for later retrieval by a sequencer | ||
91 | * or other mechanism. | ||
92 | */ | ||
93 | int trace_seq_puts(struct trace_seq *s, const char *str) | ||
94 | { | ||
95 | int len = strlen(str); | ||
96 | |||
97 | if (len > ((PAGE_SIZE - 1) - s->len)) | ||
98 | return 0; | ||
99 | |||
100 | memcpy(s->buffer + s->len, str, len); | ||
101 | s->len += len; | ||
102 | |||
103 | return len; | ||
104 | } | ||
105 | |||
106 | int trace_seq_putc(struct trace_seq *s, unsigned char c) | ||
107 | { | ||
108 | if (s->len >= (PAGE_SIZE - 1)) | ||
109 | return 0; | ||
110 | |||
111 | s->buffer[s->len++] = c; | ||
112 | |||
113 | return 1; | ||
114 | } | ||
115 | |||
116 | int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len) | ||
117 | { | ||
118 | if (len > ((PAGE_SIZE - 1) - s->len)) | ||
119 | return 0; | ||
120 | |||
121 | memcpy(s->buffer + s->len, mem, len); | ||
122 | s->len += len; | ||
123 | |||
124 | return len; | ||
125 | } | ||
126 | |||
127 | void *trace_seq_reserve(struct trace_seq *s, size_t len) | ||
128 | { | ||
129 | void *ret; | ||
130 | |||
131 | if (len > ((PAGE_SIZE - 1) - s->len)) | ||
132 | return NULL; | ||
133 | |||
134 | ret = s->buffer + s->len; | ||
135 | s->len += len; | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | int trace_seq_do_printf(struct trace_seq *s) | ||
141 | { | ||
142 | char *buf; | ||
143 | int ret; | ||
144 | |||
145 | if (!s->len) | ||
146 | return 0; | ||
147 | |||
148 | if (s->len < PAGE_SIZE) { | ||
149 | s->buffer[s->len] = 0; | ||
150 | return printf("%s", s->buffer); | ||
151 | } | ||
152 | |||
153 | buf = malloc_or_die(s->len + 1); | ||
154 | memcpy(buf, s->buffer, s->len); | ||
155 | buf[s->len] = 0; | ||
156 | ret = printf("%s", buf); | ||
157 | free(buf); | ||
158 | |||
159 | return ret; | ||
160 | } | ||
diff --git a/trace-seq.h b/trace-seq.h new file mode 100644 index 0000000..f6f0339 --- /dev/null +++ b/trace-seq.h | |||
@@ -0,0 +1,40 @@ | |||
1 | #ifndef _TRACE_SEQ_H | ||
2 | #define _TRACE_SEQ_H | ||
3 | |||
4 | #ifndef PAGE_SIZE | ||
5 | #define PAGE_SIZE 4096 | ||
6 | #endif | ||
7 | |||
8 | /* | ||
9 | * Trace sequences are used to allow a function to call several other functions | ||
10 | * to create a string of data to use (up to a max of PAGE_SIZE). | ||
11 | */ | ||
12 | |||
13 | struct trace_seq { | ||
14 | char buffer[PAGE_SIZE]; | ||
15 | unsigned int len; | ||
16 | unsigned int readpos; | ||
17 | }; | ||
18 | |||
19 | static inline void | ||
20 | trace_seq_init(struct trace_seq *s) | ||
21 | { | ||
22 | s->len = 0; | ||
23 | s->readpos = 0; | ||
24 | } | ||
25 | |||
26 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | ||
27 | __attribute__ ((format (printf, 2, 3))); | ||
28 | extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) | ||
29 | __attribute__ ((format (printf, 2, 0))); | ||
30 | |||
31 | extern int trace_seq_puts(struct trace_seq *s, const char *str); | ||
32 | extern int trace_seq_putc(struct trace_seq *s, unsigned char c); | ||
33 | extern int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len); | ||
34 | extern int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, | ||
35 | size_t len); | ||
36 | extern void *trace_seq_reserve(struct trace_seq *s, size_t len); | ||
37 | |||
38 | extern int trace_seq_do_printf(struct trace_seq *s); | ||
39 | |||
40 | #endif /* _TRACE_SEQ_H */ | ||