diff options
author | Masami Hiramatsu <mhiramat@kernel.org> | 2016-05-10 01:46:58 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-05-10 10:27:58 -0400 |
commit | 5cea57f30a12443c05e0c5273f35d2fcef00d30a (patch) | |
tree | ba665d63c69cc0ea73c0d6e8d622a4872c3a2b6e | |
parent | 9c7b37cd63d0d910c531233209286f169993cbd9 (diff) |
perf tools: Rewrite strbuf not to die()
Rewrite strbuf implementation not to use die() nor xrealloc(). Instead
of die(), now most of the API returns error code or 0 if succeeded.
Suggested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20160510054658.6158.24080.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/strbuf.c | 93 | ||||
-rw-r--r-- | tools/perf/util/strbuf.h | 25 |
2 files changed, 82 insertions, 36 deletions
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 8fb73295ec34..f95f682aa2b2 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include "debug.h" | ||
1 | #include "cache.h" | 2 | #include "cache.h" |
2 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
3 | 4 | ||
@@ -17,12 +18,13 @@ int prefixcmp(const char *str, const char *prefix) | |||
17 | */ | 18 | */ |
18 | char strbuf_slopbuf[1]; | 19 | char strbuf_slopbuf[1]; |
19 | 20 | ||
20 | void strbuf_init(struct strbuf *sb, ssize_t hint) | 21 | int strbuf_init(struct strbuf *sb, ssize_t hint) |
21 | { | 22 | { |
22 | sb->alloc = sb->len = 0; | 23 | sb->alloc = sb->len = 0; |
23 | sb->buf = strbuf_slopbuf; | 24 | sb->buf = strbuf_slopbuf; |
24 | if (hint) | 25 | if (hint) |
25 | strbuf_grow(sb, hint); | 26 | return strbuf_grow(sb, hint); |
27 | return 0; | ||
26 | } | 28 | } |
27 | 29 | ||
28 | void strbuf_release(struct strbuf *sb) | 30 | void strbuf_release(struct strbuf *sb) |
@@ -42,67 +44,104 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz) | |||
42 | return res; | 44 | return res; |
43 | } | 45 | } |
44 | 46 | ||
45 | void strbuf_grow(struct strbuf *sb, size_t extra) | 47 | int strbuf_grow(struct strbuf *sb, size_t extra) |
46 | { | 48 | { |
47 | if (sb->len + extra + 1 <= sb->len) | 49 | char *buf; |
48 | die("you want to use way too much memory"); | 50 | size_t nr = sb->len + extra + 1; |
49 | if (!sb->alloc) | 51 | |
50 | sb->buf = NULL; | 52 | if (nr < sb->alloc) |
51 | ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); | 53 | return 0; |
54 | |||
55 | if (nr <= sb->len) | ||
56 | return -E2BIG; | ||
57 | |||
58 | if (alloc_nr(sb->alloc) > nr) | ||
59 | nr = alloc_nr(sb->alloc); | ||
60 | |||
61 | /* | ||
62 | * Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is | ||
63 | * a static variable. Thus we have to avoid passing it to realloc. | ||
64 | */ | ||
65 | buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf)); | ||
66 | if (!buf) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | sb->buf = buf; | ||
70 | sb->alloc = nr; | ||
71 | return 0; | ||
52 | } | 72 | } |
53 | 73 | ||
54 | void strbuf_addch(struct strbuf *sb, int c) | 74 | int strbuf_addch(struct strbuf *sb, int c) |
55 | { | 75 | { |
56 | strbuf_grow(sb, 1); | 76 | int ret = strbuf_grow(sb, 1); |
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
57 | sb->buf[sb->len++] = c; | 80 | sb->buf[sb->len++] = c; |
58 | sb->buf[sb->len] = '\0'; | 81 | sb->buf[sb->len] = '\0'; |
82 | return 0; | ||
59 | } | 83 | } |
60 | 84 | ||
61 | void strbuf_add(struct strbuf *sb, const void *data, size_t len) | 85 | int strbuf_add(struct strbuf *sb, const void *data, size_t len) |
62 | { | 86 | { |
63 | strbuf_grow(sb, len); | 87 | int ret = strbuf_grow(sb, len); |
88 | if (ret) | ||
89 | return ret; | ||
90 | |||
64 | memcpy(sb->buf + sb->len, data, len); | 91 | memcpy(sb->buf + sb->len, data, len); |
65 | strbuf_setlen(sb, sb->len + len); | 92 | return strbuf_setlen(sb, sb->len + len); |
66 | } | 93 | } |
67 | 94 | ||
68 | static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) | 95 | static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) |
69 | { | 96 | { |
70 | int len; | 97 | int len, ret; |
71 | va_list ap_saved; | 98 | va_list ap_saved; |
72 | 99 | ||
73 | if (!strbuf_avail(sb)) | 100 | if (!strbuf_avail(sb)) { |
74 | strbuf_grow(sb, 64); | 101 | ret = strbuf_grow(sb, 64); |
102 | if (ret) | ||
103 | return ret; | ||
104 | } | ||
75 | 105 | ||
76 | va_copy(ap_saved, ap); | 106 | va_copy(ap_saved, ap); |
77 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); | 107 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); |
78 | if (len < 0) | 108 | if (len < 0) |
79 | die("your vsnprintf is broken"); | 109 | return len; |
80 | if (len > strbuf_avail(sb)) { | 110 | if (len > strbuf_avail(sb)) { |
81 | strbuf_grow(sb, len); | 111 | ret = strbuf_grow(sb, len); |
112 | if (ret) | ||
113 | return ret; | ||
82 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); | 114 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); |
83 | va_end(ap_saved); | 115 | va_end(ap_saved); |
84 | if (len > strbuf_avail(sb)) { | 116 | if (len > strbuf_avail(sb)) { |
85 | die("this should not happen, your vsnprintf is broken"); | 117 | pr_debug("this should not happen, your vsnprintf is broken"); |
118 | return -EINVAL; | ||
86 | } | 119 | } |
87 | } | 120 | } |
88 | strbuf_setlen(sb, sb->len + len); | 121 | return strbuf_setlen(sb, sb->len + len); |
89 | } | 122 | } |
90 | 123 | ||
91 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | 124 | int strbuf_addf(struct strbuf *sb, const char *fmt, ...) |
92 | { | 125 | { |
93 | va_list ap; | 126 | va_list ap; |
127 | int ret; | ||
94 | 128 | ||
95 | va_start(ap, fmt); | 129 | va_start(ap, fmt); |
96 | strbuf_addv(sb, fmt, ap); | 130 | ret = strbuf_addv(sb, fmt, ap); |
97 | va_end(ap); | 131 | va_end(ap); |
132 | return ret; | ||
98 | } | 133 | } |
99 | 134 | ||
100 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) | 135 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) |
101 | { | 136 | { |
102 | size_t oldlen = sb->len; | 137 | size_t oldlen = sb->len; |
103 | size_t oldalloc = sb->alloc; | 138 | size_t oldalloc = sb->alloc; |
139 | int ret; | ||
140 | |||
141 | ret = strbuf_grow(sb, hint ? hint : 8192); | ||
142 | if (ret) | ||
143 | return ret; | ||
104 | 144 | ||
105 | strbuf_grow(sb, hint ? hint : 8192); | ||
106 | for (;;) { | 145 | for (;;) { |
107 | ssize_t cnt; | 146 | ssize_t cnt; |
108 | 147 | ||
@@ -112,12 +151,14 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) | |||
112 | strbuf_release(sb); | 151 | strbuf_release(sb); |
113 | else | 152 | else |
114 | strbuf_setlen(sb, oldlen); | 153 | strbuf_setlen(sb, oldlen); |
115 | return -1; | 154 | return cnt; |
116 | } | 155 | } |
117 | if (!cnt) | 156 | if (!cnt) |
118 | break; | 157 | break; |
119 | sb->len += cnt; | 158 | sb->len += cnt; |
120 | strbuf_grow(sb, 8192); | 159 | ret = strbuf_grow(sb, 8192); |
160 | if (ret) | ||
161 | return ret; | ||
121 | } | 162 | } |
122 | 163 | ||
123 | sb->buf[sb->len] = '\0'; | 164 | sb->buf[sb->len] = '\0'; |
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index ab9be0fbbd40..54b409297d4a 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h | |||
@@ -51,7 +51,7 @@ struct strbuf { | |||
51 | #define STRBUF_INIT { 0, 0, strbuf_slopbuf } | 51 | #define STRBUF_INIT { 0, 0, strbuf_slopbuf } |
52 | 52 | ||
53 | /*----- strbuf life cycle -----*/ | 53 | /*----- strbuf life cycle -----*/ |
54 | void strbuf_init(struct strbuf *buf, ssize_t hint); | 54 | int strbuf_init(struct strbuf *buf, ssize_t hint); |
55 | void strbuf_release(struct strbuf *buf); | 55 | void strbuf_release(struct strbuf *buf); |
56 | char *strbuf_detach(struct strbuf *buf, size_t *); | 56 | char *strbuf_detach(struct strbuf *buf, size_t *); |
57 | 57 | ||
@@ -60,26 +60,31 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) { | |||
60 | return sb->alloc ? sb->alloc - sb->len - 1 : 0; | 60 | return sb->alloc ? sb->alloc - sb->len - 1 : 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | void strbuf_grow(struct strbuf *buf, size_t); | 63 | int strbuf_grow(struct strbuf *buf, size_t); |
64 | 64 | ||
65 | static inline void strbuf_setlen(struct strbuf *sb, size_t len) { | 65 | static inline int strbuf_setlen(struct strbuf *sb, size_t len) { |
66 | if (!sb->alloc) | 66 | int ret; |
67 | strbuf_grow(sb, 0); | 67 | if (!sb->alloc) { |
68 | ret = strbuf_grow(sb, 0); | ||
69 | if (ret) | ||
70 | return ret; | ||
71 | } | ||
68 | assert(len < sb->alloc); | 72 | assert(len < sb->alloc); |
69 | sb->len = len; | 73 | sb->len = len; |
70 | sb->buf[len] = '\0'; | 74 | sb->buf[len] = '\0'; |
75 | return 0; | ||
71 | } | 76 | } |
72 | 77 | ||
73 | /*----- add data in your buffer -----*/ | 78 | /*----- add data in your buffer -----*/ |
74 | void strbuf_addch(struct strbuf *sb, int c); | 79 | int strbuf_addch(struct strbuf *sb, int c); |
75 | 80 | ||
76 | void strbuf_add(struct strbuf *buf, const void *, size_t); | 81 | int strbuf_add(struct strbuf *buf, const void *, size_t); |
77 | static inline void strbuf_addstr(struct strbuf *sb, const char *s) { | 82 | static inline int strbuf_addstr(struct strbuf *sb, const char *s) { |
78 | strbuf_add(sb, s, strlen(s)); | 83 | return strbuf_add(sb, s, strlen(s)); |
79 | } | 84 | } |
80 | 85 | ||
81 | __attribute__((format(printf,2,3))) | 86 | __attribute__((format(printf,2,3))) |
82 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...); | 87 | int strbuf_addf(struct strbuf *sb, const char *fmt, ...); |
83 | 88 | ||
84 | /* XXX: if read fails, any partial read is undone */ | 89 | /* XXX: if read fails, any partial read is undone */ |
85 | ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); | 90 | ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); |