diff options
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/bitmap.c | 31 | ||||
-rw-r--r-- | tools/lib/bpf/Makefile | 4 | ||||
-rw-r--r-- | tools/lib/find_bit.c | 84 | ||||
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 129 | ||||
-rw-r--r-- | tools/lib/traceevent/event-parse.h | 4 | ||||
-rw-r--r-- | tools/lib/util/find_next_bit.c | 89 |
6 files changed, 191 insertions, 150 deletions
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c new file mode 100644 index 000000000000..0a1adc1111fd --- /dev/null +++ b/tools/lib/bitmap.c @@ -0,0 +1,31 @@ +/* + * From lib/bitmap.c + * Helper functions for bitmap.h. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ +#include <linux/bitmap.h> + +int __bitmap_weight(const unsigned long *bitmap, int bits) +{ + int k, w = 0, lim = bits/BITS_PER_LONG; + + for (k = 0; k < lim; k++) + w += hweight_long(bitmap[k]); + + if (bits % BITS_PER_LONG) + w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); + + return w; +} + +void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k; + int nr = BITS_TO_LONGS(bits); + + for (k = 0; k < nr; k++) + dst[k] = bitmap1[k] | bitmap2[k]; +} diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index 636e3ddb93a1..919b71780710 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -80,7 +80,11 @@ endif endif ifeq ($(check_feat),1) +ifeq ($(FEATURES_DUMP),) include $(srctree)/tools/build/Makefile.feature +else +include $(FEATURES_DUMP) +endif endif export prefix libdir src obj diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c new file mode 100644 index 000000000000..9122a9e80046 --- /dev/null +++ b/tools/lib/find_bit.c @@ -0,0 +1,84 @@ +/* bit search implementation + * + * Copied from lib/find_bit.c to tools/lib/find_bit.c + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * Copyright (C) 2008 IBM Corporation + * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au> + * (Inspired by David Howell's find_next_bit implementation) + * + * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease + * size and improve performance, 2015. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/bitops.h> +#include <linux/bitmap.h> +#include <linux/kernel.h> + +#if !defined(find_next_bit) + +/* + * This is a common helper function for find_next_bit and + * find_next_zero_bit. The difference is the "invert" argument, which + * is XORed with each fetched word before searching it for one bits. + */ +static unsigned long _find_next_bit(const unsigned long *addr, + unsigned long nbits, unsigned long start, unsigned long invert) +{ + unsigned long tmp; + + if (!nbits || start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + + /* Handle 1st word. */ + tmp &= BITMAP_FIRST_WORD_MASK(start); + start = round_down(start, BITS_PER_LONG); + + while (!tmp) { + start += BITS_PER_LONG; + if (start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + } + + return min(start + __ffs(tmp), nbits); +} +#endif + +#ifndef find_next_bit +/* + * Find the next set bit in a memory region. + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr, size, offset, 0UL); +} +#endif + +#ifndef find_first_bit +/* + * Find the first set bit in a memory region. + */ +unsigned long find_first_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long idx; + + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx]) + return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); + } + + return size; +} +#endif diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 68276f35e323..ea69ce35e902 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -4735,73 +4735,80 @@ static int is_printable_array(char *p, unsigned int len) return 1; } -static void print_event_fields(struct trace_seq *s, void *data, - int size __maybe_unused, - struct event_format *event) +void pevent_print_field(struct trace_seq *s, void *data, + struct format_field *field) { - struct format_field *field; unsigned long long val; unsigned int offset, len, i; - - field = event->format.fields; - while (field) { - trace_seq_printf(s, " %s=", field->name); - if (field->flags & FIELD_IS_ARRAY) { - offset = field->offset; - len = field->size; - if (field->flags & FIELD_IS_DYNAMIC) { - val = pevent_read_number(event->pevent, data + offset, len); - offset = val; - len = offset >> 16; - offset &= 0xffff; - } - if (field->flags & FIELD_IS_STRING && - is_printable_array(data + offset, len)) { - trace_seq_printf(s, "%s", (char *)data + offset); - } else { - trace_seq_puts(s, "ARRAY["); - for (i = 0; i < len; i++) { - if (i) - trace_seq_puts(s, ", "); - trace_seq_printf(s, "%02x", - *((unsigned char *)data + offset + i)); - } - trace_seq_putc(s, ']'); - field->flags &= ~FIELD_IS_STRING; - } + struct pevent *pevent = field->event->pevent; + + if (field->flags & FIELD_IS_ARRAY) { + offset = field->offset; + len = field->size; + if (field->flags & FIELD_IS_DYNAMIC) { + val = pevent_read_number(pevent, data + offset, len); + offset = val; + len = offset >> 16; + offset &= 0xffff; + } + if (field->flags & FIELD_IS_STRING && + is_printable_array(data + offset, len)) { + trace_seq_printf(s, "%s", (char *)data + offset); } else { - val = pevent_read_number(event->pevent, data + field->offset, - field->size); - if (field->flags & FIELD_IS_POINTER) { - trace_seq_printf(s, "0x%llx", val); - } else if (field->flags & FIELD_IS_SIGNED) { - switch (field->size) { - case 4: - /* - * If field is long then print it in hex. - * A long usually stores pointers. - */ - if (field->flags & FIELD_IS_LONG) - trace_seq_printf(s, "0x%x", (int)val); - else - trace_seq_printf(s, "%d", (int)val); - break; - case 2: - trace_seq_printf(s, "%2d", (short)val); - break; - case 1: - trace_seq_printf(s, "%1d", (char)val); - break; - default: - trace_seq_printf(s, "%lld", val); - } - } else { + trace_seq_puts(s, "ARRAY["); + for (i = 0; i < len; i++) { + if (i) + trace_seq_puts(s, ", "); + trace_seq_printf(s, "%02x", + *((unsigned char *)data + offset + i)); + } + trace_seq_putc(s, ']'); + field->flags &= ~FIELD_IS_STRING; + } + } else { + val = pevent_read_number(pevent, data + field->offset, + field->size); + if (field->flags & FIELD_IS_POINTER) { + trace_seq_printf(s, "0x%llx", val); + } else if (field->flags & FIELD_IS_SIGNED) { + switch (field->size) { + case 4: + /* + * If field is long then print it in hex. + * A long usually stores pointers. + */ if (field->flags & FIELD_IS_LONG) - trace_seq_printf(s, "0x%llx", val); + trace_seq_printf(s, "0x%x", (int)val); else - trace_seq_printf(s, "%llu", val); + trace_seq_printf(s, "%d", (int)val); + break; + case 2: + trace_seq_printf(s, "%2d", (short)val); + break; + case 1: + trace_seq_printf(s, "%1d", (char)val); + break; + default: + trace_seq_printf(s, "%lld", val); } + } else { + if (field->flags & FIELD_IS_LONG) + trace_seq_printf(s, "0x%llx", val); + else + trace_seq_printf(s, "%llu", val); } + } +} + +void pevent_print_fields(struct trace_seq *s, void *data, + int size __maybe_unused, struct event_format *event) +{ + struct format_field *field; + + field = event->format.fields; + while (field) { + trace_seq_printf(s, " %s=", field->name); + pevent_print_field(s, data, field); field = field->next; } } @@ -4827,7 +4834,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event if (event->flags & EVENT_FL_FAILED) { trace_seq_printf(s, "[FAILED TO PARSE]"); - print_event_fields(s, data, size, event); + pevent_print_fields(s, data, size, event); return; } @@ -5301,7 +5308,7 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event, int print_pretty = 1; if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW)) - print_event_fields(s, record->data, record->size, event); + pevent_print_fields(s, record->data, record->size, event); else { if (event->handler && !(event->flags & EVENT_FL_NOHANDLE)) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 6fc83c7edbe9..706d9bc24066 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -705,6 +705,10 @@ struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *com struct cmdline *next); int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline); +void pevent_print_field(struct trace_seq *s, void *data, + struct format_field *field); +void pevent_print_fields(struct trace_seq *s, void *data, + int size __maybe_unused, struct event_format *event); void pevent_event_info(struct trace_seq *s, struct event_format *event, struct pevent_record *record); int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, diff --git a/tools/lib/util/find_next_bit.c b/tools/lib/util/find_next_bit.c deleted file mode 100644 index 41b44f65a79e..000000000000 --- a/tools/lib/util/find_next_bit.c +++ /dev/null @@ -1,89 +0,0 @@ -/* find_next_bit.c: fallback find next bit implementation - * - * Copied from lib/find_next_bit.c to tools/lib/next_bit.c - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/bitops.h> -#include <asm/types.h> -#include <asm/byteorder.h> - -#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) - -#ifndef find_next_bit -/* - * Find the next set bit in a memory region. - */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} -#endif - -#ifndef find_first_bit -/* - * Find the first set bit in a memory region. - */ -unsigned long find_first_bit(const unsigned long *addr, unsigned long size) -{ - const unsigned long *p = addr; - unsigned long result = 0; - unsigned long tmp; - - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - - tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found: - return result + __ffs(tmp); -} -#endif |