diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-01-07 11:33:19 -0800 |
---|---|---|
committer | Andy Lutomirski <luto@kernel.org> | 2016-01-07 11:33:19 -0800 |
commit | 0fe666686e56d0f6f550111cb6a3303bf4826abf (patch) | |
tree | 6ba8005582365fa6cb0f7948dacca1d9b2a637bf | |
parent | bcc5968694d0706cdd3a3119e45c09b75b4c058e (diff) | |
download | misc-tests-0fe666686e56d0f6f550111cb6a3303bf4826abf.tar.gz |
context_switch_latency: Allow fork as an alternative to threads
-rw-r--r-- | context_switch_latency.c | 168 |
1 files changed, 97 insertions, 71 deletions
diff --git a/context_switch_latency.c b/context_switch_latency.c index 650f853..7920ea4 100644 --- a/context_switch_latency.c +++ b/context_switch_latency.c @@ -3,11 +3,14 @@ #include <time.h> #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <unistd.h> #include <sched.h> #include <pthread.h> #include <sys/eventfd.h> +#include <sys/prctl.h> +#include <signal.h> #include <err.h> int to_thread, from_thread; @@ -69,78 +72,101 @@ void killit() int main(int argc, char **argv) { - struct timespec start, end; - pthread_t thread; - uint64_t i, iters = 100000; - uint64_t ns; - int main_cpu; - - if (argc != 3) { - printf("Usage: %s <0|1> <same|different>\n\nSet the parameter to 1 to use xstate\nUse 'same' for same CPU or 'different' for cross-CPU\n", - argv[0]); - return 1; - } else { - if (!strcmp(argv[1], "1")) - use_xstate = 1; - else if (strcmp(argv[1], "0")) - errx(1, "first arg is wrong"); - - if (!strcmp(argv[2], "same")) { - main_cpu = 0; - thread_cpu = 0; - } else if (!strcmp(argv[2], "different")) { - main_cpu = 0; - thread_cpu = 1; - } else { - errx(1, "second arg is wrong"); - } - } - - printf("use_xstate = %d\n", use_xstate); - - to_thread = eventfd(0, 0); - if (to_thread < 0) - err(1, "eventfd"); - from_thread = eventfd(0, 0); - if (from_thread < 0) - err(1, "eventfd"); - - if (pthread_create(&thread, 0, threadproc, 0) != 0) - err(1, "pthread_create"); - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(main_cpu, &cpuset); - if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) - printf("[WARN]\tsched_setaffinity failed\n"); - - /* Warm up (and burn the xstate heuristic) */ - for(i = 0; i < 10000; i++) { - bounce(); - maybe_use_xstate(); - } - - /* Clear out the xstate hack. */ - state = 1; - bounce(); - - clock_gettime(CLOCK_MONOTONIC, &start); - - for (i = 0; i < iters; i++) { - bounce(); - maybe_use_xstate(); - } - - clock_gettime(CLOCK_MONOTONIC, &end); - - killit(); - - ns = 1000000000ULL * (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec); - - printf("%llu iters at %.1f ns/switch\n", + struct timespec start, end; + pthread_t thread; + uint64_t i, iters = 100000; + uint64_t ns; + int main_cpu; + bool use_thread = false; + + if (argc != 4) { + printf("Usage: %s <0|1> <thread|process> <same|different>\n\nSet the parameter to 1 to use xstate\nUse 'same' for same CPU or 'different' for cross-CPU\n", + argv[0]); + return 1; + } + + if (!strcmp(argv[1], "1")) + use_xstate = 1; + else if (strcmp(argv[1], "0")) + errx(1, "first arg is wrong"); + + if (!strcmp(argv[3], "same")) { + main_cpu = 0; + thread_cpu = 0; + } else if (!strcmp(argv[3], "different")) { + main_cpu = 0; + thread_cpu = 1; + } else { + errx(1, "third arg is wrong"); + } + + if (!strcmp(argv[2], "thread")) { + use_thread = true; + } else if (!strcmp(argv[2], "process")) { + use_thread = false; + } else { + errx(1, "second arg is wrong"); + } + + printf("use_xstate = %d\n", use_xstate); + + to_thread = eventfd(0, 0); + if (to_thread < 0) + err(1, "eventfd"); + from_thread = eventfd(0, 0); + if (from_thread < 0) + err(1, "eventfd"); + + if (use_thread) { + printf("Using threads\n"); + if (pthread_create(&thread, 0, threadproc, 0) != 0) + err(1, "pthread_create"); + } else { + printf("Using a subprocess\n"); + pid_t child = fork(); + if (child < 0) + err(1, "fork"); + + if (child == 0) { + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + threadproc(NULL); + } + } + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(main_cpu, &cpuset); + if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) + printf("[WARN]\tsched_setaffinity failed\n"); + + /* Warm up (and burn the xstate heuristic) */ + for(i = 0; i < 10000; i++) { + bounce(); + maybe_use_xstate(); + } + + /* Clear out the xstate hack. */ + state = 1; + bounce(); + + clock_gettime(CLOCK_MONOTONIC, &start); + + for (i = 0; i < iters; i++) { + bounce(); + maybe_use_xstate(); + } + + clock_gettime(CLOCK_MONOTONIC, &end); + + killit(); + + ns = 1000000000ULL * (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec); + + printf("%llu iters at %.1f ns/switch\n", (unsigned long long)iters, (double)ns / (2*iters)); - pthread_join(thread, 0); + if (use_thread) + pthread_join(thread, 0); - return 0; + return 0; } |