summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-01-07 11:33:19 -0800
committerAndy Lutomirski <luto@kernel.org>2016-01-07 11:33:19 -0800
commit0fe666686e56d0f6f550111cb6a3303bf4826abf (patch)
tree6ba8005582365fa6cb0f7948dacca1d9b2a637bf
parentbcc5968694d0706cdd3a3119e45c09b75b4c058e (diff)
downloadmisc-tests-0fe666686e56d0f6f550111cb6a3303bf4826abf.tar.gz
context_switch_latency: Allow fork as an alternative to threads
-rw-r--r--context_switch_latency.c168
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;
}