1fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* 2fe42c8a09884c2305ce101b1f3438e077d282495mbligh * High resolution timer test software 3fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 4fe42c8a09884c2305ce101b1f3438e077d282495mbligh * (C) 2005-2007 Thomas Gleixner <tglx@linutronix.de> 5fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 6fe42c8a09884c2305ce101b1f3438e077d282495mbligh * This program is free software; you can redistribute it and/or 7fe42c8a09884c2305ce101b1f3438e077d282495mbligh * modify it under the terms of the GNU General Public License Version 8fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 2 as published by the Free Software Foundation. 9fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 10fe42c8a09884c2305ce101b1f3438e077d282495mbligh */ 11fe42c8a09884c2305ce101b1f3438e077d282495mbligh 12fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define VERSION_STRING "V 0.15" 13fe42c8a09884c2305ce101b1f3438e077d282495mbligh 14fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <fcntl.h> 15fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <getopt.h> 16fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <pthread.h> 17fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <signal.h> 18fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <stdlib.h> 19fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <stdio.h> 20fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <string.h> 21fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <time.h> 22fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <unistd.h> 23fe42c8a09884c2305ce101b1f3438e077d282495mbligh 24fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <linux/unistd.h> 25fe42c8a09884c2305ce101b1f3438e077d282495mbligh 26fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/prctl.h> 27fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/stat.h> 28fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/types.h> 29fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/time.h> 30fe42c8a09884c2305ce101b1f3438e077d282495mbligh 31fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 32fe42c8a09884c2305ce101b1f3438e077d282495mbligh 33fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Ugly, but .... */ 34fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define gettid() syscall(__NR_gettid) 35fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define sigev_notify_thread_id _sigev_un._tid 36fe42c8a09884c2305ce101b1f3438e077d282495mbligh 37fe42c8a09884c2305ce101b1f3438e077d282495mblighextern int clock_nanosleep(clockid_t __clock_id, int __flags, 38fe42c8a09884c2305ce101b1f3438e077d282495mbligh __const struct timespec *__req, 39fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct timespec *__rem); 40fe42c8a09884c2305ce101b1f3438e077d282495mbligh 41fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define USEC_PER_SEC 1000000 42fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define NSEC_PER_SEC 1000000000 43fe42c8a09884c2305ce101b1f3438e077d282495mbligh 44fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_CYCLIC 0 45fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_CLOCK_NANOSLEEP 1 46fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_SYS_ITIMER 2 47fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_SYS_NANOSLEEP 3 48fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_SYS_OFFSET 2 49fe42c8a09884c2305ce101b1f3438e077d282495mbligh 50fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define TIMER_RELTIME 0 51fe42c8a09884c2305ce101b1f3438e077d282495mbligh 52fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Must be power of 2 ! */ 53fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define VALBUF_SIZE 16384 54fe42c8a09884c2305ce101b1f3438e077d282495mbligh 55fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define KVARS 32 56fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define KVARNAMELEN 32 57fe42c8a09884c2305ce101b1f3438e077d282495mbligh 58fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Struct to transfer parameters to the thread */ 59fe42c8a09884c2305ce101b1f3438e077d282495mblighstruct thread_param { 60fe42c8a09884c2305ce101b1f3438e077d282495mbligh int prio; 61fe42c8a09884c2305ce101b1f3438e077d282495mbligh int mode; 62fe42c8a09884c2305ce101b1f3438e077d282495mbligh int timermode; 63fe42c8a09884c2305ce101b1f3438e077d282495mbligh int signal; 64fe42c8a09884c2305ce101b1f3438e077d282495mbligh int clock; 65fe42c8a09884c2305ce101b1f3438e077d282495mbligh unsigned long max_cycles; 66fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct thread_stat *stats; 67fe42c8a09884c2305ce101b1f3438e077d282495mbligh int bufmsk; 68fe42c8a09884c2305ce101b1f3438e077d282495mbligh unsigned long interval; 69fe42c8a09884c2305ce101b1f3438e077d282495mbligh}; 70fe42c8a09884c2305ce101b1f3438e077d282495mbligh 71fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Struct for statistics */ 72fe42c8a09884c2305ce101b1f3438e077d282495mblighstruct thread_stat { 73fe42c8a09884c2305ce101b1f3438e077d282495mbligh unsigned long cycles; 74fe42c8a09884c2305ce101b1f3438e077d282495mbligh unsigned long cyclesread; 75fe42c8a09884c2305ce101b1f3438e077d282495mbligh long min; 76fe42c8a09884c2305ce101b1f3438e077d282495mbligh long max; 77fe42c8a09884c2305ce101b1f3438e077d282495mbligh long act; 78fe42c8a09884c2305ce101b1f3438e077d282495mbligh double avg; 79fe42c8a09884c2305ce101b1f3438e077d282495mbligh long *values; 80fe42c8a09884c2305ce101b1f3438e077d282495mbligh pthread_t thread; 81fe42c8a09884c2305ce101b1f3438e077d282495mbligh int threadstarted; 82fe42c8a09884c2305ce101b1f3438e077d282495mbligh int tid; 83fe42c8a09884c2305ce101b1f3438e077d282495mbligh}; 84fe42c8a09884c2305ce101b1f3438e077d282495mbligh 85fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int shutdown; 86fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int tracelimit = 0; 87fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int ftrace = 0; 88fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int oldtrace = 0; 89fe42c8a09884c2305ce101b1f3438e077d282495mbligh 90fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Backup of kernel variables that we modify */ 91fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic struct kvars { 92fe42c8a09884c2305ce101b1f3438e077d282495mbligh char name[KVARNAMELEN]; 93fe42c8a09884c2305ce101b1f3438e077d282495mbligh int value; 94fe42c8a09884c2305ce101b1f3438e077d282495mbligh} kv[KVARS]; 95fe42c8a09884c2305ce101b1f3438e077d282495mbligh 96fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic char *procfileprefix = "/proc/sys/kernel/"; 97fe42c8a09884c2305ce101b1f3438e077d282495mbligh 98fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int kernvar(int mode, char *name, int *value) 99fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 100fe42c8a09884c2305ce101b1f3438e077d282495mbligh int retval = 1; 101fe42c8a09884c2305ce101b1f3438e077d282495mbligh int procfilepath; 102fe42c8a09884c2305ce101b1f3438e077d282495mbligh char procfilename[128]; 103fe42c8a09884c2305ce101b1f3438e077d282495mbligh 104fe42c8a09884c2305ce101b1f3438e077d282495mbligh strncpy(procfilename, procfileprefix, sizeof(procfilename)); 105fe42c8a09884c2305ce101b1f3438e077d282495mbligh strncat(procfilename, name, 106fe42c8a09884c2305ce101b1f3438e077d282495mbligh sizeof(procfilename) - sizeof(procfileprefix)); 107fe42c8a09884c2305ce101b1f3438e077d282495mbligh procfilepath = open(procfilename, mode); 108fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (procfilepath >= 0) { 109fe42c8a09884c2305ce101b1f3438e077d282495mbligh char buffer[32]; 110fe42c8a09884c2305ce101b1f3438e077d282495mbligh 111fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (mode == O_RDONLY) { 112fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (read(procfilepath, buffer, sizeof(buffer)) > 0) { 113fe42c8a09884c2305ce101b1f3438e077d282495mbligh char *endptr; 114fe42c8a09884c2305ce101b1f3438e077d282495mbligh *value = strtol(buffer, &endptr, 0); 115fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (endptr != buffer) 116fe42c8a09884c2305ce101b1f3438e077d282495mbligh retval = 0; 117fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 118fe42c8a09884c2305ce101b1f3438e077d282495mbligh } else if (mode == O_WRONLY) { 119fe42c8a09884c2305ce101b1f3438e077d282495mbligh snprintf(buffer, sizeof(buffer), "%d\n", *value); 120fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (write(procfilepath, buffer, strlen(buffer)) 121fe42c8a09884c2305ce101b1f3438e077d282495mbligh == strlen(buffer)) 122fe42c8a09884c2305ce101b1f3438e077d282495mbligh retval = 0; 123fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 124fe42c8a09884c2305ce101b1f3438e077d282495mbligh close(procfilepath); 125fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 126fe42c8a09884c2305ce101b1f3438e077d282495mbligh return retval; 127fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 128fe42c8a09884c2305ce101b1f3438e077d282495mbligh 129fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void setkernvar(char *name, int value) 130fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 131fe42c8a09884c2305ce101b1f3438e077d282495mbligh int i; 132fe42c8a09884c2305ce101b1f3438e077d282495mbligh int oldvalue; 133fe42c8a09884c2305ce101b1f3438e077d282495mbligh 134fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (kernvar(O_RDONLY, name, &oldvalue)) 135fe42c8a09884c2305ce101b1f3438e077d282495mbligh fprintf(stderr, "could not retrieve %s\n", name); 136fe42c8a09884c2305ce101b1f3438e077d282495mbligh else { 137fe42c8a09884c2305ce101b1f3438e077d282495mbligh for (i = 0; i < KVARS; i++) { 138fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!strcmp(kv[i].name, name)) 139fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 140fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (kv[i].name[0] == '\0') { 141fe42c8a09884c2305ce101b1f3438e077d282495mbligh strncpy(kv[i].name, name, sizeof(kv[i].name)); 142fe42c8a09884c2305ce101b1f3438e077d282495mbligh kv[i].value = oldvalue; 143fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 144fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 145fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 146fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (i == KVARS) 147fe42c8a09884c2305ce101b1f3438e077d282495mbligh fprintf(stderr, "could not backup %s (%d)\n", name, 148fe42c8a09884c2305ce101b1f3438e077d282495mbligh oldvalue); 149fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 150fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (kernvar(O_WRONLY, name, &value)) 151fe42c8a09884c2305ce101b1f3438e077d282495mbligh fprintf(stderr, "could not set %s to %d\n", name, value); 152fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 153fe42c8a09884c2305ce101b1f3438e077d282495mbligh 154fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void restorekernvars(void) 155fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 156fe42c8a09884c2305ce101b1f3438e077d282495mbligh int i; 157fe42c8a09884c2305ce101b1f3438e077d282495mbligh 158fe42c8a09884c2305ce101b1f3438e077d282495mbligh for (i = 0; i < KVARS; i++) { 159fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (kv[i].name[0] != '\0') { 160fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (kernvar(O_WRONLY, kv[i].name, &kv[i].value)) 161fe42c8a09884c2305ce101b1f3438e077d282495mbligh fprintf(stderr, "could not restore %s to %d\n", 162fe42c8a09884c2305ce101b1f3438e077d282495mbligh kv[i].name, kv[i].value); 163fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 164fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 165fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 166fe42c8a09884c2305ce101b1f3438e077d282495mbligh 167fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic inline void tsnorm(struct timespec *ts) 168fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 169fe42c8a09884c2305ce101b1f3438e077d282495mbligh while (ts->tv_nsec >= NSEC_PER_SEC) { 170fe42c8a09884c2305ce101b1f3438e077d282495mbligh ts->tv_nsec -= NSEC_PER_SEC; 171fe42c8a09884c2305ce101b1f3438e077d282495mbligh ts->tv_sec++; 172fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 173fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 174fe42c8a09884c2305ce101b1f3438e077d282495mbligh 175fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic inline long calcdiff(struct timespec t1, struct timespec t2) 176fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 177fe42c8a09884c2305ce101b1f3438e077d282495mbligh long diff; 178fe42c8a09884c2305ce101b1f3438e077d282495mbligh diff = USEC_PER_SEC * ((int) t1.tv_sec - (int) t2.tv_sec); 179fe42c8a09884c2305ce101b1f3438e077d282495mbligh diff += ((int) t1.tv_nsec - (int) t2.tv_nsec) / 1000; 180fe42c8a09884c2305ce101b1f3438e077d282495mbligh return diff; 181fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 182fe42c8a09884c2305ce101b1f3438e077d282495mbligh 183fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* 184fe42c8a09884c2305ce101b1f3438e077d282495mbligh * timer thread 185fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 186fe42c8a09884c2305ce101b1f3438e077d282495mbligh * Modes: 187fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - clock_nanosleep based 188fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - cyclic timer based 189fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 190fe42c8a09884c2305ce101b1f3438e077d282495mbligh * Clock: 191fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_MONOTONIC 192fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_REALTIME 193fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_MONOTONIC_HR 194fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_REALTIME_HR 195fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 196fe42c8a09884c2305ce101b1f3438e077d282495mbligh */ 197fe42c8a09884c2305ce101b1f3438e077d282495mblighvoid *timerthread(void *param) 198fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 199fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct thread_param *par = param; 200fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct sched_param schedp; 201fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct sigevent sigev; 202fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigset_t sigset; 203fe42c8a09884c2305ce101b1f3438e077d282495mbligh timer_t timer; 204fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct timespec now, next, interval; 205fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct itimerval itimer; 206fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct itimerspec tspec; 207fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct thread_stat *stat = par->stats; 208fe42c8a09884c2305ce101b1f3438e077d282495mbligh int policy = par->prio ? SCHED_FIFO : SCHED_OTHER; 209fe42c8a09884c2305ce101b1f3438e077d282495mbligh int stopped = 0; 210fe42c8a09884c2305ce101b1f3438e077d282495mbligh 211fe42c8a09884c2305ce101b1f3438e077d282495mbligh interval.tv_sec = par->interval / USEC_PER_SEC; 212fe42c8a09884c2305ce101b1f3438e077d282495mbligh interval.tv_nsec = (par->interval % USEC_PER_SEC) * 1000; 213fe42c8a09884c2305ce101b1f3438e077d282495mbligh 214fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (tracelimit) { 215fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_all_cpus", 1); 216fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_freerunning", 1); 217fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_print_on_crash", 0); 218fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_user_triggered", 1); 219fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_user_trigger_irq", -1); 220fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_verbose", 0); 221fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("preempt_thresh", 0); 222fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("wakeup_timing", 0); 223fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("preempt_max_latency", 0); 224fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (ftrace) 225fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("mcount_enabled", 1); 226fe42c8a09884c2305ce101b1f3438e077d282495mbligh setkernvar("trace_enabled", 1); 227fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 228fe42c8a09884c2305ce101b1f3438e077d282495mbligh 229fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->tid = gettid(); 230fe42c8a09884c2305ce101b1f3438e077d282495mbligh 231fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigemptyset(&sigset); 232fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigaddset(&sigset, par->signal); 233fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigprocmask(SIG_BLOCK, &sigset, NULL); 234fe42c8a09884c2305ce101b1f3438e077d282495mbligh 235fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->mode == MODE_CYCLIC) { 236fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL; 237fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigev.sigev_signo = par->signal; 238fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigev.sigev_notify_thread_id = stat->tid; 239fe42c8a09884c2305ce101b1f3438e077d282495mbligh timer_create(par->clock, &sigev, &timer); 240fe42c8a09884c2305ce101b1f3438e077d282495mbligh tspec.it_interval = interval; 241fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 242fe42c8a09884c2305ce101b1f3438e077d282495mbligh 243fe42c8a09884c2305ce101b1f3438e077d282495mbligh memset(&schedp, 0, sizeof(schedp)); 244fe42c8a09884c2305ce101b1f3438e077d282495mbligh schedp.sched_priority = par->prio; 245fe42c8a09884c2305ce101b1f3438e077d282495mbligh sched_setscheduler(0, policy, &schedp); 246fe42c8a09884c2305ce101b1f3438e077d282495mbligh 247fe42c8a09884c2305ce101b1f3438e077d282495mbligh /* Get current time */ 248fe42c8a09884c2305ce101b1f3438e077d282495mbligh clock_gettime(par->clock, &now); 249fe42c8a09884c2305ce101b1f3438e077d282495mbligh next = now; 250fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_sec++; 251fe42c8a09884c2305ce101b1f3438e077d282495mbligh 252fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->mode == MODE_CYCLIC) { 253fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->timermode == TIMER_ABSTIME) 254fe42c8a09884c2305ce101b1f3438e077d282495mbligh tspec.it_value = next; 255fe42c8a09884c2305ce101b1f3438e077d282495mbligh else { 256fe42c8a09884c2305ce101b1f3438e077d282495mbligh tspec.it_value.tv_nsec = 0; 257fe42c8a09884c2305ce101b1f3438e077d282495mbligh tspec.it_value.tv_sec = 1; 258fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 259fe42c8a09884c2305ce101b1f3438e077d282495mbligh timer_settime(timer, par->timermode, &tspec, NULL); 260fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 261fe42c8a09884c2305ce101b1f3438e077d282495mbligh 262fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->mode == MODE_SYS_ITIMER) { 263fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_value.tv_sec = 1; 264fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_value.tv_usec = 0; 265fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_interval.tv_sec = interval.tv_sec; 266fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_interval.tv_usec = interval.tv_nsec / 1000; 267fe42c8a09884c2305ce101b1f3438e077d282495mbligh setitimer (ITIMER_REAL, &itimer, NULL); 268fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 269fe42c8a09884c2305ce101b1f3438e077d282495mbligh 270fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->threadstarted++; 271fe42c8a09884c2305ce101b1f3438e077d282495mbligh 272fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (tracelimit) { 273fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (oldtrace) 274fe42c8a09884c2305ce101b1f3438e077d282495mbligh gettimeofday(0,(struct timezone *)1); 275fe42c8a09884c2305ce101b1f3438e077d282495mbligh else 276fe42c8a09884c2305ce101b1f3438e077d282495mbligh prctl(0, 1); 277fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 278fe42c8a09884c2305ce101b1f3438e077d282495mbligh while (!shutdown) { 279fe42c8a09884c2305ce101b1f3438e077d282495mbligh 280fe42c8a09884c2305ce101b1f3438e077d282495mbligh long diff; 281fe42c8a09884c2305ce101b1f3438e077d282495mbligh int sigs; 282fe42c8a09884c2305ce101b1f3438e077d282495mbligh 283fe42c8a09884c2305ce101b1f3438e077d282495mbligh /* Wait for next period */ 284fe42c8a09884c2305ce101b1f3438e077d282495mbligh switch (par->mode) { 285fe42c8a09884c2305ce101b1f3438e077d282495mbligh case MODE_CYCLIC: 286fe42c8a09884c2305ce101b1f3438e077d282495mbligh case MODE_SYS_ITIMER: 287fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (sigwait(&sigset, &sigs) < 0) 288fe42c8a09884c2305ce101b1f3438e077d282495mbligh goto out; 289fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 290fe42c8a09884c2305ce101b1f3438e077d282495mbligh 291fe42c8a09884c2305ce101b1f3438e077d282495mbligh case MODE_CLOCK_NANOSLEEP: 292fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->timermode == TIMER_ABSTIME) 293fe42c8a09884c2305ce101b1f3438e077d282495mbligh clock_nanosleep(par->clock, TIMER_ABSTIME, 294fe42c8a09884c2305ce101b1f3438e077d282495mbligh &next, NULL); 295fe42c8a09884c2305ce101b1f3438e077d282495mbligh else { 296fe42c8a09884c2305ce101b1f3438e077d282495mbligh clock_gettime(par->clock, &now); 297fe42c8a09884c2305ce101b1f3438e077d282495mbligh clock_nanosleep(par->clock, TIMER_RELTIME, 298fe42c8a09884c2305ce101b1f3438e077d282495mbligh &interval, NULL); 299fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_sec = now.tv_sec + interval.tv_sec; 300fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_nsec = now.tv_nsec + interval.tv_nsec; 301fe42c8a09884c2305ce101b1f3438e077d282495mbligh tsnorm(&next); 302fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 303fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 304fe42c8a09884c2305ce101b1f3438e077d282495mbligh 305fe42c8a09884c2305ce101b1f3438e077d282495mbligh case MODE_SYS_NANOSLEEP: 306fe42c8a09884c2305ce101b1f3438e077d282495mbligh clock_gettime(par->clock, &now); 307fe42c8a09884c2305ce101b1f3438e077d282495mbligh nanosleep(&interval, NULL); 308fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_sec = now.tv_sec + interval.tv_sec; 309fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_nsec = now.tv_nsec + interval.tv_nsec; 310fe42c8a09884c2305ce101b1f3438e077d282495mbligh tsnorm(&next); 311fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 312fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 313fe42c8a09884c2305ce101b1f3438e077d282495mbligh clock_gettime(par->clock, &now); 314fe42c8a09884c2305ce101b1f3438e077d282495mbligh 315fe42c8a09884c2305ce101b1f3438e077d282495mbligh diff = calcdiff(now, next); 316fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (diff < stat->min) 317fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->min = diff; 318fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (diff > stat->max) 319fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->max = diff; 320fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->avg += (double) diff; 321fe42c8a09884c2305ce101b1f3438e077d282495mbligh 322fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!stopped && tracelimit && (diff > tracelimit)) { 323fe42c8a09884c2305ce101b1f3438e077d282495mbligh stopped++; 324fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (oldtrace) 325fe42c8a09884c2305ce101b1f3438e077d282495mbligh gettimeofday(0,0); 326fe42c8a09884c2305ce101b1f3438e077d282495mbligh else 327fe42c8a09884c2305ce101b1f3438e077d282495mbligh prctl(0, 0); 328fe42c8a09884c2305ce101b1f3438e077d282495mbligh shutdown++; 329fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 330fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->act = diff; 331fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->cycles++; 332fe42c8a09884c2305ce101b1f3438e077d282495mbligh 333fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->bufmsk) 334fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->values[stat->cycles & par->bufmsk] = diff; 335fe42c8a09884c2305ce101b1f3438e077d282495mbligh 336fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_sec += interval.tv_sec; 337fe42c8a09884c2305ce101b1f3438e077d282495mbligh next.tv_nsec += interval.tv_nsec; 338fe42c8a09884c2305ce101b1f3438e077d282495mbligh tsnorm(&next); 339fe42c8a09884c2305ce101b1f3438e077d282495mbligh 340fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->max_cycles && par->max_cycles == stat->cycles) 341fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 342fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 343fe42c8a09884c2305ce101b1f3438e077d282495mbligh 344fe42c8a09884c2305ce101b1f3438e077d282495mblighout: 345fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->mode == MODE_CYCLIC) 346fe42c8a09884c2305ce101b1f3438e077d282495mbligh timer_delete(timer); 347fe42c8a09884c2305ce101b1f3438e077d282495mbligh 348fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (par->mode == MODE_SYS_ITIMER) { 349fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_value.tv_sec = 0; 350fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_value.tv_usec = 0; 351fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_interval.tv_sec = 0; 352fe42c8a09884c2305ce101b1f3438e077d282495mbligh itimer.it_interval.tv_usec = 0; 353fe42c8a09884c2305ce101b1f3438e077d282495mbligh setitimer (ITIMER_REAL, &itimer, NULL); 354fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 355fe42c8a09884c2305ce101b1f3438e077d282495mbligh 356fe42c8a09884c2305ce101b1f3438e077d282495mbligh /* switch to normal */ 357fe42c8a09884c2305ce101b1f3438e077d282495mbligh schedp.sched_priority = 0; 358fe42c8a09884c2305ce101b1f3438e077d282495mbligh sched_setscheduler(0, SCHED_OTHER, &schedp); 359fe42c8a09884c2305ce101b1f3438e077d282495mbligh 360fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->threadstarted = -1; 361fe42c8a09884c2305ce101b1f3438e077d282495mbligh 362fe42c8a09884c2305ce101b1f3438e077d282495mbligh return NULL; 363fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 364fe42c8a09884c2305ce101b1f3438e077d282495mbligh 365fe42c8a09884c2305ce101b1f3438e077d282495mbligh 366fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Print usage information */ 367fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void display_help(void) 368fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 369fe42c8a09884c2305ce101b1f3438e077d282495mbligh printf("cyclictest %s\n", VERSION_STRING); 370fe42c8a09884c2305ce101b1f3438e077d282495mbligh printf("Usage:\n" 371fe42c8a09884c2305ce101b1f3438e077d282495mbligh "cyclictest <options>\n\n" 372fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n" 373fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-c CLOCK --clock=CLOCK select clock\n" 374fe42c8a09884c2305ce101b1f3438e077d282495mbligh " 0 = CLOCK_MONOTONIC (default)\n" 375fe42c8a09884c2305ce101b1f3438e077d282495mbligh " 1 = CLOCK_REALTIME\n" 376fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-d DIST --distance=DIST distance of thread intervals in us default=500\n" 377fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-f function trace (when -b is active)\n" 378fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-i INTV --interval=INTV base interval of thread in us default=1000\n" 379fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n" 380fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-n --nanosleep use clock_nanosleep\n" 381fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-p PRIO --prio=PRIO priority of highest prio thread\n" 382fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-q --quiet print only a summary on exit\n" 383fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-r --relative use relative timer instead of absolute\n" 384fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-s --system use sys_nanosleep and sys_setitimer\n" 385fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-t NUM --threads=NUM number of threads: default=1\n" 386fe42c8a09884c2305ce101b1f3438e077d282495mbligh "-v --verbose output values on stdout for statistics\n" 387fe42c8a09884c2305ce101b1f3438e077d282495mbligh " format: n:c:v n=tasknum c=count v=value in us\n"); 388fe42c8a09884c2305ce101b1f3438e077d282495mbligh exit(0); 389fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 390fe42c8a09884c2305ce101b1f3438e077d282495mbligh 391fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int use_nanosleep; 392fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int timermode = TIMER_ABSTIME; 393fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int use_system; 394fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int priority; 395fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int num_threads = 1; 396fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int max_cycles; 397fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int clocksel = 0; 398fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int verbose; 399fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int quiet; 400fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int interval = 1000; 401fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int distance = 500; 402fe42c8a09884c2305ce101b1f3438e077d282495mbligh 403fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int clocksources[] = { 404fe42c8a09884c2305ce101b1f3438e077d282495mbligh CLOCK_MONOTONIC, 405fe42c8a09884c2305ce101b1f3438e077d282495mbligh CLOCK_REALTIME, 406fe42c8a09884c2305ce101b1f3438e077d282495mbligh}; 407fe42c8a09884c2305ce101b1f3438e077d282495mbligh 408fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Process commandline options */ 409fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void process_options (int argc, char *argv[]) 410fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 411fe42c8a09884c2305ce101b1f3438e077d282495mbligh int error = 0; 412fe42c8a09884c2305ce101b1f3438e077d282495mbligh for (;;) { 413fe42c8a09884c2305ce101b1f3438e077d282495mbligh int option_index = 0; 414fe42c8a09884c2305ce101b1f3438e077d282495mbligh /** Options for getopt */ 415fe42c8a09884c2305ce101b1f3438e077d282495mbligh static struct option long_options[] = { 416fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"breaktrace", required_argument, NULL, 'b'}, 417fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"clock", required_argument, NULL, 'c'}, 418fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"distance", required_argument, NULL, 'd'}, 419fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"ftrace", no_argument, NULL, 'f'}, 420fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"interval", required_argument, NULL, 'i'}, 421fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"loops", required_argument, NULL, 'l'}, 422fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"nanosleep", no_argument, NULL, 'n'}, 423fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"priority", required_argument, NULL, 'p'}, 424fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"quiet", no_argument, NULL, 'q'}, 425fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"relative", no_argument, NULL, 'r'}, 426fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"system", no_argument, NULL, 's'}, 427fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"threads", required_argument, NULL, 't'}, 428fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"verbose", no_argument, NULL, 'v'}, 429fe42c8a09884c2305ce101b1f3438e077d282495mbligh {"help", no_argument, NULL, '?'}, 430fe42c8a09884c2305ce101b1f3438e077d282495mbligh {NULL, 0, NULL, 0} 431fe42c8a09884c2305ce101b1f3438e077d282495mbligh }; 432fe42c8a09884c2305ce101b1f3438e077d282495mbligh int c = getopt_long (argc, argv, "b:c:d:fi:l:np:qrst:v", 433fe42c8a09884c2305ce101b1f3438e077d282495mbligh long_options, &option_index); 434fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (c == -1) 435fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 436fe42c8a09884c2305ce101b1f3438e077d282495mbligh switch (c) { 437fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'b': tracelimit = atoi(optarg); break; 438fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'c': clocksel = atoi(optarg); break; 439fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'd': distance = atoi(optarg); break; 440fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'f': ftrace = 1; break; 441fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'i': interval = atoi(optarg); break; 442fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'l': max_cycles = atoi(optarg); break; 443fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'n': use_nanosleep = MODE_CLOCK_NANOSLEEP; break; 444fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'p': priority = atoi(optarg); break; 445fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'q': quiet = 1; break; 446fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'r': timermode = TIMER_RELTIME; break; 447fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 's': use_system = MODE_SYS_OFFSET; break; 448fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 't': num_threads = atoi(optarg); break; 449fe42c8a09884c2305ce101b1f3438e077d282495mbligh case 'v': verbose = 1; break; 450fe42c8a09884c2305ce101b1f3438e077d282495mbligh case '?': error = 1; break; 451fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 452fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 453fe42c8a09884c2305ce101b1f3438e077d282495mbligh 454fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (clocksel < 0 || clocksel > ARRAY_SIZE(clocksources)) 455fe42c8a09884c2305ce101b1f3438e077d282495mbligh error = 1; 456fe42c8a09884c2305ce101b1f3438e077d282495mbligh 457fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (priority < 0 || priority > 99) 458fe42c8a09884c2305ce101b1f3438e077d282495mbligh error = 1; 459fe42c8a09884c2305ce101b1f3438e077d282495mbligh 460fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (num_threads < 1) 461fe42c8a09884c2305ce101b1f3438e077d282495mbligh error = 1; 462fe42c8a09884c2305ce101b1f3438e077d282495mbligh 463fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (error) 464fe42c8a09884c2305ce101b1f3438e077d282495mbligh display_help (); 465fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 466fe42c8a09884c2305ce101b1f3438e077d282495mbligh 467fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void check_kernel(void) 468fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 469fe42c8a09884c2305ce101b1f3438e077d282495mbligh size_t len; 470fe42c8a09884c2305ce101b1f3438e077d282495mbligh char ver[256]; 471fe42c8a09884c2305ce101b1f3438e077d282495mbligh int fd, maj, min, sub; 472fe42c8a09884c2305ce101b1f3438e077d282495mbligh 473fe42c8a09884c2305ce101b1f3438e077d282495mbligh fd = open("/proc/version", O_RDONLY, 0666); 474fe42c8a09884c2305ce101b1f3438e077d282495mbligh len = read(fd, ver, 255); 475fe42c8a09884c2305ce101b1f3438e077d282495mbligh close(fd); 476fe42c8a09884c2305ce101b1f3438e077d282495mbligh ver[len-1] = 0x0; 477fe42c8a09884c2305ce101b1f3438e077d282495mbligh sscanf(ver, "Linux version %d.%d.%d", &maj, &min, &sub); 478fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (maj == 2 && min == 6 && sub < 18) 479fe42c8a09884c2305ce101b1f3438e077d282495mbligh oldtrace = 1; 480fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 481fe42c8a09884c2305ce101b1f3438e077d282495mbligh 482fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int check_timer(void) 483fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 484fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct timespec ts; 485fe42c8a09884c2305ce101b1f3438e077d282495mbligh 486fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (clock_getres(CLOCK_MONOTONIC, &ts)) 487fe42c8a09884c2305ce101b1f3438e077d282495mbligh return 1; 488fe42c8a09884c2305ce101b1f3438e077d282495mbligh 489fe42c8a09884c2305ce101b1f3438e077d282495mbligh return (ts.tv_sec != 0 || ts.tv_nsec != 1); 490fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 491fe42c8a09884c2305ce101b1f3438e077d282495mbligh 492fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void sighand(int sig) 493fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 494fe42c8a09884c2305ce101b1f3438e077d282495mbligh shutdown = 1; 495fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 496fe42c8a09884c2305ce101b1f3438e077d282495mbligh 497fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void print_stat(struct thread_param *par, int index, int verbose) 498fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 499fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct thread_stat *stat = par->stats; 500fe42c8a09884c2305ce101b1f3438e077d282495mbligh 501fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!verbose) { 502fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (quiet != 1) { 503fe42c8a09884c2305ce101b1f3438e077d282495mbligh printf("T:%2d (%5d) P:%2d I:%ld C:%7lu " 504fe42c8a09884c2305ce101b1f3438e077d282495mbligh "Min:%7ld Act:%5ld Avg:%5ld Max:%8ld\n", 505fe42c8a09884c2305ce101b1f3438e077d282495mbligh index, stat->tid, par->prio, par->interval, 506fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->cycles, stat->min, stat->act, 507fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->cycles ? 508fe42c8a09884c2305ce101b1f3438e077d282495mbligh (long)(stat->avg/stat->cycles) : 0, stat->max); 509fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 510fe42c8a09884c2305ce101b1f3438e077d282495mbligh } else { 511fe42c8a09884c2305ce101b1f3438e077d282495mbligh while (stat->cycles != stat->cyclesread) { 512fe42c8a09884c2305ce101b1f3438e077d282495mbligh long diff = stat->values[stat->cyclesread & par->bufmsk]; 513fe42c8a09884c2305ce101b1f3438e077d282495mbligh printf("%8d:%8lu:%8ld\n", index, stat->cyclesread, diff); 514fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat->cyclesread++; 515fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 516fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 517fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 518fe42c8a09884c2305ce101b1f3438e077d282495mbligh 519fe42c8a09884c2305ce101b1f3438e077d282495mblighint main(int argc, char **argv) 520fe42c8a09884c2305ce101b1f3438e077d282495mbligh{ 521fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigset_t sigset; 522fe42c8a09884c2305ce101b1f3438e077d282495mbligh int signum = SIGALRM; 523fe42c8a09884c2305ce101b1f3438e077d282495mbligh int mode; 524fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct thread_param *par; 525fe42c8a09884c2305ce101b1f3438e077d282495mbligh struct thread_stat *stat; 526fe42c8a09884c2305ce101b1f3438e077d282495mbligh int i, ret = -1; 527fe42c8a09884c2305ce101b1f3438e077d282495mbligh 528fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (geteuid()) { 529fe42c8a09884c2305ce101b1f3438e077d282495mbligh fprintf(stderr, "cyclictest: need to run as root!\n"); 530fe42c8a09884c2305ce101b1f3438e077d282495mbligh exit(-1); 531fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 532fe42c8a09884c2305ce101b1f3438e077d282495mbligh 533fe42c8a09884c2305ce101b1f3438e077d282495mbligh process_options(argc, argv); 534fe42c8a09884c2305ce101b1f3438e077d282495mbligh 535fe42c8a09884c2305ce101b1f3438e077d282495mbligh check_kernel(); 536fe42c8a09884c2305ce101b1f3438e077d282495mbligh 537fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (check_timer()) 538fe42c8a09884c2305ce101b1f3438e077d282495mbligh fprintf(stderr, "WARNING: High resolution timers not available\n"); 539fe42c8a09884c2305ce101b1f3438e077d282495mbligh 540fe42c8a09884c2305ce101b1f3438e077d282495mbligh mode = use_nanosleep + use_system; 541fe42c8a09884c2305ce101b1f3438e077d282495mbligh 542fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigemptyset(&sigset); 543fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigaddset(&sigset, signum); 544fe42c8a09884c2305ce101b1f3438e077d282495mbligh sigprocmask (SIG_BLOCK, &sigset, NULL); 545fe42c8a09884c2305ce101b1f3438e077d282495mbligh 546fe42c8a09884c2305ce101b1f3438e077d282495mbligh signal(SIGINT, sighand); 547fe42c8a09884c2305ce101b1f3438e077d282495mbligh signal(SIGTERM, sighand); 548fe42c8a09884c2305ce101b1f3438e077d282495mbligh 549fe42c8a09884c2305ce101b1f3438e077d282495mbligh par = calloc(num_threads, sizeof(struct thread_param)); 550fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!par) 551fe42c8a09884c2305ce101b1f3438e077d282495mbligh goto out; 552fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat = calloc(num_threads, sizeof(struct thread_stat)); 553fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!stat) 554fe42c8a09884c2305ce101b1f3438e077d282495mbligh goto outpar; 555fe42c8a09884c2305ce101b1f3438e077d282495mbligh 556fe42c8a09884c2305ce101b1f3438e077d282495mbligh for (i = 0; i < num_threads; i++) { 557fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (verbose) { 558fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat[i].values = calloc(VALBUF_SIZE, sizeof(long)); 559fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!stat[i].values) 560fe42c8a09884c2305ce101b1f3438e077d282495mbligh goto outall; 561fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].bufmsk = VALBUF_SIZE - 1; 562fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 563fe42c8a09884c2305ce101b1f3438e077d282495mbligh 564fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].prio = priority; 565fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (priority) 566fe42c8a09884c2305ce101b1f3438e077d282495mbligh priority--; 567fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].clock = clocksources[clocksel]; 568fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].mode = mode; 569fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].timermode = timermode; 570fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].signal = signum; 571fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].interval = interval; 572fe42c8a09884c2305ce101b1f3438e077d282495mbligh interval += distance; 573fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].max_cycles = max_cycles; 574fe42c8a09884c2305ce101b1f3438e077d282495mbligh par[i].stats = &stat[i]; 575fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat[i].min = 1000000; 576fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat[i].max = -1000000; 577fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat[i].avg = 0.0; 578fe42c8a09884c2305ce101b1f3438e077d282495mbligh pthread_create(&stat[i].thread, NULL, timerthread, &par[i]); 579fe42c8a09884c2305ce101b1f3438e077d282495mbligh stat[i].threadstarted = 1; 580fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 581fe42c8a09884c2305ce101b1f3438e077d282495mbligh 582fe42c8a09884c2305ce101b1f3438e077d282495mbligh while (!shutdown) { 583fe42c8a09884c2305ce101b1f3438e077d282495mbligh char lavg[256]; 584fe42c8a09884c2305ce101b1f3438e077d282495mbligh int fd, len, allstopped = 0; 585fe42c8a09884c2305ce101b1f3438e077d282495mbligh 586fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!verbose && !quiet) { 587fe42c8a09884c2305ce101b1f3438e077d282495mbligh fd = open("/proc/loadavg", O_RDONLY, 0666); 588fe42c8a09884c2305ce101b1f3438e077d282495mbligh len = read(fd, &lavg, 255); 589fe42c8a09884c2305ce101b1f3438e077d282495mbligh close(fd); 590fe42c8a09884c2305ce101b1f3438e077d282495mbligh lavg[len-1] = 0x0; 591fe42c8a09884c2305ce101b1f3438e077d282495mbligh printf("%s \n\n", lavg); 592fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 593fe42c8a09884c2305ce101b1f3438e077d282495mbligh 594fe42c8a09884c2305ce101b1f3438e077d282495mbligh for (i = 0; i < num_threads; i++) { 595fe42c8a09884c2305ce101b1f3438e077d282495mbligh 596fe42c8a09884c2305ce101b1f3438e077d282495mbligh print_stat(&par[i], i, verbose); 597fe42c8a09884c2305ce101b1f3438e077d282495mbligh if(max_cycles && stat[i].cycles >= max_cycles) 598fe42c8a09884c2305ce101b1f3438e077d282495mbligh allstopped++; 599fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 600fe42c8a09884c2305ce101b1f3438e077d282495mbligh usleep(10000); 601fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (shutdown || allstopped) 602fe42c8a09884c2305ce101b1f3438e077d282495mbligh break; 603fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (!verbose && !quiet) 604fe42c8a09884c2305ce101b1f3438e077d282495mbligh printf("\033[%dA", num_threads + 2); 605fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 606fe42c8a09884c2305ce101b1f3438e077d282495mbligh ret = 0; 607fe42c8a09884c2305ce101b1f3438e077d282495mbligh outall: 608fe42c8a09884c2305ce101b1f3438e077d282495mbligh shutdown = 1; 609fe42c8a09884c2305ce101b1f3438e077d282495mbligh usleep(50000); 610fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (quiet) 611fe42c8a09884c2305ce101b1f3438e077d282495mbligh quiet = 2; 612fe42c8a09884c2305ce101b1f3438e077d282495mbligh for (i = 0; i < num_threads; i++) { 613fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (stat[i].threadstarted > 0) 614fe42c8a09884c2305ce101b1f3438e077d282495mbligh pthread_kill(stat[i].thread, SIGTERM); 615fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (stat[i].threadstarted) { 616fe42c8a09884c2305ce101b1f3438e077d282495mbligh pthread_join(stat[i].thread, NULL); 617fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (quiet) 618fe42c8a09884c2305ce101b1f3438e077d282495mbligh print_stat(&par[i], i, 0); 619fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 620fe42c8a09884c2305ce101b1f3438e077d282495mbligh if (stat[i].values) 621fe42c8a09884c2305ce101b1f3438e077d282495mbligh free(stat[i].values); 622fe42c8a09884c2305ce101b1f3438e077d282495mbligh } 623fe42c8a09884c2305ce101b1f3438e077d282495mbligh free(stat); 624fe42c8a09884c2305ce101b1f3438e077d282495mbligh outpar: 625fe42c8a09884c2305ce101b1f3438e077d282495mbligh free(par); 626fe42c8a09884c2305ce101b1f3438e077d282495mbligh out: 627fe42c8a09884c2305ce101b1f3438e077d282495mbligh /* Be a nice program, cleanup */ 628fe42c8a09884c2305ce101b1f3438e077d282495mbligh restorekernvars(); 629fe42c8a09884c2305ce101b1f3438e077d282495mbligh 630fe42c8a09884c2305ce101b1f3438e077d282495mbligh exit(ret); 631fe42c8a09884c2305ce101b1f3438e077d282495mbligh} 632