• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2018 Google, Inc.
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  *
6  * A single big task executes. Task placement and upmigration latency is
7  * verified.
8  */
9 
10 #define _GNU_SOURCE
11 #include <errno.h>
12 #include <pthread.h>
13 #include <sched.h>
14 #include <time.h>
15 
16 #include "tst_test.h"
17 #include "tst_safe_file_ops.h"
18 #include "tst_safe_pthread.h"
19 
20 #include "trace_parse.h"
21 #include "util.h"
22 
23 #define TRACE_EVENTS "sched_switch"
24 
25 static int big_task_tid;
26 
27 #define MAX_UPMIGRATE_LATENCY_US 100000
28 #define MIN_CORRECT_CLUSTER_PCT 90
29 #define BURN_SEC 3
task_fn(void * arg LTP_ATTRIBUTE_UNUSED)30 static void *task_fn(void *arg LTP_ATTRIBUTE_UNUSED)
31 {
32 	big_task_tid = gettid();
33 
34 	printf("Big task executing for %ds...\n", BURN_SEC);
35 	burn(BURN_SEC * USEC_PER_SEC, 0);
36 
37 	return NULL;
38 }
39 
parse_results(void)40 static int parse_results(void)
41 {
42 	int i, pct;
43 	unsigned long long exec_start_us = 0;
44 	unsigned long long correct_us = 0;
45 	unsigned long long total_us = 0;
46 	unsigned long long start_ts_usec = 0;
47 	unsigned long long upmigration_ts_usec = 0;
48 	unsigned long long upmigration_latency_usec = 0;
49 	cpu_set_t cpuset;
50 
51 	if (find_cpus_with_capacity(1, &cpuset)) {
52 		printf("Failed to find the CPUs in the big cluster.\n");
53 		return -1;
54 	}
55 
56 	for (i = 0; i < num_trace_records; i++) {
57 		unsigned long long segment_us;
58 		struct trace_sched_switch *t = trace[i].event_data;
59 
60 		if (trace[i].event_type != TRACE_RECORD_SCHED_SWITCH)
61 			continue;
62 		if (t->next_pid == big_task_tid) {
63 			/* Start of task execution segment. */
64 			if (exec_start_us) {
65 				printf("Trace parse fail: double exec start\n");
66 				return -1;
67 			}
68 			exec_start_us = TS_TO_USEC(trace[i].ts);
69 			if (!start_ts_usec)
70 				start_ts_usec = exec_start_us;
71 			if (!upmigration_ts_usec &&
72 			    CPU_ISSET(trace[i].cpu, &cpuset))
73 				upmigration_ts_usec = exec_start_us;
74 			continue;
75 		}
76 		if (t->prev_pid != big_task_tid)
77 			continue;
78 		/* End of task execution segment. */
79 		segment_us = TS_TO_USEC(trace[i].ts);
80 		segment_us -= exec_start_us;
81 		exec_start_us = 0;
82 		if (CPU_ISSET(trace[i].cpu, &cpuset))
83 			correct_us += segment_us;
84 		total_us += segment_us;
85 	}
86 
87 	pct = (correct_us * 100) / total_us;
88 	printf("Total time task scheduled: %lld usec\n"
89 	       "Time scheduled on a big CPU: %lld usec (%d%%)\n",
90 	       total_us, correct_us, pct);
91 
92 	if (!upmigration_ts_usec) {
93 		printf("Task never upmigrated!\n");
94 		return -1;
95 	}
96 
97 	upmigration_latency_usec = upmigration_ts_usec - start_ts_usec;
98 	printf("Upmigration latency: %lld usec\n", upmigration_latency_usec);
99 
100 	return (pct < MIN_CORRECT_CLUSTER_PCT ||
101 		upmigration_latency_usec > MAX_UPMIGRATE_LATENCY_US);
102 }
103 
run(void)104 static void run(void)
105 {
106 	pthread_t task_thread;
107 
108 	tst_res(TINFO, "Minimum correct cluster time percentage: %d%%",
109 		MIN_CORRECT_CLUSTER_PCT);
110 	tst_res(TINFO, "Maximum upmigration latency: %d usec",
111 		MAX_UPMIGRATE_LATENCY_US);
112 
113 	/* configure and enable tracing */
114 	SAFE_FILE_PRINTF(TRACING_DIR "tracing_on", "0");
115 	SAFE_FILE_PRINTF(TRACING_DIR "buffer_size_kb", "16384");
116 	SAFE_FILE_PRINTF(TRACING_DIR "set_event", TRACE_EVENTS);
117 	SAFE_FILE_PRINTF(TRACING_DIR "trace", "\n");
118 	SAFE_FILE_PRINTF(TRACING_DIR "tracing_on", "1");
119 
120 	SAFE_PTHREAD_CREATE(&task_thread, NULL, task_fn, NULL);
121 	SAFE_PTHREAD_JOIN(task_thread, NULL);
122 
123 	/* disable tracing */
124 	SAFE_FILE_PRINTF(TRACING_DIR "tracing_on", "0");
125 	LOAD_TRACE();
126 
127 	if (parse_results())
128 		tst_res(TFAIL, "Task placement/migration latency did not meet "
129 			"requirements.");
130 	else
131 		tst_res(TPASS, "Task placement/migration latency met "
132 			"requirements.");
133 }
134 
135 static struct tst_test test = {
136 	.test_all = run,
137 	.cleanup = trace_cleanup,
138 };
139