aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--trace-seq.c160
-rw-r--r--trace-seq.h40
3 files changed, 202 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index a8dbce1..0291dab 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,9 @@ all: $(TARGETS)
13parse-events.o:: parse-events.h 13parse-events.o:: parse-events.h
14trace-read.o:: parse-events.h 14trace-read.o:: parse-events.h
15trace-cmd.o:: parse-events.h 15trace-cmd.o:: parse-events.h
16trace-seq.o:: parse-events.h trace-seq.h
16 17
17trace-cmd: trace-cmd.o trace-read.o parse-events.o 18trace-cmd: trace-cmd.o trace-read.o parse-events.o trace-seq.o
18 $(CC) $^ -o $@ 19 $(CC) $^ -o $@
19 20
20clean: 21clean:
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 */
29int
30trace_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 */
63int
64trace_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 */
93int 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
106int 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
116int 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
127void *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
140int 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
13struct trace_seq {
14 char buffer[PAGE_SIZE];
15 unsigned int len;
16 unsigned int readpos;
17};
18
19static inline void
20trace_seq_init(struct trace_seq *s)
21{
22 s->len = 0;
23 s->readpos = 0;
24}
25
26extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
27 __attribute__ ((format (printf, 2, 3)));
28extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
29 __attribute__ ((format (printf, 2, 0)));
30
31extern int trace_seq_puts(struct trace_seq *s, const char *str);
32extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
33extern int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len);
34extern int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
35 size_t len);
36extern void *trace_seq_reserve(struct trace_seq *s, size_t len);
37
38extern int trace_seq_do_printf(struct trace_seq *s);
39
40#endif /* _TRACE_SEQ_H */