diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 9 | ||||
-rw-r--r-- | tools/lib/traceevent/parse-filter.c | 15 | ||||
-rw-r--r-- | tools/perf/Makefile | 24 | ||||
-rw-r--r-- | tools/perf/builtin-help.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 18 | ||||
-rw-r--r-- | tools/perf/perf.h | 2 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 6 | ||||
-rw-r--r-- | tools/perf/util/parse-events-test.c | 12 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 3 | ||||
-rw-r--r-- | tools/perf/util/setup.py | 2 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 6 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 1 | ||||
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 28 | ||||
-rwxr-xr-x | tools/testing/ktest/ktest.pl | 6 | ||||
-rw-r--r-- | tools/testing/selftests/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/epoll/Makefile | 11 | ||||
-rw-r--r-- | tools/testing/selftests/epoll/test_epoll.c | 344 | ||||
-rw-r--r-- | tools/vm/page-types.c | 2 |
18 files changed, 97 insertions, 396 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 47264b4652b..f2989c525e4 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -2602,6 +2602,9 @@ find_func_handler(struct pevent *pevent, char *func_name) { struct pevent_function_handler *func; + if (!pevent) + return NULL; + for (func = pevent->func_handlers; func; func = func->next) { if (strcmp(func->name, func_name) == 0) break; @@ -4938,6 +4941,9 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, goto event_alloc_failed; } + /* Add pevent to event so that it can be referenced */ + event->pevent = pevent; + ret = event_read_format(event); if (ret < 0) { ret = PEVENT_ERRNO__READ_FORMAT_FAILED; @@ -5041,9 +5047,6 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, if (event == NULL) return ret; - /* Add pevent to event so that it can be referenced */ - event->pevent = pevent; - if (add_event(pevent, event)) { ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; goto event_add_failed; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index ad17855528f..5ea4326ad11 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -209,7 +209,16 @@ static void free_arg(struct filter_arg *arg) switch (arg->type) { case FILTER_ARG_NONE: case FILTER_ARG_BOOLEAN: + break; + case FILTER_ARG_NUM: + free_arg(arg->num.left); + free_arg(arg->num.right); + break; + + case FILTER_ARG_EXP: + free_arg(arg->exp.left); + free_arg(arg->exp.right); break; case FILTER_ARG_STR: @@ -218,6 +227,12 @@ static void free_arg(struct filter_arg *arg) free(arg->str.buffer); break; + case FILTER_ARG_VALUE: + if (arg->value.type == FILTER_STRING || + arg->value.type == FILTER_CHAR) + free(arg->value.str); + break; + case FILTER_ARG_OP: free_arg(arg->op.left); free_arg(arg->op.right); diff --git a/tools/perf/Makefile b/tools/perf/Makefile index f7c968ad517..00deed4d615 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -184,9 +184,22 @@ SCRIPT_SH += perf-archive.sh grep-libs = $(filter -l%,$(1)) strip-libs = $(filter-out -l%,$(1)) +TRACE_EVENT_DIR = ../lib/traceevent/ + +ifneq ($(OUTPUT),) + TE_PATH=$(OUTPUT) +else + TE_PATH=$(TRACE_EVENT_DIR) +endif + +LIBTRACEEVENT = $(TE_PATH)libtraceevent.a +TE_LIB := -L$(TE_PATH) -ltraceevent + PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py +export LIBTRACEEVENT + $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ --quiet build_ext; \ @@ -198,17 +211,6 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) -TRACE_EVENT_DIR = ../lib/traceevent/ - -ifneq ($(OUTPUT),) - TE_PATH=$(OUTPUT) -else - TE_PATH=$(TRACE_EVENT_DIR) -endif - -LIBTRACEEVENT = $(TE_PATH)libtraceevent.a -TE_LIB := -L$(TE_PATH) -ltraceevent - # # Single 'perf' binary right now: # diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 411ee5664e9..178b88ae3d2 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd) int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) { bool show_all = false; - enum help_format help_format = HELP_FORMAT_NONE; + enum help_format help_format = HELP_FORMAT_MAN; struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index dec8ced61fb..7aaee39f677 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id) { char tp_name[128]; struct syscall *sc; + const char *name = audit_syscall_to_name(id, trace->audit_machine); + + if (name == NULL) + return -1; if (id > trace->syscalls.max) { struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); @@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id) } sc = trace->syscalls.table + id; - sc->name = audit_syscall_to_name(id, trace->audit_machine); - if (sc->name == NULL) - return -1; - - sc->fmt = syscall_fmt__find(sc->name); + sc->name = name; + sc->fmt = syscall_fmt__find(sc->name); snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); sc->tp_format = event_format__new("syscalls", tp_name); @@ -267,6 +268,13 @@ again: if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) printf("%d ", sample.tid); + if (sample.raw_data == NULL) { + printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", + perf_evsel__name(evsel), sample.tid, + sample.cpu, sample.raw_size); + continue; + } + handler = evsel->handler.func; handler(trace, evsel, &sample); } diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 276287783a0..c50985eaec4 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -57,7 +57,7 @@ void get_term_dimensions(struct winsize *ws); #endif #ifdef __sparc__ -#include "../../arch/sparc/include/asm/unistd.h" +#include "../../arch/sparc/include/uapi/asm/unistd.h" #define rmb() asm volatile("":::"memory") #define cpu_relax() asm volatile("":::"memory") #define CPUINFO_PROC "cpu" diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 0568536ecf6..ef2f93ca749 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -610,6 +610,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(&browser->b, row); off_t row_offset = entry->row_offset; + bool first = true; if (current_entry) { browser->he_selection = entry; @@ -633,10 +634,11 @@ static int hist_browser__show_entry(struct hist_browser *browser, if (!perf_hpp__format[i].cond) continue; - if (i) { + if (!first) { slsmg_printf(" "); width -= 2; } + first = false; if (perf_hpp__format[i].color) { hpp.ptr = &percent; @@ -645,7 +647,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, ui_browser__set_percent_color(&browser->b, percent, current_entry); - if (i == 0 && symbol_conf.use_callchain) { + if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) { slsmg_printf("%c ", folded_sign); width -= 2; } diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 28c18d1d52c..516ecd9ddd6 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); @@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); @@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); @@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index aed38e4b9df..75c7b0fca6d 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -690,6 +690,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str, eH = 0; } else if (*str == 'p') { precise++; + /* use of precise requires exclude_guest */ + if (!exclude_GH) + eG = 1; } else break; diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index d0f9f29cf18..73d51026978 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split() build_lib = getenv('PYTHON_EXTBUILD_LIB') build_tmp = getenv('PYTHON_EXTBUILD_TMP') +libtraceevent = getenv('LIBTRACEEVENT') ext_sources = [f.strip() for f in file('util/python-ext-sources') if len(f.strip()) > 0 and f[0] != '#'] @@ -31,6 +32,7 @@ perf = Extension('perf', sources = ext_sources, include_dirs = ['util/include'], extra_compile_args = cflags, + extra_objects = [libtraceevent], ) setup(name='perf', diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index b5b1b921196..cfd1c0feb32 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -260,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, if (path != NULL) goto out_path; + if (!self->ms.map) + goto out_ip; + + if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10)) + goto out_ip; + snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, self->ms.map->dso->long_name, self->ip); fp = popen(cmd, "r"); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index fb4b7ea6752..8b3e5939afb 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm) err = self->comm == NULL ? -ENOMEM : 0; if (!err) { self->comm_set = true; - map_groups__flush(&self->mg); } return err; } diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 2655ae9a3ad..ea095abbe97 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -206,8 +206,10 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) retval = pread(fd, msr, sizeof *msr, offset); close(fd); - if (retval != sizeof *msr) + if (retval != sizeof *msr) { + fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset); return -1; + } return 0; } @@ -1101,7 +1103,9 @@ void turbostat_loop() restart: retval = for_all_cpus(get_counters, EVEN_COUNTERS); - if (retval) { + if (retval < -1) { + exit(retval); + } else if (retval == -1) { re_initialize(); goto restart; } @@ -1114,7 +1118,9 @@ restart: } sleep(interval_sec); retval = for_all_cpus(get_counters, ODD_COUNTERS); - if (retval) { + if (retval < -1) { + exit(retval); + } else if (retval == -1) { re_initialize(); goto restart; } @@ -1126,7 +1132,9 @@ restart: flush_stdout(); sleep(interval_sec); retval = for_all_cpus(get_counters, EVEN_COUNTERS); - if (retval) { + if (retval < -1) { + exit(retval); + } else if (retval == -1) { re_initialize(); goto restart; } @@ -1545,8 +1553,11 @@ void turbostat_init() int fork_it(char **argv) { pid_t child_pid; + int status; - for_all_cpus(get_counters, EVEN_COUNTERS); + status = for_all_cpus(get_counters, EVEN_COUNTERS); + if (status) + exit(status); /* clear affinity side-effect of get_counters() */ sched_setaffinity(0, cpu_present_setsize, cpu_present_set); gettimeofday(&tv_even, (struct timezone *)NULL); @@ -1556,7 +1567,6 @@ int fork_it(char **argv) /* child */ execvp(argv[0], argv); } else { - int status; /* parent */ if (child_pid == -1) { @@ -1568,7 +1578,7 @@ int fork_it(char **argv) signal(SIGQUIT, SIG_IGN); if (waitpid(child_pid, &status, 0) == -1) { perror("wait"); - exit(1); + exit(status); } } /* @@ -1585,7 +1595,7 @@ int fork_it(char **argv) fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0); - return 0; + return status; } void cmdline(int argc, char **argv) @@ -1594,7 +1604,7 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) { + while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:")) != -1) { switch (opt) { case 'p': show_core_only++; diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index b51d787176d..c7ba7614061 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1740,8 +1740,10 @@ sub install { open(IN, "$output_config") or dodie("Can't read config file"); while (<IN>) { if (/CONFIG_MODULES(=y)?/) { - $install_mods = 1 if (defined($1)); - last; + if (defined($1)) { + $install_mods = 1; + last; + } } } close(IN); diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 43480149119..85baf11e2ac 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -1,4 +1,4 @@ -TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll +TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug all: for TARGET in $(TARGETS); do \ diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile deleted file mode 100644 index 19806ed62f5..00000000000 --- a/tools/testing/selftests/epoll/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Makefile for epoll selftests - -all: test_epoll -%: %.c - gcc -pthread -g -o $@ $^ - -run_tests: all - ./test_epoll - -clean: - $(RM) test_epoll diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c deleted file mode 100644 index e0fcff1e833..00000000000 --- a/tools/testing/selftests/epoll/test_epoll.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * tools/testing/selftests/epoll/test_epoll.c - * - * Copyright 2012 Adobe Systems Incorporated - * - * 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. - * - * Paton J. Lewis <palewis@adobe.com> - * - */ - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/epoll.h> -#include <sys/socket.h> - -/* - * A pointer to an epoll_item_private structure will be stored in the epoll - * item's event structure so that we can get access to the epoll_item_private - * data after calling epoll_wait: - */ -struct epoll_item_private { - int index; /* Position of this struct within the epoll_items array. */ - int fd; - uint32_t events; - pthread_mutex_t mutex; /* Guards the following variables... */ - int stop; - int status; /* Stores any error encountered while handling item. */ - /* The following variable allows us to test whether we have encountered - a problem while attempting to cancel and delete the associated - event. When the test program exits, 'deleted' should be exactly - one. If it is greater than one, then the failed test reflects a real - world situation where we would have tried to access the epoll item's - private data after deleting it: */ - int deleted; -}; - -struct epoll_item_private *epoll_items; - -/* - * Delete the specified item from the epoll set. In a real-world secneario this - * is where we would free the associated data structure, but in this testing - * environment we retain the structure so that we can test for double-deletion: - */ -void delete_item(int index) -{ - __sync_fetch_and_add(&epoll_items[index].deleted, 1); -} - -/* - * A pointer to a read_thread_data structure will be passed as the argument to - * each read thread: - */ -struct read_thread_data { - int stop; - int status; /* Indicates any error encountered by the read thread. */ - int epoll_set; -}; - -/* - * The function executed by the read threads: - */ -void *read_thread_function(void *function_data) -{ - struct read_thread_data *thread_data = - (struct read_thread_data *)function_data; - struct epoll_event event_data; - struct epoll_item_private *item_data; - char socket_data; - - /* Handle events until we encounter an error or this thread's 'stop' - condition is set: */ - while (1) { - int result = epoll_wait(thread_data->epoll_set, - &event_data, - 1, /* Number of desired events */ - 1000); /* Timeout in ms */ - if (result < 0) { - /* Breakpoints signal all threads. Ignore that while - debugging: */ - if (errno == EINTR) - continue; - thread_data->status = errno; - return 0; - } else if (thread_data->stop) - return 0; - else if (result == 0) /* Timeout */ - continue; - - /* We need the mutex here because checking for the stop - condition and re-enabling the epoll item need to be done - together as one atomic operation when EPOLL_CTL_DISABLE is - available: */ - item_data = (struct epoll_item_private *)event_data.data.ptr; - pthread_mutex_lock(&item_data->mutex); - - /* Remove the item from the epoll set if we want to stop - handling that event: */ - if (item_data->stop) - delete_item(item_data->index); - else { - /* Clear the data that was written to the other end of - our non-blocking socket: */ - do { - if (read(item_data->fd, &socket_data, 1) < 1) { - if ((errno == EAGAIN) || - (errno == EWOULDBLOCK)) - break; - else - goto error_unlock; - } - } while (item_data->events & EPOLLET); - - /* The item was one-shot, so re-enable it: */ - event_data.events = item_data->events; - if (epoll_ctl(thread_data->epoll_set, - EPOLL_CTL_MOD, - item_data->fd, - &event_data) < 0) - goto error_unlock; - } - - pthread_mutex_unlock(&item_data->mutex); - } - -error_unlock: - thread_data->status = item_data->status = errno; - pthread_mutex_unlock(&item_data->mutex); - return 0; -} - -/* - * A pointer to a write_thread_data structure will be passed as the argument to - * the write thread: - */ -struct write_thread_data { - int stop; - int status; /* Indicates any error encountered by the write thread. */ - int n_fds; - int *fds; -}; - -/* - * The function executed by the write thread. It writes a single byte to each - * socket in turn until the stop condition for this thread is set. If writing to - * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for - * the moment and just move on to the next socket in the list. We don't care - * about the order in which we deliver events to the epoll set. In fact we don't - * care about the data we're writing to the pipes at all; we just want to - * trigger epoll events: - */ -void *write_thread_function(void *function_data) -{ - const char data = 'X'; - int index; - struct write_thread_data *thread_data = - (struct write_thread_data *)function_data; - while (!write_thread_data->stop) - for (index = 0; - !thread_data->stop && (index < thread_data->n_fds); - ++index) - if ((write(thread_data->fds[index], &data, 1) < 1) && - (errno != EAGAIN) && - (errno != EWOULDBLOCK)) { - write_thread_data->status = errno; - return; - } -} - -/* - * Arguments are currently ignored: - */ -int main(int argc, char **argv) -{ - const int n_read_threads = 100; - const int n_epoll_items = 500; - int index; - int epoll_set = epoll_create1(0); - struct write_thread_data write_thread_data = { - 0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int)) - }; - struct read_thread_data *read_thread_data = - malloc(n_read_threads * sizeof(struct read_thread_data)); - pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t)); - pthread_t write_thread; - - printf("-----------------\n"); - printf("Runing test_epoll\n"); - printf("-----------------\n"); - - epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private)); - - if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 || - read_thread_data == 0 || read_threads == 0) - goto error; - - if (sysconf(_SC_NPROCESSORS_ONLN) < 2) { - printf("Error: please run this test on a multi-core system.\n"); - goto error; - } - - /* Create the socket pairs and epoll items: */ - for (index = 0; index < n_epoll_items; ++index) { - int socket_pair[2]; - struct epoll_event event_data; - if (socketpair(AF_UNIX, - SOCK_STREAM | SOCK_NONBLOCK, - 0, - socket_pair) < 0) - goto error; - write_thread_data.fds[index] = socket_pair[0]; - epoll_items[index].index = index; - epoll_items[index].fd = socket_pair[1]; - if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0) - goto error; - /* We always use EPOLLONESHOT because this test is currently - structured to demonstrate the need for EPOLL_CTL_DISABLE, - which only produces useful information in the EPOLLONESHOT - case (without EPOLLONESHOT, calling epoll_ctl with - EPOLL_CTL_DISABLE will never return EBUSY). If support for - testing events without EPOLLONESHOT is desired, it should - probably be implemented in a separate unit test. */ - epoll_items[index].events = EPOLLIN | EPOLLONESHOT; - if (index < n_epoll_items / 2) - epoll_items[index].events |= EPOLLET; - epoll_items[index].stop = 0; - epoll_items[index].status = 0; - epoll_items[index].deleted = 0; - event_data.events = epoll_items[index].events; - event_data.data.ptr = &epoll_items[index]; - if (epoll_ctl(epoll_set, - EPOLL_CTL_ADD, - epoll_items[index].fd, - &event_data) < 0) - goto error; - } - - /* Create and start the read threads: */ - for (index = 0; index < n_read_threads; ++index) { - read_thread_data[index].stop = 0; - read_thread_data[index].status = 0; - read_thread_data[index].epoll_set = epoll_set; - if (pthread_create(&read_threads[index], - NULL, - read_thread_function, - &read_thread_data[index]) != 0) - goto error; - } - - if (pthread_create(&write_thread, - NULL, - write_thread_function, - &write_thread_data) != 0) - goto error; - - /* Cancel all event pollers: */ -#ifdef EPOLL_CTL_DISABLE - for (index = 0; index < n_epoll_items; ++index) { - pthread_mutex_lock(&epoll_items[index].mutex); - ++epoll_items[index].stop; - if (epoll_ctl(epoll_set, - EPOLL_CTL_DISABLE, - epoll_items[index].fd, - NULL) == 0) - delete_item(index); - else if (errno != EBUSY) { - pthread_mutex_unlock(&epoll_items[index].mutex); - goto error; - } - /* EBUSY means events were being handled; allow the other thread - to delete the item. */ - pthread_mutex_unlock(&epoll_items[index].mutex); - } -#else - for (index = 0; index < n_epoll_items; ++index) { - pthread_mutex_lock(&epoll_items[index].mutex); - ++epoll_items[index].stop; - pthread_mutex_unlock(&epoll_items[index].mutex); - /* Wait in case a thread running read_thread_function is - currently executing code between epoll_wait and - pthread_mutex_lock with this item. Note that a longer delay - would make double-deletion less likely (at the expense of - performance), but there is no guarantee that any delay would - ever be sufficient. Note also that we delete all event - pollers at once for testing purposes, but in a real-world - environment we are likely to want to be able to cancel event - pollers at arbitrary times. Therefore we can't improve this - situation by just splitting this loop into two loops - (i.e. signal 'stop' for all items, sleep, and then delete all - items). We also can't fix the problem via EPOLL_CTL_DEL - because that command can't prevent the case where some other - thread is executing read_thread_function within the region - mentioned above: */ - usleep(1); - pthread_mutex_lock(&epoll_items[index].mutex); - if (!epoll_items[index].deleted) - delete_item(index); - pthread_mutex_unlock(&epoll_items[index].mutex); - } -#endif - - /* Shut down the read threads: */ - for (index = 0; index < n_read_threads; ++index) - __sync_fetch_and_add(&read_thread_data[index].stop, 1); - for (index = 0; index < n_read_threads; ++index) { - if (pthread_join(read_threads[index], NULL) != 0) - goto error; - if (read_thread_data[index].status) - goto error; - } - - /* Shut down the write thread: */ - __sync_fetch_and_add(&write_thread_data.stop, 1); - if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status) - goto error; - - /* Check for final error conditions: */ - for (index = 0; index < n_epoll_items; ++index) { - if (epoll_items[index].status != 0) - goto error; - if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0) - goto error; - } - for (index = 0; index < n_epoll_items; ++index) - if (epoll_items[index].deleted != 1) { - printf("Error: item data deleted %1d times.\n", - epoll_items[index].deleted); - goto error; - } - - printf("[PASS]\n"); - return 0; - - error: - printf("[FAIL]\n"); - return errno; -} diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c index cd1b03e8089..b76edf2f833 100644 --- a/tools/vm/page-types.c +++ b/tools/vm/page-types.c @@ -35,7 +35,7 @@ #include <sys/mount.h> #include <sys/statfs.h> #include "../../include/uapi/linux/magic.h" -#include "../../include/linux/kernel-page-flags.h" +#include "../../include/uapi/linux/kernel-page-flags.h" #ifndef MAX_PATH |