1f08c3bdfSopenharmony_ci 2f08c3bdfSopenharmony_ci/****************************************************************************** 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Copyright (C) 2007-2009 Steven Rostedt <srostedt@redhat.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 9f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 10f08c3bdfSopenharmony_ci * the Free Software Foundation; version 2 of the License (not later!) 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 13f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15f08c3bdfSopenharmony_ci * GNU General Public License for more details. 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 18f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 19f08c3bdfSopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * NAME 22f08c3bdfSopenharmony_ci * rt-migrate-test.c 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * DESCRIPTION 25f08c3bdfSopenharmony_ci * This test makes sure that all the high prio tasks that are in the 26f08c3bdfSopenharmony_ci * running state are actually running on a CPU if it can. 27f08c3bdfSopenharmony_ci ** Steps: 28f08c3bdfSopenharmony_ci * - Creates N+1 threads with lower real time priorities. 29f08c3bdfSopenharmony_ci * Where N is the number of CPUs in the system. 30f08c3bdfSopenharmony_ci * - If the thread is high priority, and if a CPU is available, the 31f08c3bdfSopenharmony_ci * thread runs on that CPU. 32f08c3bdfSopenharmony_ci * - The thread records the start time and the number of ticks in the run 33f08c3bdfSopenharmony_ci * interval. 34f08c3bdfSopenharmony_ci * - The output indicates if lower prio task is quicker than higher 35f08c3bdfSopenharmony_ci * priority task. 36f08c3bdfSopenharmony_ci * 37f08c3bdfSopenharmony_ci * USAGE: 38f08c3bdfSopenharmony_ci * Use run_auto.sh in the current directory to build and run the test. 39f08c3bdfSopenharmony_ci * 40f08c3bdfSopenharmony_ci * AUTHOR 41f08c3bdfSopenharmony_ci * Steven Rostedt <srostedt@redhat.com> 42f08c3bdfSopenharmony_ci * 43f08c3bdfSopenharmony_ci * HISTORY 44f08c3bdfSopenharmony_ci * 30 July, 2009: Initial version by Steven Rostedt 45f08c3bdfSopenharmony_ci * 11 Aug, 2009: Converted the coding style to the one used by the realtime 46f08c3bdfSopenharmony_ci * testcases by Kiran Prakash 47f08c3bdfSopenharmony_ci * 48f08c3bdfSopenharmony_ci */ 49f08c3bdfSopenharmony_ci#ifndef _GNU_SOURCE 50f08c3bdfSopenharmony_ci#define _GNU_SOURCE 51f08c3bdfSopenharmony_ci#endif 52f08c3bdfSopenharmony_ci#include <stdio.h> 53f08c3bdfSopenharmony_ci#include <stdlib.h> 54f08c3bdfSopenharmony_ci#include <string.h> 55f08c3bdfSopenharmony_ci#include <getopt.h> 56f08c3bdfSopenharmony_ci#include <stdarg.h> 57f08c3bdfSopenharmony_ci#include <unistd.h> 58f08c3bdfSopenharmony_ci#include <ctype.h> 59f08c3bdfSopenharmony_ci#include <time.h> 60f08c3bdfSopenharmony_ci#include <sys/types.h> 61f08c3bdfSopenharmony_ci#include <sys/stat.h> 62f08c3bdfSopenharmony_ci#include <fcntl.h> 63f08c3bdfSopenharmony_ci#include <signal.h> 64f08c3bdfSopenharmony_ci#include <sys/time.h> 65f08c3bdfSopenharmony_ci#include <linux/unistd.h> 66f08c3bdfSopenharmony_ci#include <sys/syscall.h> 67f08c3bdfSopenharmony_ci#include <errno.h> 68f08c3bdfSopenharmony_ci#include <sched.h> 69f08c3bdfSopenharmony_ci#include <pthread.h> 70f08c3bdfSopenharmony_ci#include <librttest.h> 71f08c3bdfSopenharmony_ci#include <libstats.h> 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci#define gettid() syscall(__NR_gettid) 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci#define VERSION_STRING "V 0.4LTP" 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ciint nr_tasks; 78f08c3bdfSopenharmony_ciint lfd; 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ciint numcpus; 81f08c3bdfSopenharmony_cistatic int mark_fd = -1; 82f08c3bdfSopenharmony_cistatic __thread char buff[BUFSIZ + 1]; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_cistatic void setup_ftrace_marker(void) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci struct stat st; 87f08c3bdfSopenharmony_ci char *files[] = { 88f08c3bdfSopenharmony_ci "/sys/kernel/debug/tracing/trace_marker", 89f08c3bdfSopenharmony_ci "/debug/tracing/trace_marker", 90f08c3bdfSopenharmony_ci "/debugfs/tracing/trace_marker", 91f08c3bdfSopenharmony_ci }; 92f08c3bdfSopenharmony_ci int ret; 93f08c3bdfSopenharmony_ci int i; 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci for (i = 0; i < (sizeof(files) / sizeof(char *)); i++) { 96f08c3bdfSopenharmony_ci ret = stat(files[i], &st); 97f08c3bdfSopenharmony_ci if (ret >= 0) 98f08c3bdfSopenharmony_ci goto found; 99f08c3bdfSopenharmony_ci } 100f08c3bdfSopenharmony_ci /* todo, check mounts system */ 101f08c3bdfSopenharmony_ci return; 102f08c3bdfSopenharmony_cifound: 103f08c3bdfSopenharmony_ci mark_fd = open(files[i], O_WRONLY); 104f08c3bdfSopenharmony_ci} 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_cistatic void ftrace_write(const char *fmt, ...) 107f08c3bdfSopenharmony_ci{ 108f08c3bdfSopenharmony_ci va_list ap; 109f08c3bdfSopenharmony_ci int n; 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci if (mark_fd < 0) 112f08c3bdfSopenharmony_ci return; 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci va_start(ap, fmt); 115f08c3bdfSopenharmony_ci n = vsnprintf(buff, BUFSIZ, fmt, ap); 116f08c3bdfSopenharmony_ci va_end(ap); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci /* 119f08c3bdfSopenharmony_ci * This doesn't return any valid vs invalid exit codes, so printing out 120f08c3bdfSopenharmony_ci * a perror to warn the end-user of an issue is sufficient. 121f08c3bdfSopenharmony_ci */ 122f08c3bdfSopenharmony_ci if (write(mark_fd, buff, n) < 0) { 123f08c3bdfSopenharmony_ci perror("write"); 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci} 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci#define INTERVAL 100ULL * NS_PER_MS 128f08c3bdfSopenharmony_ci#define RUN_INTERVAL 20ULL * NS_PER_MS 129f08c3bdfSopenharmony_ci#define NR_RUNS 50 130f08c3bdfSopenharmony_ci#define PRIO_START 2 131f08c3bdfSopenharmony_ci/* 1 millisec off */ 132f08c3bdfSopenharmony_ci#define MAX_ERR 1000 * NS_PER_US 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci#define PROGRESS_CHARS 70 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_cistatic unsigned long long interval = INTERVAL; 137f08c3bdfSopenharmony_cistatic unsigned long long run_interval = RUN_INTERVAL; 138f08c3bdfSopenharmony_cistatic unsigned long long max_err = MAX_ERR; 139f08c3bdfSopenharmony_cistatic int nr_runs = NR_RUNS; 140f08c3bdfSopenharmony_cistatic int prio_start = PRIO_START; 141f08c3bdfSopenharmony_cistatic int check = 1; 142f08c3bdfSopenharmony_cistatic int stop; 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_cistatic unsigned long long now; 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_cistatic int done; 147f08c3bdfSopenharmony_cistatic int loop; 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_cistatic pthread_barrier_t start_barrier; 150f08c3bdfSopenharmony_cistatic pthread_barrier_t end_barrier; 151f08c3bdfSopenharmony_cistats_container_t *intervals; 152f08c3bdfSopenharmony_cistats_container_t *intervals_length; 153f08c3bdfSopenharmony_cistats_container_t *intervals_loops; 154f08c3bdfSopenharmony_cistatic long *thread_pids; 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_cistatic void print_progress_bar(int percent) 157f08c3bdfSopenharmony_ci{ 158f08c3bdfSopenharmony_ci int i; 159f08c3bdfSopenharmony_ci int p; 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci if (percent > 100) 162f08c3bdfSopenharmony_ci percent = 100; 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci /* Use stderr, so we don't capture it */ 165f08c3bdfSopenharmony_ci putc('\r', stderr); 166f08c3bdfSopenharmony_ci putc('|', stderr); 167f08c3bdfSopenharmony_ci for (i = 0; i < PROGRESS_CHARS; i++) 168f08c3bdfSopenharmony_ci putc(' ', stderr); 169f08c3bdfSopenharmony_ci putc('|', stderr); 170f08c3bdfSopenharmony_ci putc('\r', stderr); 171f08c3bdfSopenharmony_ci putc('|', stderr); 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_ci p = PROGRESS_CHARS * percent / 100; 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci for (i = 0; i < p; i++) 176f08c3bdfSopenharmony_ci putc('-', stderr); 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci fflush(stderr); 179f08c3bdfSopenharmony_ci} 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_cistatic void usage() 182f08c3bdfSopenharmony_ci{ 183f08c3bdfSopenharmony_ci rt_help(); 184f08c3bdfSopenharmony_ci printf("Usage:\n" 185f08c3bdfSopenharmony_ci "-a priority Priority of the threads" 186f08c3bdfSopenharmony_ci "-r time Run time (ms) to busy loop the threads (20)\n" 187f08c3bdfSopenharmony_ci "-t time Sleep time (ms) between intervals (100)\n" 188f08c3bdfSopenharmony_ci "-e time Max allowed error (microsecs)\n" 189f08c3bdfSopenharmony_ci "-l loops Number of iterations to run (50)\n"); 190f08c3bdfSopenharmony_ci} 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci/* 193f08c3bdfSopenharmony_ciint rt_init(const char *options, int (*parse_arg)(int option, char *value), 194f08c3bdfSopenharmony_ci int argc, char *argv[]); 195f08c3bdfSopenharmony_ci */ 196f08c3bdfSopenharmony_cistatic int parse_args(int c, char *v) 197f08c3bdfSopenharmony_ci{ 198f08c3bdfSopenharmony_ci int handled = 1; 199f08c3bdfSopenharmony_ci switch (c) { 200f08c3bdfSopenharmony_ci case 'a': 201f08c3bdfSopenharmony_ci prio_start = atoi(v); 202f08c3bdfSopenharmony_ci break; 203f08c3bdfSopenharmony_ci case 'r': 204f08c3bdfSopenharmony_ci run_interval = atoi(v); 205f08c3bdfSopenharmony_ci break; 206f08c3bdfSopenharmony_ci case 't': 207f08c3bdfSopenharmony_ci interval = atoi(v); 208f08c3bdfSopenharmony_ci break; 209f08c3bdfSopenharmony_ci case 'l': 210f08c3bdfSopenharmony_ci nr_runs = atoi(v); 211f08c3bdfSopenharmony_ci break; 212f08c3bdfSopenharmony_ci case 'e': 213f08c3bdfSopenharmony_ci max_err = atoi(v) * NS_PER_US; 214f08c3bdfSopenharmony_ci break; 215f08c3bdfSopenharmony_ci case '?': 216f08c3bdfSopenharmony_ci case 'h': 217f08c3bdfSopenharmony_ci usage(); 218f08c3bdfSopenharmony_ci handled = 0; 219f08c3bdfSopenharmony_ci } 220f08c3bdfSopenharmony_ci return handled; 221f08c3bdfSopenharmony_ci} 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_cistatic void record_time(int id, unsigned long long time, unsigned long l) 224f08c3bdfSopenharmony_ci{ 225f08c3bdfSopenharmony_ci unsigned long long ltime; 226f08c3bdfSopenharmony_ci stats_record_t rec; 227f08c3bdfSopenharmony_ci if (loop >= nr_runs) 228f08c3bdfSopenharmony_ci return; 229f08c3bdfSopenharmony_ci time -= now; 230f08c3bdfSopenharmony_ci ltime = rt_gettime() / NS_PER_US; 231f08c3bdfSopenharmony_ci ltime -= now; 232f08c3bdfSopenharmony_ci rec.x = loop; 233f08c3bdfSopenharmony_ci rec.y = time; 234f08c3bdfSopenharmony_ci stats_container_append(&intervals[id], rec); 235f08c3bdfSopenharmony_ci rec.x = loop; 236f08c3bdfSopenharmony_ci rec.y = ltime; 237f08c3bdfSopenharmony_ci stats_container_append(&intervals_length[id], rec); 238f08c3bdfSopenharmony_ci rec.x = loop; 239f08c3bdfSopenharmony_ci rec.y = l; 240f08c3bdfSopenharmony_ci stats_container_append(&intervals_loops[id], rec); 241f08c3bdfSopenharmony_ci} 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_cistatic void print_results(void) 244f08c3bdfSopenharmony_ci{ 245f08c3bdfSopenharmony_ci int i; 246f08c3bdfSopenharmony_ci int t; 247f08c3bdfSopenharmony_ci unsigned long long tasks_max[nr_tasks]; 248f08c3bdfSopenharmony_ci unsigned long long tasks_min[nr_tasks]; 249f08c3bdfSopenharmony_ci unsigned long long tasks_avg[nr_tasks]; 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci memset(tasks_max, 0, sizeof(tasks_max[0]) * nr_tasks); 252f08c3bdfSopenharmony_ci memset(tasks_min, 0xff, sizeof(tasks_min[0]) * nr_tasks); 253f08c3bdfSopenharmony_ci memset(tasks_avg, 0, sizeof(tasks_avg[0]) * nr_tasks); 254f08c3bdfSopenharmony_ci 255f08c3bdfSopenharmony_ci printf("Iter: "); 256f08c3bdfSopenharmony_ci for (t = 0; t < nr_tasks; t++) 257f08c3bdfSopenharmony_ci printf("%6d ", t); 258f08c3bdfSopenharmony_ci printf("\n"); 259f08c3bdfSopenharmony_ci 260f08c3bdfSopenharmony_ci for (t = 0; t < nr_tasks; t++) { 261f08c3bdfSopenharmony_ci tasks_max[t] = stats_max(&intervals[t]); 262f08c3bdfSopenharmony_ci tasks_min[t] = stats_min(&intervals[t]); 263f08c3bdfSopenharmony_ci tasks_avg[t] = stats_avg(&intervals[t]); 264f08c3bdfSopenharmony_ci } 265f08c3bdfSopenharmony_ci for (i = 0; i < nr_runs; i++) { 266f08c3bdfSopenharmony_ci printf("%4d: ", i); 267f08c3bdfSopenharmony_ci for (t = 0; t < nr_tasks; t++) 268f08c3bdfSopenharmony_ci printf("%6ld ", intervals[t].records[i].y); 269f08c3bdfSopenharmony_ci 270f08c3bdfSopenharmony_ci printf("\n"); 271f08c3bdfSopenharmony_ci printf(" len: "); 272f08c3bdfSopenharmony_ci for (t = 0; t < nr_tasks; t++) 273f08c3bdfSopenharmony_ci printf("%6ld ", intervals_length[t].records[i].y); 274f08c3bdfSopenharmony_ci 275f08c3bdfSopenharmony_ci printf("\n"); 276f08c3bdfSopenharmony_ci printf(" loops: "); 277f08c3bdfSopenharmony_ci for (t = 0; t < nr_tasks; t++) 278f08c3bdfSopenharmony_ci printf("%6ld ", intervals_loops[t].records[i].y); 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci printf("\n"); 281f08c3bdfSopenharmony_ci printf("\n"); 282f08c3bdfSopenharmony_ci } 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci printf("Parent pid: %d\n", getpid()); 285f08c3bdfSopenharmony_ci 286f08c3bdfSopenharmony_ci for (t = 0; t < nr_tasks; t++) { 287f08c3bdfSopenharmony_ci printf(" Task %d (prio %d) (pid %ld):\n", t, t + prio_start, 288f08c3bdfSopenharmony_ci thread_pids[t]); 289f08c3bdfSopenharmony_ci printf(" Max: %lld us\n", tasks_max[t]); 290f08c3bdfSopenharmony_ci printf(" Min: %lld us\n", tasks_min[t]); 291f08c3bdfSopenharmony_ci printf(" Tot: %lld us\n", tasks_avg[t] * nr_runs); 292f08c3bdfSopenharmony_ci printf(" Avg: %lld us\n", tasks_avg[t]); 293f08c3bdfSopenharmony_ci printf("\n"); 294f08c3bdfSopenharmony_ci } 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_ci printf(" Result: %s\n", (check < 0) ? "FAIL" : "PASS"); 297f08c3bdfSopenharmony_ci} 298f08c3bdfSopenharmony_ci 299f08c3bdfSopenharmony_cistatic unsigned long busy_loop(unsigned long long start_time) 300f08c3bdfSopenharmony_ci{ 301f08c3bdfSopenharmony_ci unsigned long long time; 302f08c3bdfSopenharmony_ci unsigned long l = 0; 303f08c3bdfSopenharmony_ci 304f08c3bdfSopenharmony_ci do { 305f08c3bdfSopenharmony_ci l++; 306f08c3bdfSopenharmony_ci time = rt_gettime(); 307f08c3bdfSopenharmony_ci } while ((time - start_time) < RUN_INTERVAL); 308f08c3bdfSopenharmony_ci 309f08c3bdfSopenharmony_ci return l; 310f08c3bdfSopenharmony_ci} 311f08c3bdfSopenharmony_ci 312f08c3bdfSopenharmony_civoid *start_task(void *data) 313f08c3bdfSopenharmony_ci{ 314f08c3bdfSopenharmony_ci struct thread *thr = (struct thread *)data; 315f08c3bdfSopenharmony_ci long id = (long)thr->arg; 316f08c3bdfSopenharmony_ci thread_pids[id] = gettid(); 317f08c3bdfSopenharmony_ci unsigned long long start_time; 318f08c3bdfSopenharmony_ci int ret; 319f08c3bdfSopenharmony_ci int high = 0; 320f08c3bdfSopenharmony_ci cpu_set_t cpumask; 321f08c3bdfSopenharmony_ci cpu_set_t save_cpumask; 322f08c3bdfSopenharmony_ci int cpu = 0; 323f08c3bdfSopenharmony_ci unsigned long l; 324f08c3bdfSopenharmony_ci long pid; 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci ret = sched_getaffinity(0, sizeof(save_cpumask), &save_cpumask); 327f08c3bdfSopenharmony_ci if (ret < 0) 328f08c3bdfSopenharmony_ci debug(DBG_ERR, "sched_getaffinity failed: %s\n", strerror(ret)); 329f08c3bdfSopenharmony_ci 330f08c3bdfSopenharmony_ci pid = gettid(); 331f08c3bdfSopenharmony_ci 332f08c3bdfSopenharmony_ci /* Check if we are the highest prio task */ 333f08c3bdfSopenharmony_ci if (id == nr_tasks - 1) 334f08c3bdfSopenharmony_ci high = 1; 335f08c3bdfSopenharmony_ci 336f08c3bdfSopenharmony_ci while (!done) { 337f08c3bdfSopenharmony_ci if (high) { 338f08c3bdfSopenharmony_ci /* rotate around the CPUS */ 339f08c3bdfSopenharmony_ci if (!CPU_ISSET(cpu, &save_cpumask)) 340f08c3bdfSopenharmony_ci cpu = 0; 341f08c3bdfSopenharmony_ci CPU_ZERO(&cpumask); 342f08c3bdfSopenharmony_ci CPU_SET(cpu, &cpumask); 343f08c3bdfSopenharmony_ci cpu++; 344f08c3bdfSopenharmony_ci sched_setaffinity(0, sizeof(cpumask), &cpumask); 345f08c3bdfSopenharmony_ci } 346f08c3bdfSopenharmony_ci pthread_barrier_wait(&start_barrier); 347f08c3bdfSopenharmony_ci start_time = rt_gettime(); 348f08c3bdfSopenharmony_ci ftrace_write("Thread %d: started %lld diff %lld\n", 349f08c3bdfSopenharmony_ci pid, start_time, start_time - now); 350f08c3bdfSopenharmony_ci l = busy_loop(start_time); 351f08c3bdfSopenharmony_ci record_time(id, start_time / NS_PER_US, l); 352f08c3bdfSopenharmony_ci pthread_barrier_wait(&end_barrier); 353f08c3bdfSopenharmony_ci } 354f08c3bdfSopenharmony_ci 355f08c3bdfSopenharmony_ci return (void *)pid; 356f08c3bdfSopenharmony_ci} 357f08c3bdfSopenharmony_ci 358f08c3bdfSopenharmony_cistatic int check_times(int l) 359f08c3bdfSopenharmony_ci{ 360f08c3bdfSopenharmony_ci int i; 361f08c3bdfSopenharmony_ci unsigned long long last; 362f08c3bdfSopenharmony_ci unsigned long long last_loops; 363f08c3bdfSopenharmony_ci unsigned long long last_length; 364f08c3bdfSopenharmony_ci 365f08c3bdfSopenharmony_ci for (i = 0; i < nr_tasks; i++) { 366f08c3bdfSopenharmony_ci if (i && last < intervals[i].records[l].y && 367f08c3bdfSopenharmony_ci ((intervals[i].records[l].y - last) > max_err)) { 368f08c3bdfSopenharmony_ci /* 369f08c3bdfSopenharmony_ci * May be a false positive. 370f08c3bdfSopenharmony_ci * Make sure that we did more loops 371f08c3bdfSopenharmony_ci * our start is before the end 372f08c3bdfSopenharmony_ci * and the end should be tested. 373f08c3bdfSopenharmony_ci */ 374f08c3bdfSopenharmony_ci if (intervals_loops[i].records[l].y < last_loops || 375f08c3bdfSopenharmony_ci intervals[i].records[l].y > last_length || 376f08c3bdfSopenharmony_ci (intervals_length[i].records[l].y > last_length && 377f08c3bdfSopenharmony_ci intervals_length[i].records[l].y - last_length > 378f08c3bdfSopenharmony_ci max_err)) { 379f08c3bdfSopenharmony_ci check = -1; 380f08c3bdfSopenharmony_ci return 1; 381f08c3bdfSopenharmony_ci } 382f08c3bdfSopenharmony_ci } 383f08c3bdfSopenharmony_ci last = intervals[i].records[l].y; 384f08c3bdfSopenharmony_ci last_loops = intervals_loops[i].records[l].y; 385f08c3bdfSopenharmony_ci last_length = intervals_length[i].records[l].y; 386f08c3bdfSopenharmony_ci } 387f08c3bdfSopenharmony_ci return 0; 388f08c3bdfSopenharmony_ci} 389f08c3bdfSopenharmony_ci 390f08c3bdfSopenharmony_cistatic void stop_log(int sig) 391f08c3bdfSopenharmony_ci{ 392f08c3bdfSopenharmony_ci stop = 1; 393f08c3bdfSopenharmony_ci} 394f08c3bdfSopenharmony_ci 395f08c3bdfSopenharmony_ciint main(int argc, char **argv) 396f08c3bdfSopenharmony_ci{ 397f08c3bdfSopenharmony_ci int *threads; 398f08c3bdfSopenharmony_ci long i; 399f08c3bdfSopenharmony_ci int ret; 400f08c3bdfSopenharmony_ci struct timespec intv; 401f08c3bdfSopenharmony_ci struct sched_param param; 402f08c3bdfSopenharmony_ci 403f08c3bdfSopenharmony_ci rt_init("a:r:t:e:l:h:", parse_args, argc, argv); 404f08c3bdfSopenharmony_ci signal(SIGINT, stop_log); 405f08c3bdfSopenharmony_ci 406f08c3bdfSopenharmony_ci if (argc >= (optind + 1)) 407f08c3bdfSopenharmony_ci nr_tasks = atoi(argv[optind]); 408f08c3bdfSopenharmony_ci else { 409f08c3bdfSopenharmony_ci numcpus = sysconf(_SC_NPROCESSORS_ONLN); 410f08c3bdfSopenharmony_ci nr_tasks = numcpus + 1; 411f08c3bdfSopenharmony_ci } 412f08c3bdfSopenharmony_ci 413f08c3bdfSopenharmony_ci intervals = malloc(sizeof(stats_container_t) * nr_tasks); 414f08c3bdfSopenharmony_ci if (!intervals) 415f08c3bdfSopenharmony_ci debug(DBG_ERR, "malloc failed\n"); 416f08c3bdfSopenharmony_ci memset(intervals, 0, sizeof(stats_container_t) * nr_tasks); 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci intervals_length = malloc(sizeof(stats_container_t) * nr_tasks); 419f08c3bdfSopenharmony_ci if (!intervals_length) 420f08c3bdfSopenharmony_ci debug(DBG_ERR, "malloc failed\n"); 421f08c3bdfSopenharmony_ci memset(intervals_length, 0, sizeof(stats_container_t) * nr_tasks); 422f08c3bdfSopenharmony_ci 423f08c3bdfSopenharmony_ci if (!intervals_loops) 424f08c3bdfSopenharmony_ci debug(DBG_ERR, "malloc failed\n"); 425f08c3bdfSopenharmony_ci intervals_loops = malloc(sizeof(stats_container_t) * nr_tasks); 426f08c3bdfSopenharmony_ci memset(intervals_loops, 0, sizeof(stats_container_t) * nr_tasks); 427f08c3bdfSopenharmony_ci 428f08c3bdfSopenharmony_ci threads = malloc(sizeof(*threads) * nr_tasks); 429f08c3bdfSopenharmony_ci if (!threads) 430f08c3bdfSopenharmony_ci debug(DBG_ERR, "malloc failed\n"); 431f08c3bdfSopenharmony_ci memset(threads, 0, sizeof(*threads) * nr_tasks); 432f08c3bdfSopenharmony_ci 433f08c3bdfSopenharmony_ci ret = pthread_barrier_init(&start_barrier, NULL, nr_tasks + 1); 434f08c3bdfSopenharmony_ci ret = pthread_barrier_init(&end_barrier, NULL, nr_tasks + 1); 435f08c3bdfSopenharmony_ci if (ret < 0) 436f08c3bdfSopenharmony_ci debug(DBG_ERR, "pthread_barrier_init failed: %s\n", 437f08c3bdfSopenharmony_ci strerror(ret)); 438f08c3bdfSopenharmony_ci 439f08c3bdfSopenharmony_ci for (i = 0; i < nr_tasks; i++) { 440f08c3bdfSopenharmony_ci stats_container_init(&intervals[i], nr_runs); 441f08c3bdfSopenharmony_ci stats_container_init(&intervals_length[i], nr_runs); 442f08c3bdfSopenharmony_ci stats_container_init(&intervals_loops[i], nr_runs); 443f08c3bdfSopenharmony_ci } 444f08c3bdfSopenharmony_ci 445f08c3bdfSopenharmony_ci thread_pids = malloc(sizeof(long) * nr_tasks); 446f08c3bdfSopenharmony_ci if (!thread_pids) 447f08c3bdfSopenharmony_ci debug(DBG_ERR, "malloc thread_pids failed\n"); 448f08c3bdfSopenharmony_ci 449f08c3bdfSopenharmony_ci for (i = 0; i < nr_tasks; i++) { 450f08c3bdfSopenharmony_ci threads[i] = create_fifo_thread(start_task, (void *)i, 451f08c3bdfSopenharmony_ci prio_start + i); 452f08c3bdfSopenharmony_ci } 453f08c3bdfSopenharmony_ci 454f08c3bdfSopenharmony_ci /* 455f08c3bdfSopenharmony_ci * Progress bar uses stderr to let users see it when 456f08c3bdfSopenharmony_ci * redirecting output. So we convert stderr to use line 457f08c3bdfSopenharmony_ci * buffering so the progress bar doesn't flicker. 458f08c3bdfSopenharmony_ci */ 459f08c3bdfSopenharmony_ci setlinebuf(stderr); 460f08c3bdfSopenharmony_ci 461f08c3bdfSopenharmony_ci /* up our prio above all tasks */ 462f08c3bdfSopenharmony_ci memset(¶m, 0, sizeof(param)); 463f08c3bdfSopenharmony_ci param.sched_priority = nr_tasks + prio_start; 464f08c3bdfSopenharmony_ci if (sched_setscheduler(0, SCHED_FIFO, ¶m)) 465f08c3bdfSopenharmony_ci debug(DBG_WARN, "Warning, can't set priority of main thread!\n"); 466f08c3bdfSopenharmony_ci intv.tv_sec = INTERVAL / NS_PER_SEC; 467f08c3bdfSopenharmony_ci intv.tv_nsec = INTERVAL % (1 * NS_PER_SEC); 468f08c3bdfSopenharmony_ci 469f08c3bdfSopenharmony_ci print_progress_bar(0); 470f08c3bdfSopenharmony_ci 471f08c3bdfSopenharmony_ci setup_ftrace_marker(); 472f08c3bdfSopenharmony_ci 473f08c3bdfSopenharmony_ci for (loop = 0; loop < nr_runs; loop++) { 474f08c3bdfSopenharmony_ci unsigned long long end; 475f08c3bdfSopenharmony_ci 476f08c3bdfSopenharmony_ci now = rt_gettime() / NS_PER_US; 477f08c3bdfSopenharmony_ci 478f08c3bdfSopenharmony_ci ftrace_write("Loop %d now=%lld\n", loop, now); 479f08c3bdfSopenharmony_ci 480f08c3bdfSopenharmony_ci pthread_barrier_wait(&start_barrier); 481f08c3bdfSopenharmony_ci 482f08c3bdfSopenharmony_ci ftrace_write("All running!!!\n"); 483f08c3bdfSopenharmony_ci 484f08c3bdfSopenharmony_ci rt_nanosleep(intv.tv_nsec); 485f08c3bdfSopenharmony_ci print_progress_bar((loop * 100) / nr_runs); 486f08c3bdfSopenharmony_ci 487f08c3bdfSopenharmony_ci end = rt_gettime() / NS_PER_US; 488f08c3bdfSopenharmony_ci ftrace_write("Loop %d end now=%lld diff=%lld\n", 489f08c3bdfSopenharmony_ci loop, end, end - now); 490f08c3bdfSopenharmony_ci ret = pthread_barrier_wait(&end_barrier); 491f08c3bdfSopenharmony_ci 492f08c3bdfSopenharmony_ci if (stop || (check && check_times(loop))) { 493f08c3bdfSopenharmony_ci loop++; 494f08c3bdfSopenharmony_ci nr_runs = loop; 495f08c3bdfSopenharmony_ci break; 496f08c3bdfSopenharmony_ci } 497f08c3bdfSopenharmony_ci } 498f08c3bdfSopenharmony_ci putc('\n', stderr); 499f08c3bdfSopenharmony_ci 500f08c3bdfSopenharmony_ci pthread_barrier_wait(&start_barrier); 501f08c3bdfSopenharmony_ci done = 1; 502f08c3bdfSopenharmony_ci pthread_barrier_wait(&end_barrier); 503f08c3bdfSopenharmony_ci 504f08c3bdfSopenharmony_ci join_threads(); 505f08c3bdfSopenharmony_ci print_results(); 506f08c3bdfSopenharmony_ci 507f08c3bdfSopenharmony_ci if (stop) { 508f08c3bdfSopenharmony_ci /* 509f08c3bdfSopenharmony_ci * We use this test in bash while loops 510f08c3bdfSopenharmony_ci * So if we hit Ctrl-C then let the while 511f08c3bdfSopenharmony_ci * loop know to break. 512f08c3bdfSopenharmony_ci */ 513f08c3bdfSopenharmony_ci if (check < 0) 514f08c3bdfSopenharmony_ci exit(-1); 515f08c3bdfSopenharmony_ci else 516f08c3bdfSopenharmony_ci exit(1); 517f08c3bdfSopenharmony_ci } 518f08c3bdfSopenharmony_ci 519f08c3bdfSopenharmony_ci if (check < 0) 520f08c3bdfSopenharmony_ci exit(-1); 521f08c3bdfSopenharmony_ci else 522f08c3bdfSopenharmony_ci exit(0); 523f08c3bdfSopenharmony_ci} 524