Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 1/5] tools lib traceevent: Add WARN and WARN_ONCE macros

4 views
Skip to first unread message

Namhyung Kim

unread,
Jan 6, 2014, 10:10:01 PM1/6/14
to
They're copied from the perf code and will be used to print error
message during trace_seq_printf() and friends.

Suggested-by: Jiri Olsa <jo...@redhat.com>
Signed-off-by: Namhyung Kim <namh...@kernel.org>
---
tools/lib/traceevent/event-utils.h | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h
index e76c9acb92cd..5dc0aec5ab50 100644
--- a/tools/lib/traceevent/event-utils.h
+++ b/tools/lib/traceevent/event-utils.h
@@ -38,6 +38,28 @@ void __vdie(const char *fmt, ...);
void __vwarning(const char *fmt, ...);
void __vpr_stat(const char *fmt, ...);

+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0)
+
+#define WARN(condition, format...) ({ \
+ int __ret_warn_on = !!(condition); \
+ if (unlikely(__ret_warn_on)) \
+ __WARN_printf(format); \
+ unlikely(__ret_warn_on); \
+})
+
+#define WARN_ONCE(condition, format...) ({ \
+ static int __warned; \
+ int __ret_warn_once = !!(condition); \
+ \
+ if (unlikely(__ret_warn_once)) \
+ if (WARN(!__warned, format)) \
+ __warned = 1; \
+ unlikely(__ret_warn_once); \
+})
+
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
--
1.7.11.7

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Namhyung Kim

unread,
Jan 6, 2014, 10:10:01 PM1/6/14
to
Use plain malloc() and check its return value.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
---
tools/lib/traceevent/trace-seq.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index b139d55a6bf9..e858bfd3b104 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -46,8 +46,11 @@ void trace_seq_init(struct trace_seq *s)
s->len = 0;
s->readpos = 0;
s->buffer_size = TRACE_SEQ_BUF_SIZE;
- s->buffer = malloc_or_die(s->buffer_size);
- s->state = TRACE_SEQ__GOOD;
+ s->buffer = malloc(s->buffer_size);
+ if (s->buffer != NULL)
+ s->state = TRACE_SEQ__GOOD;
+ else
+ s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
}

/**

Namhyung Kim

unread,
Jan 6, 2014, 10:10:01 PM1/6/14
to
If realloc() fails, it'll leak the buffer. Also increate buffer size
only if the allocation succeeded.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
---
tools/lib/traceevent/trace-seq.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index 1747aa50ecb0..b139d55a6bf9 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -80,10 +80,16 @@ void trace_seq_destroy(struct trace_seq *s)

static void expand_buffer(struct trace_seq *s)
{
- s->buffer_size += TRACE_SEQ_BUF_SIZE;
- s->buffer = realloc(s->buffer, s->buffer_size);
- if (!s->buffer)
+ char *buf;
+
+ buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE);
+ if (!buf) {
s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
+ return;
+ }
+
+ s->buffer = buf;
+ s->buffer_size += TRACE_SEQ_BUF_SIZE;

Namhyung Kim

unread,
Jan 6, 2014, 10:10:01 PM1/6/14
to
The trace_seq->state is for tracking errors during the use of
trace_seq APIs and getting rid of die() in it.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
---
tools/lib/traceevent/event-parse.h | 7 +++++++
tools/lib/traceevent/trace-seq.c | 42 ++++++++++++++++++++++++++++++++++----
2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index cf5db9013f2c..3c890cb28db7 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -58,6 +58,12 @@ struct pevent_record {
#endif
};

+enum trace_seq_fail {
+ TRACE_SEQ__GOOD,
+ TRACE_SEQ__BUFFER_POISONED,
+ TRACE_SEQ__MEM_ALLOC_FAILED,
+};
+
/*
* Trace sequences are used to allow a function to call several other functions
* to create a string of data to use (up to a max of PAGE_SIZE).
@@ -68,6 +74,7 @@ struct trace_seq {
unsigned int buffer_size;
unsigned int len;
unsigned int readpos;
+ enum trace_seq_fail state;
};

void trace_seq_init(struct trace_seq *s);
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index d7f2e68bc5b9..1747aa50ecb0 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -32,8 +32,9 @@
#define TRACE_SEQ_POISON ((void *)0xdeadbeef)
#define TRACE_SEQ_CHECK(s) \
do { \
- if ((s)->buffer == TRACE_SEQ_POISON) \
- die("Usage of trace_seq after it was destroyed"); \
+ if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON, \
+ "Usage of trace_seq after it was destroyed")) \
+ (s)->state = TRACE_SEQ__BUFFER_POISONED; \
} while (0)

/**
@@ -46,6 +47,7 @@ void trace_seq_init(struct trace_seq *s)
s->readpos = 0;
s->buffer_size = TRACE_SEQ_BUF_SIZE;
s->buffer = malloc_or_die(s->buffer_size);
+ s->state = TRACE_SEQ__GOOD;
}

/**
@@ -81,7 +83,7 @@ static void expand_buffer(struct trace_seq *s)
s->buffer_size += TRACE_SEQ_BUF_SIZE;
s->buffer = realloc(s->buffer, s->buffer_size);
if (!s->buffer)
- die("Can't allocate trace_seq buffer memory");
+ s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
}

/**
@@ -108,6 +110,9 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
TRACE_SEQ_CHECK(s);

try_again:
+ if (s->state != TRACE_SEQ__GOOD)
+ return 0;
+
len = (s->buffer_size - 1) - s->len;

va_start(ap, fmt);
@@ -144,6 +149,9 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
TRACE_SEQ_CHECK(s);

try_again:
+ if (s->state != TRACE_SEQ__GOOD)
+ return 0;
+
len = (s->buffer_size - 1) - s->len;

ret = vsnprintf(s->buffer + s->len, len, fmt, args);
@@ -174,11 +182,17 @@ int trace_seq_puts(struct trace_seq *s, const char *str)

TRACE_SEQ_CHECK(s);

+ if (s->state != TRACE_SEQ__GOOD)
+ return 0;
+
len = strlen(str);

while (len > ((s->buffer_size - 1) - s->len))
expand_buffer(s);

+ if (s->state != TRACE_SEQ__GOOD)
+ return 0;
+
memcpy(s->buffer + s->len, str, len);
s->len += len;

@@ -189,9 +203,15 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c)
{
TRACE_SEQ_CHECK(s);

+ if (s->state != TRACE_SEQ__GOOD)
+ return 0;
+
while (s->len >= (s->buffer_size - 1))
expand_buffer(s);

+ if (s->state != TRACE_SEQ__GOOD)
+ return 0;
+
s->buffer[s->len++] = c;

return 1;
@@ -201,6 +221,9 @@ void trace_seq_terminate(struct trace_seq *s)
{
TRACE_SEQ_CHECK(s);

+ if (s->state != TRACE_SEQ__GOOD)
+ return;
+
/* There's always one character left on the buffer */
s->buffer[s->len] = 0;
}
@@ -208,5 +231,16 @@ void trace_seq_terminate(struct trace_seq *s)
int trace_seq_do_printf(struct trace_seq *s)
{
TRACE_SEQ_CHECK(s);
- return printf("%.*s", s->len, s->buffer);
+
+ switch (s->state) {
+ case TRACE_SEQ__GOOD:
+ return printf("%.*s", s->len, s->buffer);
+ case TRACE_SEQ__BUFFER_POISONED:
+ puts("Usage of trace_seq after it was destroyed");
+ break;
+ case TRACE_SEQ__MEM_ALLOC_FAILED:
+ puts("Can't allocate trace_seq buffer memory");
+ break;
+ }
+ return -1;

Namhyung Kim

unread,
Jan 6, 2014, 10:10:02 PM1/6/14
to
Now all of its users were gone. :)

Signed-off-by: Namhyung Kim <namh...@kernel.org>
---
tools/lib/traceevent/event-utils.h | 4 ----
tools/lib/traceevent/parse-utils.c | 44 --------------------------------------
2 files changed, 48 deletions(-)

diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h
index 5dc0aec5ab50..496dba9fe984 100644
--- a/tools/lib/traceevent/event-utils.h
+++ b/tools/lib/traceevent/event-utils.h
@@ -23,18 +23,14 @@
#include <ctype.h>

/* Can be overridden */
-void die(const char *fmt, ...);
-void *malloc_or_die(unsigned int size);
void warning(const char *fmt, ...);
void pr_stat(const char *fmt, ...);
void vpr_stat(const char *fmt, va_list ap);

/* Always available */
-void __die(const char *fmt, ...);
void __warning(const char *fmt, ...);
void __pr_stat(const char *fmt, ...);

-void __vdie(const char *fmt, ...);
void __vwarning(const char *fmt, ...);
void __vpr_stat(const char *fmt, ...);

diff --git a/tools/lib/traceevent/parse-utils.c b/tools/lib/traceevent/parse-utils.c
index bba701cf10e6..eda07fa31dca 100644
--- a/tools/lib/traceevent/parse-utils.c
+++ b/tools/lib/traceevent/parse-utils.c
@@ -25,40 +25,6 @@

#define __weak __attribute__((weak))

-void __vdie(const char *fmt, va_list ap)
-{
- int ret = errno;
-
- if (errno)
- perror("trace-cmd");
- else
- ret = -1;
-
- fprintf(stderr, " ");
- vfprintf(stderr, fmt, ap);
-
- fprintf(stderr, "\n");
- exit(ret);
-}
-
-void __die(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- __vdie(fmt, ap);
- va_end(ap);
-}
-
-void __weak die(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- __vdie(fmt, ap);
- va_end(ap);
-}
-
void __vwarning(const char *fmt, va_list ap)
{
if (errno)
@@ -117,13 +83,3 @@ void __weak pr_stat(const char *fmt, ...)
__vpr_stat(fmt, ap);
va_end(ap);
}
-
-void __weak *malloc_or_die(unsigned int size)
-{
- void *data;
-
- data = malloc(size);
- if (!data)
- die("malloc");
- return data;
-}

Namhyung Kim

unread,
Jan 6, 2014, 10:10:01 PM1/6/14
to
Hello,

I've added WARN_ONCE in TRACE_SEQ_CHECK() as Jiri said. Other patches
are same as the privous version.

You can also get this on my 'libtraceevent/die-removal-v5' branch in my tree

git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git


Thanks,
Namhyung


Namhyung Kim (5):
tools lib traceevent: Add WARN and WARN_ONCE macros
tools lib traceevent: Add state member to struct trace_seq
tools lib traceevent: Check return value of realloc()
tools lib traceevent: Get rid of malloc_or_die() in trace_seq_init()
tools lib traceevent: Get rid of die() finally!!

tools/lib/traceevent/event-parse.h | 7 +++++
tools/lib/traceevent/event-utils.h | 26 ++++++++++++++---
tools/lib/traceevent/parse-utils.c | 44 -----------------------------
tools/lib/traceevent/trace-seq.c | 57 +++++++++++++++++++++++++++++++++-----
4 files changed, 79 insertions(+), 55 deletions(-)

Steven Rostedt

unread,
Jan 6, 2014, 10:30:02 PM1/6/14
to
On Tue, 7 Jan 2014 12:00:12 +0900
Namhyung Kim <namh...@kernel.org> wrote:

> Now all of its users were gone. :)
>

Die die!

;-)

-- Steve

Jiri Olsa

unread,
Jan 7, 2014, 8:10:02 AM1/7/14
to
On Tue, Jan 07, 2014 at 12:00:09PM +0900, Namhyung Kim wrote:

SNIP
and also here?

if (WARN_ONCE(!s->buffer))
s->state = TRACE_SEQ__MEM_ALLOC_FAILED;

otherwise the whole series seems ok,
jirka

Arnaldo Carvalho de Melo

unread,
Jan 7, 2014, 9:10:03 AM1/7/14
to
Em Tue, Jan 07, 2014 at 12:00:08PM +0900, Namhyung Kim escreveu:
> They're copied from the perf code and will be used to print error
> message during trace_seq_printf() and friends.
>
> Suggested-by: Jiri Olsa <jo...@redhat.com>
> Signed-off-by: Namhyung Kim <namh...@kernel.org>

We could take this opportunity and come up with
tools/lib/{bug,compiler}.h, matching the files in include/linux/ where
those helpers come from, no?

Then make both tools/perf/ and tools/lib/traceevent/ use it, instead of
creating the third copy (kernel proper, perf, libtraceevent).

Then, does anybody know why likely/unlikely is guarded inside __KERNEL__
in include/linux/compiler.h? I think the best thing would be for us to
just use:

#include <linux/compiler.h>

just like kernel code and be done with it :-\

- Arnaldo

Namhyung Kim

unread,
Jan 7, 2014, 11:10:01 PM1/7/14
to
Hi Jiri,
Ah, will fix.

>
> otherwise the whole series seems ok,

Thanks for your review!
Namhyung

Namhyung Kim

unread,
Jan 8, 2014, 2:40:02 AM1/8/14
to
Hi Arnaldo,

On Tue, 7 Jan 2014 11:07:47 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jan 07, 2014 at 12:00:08PM +0900, Namhyung Kim escreveu:
>> They're copied from the perf code and will be used to print error
>> message during trace_seq_printf() and friends.
>>
>> Suggested-by: Jiri Olsa <jo...@redhat.com>
>> Signed-off-by: Namhyung Kim <namh...@kernel.org>
>
> We could take this opportunity and come up with
> tools/lib/{bug,compiler}.h, matching the files in include/linux/ where
> those helpers come from, no?

Hmm.. maybe under tools/include/ ?

>
> Then make both tools/perf/ and tools/lib/traceevent/ use it, instead of
> creating the third copy (kernel proper, perf, libtraceevent).

Okay.

>
> Then, does anybody know why likely/unlikely is guarded inside __KERNEL__
> in include/linux/compiler.h?

IIUC it's because of BRANCH_PROFILING..


> I think the best thing would be for us to just use:
>
> #include <linux/compiler.h>
>
> just like kernel code and be done with it :-\

Yeah, but it seems to require some modifications.

Thanks,
Namhyung
0 new messages