162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Context switch microbenchmark. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2015 Anton Blanchard <anton@au.ibm.com>, IBM 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define _GNU_SOURCE 962306a36Sopenharmony_ci#include <errno.h> 1062306a36Sopenharmony_ci#include <sched.h> 1162306a36Sopenharmony_ci#include <string.h> 1262306a36Sopenharmony_ci#include <stdio.h> 1362306a36Sopenharmony_ci#include <unistd.h> 1462306a36Sopenharmony_ci#include <stdlib.h> 1562306a36Sopenharmony_ci#include <getopt.h> 1662306a36Sopenharmony_ci#include <signal.h> 1762306a36Sopenharmony_ci#include <assert.h> 1862306a36Sopenharmony_ci#include <pthread.h> 1962306a36Sopenharmony_ci#include <limits.h> 2062306a36Sopenharmony_ci#include <sys/time.h> 2162306a36Sopenharmony_ci#include <sys/syscall.h> 2262306a36Sopenharmony_ci#include <sys/sysinfo.h> 2362306a36Sopenharmony_ci#include <sys/types.h> 2462306a36Sopenharmony_ci#include <sys/shm.h> 2562306a36Sopenharmony_ci#include <linux/futex.h> 2662306a36Sopenharmony_ci#ifdef __powerpc__ 2762306a36Sopenharmony_ci#include <altivec.h> 2862306a36Sopenharmony_ci#endif 2962306a36Sopenharmony_ci#include "utils.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic unsigned int timeout = 30; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic int touch_vdso; 3462306a36Sopenharmony_cistruct timeval tv; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int touch_fp = 1; 3762306a36Sopenharmony_cidouble fp; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int touch_vector = 1; 4062306a36Sopenharmony_civector int a, b, c; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#ifdef __powerpc__ 4362306a36Sopenharmony_cistatic int touch_altivec = 1; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * Note: LTO (Link Time Optimisation) doesn't play well with this function 4762306a36Sopenharmony_ci * attribute. Be very careful enabling LTO for this test. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_cistatic void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci c = a + b; 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci#endif 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic void touch(void) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci if (touch_vdso) 5862306a36Sopenharmony_ci gettimeofday(&tv, NULL); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci if (touch_fp) 6162306a36Sopenharmony_ci fp += 0.1; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#ifdef __powerpc__ 6462306a36Sopenharmony_ci if (touch_altivec) 6562306a36Sopenharmony_ci altivec_touch_fn(); 6662306a36Sopenharmony_ci#endif 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (touch_vector) 6962306a36Sopenharmony_ci c = a + b; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci asm volatile("# %0 %1 %2": : "r"(&tv), "r"(&fp), "r"(&c)); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci int rc; 7762306a36Sopenharmony_ci pthread_t tid; 7862306a36Sopenharmony_ci cpu_set_t cpuset; 7962306a36Sopenharmony_ci pthread_attr_t attr; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci CPU_ZERO(&cpuset); 8262306a36Sopenharmony_ci CPU_SET(cpu, &cpuset); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci rc = pthread_attr_init(&attr); 8562306a36Sopenharmony_ci if (rc) { 8662306a36Sopenharmony_ci errno = rc; 8762306a36Sopenharmony_ci perror("pthread_attr_init"); 8862306a36Sopenharmony_ci exit(1); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); 9262306a36Sopenharmony_ci if (rc) { 9362306a36Sopenharmony_ci errno = rc; 9462306a36Sopenharmony_ci perror("pthread_attr_setaffinity_np"); 9562306a36Sopenharmony_ci exit(1); 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci rc = pthread_create(&tid, &attr, fn, arg); 9962306a36Sopenharmony_ci if (rc) { 10062306a36Sopenharmony_ci errno = rc; 10162306a36Sopenharmony_ci perror("pthread_create"); 10262306a36Sopenharmony_ci exit(1); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic void start_process_on(void *(*fn)(void *), void *arg, unsigned long cpu) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci int pid, ncpus; 10962306a36Sopenharmony_ci cpu_set_t *cpuset; 11062306a36Sopenharmony_ci size_t size; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci pid = fork(); 11362306a36Sopenharmony_ci if (pid == -1) { 11462306a36Sopenharmony_ci perror("fork"); 11562306a36Sopenharmony_ci exit(1); 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (pid) 11962306a36Sopenharmony_ci return; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci ncpus = get_nprocs(); 12262306a36Sopenharmony_ci size = CPU_ALLOC_SIZE(ncpus); 12362306a36Sopenharmony_ci cpuset = CPU_ALLOC(ncpus); 12462306a36Sopenharmony_ci if (!cpuset) { 12562306a36Sopenharmony_ci perror("malloc"); 12662306a36Sopenharmony_ci exit(1); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci CPU_ZERO_S(size, cpuset); 12962306a36Sopenharmony_ci CPU_SET_S(cpu, size, cpuset); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (sched_setaffinity(0, size, cpuset)) { 13262306a36Sopenharmony_ci perror("sched_setaffinity"); 13362306a36Sopenharmony_ci CPU_FREE(cpuset); 13462306a36Sopenharmony_ci exit(1); 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci CPU_FREE(cpuset); 13862306a36Sopenharmony_ci fn(arg); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci exit(0); 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic unsigned long iterations; 14462306a36Sopenharmony_cistatic unsigned long iterations_prev; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic void sigalrm_handler(int junk) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci unsigned long i = iterations; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci printf("%ld\n", i - iterations_prev); 15162306a36Sopenharmony_ci iterations_prev = i; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (--timeout == 0) 15462306a36Sopenharmony_ci kill(0, SIGUSR1); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci alarm(1); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic void sigusr1_handler(int junk) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci exit(0); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistruct actions { 16562306a36Sopenharmony_ci void (*setup)(int, int); 16662306a36Sopenharmony_ci void *(*thread1)(void *); 16762306a36Sopenharmony_ci void *(*thread2)(void *); 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#define READ 0 17162306a36Sopenharmony_ci#define WRITE 1 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic int pipe_fd1[2]; 17462306a36Sopenharmony_cistatic int pipe_fd2[2]; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic void pipe_setup(int cpu1, int cpu2) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci if (pipe(pipe_fd1) || pipe(pipe_fd2)) 17962306a36Sopenharmony_ci exit(1); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic void *pipe_thread1(void *arg) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci signal(SIGALRM, sigalrm_handler); 18562306a36Sopenharmony_ci alarm(1); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci while (1) { 18862306a36Sopenharmony_ci assert(read(pipe_fd1[READ], &c, 1) == 1); 18962306a36Sopenharmony_ci touch(); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci assert(write(pipe_fd2[WRITE], &c, 1) == 1); 19262306a36Sopenharmony_ci touch(); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci iterations += 2; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return NULL; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic void *pipe_thread2(void *arg) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci while (1) { 20362306a36Sopenharmony_ci assert(write(pipe_fd1[WRITE], &c, 1) == 1); 20462306a36Sopenharmony_ci touch(); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci assert(read(pipe_fd2[READ], &c, 1) == 1); 20762306a36Sopenharmony_ci touch(); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return NULL; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic struct actions pipe_actions = { 21462306a36Sopenharmony_ci .setup = pipe_setup, 21562306a36Sopenharmony_ci .thread1 = pipe_thread1, 21662306a36Sopenharmony_ci .thread2 = pipe_thread2, 21762306a36Sopenharmony_ci}; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic void yield_setup(int cpu1, int cpu2) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci if (cpu1 != cpu2) { 22262306a36Sopenharmony_ci fprintf(stderr, "Both threads must be on the same CPU for yield test\n"); 22362306a36Sopenharmony_ci exit(1); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic void *yield_thread1(void *arg) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci signal(SIGALRM, sigalrm_handler); 23062306a36Sopenharmony_ci alarm(1); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci while (1) { 23362306a36Sopenharmony_ci sched_yield(); 23462306a36Sopenharmony_ci touch(); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci iterations += 2; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci return NULL; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic void *yield_thread2(void *arg) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci while (1) { 24562306a36Sopenharmony_ci sched_yield(); 24662306a36Sopenharmony_ci touch(); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return NULL; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic struct actions yield_actions = { 25362306a36Sopenharmony_ci .setup = yield_setup, 25462306a36Sopenharmony_ci .thread1 = yield_thread1, 25562306a36Sopenharmony_ci .thread2 = yield_thread2, 25662306a36Sopenharmony_ci}; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, 25962306a36Sopenharmony_ci void *addr2, int val3) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic unsigned long cmpxchg(unsigned long *p, unsigned long expected, 26562306a36Sopenharmony_ci unsigned long desired) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci unsigned long exp = expected; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci __atomic_compare_exchange_n(p, &exp, desired, 0, 27062306a36Sopenharmony_ci __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 27162306a36Sopenharmony_ci return exp; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic unsigned long xchg(unsigned long *p, unsigned long val) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci return __atomic_exchange_n(p, val, __ATOMIC_SEQ_CST); 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic int processes; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic int mutex_lock(unsigned long *m) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci int c; 28462306a36Sopenharmony_ci int flags = FUTEX_WAIT; 28562306a36Sopenharmony_ci if (!processes) 28662306a36Sopenharmony_ci flags |= FUTEX_PRIVATE_FLAG; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci c = cmpxchg(m, 0, 1); 28962306a36Sopenharmony_ci if (!c) 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (c == 1) 29362306a36Sopenharmony_ci c = xchg(m, 2); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci while (c) { 29662306a36Sopenharmony_ci sys_futex(m, flags, 2, NULL, NULL, 0); 29762306a36Sopenharmony_ci c = xchg(m, 2); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return 0; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic int mutex_unlock(unsigned long *m) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci int flags = FUTEX_WAKE; 30662306a36Sopenharmony_ci if (!processes) 30762306a36Sopenharmony_ci flags |= FUTEX_PRIVATE_FLAG; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (*m == 2) 31062306a36Sopenharmony_ci *m = 0; 31162306a36Sopenharmony_ci else if (xchg(m, 0) == 1) 31262306a36Sopenharmony_ci return 0; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci sys_futex(m, flags, 1, NULL, NULL, 0); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic unsigned long *m1, *m2; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic void futex_setup(int cpu1, int cpu2) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci if (!processes) { 32462306a36Sopenharmony_ci static unsigned long _m1, _m2; 32562306a36Sopenharmony_ci m1 = &_m1; 32662306a36Sopenharmony_ci m2 = &_m2; 32762306a36Sopenharmony_ci } else { 32862306a36Sopenharmony_ci int shmid; 32962306a36Sopenharmony_ci void *shmaddr; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci shmid = shmget(IPC_PRIVATE, getpagesize(), SHM_R | SHM_W); 33262306a36Sopenharmony_ci if (shmid < 0) { 33362306a36Sopenharmony_ci perror("shmget"); 33462306a36Sopenharmony_ci exit(1); 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci shmaddr = shmat(shmid, NULL, 0); 33862306a36Sopenharmony_ci if (shmaddr == (char *)-1) { 33962306a36Sopenharmony_ci perror("shmat"); 34062306a36Sopenharmony_ci shmctl(shmid, IPC_RMID, NULL); 34162306a36Sopenharmony_ci exit(1); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci shmctl(shmid, IPC_RMID, NULL); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci m1 = shmaddr; 34762306a36Sopenharmony_ci m2 = shmaddr + sizeof(*m1); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci *m1 = 0; 35162306a36Sopenharmony_ci *m2 = 0; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci mutex_lock(m1); 35462306a36Sopenharmony_ci mutex_lock(m2); 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic void *futex_thread1(void *arg) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci signal(SIGALRM, sigalrm_handler); 36062306a36Sopenharmony_ci alarm(1); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci while (1) { 36362306a36Sopenharmony_ci mutex_lock(m2); 36462306a36Sopenharmony_ci mutex_unlock(m1); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci iterations += 2; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return NULL; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic void *futex_thread2(void *arg) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci while (1) { 37562306a36Sopenharmony_ci mutex_unlock(m2); 37662306a36Sopenharmony_ci mutex_lock(m1); 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return NULL; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic struct actions futex_actions = { 38362306a36Sopenharmony_ci .setup = futex_setup, 38462306a36Sopenharmony_ci .thread1 = futex_thread1, 38562306a36Sopenharmony_ci .thread2 = futex_thread2, 38662306a36Sopenharmony_ci}; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic struct option options[] = { 38962306a36Sopenharmony_ci { "test", required_argument, 0, 't' }, 39062306a36Sopenharmony_ci { "process", no_argument, &processes, 1 }, 39162306a36Sopenharmony_ci { "timeout", required_argument, 0, 's' }, 39262306a36Sopenharmony_ci { "vdso", no_argument, &touch_vdso, 1 }, 39362306a36Sopenharmony_ci { "no-fp", no_argument, &touch_fp, 0 }, 39462306a36Sopenharmony_ci#ifdef __powerpc__ 39562306a36Sopenharmony_ci { "no-altivec", no_argument, &touch_altivec, 0 }, 39662306a36Sopenharmony_ci#endif 39762306a36Sopenharmony_ci { "no-vector", no_argument, &touch_vector, 0 }, 39862306a36Sopenharmony_ci { 0, }, 39962306a36Sopenharmony_ci}; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic void usage(void) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci fprintf(stderr, "Usage: context_switch2 <options> CPU1 CPU2\n\n"); 40462306a36Sopenharmony_ci fprintf(stderr, "\t\t--test=X\tpipe, futex or yield (default)\n"); 40562306a36Sopenharmony_ci fprintf(stderr, "\t\t--process\tUse processes (default threads)\n"); 40662306a36Sopenharmony_ci fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n"); 40762306a36Sopenharmony_ci fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n"); 40862306a36Sopenharmony_ci fprintf(stderr, "\t\t--no-fp\t\tDon't touch FP\n"); 40962306a36Sopenharmony_ci#ifdef __powerpc__ 41062306a36Sopenharmony_ci fprintf(stderr, "\t\t--no-altivec\tDon't touch altivec\n"); 41162306a36Sopenharmony_ci#endif 41262306a36Sopenharmony_ci fprintf(stderr, "\t\t--no-vector\tDon't touch vector\n"); 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciint main(int argc, char *argv[]) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci signed char c; 41862306a36Sopenharmony_ci struct actions *actions = &yield_actions; 41962306a36Sopenharmony_ci int cpu1; 42062306a36Sopenharmony_ci int cpu2; 42162306a36Sopenharmony_ci static void (*start_fn)(void *(*fn)(void *), void *arg, unsigned long cpu); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci while (1) { 42462306a36Sopenharmony_ci int option_index = 0; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci c = getopt_long(argc, argv, "", options, &option_index); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci if (c == -1) 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci switch (c) { 43262306a36Sopenharmony_ci case 0: 43362306a36Sopenharmony_ci if (options[option_index].flag != 0) 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci usage(); 43762306a36Sopenharmony_ci exit(1); 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci case 't': 44162306a36Sopenharmony_ci if (!strcmp(optarg, "pipe")) { 44262306a36Sopenharmony_ci actions = &pipe_actions; 44362306a36Sopenharmony_ci } else if (!strcmp(optarg, "yield")) { 44462306a36Sopenharmony_ci actions = &yield_actions; 44562306a36Sopenharmony_ci } else if (!strcmp(optarg, "futex")) { 44662306a36Sopenharmony_ci actions = &futex_actions; 44762306a36Sopenharmony_ci } else { 44862306a36Sopenharmony_ci usage(); 44962306a36Sopenharmony_ci exit(1); 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci break; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci case 's': 45462306a36Sopenharmony_ci timeout = atoi(optarg); 45562306a36Sopenharmony_ci break; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci default: 45862306a36Sopenharmony_ci usage(); 45962306a36Sopenharmony_ci exit(1); 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (processes) 46462306a36Sopenharmony_ci start_fn = start_process_on; 46562306a36Sopenharmony_ci else 46662306a36Sopenharmony_ci start_fn = start_thread_on; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if (((argc - optind) != 2)) { 46962306a36Sopenharmony_ci cpu1 = cpu2 = pick_online_cpu(); 47062306a36Sopenharmony_ci } else { 47162306a36Sopenharmony_ci cpu1 = atoi(argv[optind++]); 47262306a36Sopenharmony_ci cpu2 = atoi(argv[optind++]); 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci printf("Using %s with ", processes ? "processes" : "threads"); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (actions == &pipe_actions) 47862306a36Sopenharmony_ci printf("pipe"); 47962306a36Sopenharmony_ci else if (actions == &yield_actions) 48062306a36Sopenharmony_ci printf("yield"); 48162306a36Sopenharmony_ci else 48262306a36Sopenharmony_ci printf("futex"); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if (!have_hwcap(PPC_FEATURE_HAS_ALTIVEC)) 48562306a36Sopenharmony_ci touch_altivec = 0; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (!have_hwcap(PPC_FEATURE_HAS_VSX)) 48862306a36Sopenharmony_ci touch_vector = 0; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci printf(" on cpus %d/%d touching FP:%s altivec:%s vector:%s vdso:%s\n", 49162306a36Sopenharmony_ci cpu1, cpu2, touch_fp ? "yes" : "no", touch_altivec ? "yes" : "no", 49262306a36Sopenharmony_ci touch_vector ? "yes" : "no", touch_vdso ? "yes" : "no"); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci /* Create a new process group so we can signal everyone for exit */ 49562306a36Sopenharmony_ci setpgid(getpid(), getpid()); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci signal(SIGUSR1, sigusr1_handler); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci actions->setup(cpu1, cpu2); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci start_fn(actions->thread1, NULL, cpu1); 50262306a36Sopenharmony_ci start_fn(actions->thread2, NULL, cpu2); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci while (1) 50562306a36Sopenharmony_ci sleep(3600); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return 0; 50862306a36Sopenharmony_ci} 509