Hi Subrata, This patch places the rt-migrate testcase into the realtime/func/rt-migrate directory.
Signed-off-by: Kiran Prakash <[email protected]> diff -Naur ltp-orig/testcases/realtime/func/Makefile ltp/testcases/realtime/func/Makefile --- ltp-orig/testcases/realtime/func/Makefile 2009-09-04 12:13:40.000000000 +0530 +++ ltp/testcases/realtime/func/Makefile 2009-09-04 12:51:44.000000000 +0530 @@ -17,7 +17,8 @@ sched_football \ sched_jitter \ sched_latency \ - thread_clock + thread_clock \ + rt-migrate all: @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done diff -Naur ltp-orig/testcases/realtime/func/rt-migrate/Makefile ltp/testcases/realtime/func/rt-migrate/Makefile --- ltp-orig/testcases/realtime/func/rt-migrate/Makefile 1970-01-01 05:30:00.000000000 +0530 +++ ltp/testcases/realtime/func/rt-migrate/Makefile 2009-09-04 12:14:11.000000000 +0530 @@ -0,0 +1,21 @@ + +srcdir := ../.. +include $(srcdir)/config.mk + + +SRCS = $(wildcard *.c) + +ifeq ($(HAVE_PI_MUTEX), yes) +TARGETS = $(SRCS:%.c=%) +else +TARGETS = +endif + +all: $(TARGETS) + +install: + @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i; done + +clean: + rm -f $(TARGETS) *~ + diff -Naur ltp-orig/testcases/realtime/func/rt-migrate/rt-migrate.c ltp/testcases/realtime/func/rt-migrate/rt-migrate.c --- ltp-orig/testcases/realtime/func/rt-migrate/rt-migrate.c 1970-01-01 05:30:00.000000000 +0530 +++ ltp/testcases/realtime/func/rt-migrate/rt-migrate.c 2009-09-04 14:42:57.000000000 +0530 @@ -0,0 +1,507 @@ + +/****************************************************************************** + * + * Copyright (C) 2007-2009 Steven Rostedt <[email protected]> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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; version 2 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NAME + * rt-migrate-test.c + * + * DESCRIPTION + * This test makes sure that all the high prio tasks that are in the + * running state are actually running on a CPU if it can. + ** Steps: + * - Creates N+1 threads with lower real time priorities. + * Where N is the number of CPUs in the system. + * - If the thread is high priority, and if a CPU is available, the + * thread runs on that CPU. + * - The thread records the start time and the number of ticks in the run + * interval. + * - The output indicates if lower prio task is quicker than higher + * priority task. + * + * USAGE: + * Use run_auto.sh in the current directory to build and run the test. + * + * AUTHOR + * Steven Rostedt <[email protected]> + * + * HISTORY + * 30 July, 2009: Initial version by Steven Rostedt + * 11 Aug, 2009: Converted the coding style to the one used by the realtime + * testcases by Kiran Prakash + * + */ +#define _GNU_SOURCE +#include <stdio.h> +#ifndef __USE_XOPEN2K +# define __USE_XOPEN2K +#endif +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <stdarg.h> +#include <unistd.h> +#include <ctype.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/time.h> +#include <linux/unistd.h> +#include <sys/syscall.h> +#include <errno.h> +#include <sched.h> +#include <pthread.h> +#include <librttest.h> +#include <libstats.h> + +#define gettid() syscall(__NR_gettid) + +#define VERSION_STRING "V 0.4LTP" + +int nr_tasks; +int lfd; + +int numcpus; +static int mark_fd = -1; +static __thread char buff[BUFSIZ+1]; + +static void setup_ftrace_marker(void) +{ + struct stat st; + char *files[] = { + "/sys/kernel/debug/tracing/trace_marker", + "/debug/tracing/trace_marker", + "/debugfs/tracing/trace_marker", + }; + int ret; + int i; + + for (i = 0; i < (sizeof(files) / sizeof(char *)); i++) { + ret = stat(files[i], &st); + if (ret >= 0) + goto found; + } + /* todo, check mounts system */ + return; +found: + mark_fd = open(files[i], O_WRONLY); +} + +static void ftrace_write(const char *fmt, ...) +{ + va_list ap; + int n; + + if (mark_fd < 0) + return; + + va_start(ap, fmt); + n = vsnprintf(buff, BUFSIZ, fmt, ap); + va_end(ap); + + write(mark_fd, buff, n); +} + +#define INTERVAL 100ULL * NS_PER_MS +#define RUN_INTERVAL 20ULL * NS_PER_MS +#define NR_RUNS 50 +#define PRIO_START 2 +/* 1 millisec off */ +#define MAX_ERR 1000 * NS_PER_US + +#define PROGRESS_CHARS 70 + +static unsigned long long interval = INTERVAL; +static unsigned long long run_interval = RUN_INTERVAL; +static unsigned long long max_err = MAX_ERR; +static int nr_runs = NR_RUNS; +static int prio_start = PRIO_START; +static int check = 1; +static int stop; + +static unsigned long long now; + +static int done; +static int loop; + +static pthread_barrier_t start_barrier; +static pthread_barrier_t end_barrier; +stats_container_t *intervals; +stats_container_t *intervals_length; +stats_container_t *intervals_loops; +static long *thread_pids; + +static void print_progress_bar(int percent) +{ + int i; + int p; + + if (percent > 100) + percent = 100; + + /* Use stderr, so we don't capture it */ + putc('\r', stderr); + putc('|', stderr); + for (i = 0; i < PROGRESS_CHARS; i++) + putc(' ', stderr); + putc('|', stderr); + putc('\r', stderr); + putc('|', stderr); + + p = PROGRESS_CHARS * percent / 100; + + for (i = 0; i < p; i++) + putc('-', stderr); + + fflush(stderr); +} + +static void usage() +{ + rt_help(); + printf("Usage:\n" + "-a priority Priority of the threads" + "-r time Run time (ms) to busy loop the threads (20)\n" + "-t time Sleep time (ms) between intervals (100)\n" + "-e time Max allowed error (microsecs)\n" + "-l loops Number of iterations to run (50)\n" + ); +} + +static void parse_args(int c, char *v) +{ + switch (c) { + case 'a': prio_start = atoi(v); break; + case 'r': + run_interval = atoi(v); + break; + case 't': interval = atoi(v); break; + case 'l': nr_runs = atoi(v); break; + case 'e': max_err = atoi(v) * NS_PER_US; break; + case '?': + case 'h': + usage(); + exit(0); + } +} + +static void record_time(int id, unsigned long long time, unsigned long l) +{ + unsigned long long ltime; + stats_record_t rec; + if (loop >= nr_runs) + return; + time -= now; + ltime = rt_gettime() / NS_PER_US; + ltime -= now; + rec.x = loop; + rec.y = time; + stats_container_append(&intervals[id], rec); + rec.x = loop; + rec.y = ltime; + stats_container_append(&intervals_length[id], rec); + rec.x = loop; + rec.y = l; + stats_container_append(&intervals_loops[id], rec); +} + +static void print_results(void) +{ + int i; + int t; + unsigned long long tasks_max[nr_tasks]; + unsigned long long tasks_min[nr_tasks]; + unsigned long long tasks_avg[nr_tasks]; + + memset(tasks_max, 0, sizeof(tasks_max[0])*nr_tasks); + memset(tasks_min, 0xff, sizeof(tasks_min[0])*nr_tasks); + memset(tasks_avg, 0, sizeof(tasks_avg[0])*nr_tasks); + + printf("Iter: "); + for (t = 0; t < nr_tasks; t++) + printf("%6d ", t); + printf("\n"); + + for (t = 0; t < nr_tasks; t++) { + tasks_max[t] = stats_max(&intervals[t]); + tasks_min[t] = stats_min(&intervals[t]); + tasks_avg[t] = stats_avg(&intervals[t]); + } + for (i = 0; i < nr_runs; i++) { + printf("%4d: ", i); + for (t = 0; t < nr_tasks; t++) + printf("%6lld ", intervals[t].records[i].y); + + printf("\n"); + printf(" len: "); + for (t = 0; t < nr_tasks; t++) + printf("%6lld ", intervals_length[t].records[i].y); + + printf("\n"); + printf(" loops: "); + for (t = 0; t < nr_tasks; t++) + printf("%6ld ", intervals_loops[t].records[i].y); + + printf("\n"); + printf("\n"); + } + + printf("Parent pid: %d\n", getpid()); + + for (t = 0; t < nr_tasks; t++) { + printf(" Task %d (prio %d) (pid %ld):\n", t, t + prio_start, + thread_pids[t]); + printf(" Max: %lld us\n", tasks_max[t]); + printf(" Min: %lld us\n", tasks_min[t]); + printf(" Tot: %lld us\n", tasks_avg[t] * nr_runs); + printf(" Avg: %lld us\n", tasks_avg[t]); + printf("\n"); + } + + printf(" Result: %s\n", (check < 0) ? "FAIL" : "PASS"); +} + +static unsigned long busy_loop(unsigned long long start_time) +{ + unsigned long long time; + unsigned long l = 0; + + do { + l++; + time = rt_gettime(); + } while ((time - start_time) < RUN_INTERVAL); + + return l; +} + +void *start_task(void *data) +{ + struct thread *thr = (struct thread *)data; + long id = (long) thr->arg; + thread_pids[id] = gettid(); + unsigned long long start_time; + int ret; + int high = 0; + cpu_set_t cpumask; + cpu_set_t save_cpumask; + int cpu = 0; + unsigned long l; + long pid; + + ret = sched_getaffinity(0, sizeof(save_cpumask), &save_cpumask); + if (ret < 0) + debug(DBG_ERR, "sched_getaffinity failed: %s\n", strerror(ret)); + + pid = gettid(); + + /* Check if we are the highest prio task */ + if (id == nr_tasks-1) + high = 1; + + while (!done) { + if (high) { + /* rotate around the CPUS */ + if (!CPU_ISSET(cpu, &save_cpumask)) + cpu = 0; + CPU_ZERO(&cpumask); + CPU_SET(cpu, &cpumask); cpu++; + sched_setaffinity(0, sizeof(cpumask), &cpumask); + } + pthread_barrier_wait(&start_barrier); + start_time = rt_gettime(); + ftrace_write("Thread %d: started %lld diff %lld\n", + pid, start_time, start_time - now); + l = busy_loop(start_time); + record_time(id, start_time / NS_PER_US, l); + pthread_barrier_wait(&end_barrier); + } + + return (void *)pid; +} + +static int check_times(int l) +{ + int i; + unsigned long long last; + unsigned long long last_loops; + unsigned long long last_length; + + for (i = 0; i < nr_tasks; i++) { + if (i && last < intervals[i].records[l].y && + ((intervals[i].records[l].y - last) > max_err)) { + /* + * May be a false positive. + * Make sure that we did more loops + * our start is before the end + * and the end should be tested. + */ + if (intervals_loops[i].records[l].y < last_loops || + intervals[i].records[l].y > last_length || + (intervals_length[i].records[l].y > last_length && + intervals_length[i].records[l].y - last_length > + max_err)) { + check = -1; + return 1; + } + } + last = intervals[i].records[l].y; + last_loops = intervals_loops[i].records[l].y; + last_length = intervals_length[i].records[l].y; + } + return 0; +} + +static void stop_log(int sig) +{ + stop = 1; +} + +int main(int argc, char **argv) +{ + pthread_t *threads; + long i; + int ret; + struct timespec intv; + struct sched_param param; + + rt_init("a:r:t:e:l:h:", parse_args, argc, argv); + signal(SIGINT, stop_log); + + if (argc >= (optind + 1)) + nr_tasks = atoi(argv[optind]); + else { + numcpus = sysconf(_SC_NPROCESSORS_ONLN); + nr_tasks = numcpus + 1; + } + + intervals = malloc(sizeof(stats_container_t) * nr_tasks); + if (!intervals) + debug(DBG_ERR, "malloc failed\n"); + memset(intervals, 0, sizeof(stats_container_t) * nr_tasks); + + intervals_length = malloc(sizeof(stats_container_t) * nr_tasks); + if (!intervals_length) + debug(DBG_ERR, "malloc failed\n"); + memset(intervals_length, 0, sizeof(stats_container_t) * nr_tasks); + + if (!intervals_loops) + debug(DBG_ERR, "malloc failed\n"); + intervals_loops = malloc(sizeof(stats_container_t) * nr_tasks); + memset(intervals_loops, 0, sizeof(stats_container_t) * nr_tasks); + + threads = malloc(sizeof(*threads) * nr_tasks); + if (!threads) + debug(DBG_ERR, "malloc failed\n"); + memset(threads, 0, sizeof(*threads) * nr_tasks); + + ret = pthread_barrier_init(&start_barrier, NULL, nr_tasks + 1); + ret = pthread_barrier_init(&end_barrier, NULL, nr_tasks + 1); + if (ret < 0) + debug(DBG_ERR, "pthread_barrier_init failed: %s\n", + strerror(ret)); + + + for (i = 0; i < nr_tasks; i++) { + stats_container_init(&intervals[i], nr_runs); + stats_container_init(&intervals_length[i], nr_runs); + stats_container_init(&intervals_loops[i], nr_runs); + } + + thread_pids = malloc(sizeof(long) * nr_tasks); + if (!thread_pids) + debug(DBG_ERR, "malloc thread_pids failed\n"); + + for (i = 0; i < nr_tasks; i++) { + threads[i] = create_fifo_thread(start_task, (void *)i, + prio_start + i); + } + + /* + * Progress bar uses stderr to let users see it when + * redirecting output. So we convert stderr to use line + * buffering so the progress bar doesn't flicker. + */ + setlinebuf(stderr); + + /* up our prio above all tasks */ + memset(¶m, 0, sizeof(param)); + param.sched_priority = nr_tasks + prio_start; + if (sched_setscheduler(0, SCHED_FIFO, ¶m)) + debug(DBG_WARN, "Warning, can't set priority of" + "main thread !\n"); + intv.tv_sec = INTERVAL / NS_PER_SEC; + intv.tv_nsec = INTERVAL % (1 * NS_PER_SEC); + + print_progress_bar(0); + + setup_ftrace_marker(); + + for (loop = 0; loop < nr_runs; loop++) { + unsigned long long end; + + now = rt_gettime() / NS_PER_US; + + ftrace_write("Loop %d now=%lld\n", loop, now); + + pthread_barrier_wait(&start_barrier); + + ftrace_write("All running!!!\n"); + + rt_nanosleep(intv.tv_nsec); + print_progress_bar((loop * 100) / nr_runs); + + end = rt_gettime() / NS_PER_US; + ftrace_write("Loop %d end now=%lld diff=%lld\n", + loop, end, end - now); + ret = pthread_barrier_wait(&end_barrier); + + if (stop || (check && check_times(loop))) { + loop++; + nr_runs = loop; + break; + } + } + putc('\n', stderr); + + pthread_barrier_wait(&start_barrier); + done = 1; + pthread_barrier_wait(&end_barrier); + + join_threads(); + print_results(); + + if (stop) { + /* + * We use this test in bash while loops + * So if we hit Ctrl-C then let the while + * loop know to break. + */ + if (check < 0) + exit(-1); + else + exit(1); + } + if (check < 0) + exit(-1); + else + exit(0); + + return 0; +} diff -Naur ltp-orig/testcases/realtime/func/rt-migrate/run_auto.sh ltp/testcases/realtime/func/rt-migrate/run_auto.sh --- ltp-orig/testcases/realtime/func/rt-migrate/run_auto.sh 1970-01-01 05:30:00.000000000 +0530 +++ ltp/testcases/realtime/func/rt-migrate/run_auto.sh 2009-09-04 12:37:45.000000000 +0530 @@ -0,0 +1,12 @@ +#! /bin/bash + +profile=${1:-default} + +cd $(dirname $0) # Move to test directory +if [ ! $SCRIPTS_DIR ]; then + # assume we're running standalone + export SCRIPTS_DIR=../../scripts/ +fi +source $SCRIPTS_DIR/setenv.sh +# Warning: tests args are now set in profiles +$SCRIPTS_DIR/run_c_files.sh $profile rt-migrate diff -Naur ltp-orig/testcases/realtime/profiles/default ltp/testcases/realtime/profiles/default --- ltp-orig/testcases/realtime/profiles/default 2009-09-04 12:13:40.000000000 +0530 +++ ltp/testcases/realtime/profiles/default 2009-09-04 13:13:24.000000000 +0530 @@ -60,4 +60,4 @@ func/pi-tests testpi-5 func/pi-tests testpi-6 func/pi-tests sbrk_mutex - +func/rt-migrate rt-migrate On Wed, 2009-09-02 at 12:44 +0530, Subrata Modak wrote: > Hey, > > You did not mention where it should actually go (which directory ?), and > how you are integrating the run into the RT tests ? > > Regards-- > Subrata > > On Tue, 2009-09-01 at 14:07 +0530, Kiran wrote: > > Hi, > > > > This patch converts the testcase rt-migrate-test.c to the coding format > > used by the other realtime testcases in LTP, by making use of the > > librttest and libstats infrastructure. > > > > Signed-off-by: Kiran Prakash <[email protected]> > > Acked-by: Darren Hart <[email protected]> > > Acked-by: Sripathi Kodi <[email protected]> > > > > --- rt-migrate-test_orig.c 2009-08-11 16:36:21.000000000 +0530 > > +++ rt-migrate-test.c 2009-08-17 17:20:45.000000000 +0530 > > @@ -1,5 +1,5 @@ > > -/* > > - * rt-migrate-test.c > > + > > +/****************************************************************************** > > * > > * Copyright (C) 2007-2009 Steven Rostedt <[email protected]> > > * > > @@ -18,7 +18,33 @@ > > * along with this program; if not, write to the Free Software > > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 > > USA > > * > > - * > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > + * NAME > > + * rt-migrate-test.c > > + * > > + * DESCRIPTION > > + * This test makes sure that all the high prio tasks that are in the > > + * running state are actually running on a CPU if it can. > > + ** Steps: > > + * - Creates N+1 threads with lower real time priorities. > > + * Where N is the number of CPUs in the system. > > + * - If the thread is high priority, and if a CPU is available, the > > + * thread runs on that CPU. > > + * - The thread records the start time and the number of ticks in the run > > + * interval. > > + * - The output indicates if lower prio task is quicker than higher > > + * priority task. > > + * > > + * USAGE: > > + * Use run_auto.sh in the current directory to build and run the test. > > + * > > + * AUTHOR > > + * Steven Rostedt <[email protected]> > > + * > > + * HISTORY > > + * 30 July, 2009: Initial version by Steven Rostedt > > + * 11 Aug, 2009: Converted the coding style to the one used by the > > realtime > > + * testcases by Kiran Prakash > > + * > > */ > > #define _GNU_SOURCE > > #include <stdio.h> > > @@ -42,14 +68,17 @@ > > #include <errno.h> > > #include <sched.h> > > #include <pthread.h> > > +#include <librttest.h> > > +#include <libstats.h> > > > > #define gettid() syscall(__NR_gettid) > > > > -#define VERSION_STRING "V 0.3" > > +#define VERSION_STRING "V 0.4LTP" > > > > int nr_tasks; > > int lfd; > > > > +int numcpus; > > static int mark_fd = -1; > > static __thread char buff[BUFSIZ+1]; > > > > @@ -90,18 +119,12 @@ static void ftrace_write(const char *fmt > > write(mark_fd, buff, n); > > } > > > > -#define nano2sec(nan) (nan / 1000000000ULL) > > -#define nano2ms(nan) (nan / 1000000ULL) > > -#define nano2usec(nan) (nan / 1000ULL) > > -#define usec2nano(sec) (sec * 1000ULL) > > -#define ms2nano(ms) (ms * 1000000ULL) > > -#define sec2nano(sec) (sec * 1000000000ULL) > > -#define INTERVAL ms2nano(100ULL) > > -#define RUN_INTERVAL ms2nano(20ULL) > > +#define INTERVAL 100ULL * NS_PER_MS > > +#define RUN_INTERVAL 20ULL * NS_PER_MS > > #define NR_RUNS 50 > > #define PRIO_START 2 > > /* 1 millisec off */ > > -#define MAX_ERR usec2nano(1000) > > +#define MAX_ERR 1000 * NS_PER_US > > > > #define PROGRESS_CHARS 70 > > > > @@ -110,7 +133,7 @@ static unsigned long long run_interval = > > static unsigned long long max_err = MAX_ERR; > > static int nr_runs = NR_RUNS; > > static int prio_start = PRIO_START; > > -static int check; > > +static int check = 1; > > static int stop; > > > > static unsigned long long now; > > @@ -120,26 +143,11 @@ static int loop; > > > > static pthread_barrier_t start_barrier; > > static pthread_barrier_t end_barrier; > > -static unsigned long long **intervals; > > -static unsigned long long **intervals_length; > > -static unsigned long **intervals_loops; > > +stats_container_t *intervals; > > +stats_container_t *intervals_length; > > +stats_container_t *intervals_loops; > > static long *thread_pids; > > > > -static char buffer[BUFSIZ]; > > - > > -static void perr(char *fmt, ...) > > -{ > > - va_list ap; > > - > > - va_start(ap, fmt); > > - vsnprintf(buffer, BUFSIZ, fmt, ap); > > - va_end(ap); > > - > > - perror(buffer); > > - fflush(stderr); > > - exit(-1); > > -} > > - > > static void print_progress_bar(int percent) > > { > > int i; > > @@ -151,7 +159,7 @@ static void print_progress_bar(int perce > > /* Use stderr, so we don't capture it */ > > putc('\r', stderr); > > putc('|', stderr); > > - for (i=0; i < PROGRESS_CHARS; i++) > > + for (i = 0; i < PROGRESS_CHARS; i++) > > putc(' ', stderr); > > putc('|', stderr); > > putc('\r', stderr); > > @@ -159,97 +167,59 @@ static void print_progress_bar(int perce > > > > p = PROGRESS_CHARS * percent / 100; > > > > - for (i=0; i < p; i++) > > + for (i = 0; i < p; i++) > > putc('-', stderr); > > > > fflush(stderr); > > } > > > > -static void usage(char **argv) > > +static void usage() > > { > > - char *arg = argv[0]; > > - char *p = arg+strlen(arg); > > - > > - while (p >= arg && *p != '/') > > - p--; > > - p++; > > - > > - printf("%s %s\n", p, VERSION_STRING); > > + rt_help(); > > printf("Usage:\n" > > - "%s <options> nr_tasks\n\n" > > - "-p prio --prio prio base priority to start RT tasks > > with (2) \n" > > - "-r time --run-time time Run time (ms) to busy loop the > > threads (20)\n" > > - "-s time --sleep-time time Sleep time (ms) between intervals > > (100)\n" > > - "-m time --maxerr time Max allowed error (microsecs)\n" > > - "-l loops --loops loops Number of iterations to run (50)\n" > > - "-c --check Stop if lower prio task is quick > > than higher (off)\n" > > - " () above are defaults \n", > > - p); > > - exit(0); > > -} > > - > > -static void parse_options (int argc, char *argv[]) > > -{ > > - for (;;) { > > - int option_index = 0; > > - /** Options for getopt */ > > - static struct option long_options[] = { > > - {"prio", required_argument, NULL, 'p'}, > > - {"run-time", required_argument, NULL, 'r'}, > > - {"sleep-time", required_argument, NULL, 's'}, > > - {"maxerr", required_argument, NULL, 'm'}, > > - {"loops", required_argument, NULL, 'l'}, > > - {"check", no_argument, NULL, 'c'}, > > - {"help", no_argument, NULL, '?'}, > > - {NULL, 0, NULL, 0} > > - }; > > - int c = getopt_long (argc, argv, "p:r:s:m:l:ch", > > - long_options, &option_index); > > - if (c == -1) > > - break; > > + "-a priority Priority of the threads" > > + "-r time Run time (ms) to busy loop the threads (20)\n" > > + "-t time Sleep time (ms) between intervals (100)\n" > > + "-e time Max allowed error (microsecs)\n" > > + "-l loops Number of iterations to run (50)\n" > > + ); > > +} > > + > > +static void parse_args(int c, char *v) > > +{ > > switch (c) { > > - case 'p': prio_start = atoi(optarg); break; > > + case 'a': prio_start = atoi(v); break; > > case 'r': > > - run_interval = atoi(optarg); > > + run_interval = atoi(v); > > break; > > - case 's': interval = atoi(optarg); break; > > - case 'l': nr_runs = atoi(optarg); break; > > - case 'm': max_err = usec2nano(atoi(optarg)); break; > > - case 'c': check = 1; break; > > + case 't': interval = atoi(v); break; > > + case 'l': nr_runs = atoi(v); break; > > + case 'e': max_err = atoi(v) * NS_PER_US; break; > > case '?': > > case 'h': > > - usage(argv); > > - break; > > + usage(); > > + exit(0); > > } > > - } > > - > > -} > > - > > -static unsigned long long get_time(void) > > -{ > > - struct timeval tv; > > - unsigned long long time; > > - > > - gettimeofday(&tv, NULL); > > - > > - time = sec2nano(tv.tv_sec); > > - time += usec2nano(tv.tv_usec); > > - > > - return time; > > } > > > > static void record_time(int id, unsigned long long time, unsigned long l) > > { > > unsigned long long ltime; > > - > > + stats_record_t rec; > > if (loop >= nr_runs) > > return; > > time -= now; > > - ltime = get_time(); > > + ltime = rt_gettime() / NS_PER_US; > > ltime -= now; > > - intervals[loop][id] = time; > > - intervals_length[loop][id] = ltime; > > - intervals_loops[loop][id] = l; > > + rec.x = loop; > > + rec.y = time; > > + stats_container_append(&intervals[id], rec); > > + rec.x = loop; > > + rec.y = ltime; > > + stats_container_append(&intervals_length[id], rec); > > + rec.x = loop; > > + rec.y = l; > > + stats_container_append(&intervals_loops[id], rec); > > } > > > > static void print_results(void) > > @@ -269,32 +239,26 @@ static void print_results(void) > > printf("%6d ", t); > > printf("\n"); > > > > - for (i=0; i < nr_runs; i++) { > > + for (t = 0; t < nr_tasks; t++) { > > + tasks_max[t] = stats_max(&intervals[t]); > > + tasks_min[t] = stats_min(&intervals[t]); > > + tasks_avg[t] = stats_avg(&intervals[t]); > > + } > > + for (i = 0; i < nr_runs; i++) { > > printf("%4d: ", i); > > - for (t=0; t < nr_tasks; t++) { > > - unsigned long long itv = intervals[i][t]; > > + for (t = 0; t < nr_tasks; t++) > > + printf("%6lld ", intervals[t].records[i].y); > > > > - if (tasks_max[t] < itv) > > - tasks_max[t] = itv; > > - if (tasks_min[t] > itv) > > - tasks_min[t] = itv; > > - tasks_avg[t] += itv; > > - printf("%6lld ", nano2usec(itv)); > > - } > > printf("\n"); > > printf(" len: "); > > - for (t=0; t < nr_tasks; t++) { > > - unsigned long long len = intervals_length[i][t]; > > + for (t = 0; t < nr_tasks; t++) > > + printf("%6lld ", intervals_length[t].records[i].y); > > > > - printf("%6lld ", nano2usec(len)); > > - } > > printf("\n"); > > printf(" loops: "); > > - for (t=0; t < nr_tasks; t++) { > > - unsigned long loops = intervals_loops[i][t]; > > + for (t = 0; t < nr_tasks; t++) > > + printf("%6ld ", intervals_loops[t].records[i].y); > > > > - printf("%6ld ", loops); > > - } > > printf("\n"); > > printf("\n"); > > } > > @@ -304,19 +268,14 @@ static void print_results(void) > > for (t=0; t < nr_tasks; t++) { > > printf(" Task %d (prio %d) (pid %ld):\n", t, t + prio_start, > > thread_pids[t]); > > - printf(" Max: %lld us\n", nano2usec(tasks_max[t])); > > - printf(" Min: %lld us\n", nano2usec(tasks_min[t])); > > - printf(" Tot: %lld us\n", nano2usec(tasks_avg[t])); > > - printf(" Avg: %lld us\n", nano2usec(tasks_avg[t] / nr_runs)); > > + printf(" Max: %lld us\n", tasks_max[t]); > > + printf(" Min: %lld us\n", tasks_min[t]); > > + printf(" Tot: %lld us\n", tasks_avg[t] * nr_runs); > > + printf(" Avg: %lld us\n", tasks_avg[t]); > > printf("\n"); > > } > > > > - if (check) { > > - if (check < 0) > > - printf(" Failed!\n"); > > - else > > - printf(" Passed!\n"); > > - } > > + printf(" Result: %s\n", (check < 0) ? "FAIL" : "PASS"); > > } > > > > static unsigned long busy_loop(unsigned long long start_time) > > @@ -326,7 +285,7 @@ static unsigned long busy_loop(unsigned > > > > do { > > l++; > > - time = get_time(); > > + time = rt_gettime(); > > } while ((time - start_time) < RUN_INTERVAL); > > > > return l; > > @@ -334,11 +293,10 @@ static unsigned long busy_loop(unsigned > > > > void *start_task(void *data) > > { > > - long id = (long)data; > > + struct thread *thr = (struct thread *)data; > > + long id = (long) thr->arg; > > + thread_pids[id] = gettid(); > > unsigned long long start_time; > > - struct sched_param param = { > > - .sched_priority = id + prio_start, > > - }; > > int ret; > > int high = 0; > > cpu_set_t cpumask; > > @@ -349,7 +307,7 @@ void *start_task(void *data) > > > > ret = sched_getaffinity(0, sizeof(save_cpumask), &save_cpumask); > > if (ret < 0) > > - perr("getting affinity"); > > + debug(DBG_ERR, "sched_getaffinity failed: %s\n", strerror(ret)); > > > > pid = gettid(); > > > > @@ -357,10 +315,6 @@ void *start_task(void *data) > > if (id == nr_tasks-1) > > high = 1; > > > > - ret = sched_setscheduler(0, SCHED_FIFO, ¶m); > > - if (ret < 0 && !id) > > - fprintf(stderr, "Warning, can't set priorities\n"); > > - > > while (!done) { > > if (high) { > > /* rotate around the CPUS */ > > @@ -371,11 +325,11 @@ void *start_task(void *data) > > sched_setaffinity(0, sizeof(cpumask), &cpumask); > > } > > pthread_barrier_wait(&start_barrier); > > - start_time = get_time(); > > + start_time = rt_gettime(); > > ftrace_write("Thread %d: started %lld diff %lld\n", > > pid, start_time, start_time - now); > > l = busy_loop(start_time); > > - record_time(id, start_time, l); > > + record_time(id, start_time / NS_PER_US, l); > > pthread_barrier_wait(&end_barrier); > > } > > > > @@ -389,26 +343,27 @@ static int check_times(int l) > > unsigned long long last_loops; > > unsigned long long last_length; > > > > - for (i=0; i < nr_tasks; i++) { > > - if (i && last < intervals[l][i] && > > - ((intervals[l][i] - last) > max_err)) { > > + for (i = 0; i < nr_tasks; i++) { > > + if (i && last < intervals[i].records[l].y && > > + ((intervals[i].records[l].y - last) > max_err)) { > > /* > > * May be a false positive. > > * Make sure that we did more loops > > * our start is before the end > > * and the end should be tested. > > */ > > - if (intervals_loops[l][i] < last_loops || > > - intervals[l][i] > last_length || > > - (intervals_length[l][i] > last_length && > > - intervals_length[l][i] - last_length > max_err)) { > > + if (intervals_loops[i].records[l].y < last_loops || > > + intervals[i].records[l].y > last_length || > > + (intervals_length[i].records[l].y > last_length && > > + intervals_length[i].records[l].y - last_length > > > + max_err)) { > > check = -1; > > return 1; > > } > > } > > - last = intervals[l][i]; > > - last_loops = intervals_loops[l][i]; > > - last_length = intervals_length[l][i]; > > + last = intervals[i].records[l].y; > > + last_loops = intervals_loops[i].records[l].y; > > + last_length = intervals_length[i].records[l].y; > > } > > return 0; > > } > > @@ -418,39 +373,6 @@ static void stop_log(int sig) > > stop = 1; > > } > > > > -static int count_cpus(void) > > -{ > > - FILE *fp; > > - char buf[1024]; > > - int cpus = 0; > > - char *pbuf; > > - size_t *pn; > > - size_t n; > > - int r; > > - > > - n = 1024; > > - pn = &n; > > - pbuf = buf; > > - > > - fp = fopen("/proc/cpuinfo", "r"); > > - if (!fp) > > - perr("Can not read cpuinfo"); > > - > > - while ((r = getline(&pbuf, pn, fp)) >= 0) { > > - char *p; > > - > > - if (strncmp(buf, "processor", 9) != 0) > > - continue; > > - for (p = buf+9; isspace(*p); p++) > > - ; > > - if (*p == ':') > > - cpus++; > > - } > > - fclose(fp); > > - > > - return cpus; > > -} > > - > > int main (int argc, char **argv) > > { > > pthread_t *threads; > > @@ -459,62 +381,56 @@ int main (int argc, char **argv) > > struct timespec intv; > > struct sched_param param; > > > > - parse_options(argc, argv); > > - > > + rt_init("a:r:t:e:l:h:", parse_args, argc, argv); > > signal(SIGINT, stop_log); > > > > if (argc >= (optind + 1)) > > nr_tasks = atoi(argv[optind]); > > - else > > - nr_tasks = count_cpus() + 1; > > + else { > > + numcpus = sysconf(_SC_NPROCESSORS_ONLN); > > + nr_tasks = numcpus + 1; > > + } > > + > > + intervals = malloc(sizeof(stats_container_t) * nr_tasks); > > + if (!intervals) > > + debug(DBG_ERR, "malloc failed\n"); > > + memset(intervals, 0, sizeof(stats_container_t) * nr_tasks); > > + > > + intervals_length = malloc(sizeof(stats_container_t) * nr_tasks); > > + if (!intervals_length) > > + debug(DBG_ERR, "malloc failed\n"); > > + memset(intervals_length, 0, sizeof(stats_container_t) * nr_tasks); > > + > > + if (!intervals_loops) > > + debug(DBG_ERR, "malloc failed\n"); > > + intervals_loops = malloc(sizeof(stats_container_t) * nr_tasks); > > + memset(intervals_loops, 0, sizeof(stats_container_t) * nr_tasks); > > > > threads = malloc(sizeof(*threads) * nr_tasks); > > if (!threads) > > - perr("malloc"); > > + debug(DBG_ERR, "malloc failed\n"); > > memset(threads, 0, sizeof(*threads) * nr_tasks); > > > > ret = pthread_barrier_init(&start_barrier, NULL, nr_tasks + 1); > > ret = pthread_barrier_init(&end_barrier, NULL, nr_tasks + 1); > > if (ret < 0) > > - perr("pthread_barrier_init"); > > + debug(DBG_ERR, "pthread_barrier_init failed: %s\n", > > + strerror(ret)); > > > > - intervals = malloc(sizeof(void*) * nr_runs); > > - if (!intervals) > > - perr("malloc intervals array"); > > - > > - intervals_length = malloc(sizeof(void*) * nr_runs); > > - if (!intervals_length) > > - perr("malloc intervals length array"); > > > > - intervals_loops = malloc(sizeof(void*) * nr_runs); > > - if (!intervals_loops) > > - perr("malloc intervals loops array"); > > + for (i = 0; i < nr_tasks; i++) { > > + stats_container_init(&intervals[i], nr_runs); > > + stats_container_init(&intervals_length[i], nr_runs); > > + stats_container_init(&intervals_loops[i], nr_runs); > > + } > > > > thread_pids = malloc(sizeof(long) * nr_tasks); > > if (!thread_pids) > > - perr("malloc thread_pids"); > > - > > - for (i=0; i < nr_runs; i++) { > > - intervals[i] = malloc(sizeof(unsigned long long)*nr_tasks); > > - if (!intervals[i]) > > - perr("malloc intervals"); > > - memset(intervals[i], 0, sizeof(unsigned long long)*nr_tasks); > > - > > - intervals_length[i] = malloc(sizeof(unsigned long > > long)*nr_tasks); > > - if (!intervals_length[i]) > > - perr("malloc length intervals"); > > - memset(intervals_length[i], 0, sizeof(unsigned long > > long)*nr_tasks); > > - > > - intervals_loops[i] = malloc(sizeof(unsigned long)*nr_tasks); > > - if (!intervals_loops[i]) > > - perr("malloc loops intervals"); > > - memset(intervals_loops[i], 0, sizeof(unsigned long)*nr_tasks); > > - } > > - > > - for (i=0; i < nr_tasks; i++) { > > - if (pthread_create(&threads[i], NULL, start_task, (void *)i)) > > - perr("pthread_create"); > > + debug(DBG_ERR, "malloc thread_pids failed\n"); > > > > + for (i = 0; i < nr_tasks; i++) { > > + threads[i] = create_fifo_thread(start_task, (void *)i, > > + prio_start + i); > > } > > > > /* > > @@ -528,12 +444,10 @@ int main (int argc, char **argv) > > memset(¶m, 0, sizeof(param)); > > param.sched_priority = nr_tasks + prio_start; > > if (sched_setscheduler(0, SCHED_FIFO, ¶m)) > > - fprintf(stderr, "Warning, can't set priority of main > > thread!\n"); > > - > > - > > - > > - intv.tv_sec = nano2sec(INTERVAL); > > - intv.tv_nsec = INTERVAL % sec2nano(1); > > + debug(DBG_WARN, "Warning, can't set priority of" > > + "main thread !\n"); > > + intv.tv_sec = INTERVAL / NS_PER_SEC; > > + intv.tv_nsec = INTERVAL % (1 * NS_PER_SEC); > > > > print_progress_bar(0); > > > > @@ -542,7 +456,7 @@ int main (int argc, char **argv) > > for (loop=0; loop < nr_runs; loop++) { > > unsigned long long end; > > > > - now = get_time(); > > + now = rt_gettime() / NS_PER_US; > > > > ftrace_write("Loop %d now=%lld\n", loop, now); > > > > @@ -550,14 +464,12 @@ int main (int argc, char **argv) > > > > ftrace_write("All running!!!\n"); > > > > - nanosleep(&intv, NULL); > > - > > + rt_nanosleep(intv.tv_nsec); > > print_progress_bar((loop * 100)/ nr_runs); > > > > - end = get_time(); > > + end = rt_gettime() / NS_PER_US; > > ftrace_write("Loop %d end now=%lld diff=%lld\n", loop, end, end > > - now); > > - > > - pthread_barrier_wait(&end_barrier); > > + ret = pthread_barrier_wait(&end_barrier); > > > > if (stop || (check && check_times(loop))) { > > loop++; > > @@ -571,9 +483,7 @@ int main (int argc, char **argv) > > done = 1; > > pthread_barrier_wait(&end_barrier); > > > > - for (i=0; i < nr_tasks; i++) > > - pthread_join(threads[i], (void*)&thread_pids[i]); > > - > > + join_threads(); > > print_results(); > > > > if (stop) { > > > > > > > > ------------------------------------------------------------------------------ > > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > > trial. Simplify your report design, integration and deployment - and focus > > on > > what you do best, core application coding. Discover what's new with > > Crystal Reports now. http://p.sf.net/sfu/bobj-july > > _______________________________________________ > > Ltp-list mailing list > > [email protected] > > https://lists.sourceforge.net/lists/listinfo/ltp-list > ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Ltp-list mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ltp-list
