aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-09-03 10:31:54 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-09-03 10:31:54 -0400
commite892161f731e958980fa977e2d7980f3cf0819ce (patch)
treed908acca1971f2c4b8bf9dea0f832696401e0f07
parentb3d6a163f12ef3babab017914a04e3f0505c5d81 (diff)
parse-events: Make trace_seq dynamically expand its buffers
The trace_seq code that is used to copy data into a buffer to later be able to print was originally taken from the Linux kernel. But the constraints on the kernel are different than what they are in userspace. Since the kernel uses the trace_seq in critical paths, it can not allocate memory during use, so it used a static page buffer. But in userspace, we do not have this constraint, and are allowed to realloc the buffer when needed. There's no reason to fill the buffer when we hit the buffer size, we can simply allocate more memory. The downside to this is that we must call a destructor on the trace_seq structure. All trace_seq's must be initialized with trace_seq_init(), so this patch matched all trace_seq_init()'s with the new function trace_seq_destroy(). Suggested-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.c7
-rw-r--r--parse-events.h17
-rw-r--r--trace-cmd.c1
-rw-r--r--trace-graph.c8
-rw-r--r--trace-read.c5
-rw-r--r--trace-seq.c104
-rw-r--r--trace-view-store.c2
7 files changed, 103 insertions, 41 deletions
diff --git a/parse-events.c b/parse-events.c
index e5fe89a..1a3fd8d 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -2887,7 +2887,9 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
2887 case PRINT_FUNC: { 2887 case PRINT_FUNC: {
2888 struct trace_seq s; 2888 struct trace_seq s;
2889 trace_seq_init(&s); 2889 trace_seq_init(&s);
2890 return process_defined_func(&s, data, size, event, arg); 2890 val = process_defined_func(&s, data, size, event, arg);
2891 trace_seq_destroy(&s);
2892 return val;
2891 } 2893 }
2892 case PRINT_OP: 2894 case PRINT_OP:
2893 if (strcmp(arg->op.op, "[") == 0) { 2895 if (strcmp(arg->op.op, "[") == 0) {
@@ -3220,6 +3222,7 @@ process_defined_func(struct trace_seq *s, void *data, int size,
3220 string->next = strings; 3222 string->next = strings;
3221 string->str = strdup(str.buffer); 3223 string->str = strdup(str.buffer);
3222 strings = string; 3224 strings = string;
3225 trace_seq_destroy(&str);
3223 break; 3226 break;
3224 default: 3227 default:
3225 /* 3228 /*
@@ -4097,6 +4100,7 @@ static void print_args(struct print_arg *args)
4097 trace_seq_init(&s); 4100 trace_seq_init(&s);
4098 print_fields(&s, args->flags.flags); 4101 print_fields(&s, args->flags.flags);
4099 trace_seq_do_printf(&s); 4102 trace_seq_do_printf(&s);
4103 trace_seq_destroy(&s);
4100 printf(")"); 4104 printf(")");
4101 break; 4105 break;
4102 case PRINT_SYMBOL: 4106 case PRINT_SYMBOL:
@@ -4106,6 +4110,7 @@ static void print_args(struct print_arg *args)
4106 trace_seq_init(&s); 4110 trace_seq_init(&s);
4107 print_fields(&s, args->symbol.symbols); 4111 print_fields(&s, args->symbol.symbols);
4108 trace_seq_do_printf(&s); 4112 trace_seq_do_printf(&s);
4113 trace_seq_destroy(&s);
4109 printf(")"); 4114 printf(")");
4110 break; 4115 break;
4111 case PRINT_STRING: 4116 case PRINT_STRING:
diff --git a/parse-events.h b/parse-events.h
index 98eb76c..efbf8d4 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -31,8 +31,8 @@
31/* ----------------------- trace_seq ----------------------- */ 31/* ----------------------- trace_seq ----------------------- */
32 32
33 33
34#ifndef TRACE_SEQ_SIZE 34#ifndef TRACE_SEQ_BUF_SIZE
35#define TRACE_SEQ_SIZE 4096 35#define TRACE_SEQ_BUF_SIZE 4096
36#endif 36#endif
37 37
38struct record { 38struct record {
@@ -54,19 +54,14 @@ struct record {
54 */ 54 */
55 55
56struct trace_seq { 56struct trace_seq {
57 char buffer[TRACE_SEQ_SIZE]; 57 char *buffer;
58 unsigned int buffer_size;
58 unsigned int len; 59 unsigned int len;
59 unsigned int readpos; 60 unsigned int readpos;
60 int full;
61}; 61};
62 62
63static inline void 63void trace_seq_init(struct trace_seq *s);
64trace_seq_init(struct trace_seq *s) 64void trace_seq_destroy(struct trace_seq *s);
65{
66 s->len = 0;
67 s->readpos = 0;
68 s->full = 0;
69}
70 65
71extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 66extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
72 __attribute__ ((format (printf, 2, 3))); 67 __attribute__ ((format (printf, 2, 3)));
diff --git a/trace-cmd.c b/trace-cmd.c
index b4eb0fe..6cfdfdc 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -1713,6 +1713,7 @@ int main (int argc, char **argv)
1713 trace_seq_printf(&s, "CPU: %d\n", cpu); 1713 trace_seq_printf(&s, "CPU: %d\n", cpu);
1714 tracecmd_stat_cpu(&s, cpu); 1714 tracecmd_stat_cpu(&s, cpu);
1715 trace_seq_do_printf(&s); 1715 trace_seq_do_printf(&s);
1716 trace_seq_destroy(&s);
1716 printf("\n"); 1717 printf("\n");
1717 } 1718 }
1718 1719
diff --git a/trace-graph.c b/trace-graph.c
index a53ab84..44c1273 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -326,6 +326,7 @@ static void update_label_time(GtkWidget *label, gint64 time)
326 trace_seq_printf(&s, "%s%lu.%06lu", min, sec, usec); 326 trace_seq_printf(&s, "%s%lu.%06lu", min, sec, usec);
327 327
328 gtk_label_set_text(GTK_LABEL(label), s.buffer); 328 gtk_label_set_text(GTK_LABEL(label), s.buffer);
329 trace_seq_destroy(&s);
329} 330}
330 331
331static void update_cursor(struct graph_info *ginfo) 332static void update_cursor(struct graph_info *ginfo)
@@ -1225,6 +1226,7 @@ static void draw_plot_info(struct graph_info *ginfo, struct graph_plot *plot,
1225 1226
1226 if (!trace_graph_plot_display_info(ginfo, plot, &s, time)) { 1227 if (!trace_graph_plot_display_info(ginfo, plot, &s, time)) {
1227 /* Just display the current time */ 1228 /* Just display the current time */
1229 trace_seq_destroy(&s);
1228 trace_seq_init(&s); 1230 trace_seq_init(&s);
1229 trace_seq_printf(&s, "%lu.%06lu", sec, usec); 1231 trace_seq_printf(&s, "%lu.%06lu", sec, usec);
1230 } 1232 }
@@ -1232,6 +1234,7 @@ static void draw_plot_info(struct graph_info *ginfo, struct graph_plot *plot,
1232 trace_seq_putc(&s, 0); 1234 trace_seq_putc(&s, 0);
1233 1235
1234 draw_info_box(ginfo, s.buffer, x, y); 1236 draw_info_box(ginfo, s.buffer, x, y);
1237 trace_seq_destroy(&s);
1235} 1238}
1236 1239
1237static void draw_latency(struct graph_info *ginfo, gint x, gint y) 1240static void draw_latency(struct graph_info *ginfo, gint x, gint y)
@@ -1261,6 +1264,7 @@ static void draw_latency(struct graph_info *ginfo, gint x, gint y)
1261 trace_seq_printf(&s, "Diff: %s%ld.%06lu secs", neg ? "-":"", sec, usec); 1264 trace_seq_printf(&s, "Diff: %s%ld.%06lu secs", neg ? "-":"", sec, usec);
1262 1265
1263 draw_info_box(ginfo, s.buffer, x, y); 1266 draw_info_box(ginfo, s.buffer, x, y);
1267 trace_seq_destroy(&s);
1264} 1268}
1265 1269
1266static gboolean 1270static gboolean
@@ -1662,6 +1666,7 @@ static gint draw_event_label(struct graph_info *ginfo, gint i,
1662 */ 1666 */
1663 ret = trace_graph_plot_display_last_event(ginfo, plot, &s, 1667 ret = trace_graph_plot_display_last_event(ginfo, plot, &s,
1664 convert_x_to_time(ginfo, p2-1)); 1668 convert_x_to_time(ginfo, p2-1));
1669 trace_seq_destroy(&s);
1665 if (!ret) 1670 if (!ret)
1666 return p2; 1671 return p2;
1667 1672
@@ -1935,6 +1940,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
1935 gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, 1940 gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc,
1936 1, height+10, layout); 1941 1, height+10, layout);
1937 g_object_unref(layout); 1942 g_object_unref(layout);
1943 trace_seq_destroy(&s);
1938 1944
1939 1945
1940 /* --- draw ending time --- */ 1946 /* --- draw ending time --- */
@@ -1948,6 +1954,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
1948 gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc, 1954 gdk_draw_layout(ginfo->curr_pixmap, ginfo->draw->style->black_gc,
1949 width - (w + 2), height+10, layout); 1955 width - (w + 2), height+10, layout);
1950 g_object_unref(layout); 1956 g_object_unref(layout);
1957 trace_seq_destroy(&s);
1951 1958
1952 1959
1953 /* --- draw time at intervals --- */ 1960 /* --- draw time at intervals --- */
@@ -1960,6 +1967,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
1960 convert_nano(time, &sec, &usec); 1967 convert_nano(time, &sec, &usec);
1961 trace_seq_init(&s); 1968 trace_seq_init(&s);
1962 trace_seq_printf(&s, "%lu.%06lu", sec, usec); 1969 trace_seq_printf(&s, "%lu.%06lu", sec, usec);
1970 trace_seq_destroy(&s);
1963 1971
1964 gdk_draw_line(ginfo->curr_pixmap, ginfo->draw->style->black_gc, 1972 gdk_draw_line(ginfo->curr_pixmap, ginfo->draw->style->black_gc,
1965 mid, height, mid, height + 5); 1973 mid, height, mid, height + 5);
diff --git a/trace-read.c b/trace-read.c
index f09dcf8..f8455a3 100644
--- a/trace-read.c
+++ b/trace-read.c
@@ -108,6 +108,7 @@ static void show_test(struct tracecmd_input *handle)
108 trace_seq_init(&s); 108 trace_seq_init(&s);
109 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); 109 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts);
110 trace_seq_do_printf(&s); 110 trace_seq_do_printf(&s);
111 trace_seq_destroy(&s);
111 printf("\n"); 112 printf("\n");
112 113
113 free_record(record); 114 free_record(record);
@@ -154,6 +155,7 @@ static void show_test(struct tracecmd_input *handle)
154 trace_seq_init(&s); 155 trace_seq_init(&s);
155 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); 156 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts);
156 trace_seq_do_printf(&s); 157 trace_seq_do_printf(&s);
158 trace_seq_destroy(&s);
157 printf("\n"); 159 printf("\n");
158 160
159 free_record(record); 161 free_record(record);
@@ -194,6 +196,7 @@ static void show_test(struct tracecmd_input *handle)
194 trace_seq_init(&s); 196 trace_seq_init(&s);
195 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); 197 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts);
196 trace_seq_do_printf(&s); 198 trace_seq_do_printf(&s);
199 trace_seq_destroy(&s);
197 printf("\n"); 200 printf("\n");
198 201
199 free_record(record); 202 free_record(record);
@@ -209,6 +212,7 @@ static void show_test(struct tracecmd_input *handle)
209 trace_seq_init(&s); 212 trace_seq_init(&s);
210 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); 213 pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts);
211 trace_seq_do_printf(&s); 214 trace_seq_do_printf(&s);
215 trace_seq_destroy(&s);
212 printf("\n"); 216 printf("\n");
213 217
214 free_record(record); 218 free_record(record);
@@ -473,6 +477,7 @@ static void show_data(struct tracecmd_input *handle,
473 record->cpu); 477 record->cpu);
474 pevent_print_event(pevent, &s, record); 478 pevent_print_event(pevent, &s, record);
475 trace_seq_do_printf(&s); 479 trace_seq_do_printf(&s);
480 trace_seq_destroy(&s);
476 481
477 process_wakeup(pevent, record); 482 process_wakeup(pevent, record);
478 483
diff --git a/trace-seq.c b/trace-seq.c
index d84a5bd..da5eae9 100644
--- a/trace-seq.c
+++ b/trace-seq.c
@@ -25,6 +25,52 @@
25 25
26#include "parse-events.h" 26#include "parse-events.h"
27 27
28/*
29 * The TRACE_SEQ_POISON is to catch the use of using
30 * a trace_seq structure after it was destroyed.
31 */
32#define TRACE_SEQ_POISON ((void *)0xdeadbeef)
33#define TRACE_SEQ_CHECK(s) \
34do { \
35 if ((s)->buffer == TRACE_SEQ_POISON) \
36 die("Usage of trace_seq after it was destroyed"); \
37} while (0)
38
39/**
40 * trace_seq_init - initialize the trace_seq structure
41 * @s: a pointer to the trace_seq structure to initialize
42 */
43void trace_seq_init(struct trace_seq *s)
44{
45 s->len = 0;
46 s->readpos = 0;
47 s->buffer_size = TRACE_SEQ_BUF_SIZE;
48 s->buffer = malloc_or_die(s->buffer_size);
49}
50
51/**
52 * trace_seq_destroy - free up memory of a trace_seq
53 * @s: a pointer to the trace_seq to free the buffer
54 *
55 * Only frees the buffer, not the trace_seq struct itself.
56 */
57void trace_seq_destroy(struct trace_seq *s)
58{
59 if (!s)
60 return;
61 TRACE_SEQ_CHECK(s);
62 free(s->buffer);
63 s->buffer = TRACE_SEQ_POISON;
64}
65
66static void expand_buffer(struct trace_seq *s)
67{
68 s->buffer_size += TRACE_SEQ_BUF_SIZE;
69 s->buffer = realloc(s->buffer, s->buffer_size);
70 if (!s->buffer)
71 die("Can't allocate trace_seq buffer memory");
72}
73
28/** 74/**
29 * trace_seq_printf - sequence printing of trace information 75 * trace_seq_printf - sequence printing of trace information
30 * @s: trace sequence descriptor 76 * @s: trace sequence descriptor
@@ -42,21 +88,22 @@
42int 88int
43trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 89trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
44{ 90{
45 int len = (TRACE_SEQ_SIZE - 1) - s->len;
46 va_list ap; 91 va_list ap;
92 int len;
47 int ret; 93 int ret;
48 94
49 if (s->full || !len) 95 TRACE_SEQ_CHECK(s);
50 return 0; 96
97 try_again:
98 len = (s->buffer_size - 1) - s->len;
51 99
52 va_start(ap, fmt); 100 va_start(ap, fmt);
53 ret = vsnprintf(s->buffer + s->len, len, fmt, ap); 101 ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
54 va_end(ap); 102 va_end(ap);
55 103
56 /* If we can't write it all, don't bother writing anything */
57 if (ret >= len) { 104 if (ret >= len) {
58 s->full = 1; 105 expand_buffer(s);
59 return 0; 106 goto try_again;
60 } 107 }
61 108
62 s->len += ret; 109 s->len += ret;
@@ -78,18 +125,19 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
78int 125int
79trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 126trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
80{ 127{
81 int len = (TRACE_SEQ_SIZE - 1) - s->len; 128 int len;
82 int ret; 129 int ret;
83 130
84 if (s->full || !len) 131 TRACE_SEQ_CHECK(s);
85 return 0; 132
133 try_again:
134 len = (s->buffer_size - 1) - s->len;
86 135
87 ret = vsnprintf(s->buffer + s->len, len, fmt, args); 136 ret = vsnprintf(s->buffer + s->len, len, fmt, args);
88 137
89 /* If we can't write it all, don't bother writing anything */
90 if (ret >= len) { 138 if (ret >= len) {
91 s->full = 1; 139 expand_buffer(s);
92 return 0; 140 goto try_again;
93 } 141 }
94 142
95 s->len += ret; 143 s->len += ret;
@@ -109,15 +157,14 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
109 */ 157 */
110int trace_seq_puts(struct trace_seq *s, const char *str) 158int trace_seq_puts(struct trace_seq *s, const char *str)
111{ 159{
112 int len = strlen(str); 160 int len;
113 161
114 if (s->full) 162 TRACE_SEQ_CHECK(s);
115 return 0;
116 163
117 if (len > ((TRACE_SEQ_SIZE - 1) - s->len)) { 164 len = strlen(str);
118 s->full = 1; 165
119 return 0; 166 while (len > ((s->buffer_size - 1) - s->len))
120 } 167 expand_buffer(s);
121 168
122 memcpy(s->buffer + s->len, str, len); 169 memcpy(s->buffer + s->len, str, len);
123 s->len += len; 170 s->len += len;
@@ -127,13 +174,10 @@ int trace_seq_puts(struct trace_seq *s, const char *str)
127 174
128int trace_seq_putc(struct trace_seq *s, unsigned char c) 175int trace_seq_putc(struct trace_seq *s, unsigned char c)
129{ 176{
130 if (s->full) 177 TRACE_SEQ_CHECK(s);
131 return 0;
132 178
133 if (s->len >= (TRACE_SEQ_SIZE - 1)) { 179 while (s->len >= (s->buffer_size - 1))
134 s->full = 1; 180 expand_buffer(s);
135 return 0;
136 }
137 181
138 s->buffer[s->len++] = c; 182 s->buffer[s->len++] = c;
139 183
@@ -142,12 +186,14 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c)
142 186
143void trace_seq_terminate(struct trace_seq *s) 187void trace_seq_terminate(struct trace_seq *s)
144{ 188{
145 if (!s->full) 189 TRACE_SEQ_CHECK(s);
146 s->buffer[s->len] = 0; 190
191 /* There's always one character left on the buffer */
192 s->buffer[s->len] = 0;
147} 193}
148 194
149int trace_seq_do_printf(struct trace_seq *s) 195int trace_seq_do_printf(struct trace_seq *s)
150{ 196{
151 return printf("%.*s%s", s->len, s->buffer, 197 TRACE_SEQ_CHECK(s);
152 s->full ? "[truncated]" : ""); 198 return printf("%.*s", s->len, s->buffer);
153} 199}
diff --git a/trace-view-store.c b/trace-view-store.c
index 6f70ca5..0834df7 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -500,6 +500,7 @@ trace_view_store_get_value (GtkTreeModel *tree_model,
500 trace_seq_init(&s); 500 trace_seq_init(&s);
501 pevent_data_lat_fmt(pevent, &s, data); 501 pevent_data_lat_fmt(pevent, &s, data);
502 g_value_set_string(value, s.buffer); 502 g_value_set_string(value, s.buffer);
503 trace_seq_destroy(&s);
503 break; 504 break;
504 505
505 case TRACE_VIEW_STORE_COL_EVENT: 506 case TRACE_VIEW_STORE_COL_EVENT:
@@ -515,6 +516,7 @@ trace_view_store_get_value (GtkTreeModel *tree_model,
515 trace_seq_init(&s); 516 trace_seq_init(&s);
516 pevent_event_info(&s, event, data); 517 pevent_event_info(&s, event, data);
517 g_value_set_string(value, s.buffer); 518 g_value_set_string(value, s.buffer);
519 trace_seq_destroy(&s);
518 break; 520 break;
519 } 521 }
520 free_record(data); 522 free_record(data);