18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Context switch microbenchmark. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Anton Blanchard <anton@au.ibm.com>, IBM 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define _GNU_SOURCE 98c2ecf20Sopenharmony_ci#include <errno.h> 108c2ecf20Sopenharmony_ci#include <sched.h> 118c2ecf20Sopenharmony_ci#include <string.h> 128c2ecf20Sopenharmony_ci#include <stdio.h> 138c2ecf20Sopenharmony_ci#include <unistd.h> 148c2ecf20Sopenharmony_ci#include <stdlib.h> 158c2ecf20Sopenharmony_ci#include <getopt.h> 168c2ecf20Sopenharmony_ci#include <signal.h> 178c2ecf20Sopenharmony_ci#include <assert.h> 188c2ecf20Sopenharmony_ci#include <pthread.h> 198c2ecf20Sopenharmony_ci#include <limits.h> 208c2ecf20Sopenharmony_ci#include <sys/time.h> 218c2ecf20Sopenharmony_ci#include <sys/syscall.h> 228c2ecf20Sopenharmony_ci#include <sys/sysinfo.h> 238c2ecf20Sopenharmony_ci#include <sys/types.h> 248c2ecf20Sopenharmony_ci#include <sys/shm.h> 258c2ecf20Sopenharmony_ci#include <linux/futex.h> 268c2ecf20Sopenharmony_ci#ifdef __powerpc__ 278c2ecf20Sopenharmony_ci#include <altivec.h> 288c2ecf20Sopenharmony_ci#endif 298c2ecf20Sopenharmony_ci#include "utils.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic unsigned int timeout = 30; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int touch_vdso; 348c2ecf20Sopenharmony_cistruct timeval tv; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int touch_fp = 1; 378c2ecf20Sopenharmony_cidouble fp; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int touch_vector = 1; 408c2ecf20Sopenharmony_civector int a, b, c; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#ifdef __powerpc__ 438c2ecf20Sopenharmony_cistatic int touch_altivec = 1; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * Note: LTO (Link Time Optimisation) doesn't play well with this function 478c2ecf20Sopenharmony_ci * attribute. Be very careful enabling LTO for this test. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_cistatic void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci c = a + b; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci#endif 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic void touch(void) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci if (touch_vdso) 588c2ecf20Sopenharmony_ci gettimeofday(&tv, NULL); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (touch_fp) 618c2ecf20Sopenharmony_ci fp += 0.1; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#ifdef __powerpc__ 648c2ecf20Sopenharmony_ci if (touch_altivec) 658c2ecf20Sopenharmony_ci altivec_touch_fn(); 668c2ecf20Sopenharmony_ci#endif 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (touch_vector) 698c2ecf20Sopenharmony_ci c = a + b; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci asm volatile("# %0 %1 %2": : "r"(&tv), "r"(&fp), "r"(&c)); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci int rc; 778c2ecf20Sopenharmony_ci pthread_t tid; 788c2ecf20Sopenharmony_ci cpu_set_t cpuset; 798c2ecf20Sopenharmony_ci pthread_attr_t attr; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci CPU_ZERO(&cpuset); 828c2ecf20Sopenharmony_ci CPU_SET(cpu, &cpuset); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci rc = pthread_attr_init(&attr); 858c2ecf20Sopenharmony_ci if (rc) { 868c2ecf20Sopenharmony_ci errno = rc; 878c2ecf20Sopenharmony_ci perror("pthread_attr_init"); 888c2ecf20Sopenharmony_ci exit(1); 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); 928c2ecf20Sopenharmony_ci if (rc) { 938c2ecf20Sopenharmony_ci errno = rc; 948c2ecf20Sopenharmony_ci perror("pthread_attr_setaffinity_np"); 958c2ecf20Sopenharmony_ci exit(1); 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci rc = pthread_create(&tid, &attr, fn, arg); 998c2ecf20Sopenharmony_ci if (rc) { 1008c2ecf20Sopenharmony_ci errno = rc; 1018c2ecf20Sopenharmony_ci perror("pthread_create"); 1028c2ecf20Sopenharmony_ci exit(1); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic void start_process_on(void *(*fn)(void *), void *arg, unsigned long cpu) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci int pid, ncpus; 1098c2ecf20Sopenharmony_ci cpu_set_t *cpuset; 1108c2ecf20Sopenharmony_ci size_t size; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci pid = fork(); 1138c2ecf20Sopenharmony_ci if (pid == -1) { 1148c2ecf20Sopenharmony_ci perror("fork"); 1158c2ecf20Sopenharmony_ci exit(1); 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (pid) 1198c2ecf20Sopenharmony_ci return; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci ncpus = get_nprocs(); 1228c2ecf20Sopenharmony_ci size = CPU_ALLOC_SIZE(ncpus); 1238c2ecf20Sopenharmony_ci cpuset = CPU_ALLOC(ncpus); 1248c2ecf20Sopenharmony_ci if (!cpuset) { 1258c2ecf20Sopenharmony_ci perror("malloc"); 1268c2ecf20Sopenharmony_ci exit(1); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci CPU_ZERO_S(size, cpuset); 1298c2ecf20Sopenharmony_ci CPU_SET_S(cpu, size, cpuset); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (sched_setaffinity(0, size, cpuset)) { 1328c2ecf20Sopenharmony_ci perror("sched_setaffinity"); 1338c2ecf20Sopenharmony_ci CPU_FREE(cpuset); 1348c2ecf20Sopenharmony_ci exit(1); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci CPU_FREE(cpuset); 1388c2ecf20Sopenharmony_ci fn(arg); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci exit(0); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic unsigned long iterations; 1448c2ecf20Sopenharmony_cistatic unsigned long iterations_prev; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic void sigalrm_handler(int junk) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci unsigned long i = iterations; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci printf("%ld\n", i - iterations_prev); 1518c2ecf20Sopenharmony_ci iterations_prev = i; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (--timeout == 0) 1548c2ecf20Sopenharmony_ci kill(0, SIGUSR1); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci alarm(1); 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic void sigusr1_handler(int junk) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci exit(0); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistruct actions { 1658c2ecf20Sopenharmony_ci void (*setup)(int, int); 1668c2ecf20Sopenharmony_ci void *(*thread1)(void *); 1678c2ecf20Sopenharmony_ci void *(*thread2)(void *); 1688c2ecf20Sopenharmony_ci}; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define READ 0 1718c2ecf20Sopenharmony_ci#define WRITE 1 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic int pipe_fd1[2]; 1748c2ecf20Sopenharmony_cistatic int pipe_fd2[2]; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic void pipe_setup(int cpu1, int cpu2) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci if (pipe(pipe_fd1) || pipe(pipe_fd2)) 1798c2ecf20Sopenharmony_ci exit(1); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic void *pipe_thread1(void *arg) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci signal(SIGALRM, sigalrm_handler); 1858c2ecf20Sopenharmony_ci alarm(1); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci while (1) { 1888c2ecf20Sopenharmony_ci assert(read(pipe_fd1[READ], &c, 1) == 1); 1898c2ecf20Sopenharmony_ci touch(); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci assert(write(pipe_fd2[WRITE], &c, 1) == 1); 1928c2ecf20Sopenharmony_ci touch(); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci iterations += 2; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return NULL; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic void *pipe_thread2(void *arg) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci while (1) { 2038c2ecf20Sopenharmony_ci assert(write(pipe_fd1[WRITE], &c, 1) == 1); 2048c2ecf20Sopenharmony_ci touch(); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci assert(read(pipe_fd2[READ], &c, 1) == 1); 2078c2ecf20Sopenharmony_ci touch(); 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci return NULL; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic struct actions pipe_actions = { 2148c2ecf20Sopenharmony_ci .setup = pipe_setup, 2158c2ecf20Sopenharmony_ci .thread1 = pipe_thread1, 2168c2ecf20Sopenharmony_ci .thread2 = pipe_thread2, 2178c2ecf20Sopenharmony_ci}; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic void yield_setup(int cpu1, int cpu2) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci if (cpu1 != cpu2) { 2228c2ecf20Sopenharmony_ci fprintf(stderr, "Both threads must be on the same CPU for yield test\n"); 2238c2ecf20Sopenharmony_ci exit(1); 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic void *yield_thread1(void *arg) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci signal(SIGALRM, sigalrm_handler); 2308c2ecf20Sopenharmony_ci alarm(1); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci while (1) { 2338c2ecf20Sopenharmony_ci sched_yield(); 2348c2ecf20Sopenharmony_ci touch(); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci iterations += 2; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return NULL; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic void *yield_thread2(void *arg) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci while (1) { 2458c2ecf20Sopenharmony_ci sched_yield(); 2468c2ecf20Sopenharmony_ci touch(); 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci return NULL; 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic struct actions yield_actions = { 2538c2ecf20Sopenharmony_ci .setup = yield_setup, 2548c2ecf20Sopenharmony_ci .thread1 = yield_thread1, 2558c2ecf20Sopenharmony_ci .thread2 = yield_thread2, 2568c2ecf20Sopenharmony_ci}; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, 2598c2ecf20Sopenharmony_ci void *addr2, int val3) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic unsigned long cmpxchg(unsigned long *p, unsigned long expected, 2658c2ecf20Sopenharmony_ci unsigned long desired) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci unsigned long exp = expected; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci __atomic_compare_exchange_n(p, &exp, desired, 0, 2708c2ecf20Sopenharmony_ci __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 2718c2ecf20Sopenharmony_ci return exp; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic unsigned long xchg(unsigned long *p, unsigned long val) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci return __atomic_exchange_n(p, val, __ATOMIC_SEQ_CST); 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int processes; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic int mutex_lock(unsigned long *m) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci int c; 2848c2ecf20Sopenharmony_ci int flags = FUTEX_WAIT; 2858c2ecf20Sopenharmony_ci if (!processes) 2868c2ecf20Sopenharmony_ci flags |= FUTEX_PRIVATE_FLAG; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci c = cmpxchg(m, 0, 1); 2898c2ecf20Sopenharmony_ci if (!c) 2908c2ecf20Sopenharmony_ci return 0; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (c == 1) 2938c2ecf20Sopenharmony_ci c = xchg(m, 2); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci while (c) { 2968c2ecf20Sopenharmony_ci sys_futex(m, flags, 2, NULL, NULL, 0); 2978c2ecf20Sopenharmony_ci c = xchg(m, 2); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int mutex_unlock(unsigned long *m) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci int flags = FUTEX_WAKE; 3068c2ecf20Sopenharmony_ci if (!processes) 3078c2ecf20Sopenharmony_ci flags |= FUTEX_PRIVATE_FLAG; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (*m == 2) 3108c2ecf20Sopenharmony_ci *m = 0; 3118c2ecf20Sopenharmony_ci else if (xchg(m, 0) == 1) 3128c2ecf20Sopenharmony_ci return 0; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci sys_futex(m, flags, 1, NULL, NULL, 0); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic unsigned long *m1, *m2; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void futex_setup(int cpu1, int cpu2) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci if (!processes) { 3248c2ecf20Sopenharmony_ci static unsigned long _m1, _m2; 3258c2ecf20Sopenharmony_ci m1 = &_m1; 3268c2ecf20Sopenharmony_ci m2 = &_m2; 3278c2ecf20Sopenharmony_ci } else { 3288c2ecf20Sopenharmony_ci int shmid; 3298c2ecf20Sopenharmony_ci void *shmaddr; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci shmid = shmget(IPC_PRIVATE, getpagesize(), SHM_R | SHM_W); 3328c2ecf20Sopenharmony_ci if (shmid < 0) { 3338c2ecf20Sopenharmony_ci perror("shmget"); 3348c2ecf20Sopenharmony_ci exit(1); 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci shmaddr = shmat(shmid, NULL, 0); 3388c2ecf20Sopenharmony_ci if (shmaddr == (char *)-1) { 3398c2ecf20Sopenharmony_ci perror("shmat"); 3408c2ecf20Sopenharmony_ci shmctl(shmid, IPC_RMID, NULL); 3418c2ecf20Sopenharmony_ci exit(1); 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci shmctl(shmid, IPC_RMID, NULL); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci m1 = shmaddr; 3478c2ecf20Sopenharmony_ci m2 = shmaddr + sizeof(*m1); 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci *m1 = 0; 3518c2ecf20Sopenharmony_ci *m2 = 0; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci mutex_lock(m1); 3548c2ecf20Sopenharmony_ci mutex_lock(m2); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic void *futex_thread1(void *arg) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci signal(SIGALRM, sigalrm_handler); 3608c2ecf20Sopenharmony_ci alarm(1); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci while (1) { 3638c2ecf20Sopenharmony_ci mutex_lock(m2); 3648c2ecf20Sopenharmony_ci mutex_unlock(m1); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci iterations += 2; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci return NULL; 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic void *futex_thread2(void *arg) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci while (1) { 3758c2ecf20Sopenharmony_ci mutex_unlock(m2); 3768c2ecf20Sopenharmony_ci mutex_lock(m1); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci return NULL; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic struct actions futex_actions = { 3838c2ecf20Sopenharmony_ci .setup = futex_setup, 3848c2ecf20Sopenharmony_ci .thread1 = futex_thread1, 3858c2ecf20Sopenharmony_ci .thread2 = futex_thread2, 3868c2ecf20Sopenharmony_ci}; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic struct option options[] = { 3898c2ecf20Sopenharmony_ci { "test", required_argument, 0, 't' }, 3908c2ecf20Sopenharmony_ci { "process", no_argument, &processes, 1 }, 3918c2ecf20Sopenharmony_ci { "timeout", required_argument, 0, 's' }, 3928c2ecf20Sopenharmony_ci { "vdso", no_argument, &touch_vdso, 1 }, 3938c2ecf20Sopenharmony_ci { "no-fp", no_argument, &touch_fp, 0 }, 3948c2ecf20Sopenharmony_ci#ifdef __powerpc__ 3958c2ecf20Sopenharmony_ci { "no-altivec", no_argument, &touch_altivec, 0 }, 3968c2ecf20Sopenharmony_ci#endif 3978c2ecf20Sopenharmony_ci { "no-vector", no_argument, &touch_vector, 0 }, 3988c2ecf20Sopenharmony_ci { 0, }, 3998c2ecf20Sopenharmony_ci}; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistatic void usage(void) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci fprintf(stderr, "Usage: context_switch2 <options> CPU1 CPU2\n\n"); 4048c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--test=X\tpipe, futex or yield (default)\n"); 4058c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--process\tUse processes (default threads)\n"); 4068c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n"); 4078c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n"); 4088c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--no-fp\t\tDon't touch FP\n"); 4098c2ecf20Sopenharmony_ci#ifdef __powerpc__ 4108c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--no-altivec\tDon't touch altivec\n"); 4118c2ecf20Sopenharmony_ci#endif 4128c2ecf20Sopenharmony_ci fprintf(stderr, "\t\t--no-vector\tDon't touch vector\n"); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci signed char c; 4188c2ecf20Sopenharmony_ci struct actions *actions = &yield_actions; 4198c2ecf20Sopenharmony_ci int cpu1; 4208c2ecf20Sopenharmony_ci int cpu2; 4218c2ecf20Sopenharmony_ci static void (*start_fn)(void *(*fn)(void *), void *arg, unsigned long cpu); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci while (1) { 4248c2ecf20Sopenharmony_ci int option_index = 0; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci c = getopt_long(argc, argv, "", options, &option_index); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (c == -1) 4298c2ecf20Sopenharmony_ci break; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci switch (c) { 4328c2ecf20Sopenharmony_ci case 0: 4338c2ecf20Sopenharmony_ci if (options[option_index].flag != 0) 4348c2ecf20Sopenharmony_ci break; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci usage(); 4378c2ecf20Sopenharmony_ci exit(1); 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci case 't': 4418c2ecf20Sopenharmony_ci if (!strcmp(optarg, "pipe")) { 4428c2ecf20Sopenharmony_ci actions = &pipe_actions; 4438c2ecf20Sopenharmony_ci } else if (!strcmp(optarg, "yield")) { 4448c2ecf20Sopenharmony_ci actions = &yield_actions; 4458c2ecf20Sopenharmony_ci } else if (!strcmp(optarg, "futex")) { 4468c2ecf20Sopenharmony_ci actions = &futex_actions; 4478c2ecf20Sopenharmony_ci } else { 4488c2ecf20Sopenharmony_ci usage(); 4498c2ecf20Sopenharmony_ci exit(1); 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci break; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci case 's': 4548c2ecf20Sopenharmony_ci timeout = atoi(optarg); 4558c2ecf20Sopenharmony_ci break; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci default: 4588c2ecf20Sopenharmony_ci usage(); 4598c2ecf20Sopenharmony_ci exit(1); 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (processes) 4648c2ecf20Sopenharmony_ci start_fn = start_process_on; 4658c2ecf20Sopenharmony_ci else 4668c2ecf20Sopenharmony_ci start_fn = start_thread_on; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci if (((argc - optind) != 2)) { 4698c2ecf20Sopenharmony_ci cpu1 = cpu2 = pick_online_cpu(); 4708c2ecf20Sopenharmony_ci } else { 4718c2ecf20Sopenharmony_ci cpu1 = atoi(argv[optind++]); 4728c2ecf20Sopenharmony_ci cpu2 = atoi(argv[optind++]); 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci printf("Using %s with ", processes ? "processes" : "threads"); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (actions == &pipe_actions) 4788c2ecf20Sopenharmony_ci printf("pipe"); 4798c2ecf20Sopenharmony_ci else if (actions == &yield_actions) 4808c2ecf20Sopenharmony_ci printf("yield"); 4818c2ecf20Sopenharmony_ci else 4828c2ecf20Sopenharmony_ci printf("futex"); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (!have_hwcap(PPC_FEATURE_HAS_ALTIVEC)) 4858c2ecf20Sopenharmony_ci touch_altivec = 0; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (!have_hwcap(PPC_FEATURE_HAS_VSX)) 4888c2ecf20Sopenharmony_ci touch_vector = 0; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci printf(" on cpus %d/%d touching FP:%s altivec:%s vector:%s vdso:%s\n", 4918c2ecf20Sopenharmony_ci cpu1, cpu2, touch_fp ? "yes" : "no", touch_altivec ? "yes" : "no", 4928c2ecf20Sopenharmony_ci touch_vector ? "yes" : "no", touch_vdso ? "yes" : "no"); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci /* Create a new process group so we can signal everyone for exit */ 4958c2ecf20Sopenharmony_ci setpgid(getpid(), getpid()); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci signal(SIGUSR1, sigusr1_handler); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci actions->setup(cpu1, cpu2); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci start_fn(actions->thread1, NULL, cpu1); 5028c2ecf20Sopenharmony_ci start_fn(actions->thread2, NULL, cpu2); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci while (1) 5058c2ecf20Sopenharmony_ci sleep(3600); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci return 0; 5088c2ecf20Sopenharmony_ci} 509