From ee95ac26879e79b88ecf56d4b35c3bb0e23a74d9 Mon Sep 17 00:00:00 2001 From: Clark Williams Date: Thu, 1 Sep 2011 09:41:37 -0500 Subject: commit WIP for rostedt Signed-off-by: Clark Williams --- src/cyclictest/cyclictest.c | 75 +++++++++------------ src/include/rt-utils.h | 9 +++ src/lib/rt-utils.c | 161 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 45 deletions(-) diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c index 6be5521..0f3e981 100644 --- a/src/cyclictest/cyclictest.c +++ b/src/cyclictest/cyclictest.c @@ -114,6 +114,7 @@ enum { IRQPREEMPTOFF, WAKEUP, WAKEUPRT, + LATENCY, CUSTOM, }; @@ -154,7 +155,7 @@ struct thread_stat { static int shutdown; static int tracelimit = 0; -static int ftrace = 1; +static int ftrace = 0; static int kernelversion; static int verbose = 0; static int oscope_reduction = 1; @@ -172,6 +173,7 @@ static pthread_mutex_t refresh_on_max_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t break_thread_id_lock = PTHREAD_MUTEX_INITIALIZER; static pid_t break_thread_id = 0; +static uint64_t break_thread_value = 0; /* Backup of kernel variables that we modify */ static struct kvars { @@ -369,44 +371,11 @@ void tracing(int on) static int settracer(char *tracer) { - char filename[MAX_PATH]; - char tracers[MAX_PATH]; - char *name; - FILE *fp; - int ret = -1; - int len; - const char *delim = " \t\n"; - char *prefix = get_debugfileprefix(); - - /* Make sure tracer is available */ - strncpy(filename, prefix, sizeof(filename)); - strncat(filename, "available_tracers", - sizeof(filename) - strlen(prefix)); - - fp = fopen(filename, "r"); - if (!fp) - return -1; - - if (!(len = fread(tracers, 1, sizeof(tracers), fp))) { - fclose(fp); - return -1; - } - tracers[len] = '\0'; - fclose(fp); - - name = strtok(tracers, delim); - while (name) { - if (strcmp(name, tracer) == 0) { - ret = 0; - break; - } - name = strtok(NULL, delim); - } - - if (!ret) + if (valid_tracer(tracer)) { setkernvar("current_tracer", tracer); - - return ret; + return 0; + } + return -1; } static void setup_tracer(void) @@ -414,6 +383,9 @@ static void setup_tracer(void) if (!tracelimit) return; + if (mount_debugfs(NULL)) + fatal("could not mount debugfs"); + if (kernelversion >= KV_26_33) { char testname[MAX_PATH]; @@ -447,10 +419,8 @@ static void setup_tracer(void) switch (tracetype) { case NOTRACE: - if (ftrace) - ret = settracer(functiontracer); - else - ret = 0; + setkernvar("events/enable", "1"); + ret = settracer("nop"); break; case IRQSOFF: ret = settracer("irqsoff"); @@ -463,11 +433,20 @@ static void setup_tracer(void) break; case EVENTS: /* per rostedt: use nop tracer with event tracing */ - setkernvar("events/enable", "1"); ret = settracer("nop"); + /* turn on all events */ + event_enable_all(); break; case CTXTSWITCH: - ret = settracer("sched_switch"); + if (valid_tracer("sched_switch")) + ret = settracer("sched_switch"); + else { + if ((ret = settracer("nop"))) + break; + if ((ret = event_enable("sched/sched_wakeup"))) + break; + ret = event_enable("sched/sched_switch"); + } break; case WAKEUP: ret = settracer("wakeup"); @@ -745,6 +724,7 @@ void *timerthread(void *param) pthread_mutex_lock(&break_thread_id_lock); if (break_thread_id == 0) break_thread_id = stat->tid; + break_thread_value = diff; pthread_mutex_unlock(&break_thread_id_lock); } stat->act = diff; @@ -1533,8 +1513,10 @@ int main(int argc, char **argv) if (tracelimit) { print_tids(parameters, num_threads); - if (break_thread_id) + if (break_thread_id) { printf("# Break thread: %d\n", break_thread_id); + printf("# Break value: %lu\n", break_thread_value); + } } @@ -1561,6 +1543,9 @@ int main(int argc, char **argv) if (trace_fd >= 0) close(trace_fd); + /* turn off all events */ + event_disable_all(); + /* unlock everything */ if (lockall) munlockall(); diff --git a/src/include/rt-utils.h b/src/include/rt-utils.h index 68857f3..730344e 100644 --- a/src/include/rt-utils.h +++ b/src/include/rt-utils.h @@ -8,6 +8,15 @@ int check_privs(void); char *get_debugfileprefix(void); +int mount_debugfs(char *); +int get_tracers(char ***); +int valid_tracer(char *); + +int setevent(char *event, char *val); +int event_enable(char *event); +int event_disable(char *event); +int event_enable_all(void); +int event_disable_all(void); void warn(char *fmt, ...); void fatal(char *fmt, ...); diff --git a/src/lib/rt-utils.c b/src/lib/rt-utils.c index da27a3a..952ad7f 100644 --- a/src/lib/rt-utils.c +++ b/src/lib/rt-utils.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "rt-utils.h" static char debugfileprefix[MAX_PATH]; @@ -50,6 +52,165 @@ char *get_debugfileprefix(void) return debugfileprefix; } +int mount_debugfs(char *path) +{ + char *mountpoint = path; + char cmd[MAX_PATH]; + int ret; + + if (get_debugfileprefix()) + return 0; + + if (!mountpoint) + mountpoint = "/sys/kernel/debug"; + + sprintf(cmd, "mount -t debugfs debugfs %s", mountpoint); + ret = system(cmd); + if (ret != 0) { + fprintf(stderr, "Error mounting debugfs at %s: %s\n", mountpoint, strerror(errno)); + return -1; + } + return 0; + +} + +static char **tracer_list; +static char *tracer_buffer; +static int num_tracers; +#define CHUNKSZ 1024 + +/* + * return a list of the tracers configured into the running kernel + */ + +int get_tracers(char ***list) +{ + int ret; + FILE *fp; + char buffer[CHUNKSZ]; + char *prefix = get_debugfileprefix(); + char *tmpbuf = NULL; + char *ptr; + int tmpsz = 0; + + /* if we've already parse it, return what we have */ + if (tracer_list) { + *list = tracer_list; + return num_tracers; + } + + /* open the tracing file available_tracers */ + sprintf(buffer, "%savailable_tracers", prefix); + if ((fp = fopen(buffer, "r")) == NULL) + fatal ("Can't open %s for reading\n", buffer); + + /* allocate initial buffer */ + ptr = tmpbuf = malloc(CHUNKSZ); + if (ptr == NULL) + fatal("error allocating initial space for tracer list\n"); + + /* read in the list of available tracers */ + while((ret = fread(buffer, sizeof(char), CHUNKSZ, fp))) { + if ((ptr+ret+1) > (tmpbuf+tmpsz)) { + tmpbuf = realloc(tmpbuf, tmpsz + CHUNKSZ); + if (tmpbuf == NULL) + fatal("error allocating space for list of valid tracers\n"); + tmpsz += CHUNKSZ; + } + strncpy(ptr, buffer, ret); + ptr += ret; + } + fclose(fp); + if (tmpsz == 0) + fatal("error reading available tracers\n"); + + tracer_buffer = tmpbuf; + + /* get a buffer for the pointers to tracers */ + if (!(tracer_list = malloc(sizeof(char *)))) + fatal ("error allocatinging tracer list buffer\n"); + + /* parse the buffer */ + ptr = strtok(tmpbuf, " \t\n\r"); + do { + tracer_list[num_tracers++] = ptr; + tracer_list = realloc(tracer_list, sizeof(char*)*(num_tracers+1)); + tracer_list[num_tracers] = NULL; + } while ((ptr = strtok(NULL, " \t\n\r")) != NULL); + + /* return the list and number of tracers */ + *list = tracer_list; + return num_tracers; +} + + +/* + * return zero if tracername is not a valid tracer, non-zero if it is + */ + +int valid_tracer(char *tracername) +{ + char **list; + int ntracers; + int i; + + ntracers = get_tracers(&list); + if (ntracers == 0 || tracername == NULL) + return 0; + for (i = 0; i < ntracers; i++) + if (strncmp(list[i], tracername, strlen(list[i])) == 0) + return 1; + return 0; +} + +/* + * enable event tracepoint + */ +int setevent(char *event, char *val) +{ + char *prefix = get_debugfileprefix(); + char buffer[MAX_PATH]; + int fd; + int ret; + + sprintf(buffer, "%s%s", prefix, event); + if ((fd = open(buffer, O_WRONLY)) < 0) { + warn("unable to open %s\n", buffer); + return -1; + } + if ((ret = write(fd, val, strlen(val))) < 0) { + warn("unable to write %s to %s\n", val, buffer); + close(fd); + return -1; + } + close(fd); + return 0; +} + +int event_enable_all(void) +{ + return setevent("events/enable", "1"); +} + +int event_disable_all(void) +{ + return setevent("events/enable", "0"); +} + +int event_enable(char *event) +{ + char path[MAX_PATH]; + sprintf(path, "events/%s/enable", event); + return setevent(path, "1"); +} + +int event_disable(char *event) +{ + char path[MAX_PATH]; + sprintf(path, "events/%s/enable", event); + return setevent(path, "0"); +} + int check_privs(void) { int policy = sched_getscheduler(0); -- cgit 1.2.3-korg