1*49cdfc7eSAndroid Build Coastguard Worker /* time-schedule.c
2*49cdfc7eSAndroid Build Coastguard Worker
3*49cdfc7eSAndroid Build Coastguard Worker Programme to test how long a context switch takes.
4*49cdfc7eSAndroid Build Coastguard Worker
5*49cdfc7eSAndroid Build Coastguard Worker Copyright (C) 1998 Richard Gooch
6*49cdfc7eSAndroid Build Coastguard Worker
7*49cdfc7eSAndroid Build Coastguard Worker This program is free software; you can redistribute it and/or modify
8*49cdfc7eSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
9*49cdfc7eSAndroid Build Coastguard Worker the Free Software Foundation; either version 2 of the License, or
10*49cdfc7eSAndroid Build Coastguard Worker (at your option) any later version.
11*49cdfc7eSAndroid Build Coastguard Worker
12*49cdfc7eSAndroid Build Coastguard Worker This program is distributed in the hope that it will be useful,
13*49cdfc7eSAndroid Build Coastguard Worker but WITHOUT ANY WARRANTY; without even the implied warranty of
14*49cdfc7eSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*49cdfc7eSAndroid Build Coastguard Worker GNU General Public License for more details.
16*49cdfc7eSAndroid Build Coastguard Worker
17*49cdfc7eSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
18*49cdfc7eSAndroid Build Coastguard Worker along with this program; if not, write to the Free Software
19*49cdfc7eSAndroid Build Coastguard Worker Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20*49cdfc7eSAndroid Build Coastguard Worker
21*49cdfc7eSAndroid Build Coastguard Worker Richard Gooch may be reached by email at [email protected]
22*49cdfc7eSAndroid Build Coastguard Worker The postal address is:
23*49cdfc7eSAndroid Build Coastguard Worker Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
24*49cdfc7eSAndroid Build Coastguard Worker */
25*49cdfc7eSAndroid Build Coastguard Worker
26*49cdfc7eSAndroid Build Coastguard Worker /*
27*49cdfc7eSAndroid Build Coastguard Worker This programme will determine the context switch (scheduling) overhead on
28*49cdfc7eSAndroid Build Coastguard Worker a system. It takes into account SMP machines. True context switches are
29*49cdfc7eSAndroid Build Coastguard Worker measured.
30*49cdfc7eSAndroid Build Coastguard Worker
31*49cdfc7eSAndroid Build Coastguard Worker Written by Richard Gooch 15-SEP-1998
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker Last updated by Richard Gooch 25-SEP-1998
34*49cdfc7eSAndroid Build Coastguard Worker
35*49cdfc7eSAndroid Build Coastguard Worker */
36*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
37*49cdfc7eSAndroid Build Coastguard Worker #ifdef _POSIX_THREADS
38*49cdfc7eSAndroid Build Coastguard Worker #ifndef _REENTRANT
39*49cdfc7eSAndroid Build Coastguard Worker #define _REENTRANT
40*49cdfc7eSAndroid Build Coastguard Worker #endif
41*49cdfc7eSAndroid Build Coastguard Worker #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
42*49cdfc7eSAndroid Build Coastguard Worker #define _POSIX_THREAD_SAFE_FUNCTIONS
43*49cdfc7eSAndroid Build Coastguard Worker #endif
44*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
45*49cdfc7eSAndroid Build Coastguard Worker #endif
46*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
47*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
48*49cdfc7eSAndroid Build Coastguard Worker #include <math.h>
49*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
50*49cdfc7eSAndroid Build Coastguard Worker #include <ctype.h>
51*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
52*49cdfc7eSAndroid Build Coastguard Worker #include <sched.h>
53*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
54*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
55*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
56*49cdfc7eSAndroid Build Coastguard Worker #include <dirent.h>
57*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
58*49cdfc7eSAndroid Build Coastguard Worker
59*49cdfc7eSAndroid Build Coastguard Worker #ifndef __KARMA__
60*49cdfc7eSAndroid Build Coastguard Worker #define mt_num_processors() 1 /* Set to the number of processors */
61*49cdfc7eSAndroid Build Coastguard Worker #define ERRSTRING strerror(errno)
62*49cdfc7eSAndroid Build Coastguard Worker #define FALSE 0
63*49cdfc7eSAndroid Build Coastguard Worker #define TRUE 1
64*49cdfc7eSAndroid Build Coastguard Worker #else
65*49cdfc7eSAndroid Build Coastguard Worker #include <karma.h>
66*49cdfc7eSAndroid Build Coastguard Worker #include <karma_mt.h>
67*49cdfc7eSAndroid Build Coastguard Worker #endif
68*49cdfc7eSAndroid Build Coastguard Worker
69*49cdfc7eSAndroid Build Coastguard Worker #define MAX_ITERATIONS 1000
70*49cdfc7eSAndroid Build Coastguard Worker
71*49cdfc7eSAndroid Build Coastguard Worker static unsigned int hog_other_cpus();
72*49cdfc7eSAndroid Build Coastguard Worker static void run_yielder(int use_threads, int read_fd);
73*49cdfc7eSAndroid Build Coastguard Worker static void *yielder_main(void *arg);
74*49cdfc7eSAndroid Build Coastguard Worker static void s_term_handler();
75*49cdfc7eSAndroid Build Coastguard Worker static void run_low_priority(unsigned int num, int read_fd);
76*49cdfc7eSAndroid Build Coastguard Worker static unsigned long compute_median(unsigned long values[MAX_ITERATIONS],
77*49cdfc7eSAndroid Build Coastguard Worker unsigned long max_value);
78*49cdfc7eSAndroid Build Coastguard Worker static unsigned int get_run_queue_size();
79*49cdfc7eSAndroid Build Coastguard Worker static unsigned long get_num_switches();
80*49cdfc7eSAndroid Build Coastguard Worker static void use_fpu_value(double val);
81*49cdfc7eSAndroid Build Coastguard Worker
82*49cdfc7eSAndroid Build Coastguard Worker static volatile unsigned int sched_count = 0;
83*49cdfc7eSAndroid Build Coastguard Worker /* For yielder */
84*49cdfc7eSAndroid Build Coastguard Worker static int pipe_read_fd = -1;
85*49cdfc7eSAndroid Build Coastguard Worker static int pipe_write_fd = -1;
86*49cdfc7eSAndroid Build Coastguard Worker static pid_t child = -1;
87*49cdfc7eSAndroid Build Coastguard Worker
main(int argc,char ** argv)88*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char **argv)
89*49cdfc7eSAndroid Build Coastguard Worker {
90*49cdfc7eSAndroid Build Coastguard Worker int use_threads = FALSE;
91*49cdfc7eSAndroid Build Coastguard Worker int use_pipe = FALSE;
92*49cdfc7eSAndroid Build Coastguard Worker int no_test = FALSE;
93*49cdfc7eSAndroid Build Coastguard Worker int frob_fpu = FALSE;
94*49cdfc7eSAndroid Build Coastguard Worker int read_fd = -1;
95*49cdfc7eSAndroid Build Coastguard Worker int write_fd = -1;
96*49cdfc7eSAndroid Build Coastguard Worker int num_low_priority = -1;
97*49cdfc7eSAndroid Build Coastguard Worker int i, j;
98*49cdfc7eSAndroid Build Coastguard Worker int fds[2];
99*49cdfc7eSAndroid Build Coastguard Worker unsigned int count, num_yields, run_queue_size1, run_queue_size2,
100*49cdfc7eSAndroid Build Coastguard Worker num_hogs;
101*49cdfc7eSAndroid Build Coastguard Worker unsigned long median, switches1, num_switches, num_overhead_switches;
102*49cdfc7eSAndroid Build Coastguard Worker signed long overhead, total_diffs;
103*49cdfc7eSAndroid Build Coastguard Worker signed long min_diff = 1000000000;
104*49cdfc7eSAndroid Build Coastguard Worker signed long max_diff = -1000000000;
105*49cdfc7eSAndroid Build Coastguard Worker double dcount = 0.0;
106*49cdfc7eSAndroid Build Coastguard Worker unsigned long diffs[MAX_ITERATIONS];
107*49cdfc7eSAndroid Build Coastguard Worker struct timeval before, after;
108*49cdfc7eSAndroid Build Coastguard Worker sigset_t set;
109*49cdfc7eSAndroid Build Coastguard Worker static char *usage =
110*49cdfc7eSAndroid Build Coastguard Worker "time-schedule [-h] [-thread] [-notest] [-pipe] [-fpu] [num_running]";
111*49cdfc7eSAndroid Build Coastguard Worker
112*49cdfc7eSAndroid Build Coastguard Worker setpgrp();
113*49cdfc7eSAndroid Build Coastguard Worker /* First create pipe used to sychronise low priority processes */
114*49cdfc7eSAndroid Build Coastguard Worker if (pipe(fds) != 0) {
115*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error creating pipe\t%s\n", ERRSTRING);
116*49cdfc7eSAndroid Build Coastguard Worker exit(1);
117*49cdfc7eSAndroid Build Coastguard Worker }
118*49cdfc7eSAndroid Build Coastguard Worker read_fd = fds[0];
119*49cdfc7eSAndroid Build Coastguard Worker pipe_write_fd = fds[1];
120*49cdfc7eSAndroid Build Coastguard Worker for (count = 1; count < argc; ++count) {
121*49cdfc7eSAndroid Build Coastguard Worker if (strcmp(argv[count], "-thread") == 0) {
122*49cdfc7eSAndroid Build Coastguard Worker #ifdef _POSIX_THREADS
123*49cdfc7eSAndroid Build Coastguard Worker use_threads = TRUE;
124*49cdfc7eSAndroid Build Coastguard Worker #else
125*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "POSIX threads not available\n");
126*49cdfc7eSAndroid Build Coastguard Worker #endif
127*49cdfc7eSAndroid Build Coastguard Worker } else if (strcmp(argv[count], "-pipe") == 0)
128*49cdfc7eSAndroid Build Coastguard Worker use_pipe = TRUE;
129*49cdfc7eSAndroid Build Coastguard Worker else if (strcmp(argv[count], "-notest") == 0)
130*49cdfc7eSAndroid Build Coastguard Worker no_test = TRUE;
131*49cdfc7eSAndroid Build Coastguard Worker else if (strcmp(argv[count], "-fpu") == 0)
132*49cdfc7eSAndroid Build Coastguard Worker frob_fpu = TRUE;
133*49cdfc7eSAndroid Build Coastguard Worker else if (isdigit(argv[count][0]))
134*49cdfc7eSAndroid Build Coastguard Worker num_low_priority = atoi(argv[count]);
135*49cdfc7eSAndroid Build Coastguard Worker else {
136*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
137*49cdfc7eSAndroid Build Coastguard Worker "Programme to time context switches (schedules)\n");
138*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
139*49cdfc7eSAndroid Build Coastguard Worker "(C) 1998 Richard Gooch <[email protected]>\n");
140*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Usage:\t%s\n", usage);
141*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
142*49cdfc7eSAndroid Build Coastguard Worker "\t-thread\t\tswitch threads not processes\n");
143*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
144*49cdfc7eSAndroid Build Coastguard Worker "\t-pipe\t\tuse pipes not sched_yield()\n");
145*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
146*49cdfc7eSAndroid Build Coastguard Worker "\t-fpu\t\tpollute the FPU after each switch in main\n");
147*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
148*49cdfc7eSAndroid Build Coastguard Worker "\tnum_running\tnumber of extra processes\n");
149*49cdfc7eSAndroid Build Coastguard Worker exit(0);
150*49cdfc7eSAndroid Build Coastguard Worker }
151*49cdfc7eSAndroid Build Coastguard Worker }
152*49cdfc7eSAndroid Build Coastguard Worker if (no_test) {
153*49cdfc7eSAndroid Build Coastguard Worker if (num_low_priority > 0)
154*49cdfc7eSAndroid Build Coastguard Worker run_low_priority(num_low_priority, read_fd);
155*49cdfc7eSAndroid Build Coastguard Worker while (TRUE)
156*49cdfc7eSAndroid Build Coastguard Worker pause();
157*49cdfc7eSAndroid Build Coastguard Worker }
158*49cdfc7eSAndroid Build Coastguard Worker if (geteuid() == 0) {
159*49cdfc7eSAndroid Build Coastguard Worker struct sched_param sp;
160*49cdfc7eSAndroid Build Coastguard Worker
161*49cdfc7eSAndroid Build Coastguard Worker memset(&sp, 0, sizeof sp);
162*49cdfc7eSAndroid Build Coastguard Worker sp.sched_priority = 10;
163*49cdfc7eSAndroid Build Coastguard Worker if (sched_setscheduler(0, SCHED_FIFO, &sp) != 0) {
164*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error changing to RT class\t%s\n",
165*49cdfc7eSAndroid Build Coastguard Worker ERRSTRING);
166*49cdfc7eSAndroid Build Coastguard Worker exit(1);
167*49cdfc7eSAndroid Build Coastguard Worker }
168*49cdfc7eSAndroid Build Coastguard Worker if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
169*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error locking pages\t%s\n", ERRSTRING);
170*49cdfc7eSAndroid Build Coastguard Worker exit(1);
171*49cdfc7eSAndroid Build Coastguard Worker }
172*49cdfc7eSAndroid Build Coastguard Worker } else
173*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Not running with RT priority!\n");
174*49cdfc7eSAndroid Build Coastguard Worker /* Give shell and login programme time to finish up and get off the run
175*49cdfc7eSAndroid Build Coastguard Worker queue */
176*49cdfc7eSAndroid Build Coastguard Worker usleep(200000);
177*49cdfc7eSAndroid Build Coastguard Worker if (use_pipe) {
178*49cdfc7eSAndroid Build Coastguard Worker if (pipe(fds) != 0) {
179*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error creating pipe\t%s\n", ERRSTRING);
180*49cdfc7eSAndroid Build Coastguard Worker exit(1);
181*49cdfc7eSAndroid Build Coastguard Worker }
182*49cdfc7eSAndroid Build Coastguard Worker pipe_read_fd = fds[0];
183*49cdfc7eSAndroid Build Coastguard Worker write_fd = fds[1];
184*49cdfc7eSAndroid Build Coastguard Worker }
185*49cdfc7eSAndroid Build Coastguard Worker num_hogs = hog_other_cpus();
186*49cdfc7eSAndroid Build Coastguard Worker /* Determine overhead. Do it in a loop=2. The first iteration should warm
187*49cdfc7eSAndroid Build Coastguard Worker the cache, the second will compute the overhead */
188*49cdfc7eSAndroid Build Coastguard Worker for (j = 0; j < 2; ++j) {
189*49cdfc7eSAndroid Build Coastguard Worker switches1 = get_num_switches();
190*49cdfc7eSAndroid Build Coastguard Worker gettimeofday(&before, NULL);
191*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < 20; ++i) {
192*49cdfc7eSAndroid Build Coastguard Worker if (use_pipe) {
193*49cdfc7eSAndroid Build Coastguard Worker char ch = 0;
194*49cdfc7eSAndroid Build Coastguard Worker
195*49cdfc7eSAndroid Build Coastguard Worker write(pipe_write_fd, &ch, 1);
196*49cdfc7eSAndroid Build Coastguard Worker read(read_fd, &ch, 1);
197*49cdfc7eSAndroid Build Coastguard Worker } else
198*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
199*49cdfc7eSAndroid Build Coastguard Worker if (frob_fpu)
200*49cdfc7eSAndroid Build Coastguard Worker ++dcount;
201*49cdfc7eSAndroid Build Coastguard Worker }
202*49cdfc7eSAndroid Build Coastguard Worker gettimeofday(&after, NULL);
203*49cdfc7eSAndroid Build Coastguard Worker num_overhead_switches = get_num_switches() - switches1;
204*49cdfc7eSAndroid Build Coastguard Worker overhead = 1000000 * (after.tv_sec - before.tv_sec);
205*49cdfc7eSAndroid Build Coastguard Worker overhead += after.tv_usec - before.tv_usec;
206*49cdfc7eSAndroid Build Coastguard Worker }
207*49cdfc7eSAndroid Build Coastguard Worker use_fpu_value(dcount);
208*49cdfc7eSAndroid Build Coastguard Worker if (num_low_priority > 0)
209*49cdfc7eSAndroid Build Coastguard Worker run_low_priority(num_low_priority, read_fd);
210*49cdfc7eSAndroid Build Coastguard Worker /* Set up for the benchmark */
211*49cdfc7eSAndroid Build Coastguard Worker run_yielder(use_threads, read_fd);
212*49cdfc7eSAndroid Build Coastguard Worker memset(diffs, 0, sizeof diffs);
213*49cdfc7eSAndroid Build Coastguard Worker run_queue_size1 = get_run_queue_size();
214*49cdfc7eSAndroid Build Coastguard Worker total_diffs = 0;
215*49cdfc7eSAndroid Build Coastguard Worker switches1 = get_num_switches();
216*49cdfc7eSAndroid Build Coastguard Worker /* Benchmark! */
217*49cdfc7eSAndroid Build Coastguard Worker for (count = 0; count < MAX_ITERATIONS; ++count) {
218*49cdfc7eSAndroid Build Coastguard Worker signed long diff;
219*49cdfc7eSAndroid Build Coastguard Worker
220*49cdfc7eSAndroid Build Coastguard Worker gettimeofday(&before, NULL);
221*49cdfc7eSAndroid Build Coastguard Worker /* Generate 20 context switches */
222*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < 10; ++i) {
223*49cdfc7eSAndroid Build Coastguard Worker if (use_pipe) {
224*49cdfc7eSAndroid Build Coastguard Worker char ch = 0;
225*49cdfc7eSAndroid Build Coastguard Worker
226*49cdfc7eSAndroid Build Coastguard Worker write(write_fd, &ch, 1);
227*49cdfc7eSAndroid Build Coastguard Worker read(read_fd, &ch, 1);
228*49cdfc7eSAndroid Build Coastguard Worker } else
229*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
230*49cdfc7eSAndroid Build Coastguard Worker if (frob_fpu)
231*49cdfc7eSAndroid Build Coastguard Worker dcount += 1.0;
232*49cdfc7eSAndroid Build Coastguard Worker }
233*49cdfc7eSAndroid Build Coastguard Worker gettimeofday(&after, NULL);
234*49cdfc7eSAndroid Build Coastguard Worker diff = 1000000 * (after.tv_sec - before.tv_sec);
235*49cdfc7eSAndroid Build Coastguard Worker diff += after.tv_usec - before.tv_usec;
236*49cdfc7eSAndroid Build Coastguard Worker diffs[count] = diff;
237*49cdfc7eSAndroid Build Coastguard Worker total_diffs += diff;
238*49cdfc7eSAndroid Build Coastguard Worker if (diff < min_diff)
239*49cdfc7eSAndroid Build Coastguard Worker min_diff = diff;
240*49cdfc7eSAndroid Build Coastguard Worker if (diff > max_diff)
241*49cdfc7eSAndroid Build Coastguard Worker max_diff = diff;
242*49cdfc7eSAndroid Build Coastguard Worker }
243*49cdfc7eSAndroid Build Coastguard Worker num_yields = sched_count;
244*49cdfc7eSAndroid Build Coastguard Worker run_queue_size2 = get_run_queue_size();
245*49cdfc7eSAndroid Build Coastguard Worker num_switches = get_num_switches() - switches1;
246*49cdfc7eSAndroid Build Coastguard Worker if (!use_threads)
247*49cdfc7eSAndroid Build Coastguard Worker kill(child, SIGTERM);
248*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Started %u hog processes\n", num_hogs);
249*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Syscall%s overhead: %.1f us\n", frob_fpu ? "/FPU" : "",
250*49cdfc7eSAndroid Build Coastguard Worker (double)overhead / 20.0);
251*49cdfc7eSAndroid Build Coastguard Worker if (switches1 > 0)
252*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Num switches during overhead check: %lu\n",
253*49cdfc7eSAndroid Build Coastguard Worker num_overhead_switches);
254*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Minimum scheduling latency: %.1f (%.1f) us\n",
255*49cdfc7eSAndroid Build Coastguard Worker (double)min_diff / 20.0, (double)(min_diff - overhead) / 20.0);
256*49cdfc7eSAndroid Build Coastguard Worker median = compute_median(diffs, max_diff);
257*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Median scheduling latency: %.1f (%.1f) us\n",
258*49cdfc7eSAndroid Build Coastguard Worker (double)median / 20.0, (double)(median - overhead) / 20.0);
259*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Average scheduling latency: %.1f (%.1f) us\n",
260*49cdfc7eSAndroid Build Coastguard Worker (double)total_diffs / (double)MAX_ITERATIONS / 20.0,
261*49cdfc7eSAndroid Build Coastguard Worker (double)(total_diffs - overhead * MAX_ITERATIONS) /
262*49cdfc7eSAndroid Build Coastguard Worker (double)MAX_ITERATIONS / 20.0);
263*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Maximum scheduling latency: %.1f (%.1f) us\n",
264*49cdfc7eSAndroid Build Coastguard Worker (double)max_diff / 20.0, (double)(max_diff - overhead) / 20.0);
265*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Run queue size: %u, %u\n",
266*49cdfc7eSAndroid Build Coastguard Worker run_queue_size1, run_queue_size2);
267*49cdfc7eSAndroid Build Coastguard Worker use_fpu_value(dcount);
268*49cdfc7eSAndroid Build Coastguard Worker if (use_threads)
269*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Number of yields: %u\n", num_yields);
270*49cdfc7eSAndroid Build Coastguard Worker if (num_switches > 0)
271*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Num switches: %lu\n", num_switches);
272*49cdfc7eSAndroid Build Coastguard Worker
273*49cdfc7eSAndroid Build Coastguard Worker /* Terminate all child processes */
274*49cdfc7eSAndroid Build Coastguard Worker sigemptyset(&set);
275*49cdfc7eSAndroid Build Coastguard Worker sigaddset(&set, SIGTERM);
276*49cdfc7eSAndroid Build Coastguard Worker sigprocmask(SIG_BLOCK, &set, NULL);
277*49cdfc7eSAndroid Build Coastguard Worker
278*49cdfc7eSAndroid Build Coastguard Worker kill(0, SIGTERM);
279*49cdfc7eSAndroid Build Coastguard Worker return (0);
280*49cdfc7eSAndroid Build Coastguard Worker } /* End Function main */
281*49cdfc7eSAndroid Build Coastguard Worker
hog_other_cpus()282*49cdfc7eSAndroid Build Coastguard Worker static unsigned int hog_other_cpus()
283*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Hog other CPUs with a high-priority job.
284*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] The number of hogged CPUs.
285*49cdfc7eSAndroid Build Coastguard Worker */
286*49cdfc7eSAndroid Build Coastguard Worker {
287*49cdfc7eSAndroid Build Coastguard Worker unsigned int count;
288*49cdfc7eSAndroid Build Coastguard Worker
289*49cdfc7eSAndroid Build Coastguard Worker for (count = mt_num_processors(); count > 1; --count) {
290*49cdfc7eSAndroid Build Coastguard Worker switch (fork()) {
291*49cdfc7eSAndroid Build Coastguard Worker case 0:
292*49cdfc7eSAndroid Build Coastguard Worker /* Child */
293*49cdfc7eSAndroid Build Coastguard Worker while (TRUE) ;
294*49cdfc7eSAndroid Build Coastguard Worker break;
295*49cdfc7eSAndroid Build Coastguard Worker case -1:
296*49cdfc7eSAndroid Build Coastguard Worker /* Error */
297*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error forking\t%s\n", ERRSTRING);
298*49cdfc7eSAndroid Build Coastguard Worker kill(0, SIGTERM);
299*49cdfc7eSAndroid Build Coastguard Worker break;
300*49cdfc7eSAndroid Build Coastguard Worker default:
301*49cdfc7eSAndroid Build Coastguard Worker /* Parent */
302*49cdfc7eSAndroid Build Coastguard Worker break;
303*49cdfc7eSAndroid Build Coastguard Worker }
304*49cdfc7eSAndroid Build Coastguard Worker }
305*49cdfc7eSAndroid Build Coastguard Worker return mt_num_processors() - 1;
306*49cdfc7eSAndroid Build Coastguard Worker } /* End Function hog_other_cpus */
307*49cdfc7eSAndroid Build Coastguard Worker
run_yielder(int use_threads,int read_fd)308*49cdfc7eSAndroid Build Coastguard Worker static void run_yielder(int use_threads, int read_fd)
309*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Run other process which will continuously yield.
310*49cdfc7eSAndroid Build Coastguard Worker <use_threads> If TRUE, the yielding process is just a thread.
311*49cdfc7eSAndroid Build Coastguard Worker <read_fd> The pipe to read the synchronisation byte from.
312*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] Nothing.
313*49cdfc7eSAndroid Build Coastguard Worker */
314*49cdfc7eSAndroid Build Coastguard Worker {
315*49cdfc7eSAndroid Build Coastguard Worker char ch;
316*49cdfc7eSAndroid Build Coastguard Worker struct sigaction new_action;
317*49cdfc7eSAndroid Build Coastguard Worker #ifdef _POSIX_THREADS
318*49cdfc7eSAndroid Build Coastguard Worker pthread_t thread;
319*49cdfc7eSAndroid Build Coastguard Worker
320*49cdfc7eSAndroid Build Coastguard Worker if (use_threads) {
321*49cdfc7eSAndroid Build Coastguard Worker if (pthread_create(&thread, NULL, yielder_main, NULL) != 0) {
322*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error creating thread\t%s\n",
323*49cdfc7eSAndroid Build Coastguard Worker ERRSTRING);
324*49cdfc7eSAndroid Build Coastguard Worker kill(0, SIGTERM);
325*49cdfc7eSAndroid Build Coastguard Worker }
326*49cdfc7eSAndroid Build Coastguard Worker read(read_fd, &ch, 1);
327*49cdfc7eSAndroid Build Coastguard Worker return;
328*49cdfc7eSAndroid Build Coastguard Worker }
329*49cdfc7eSAndroid Build Coastguard Worker #endif
330*49cdfc7eSAndroid Build Coastguard Worker switch (child = fork()) {
331*49cdfc7eSAndroid Build Coastguard Worker case 0:
332*49cdfc7eSAndroid Build Coastguard Worker /* Child */
333*49cdfc7eSAndroid Build Coastguard Worker break;
334*49cdfc7eSAndroid Build Coastguard Worker case -1:
335*49cdfc7eSAndroid Build Coastguard Worker /* Error */
336*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error forking\t%s\n", ERRSTRING);
337*49cdfc7eSAndroid Build Coastguard Worker kill(0, SIGTERM);
338*49cdfc7eSAndroid Build Coastguard Worker break;
339*49cdfc7eSAndroid Build Coastguard Worker default:
340*49cdfc7eSAndroid Build Coastguard Worker /* Parent */
341*49cdfc7eSAndroid Build Coastguard Worker read(read_fd, &ch, 1);
342*49cdfc7eSAndroid Build Coastguard Worker return;
343*49cdfc7eSAndroid Build Coastguard Worker /*break; */
344*49cdfc7eSAndroid Build Coastguard Worker }
345*49cdfc7eSAndroid Build Coastguard Worker memset(&new_action, 0, sizeof new_action);
346*49cdfc7eSAndroid Build Coastguard Worker sigemptyset(&new_action.sa_mask);
347*49cdfc7eSAndroid Build Coastguard Worker new_action.sa_handler = s_term_handler;
348*49cdfc7eSAndroid Build Coastguard Worker if (sigaction(SIGTERM, &new_action, NULL) != 0) {
349*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error setting SIGTERM handler\t%s\n",
350*49cdfc7eSAndroid Build Coastguard Worker ERRSTRING);
351*49cdfc7eSAndroid Build Coastguard Worker exit(1);
352*49cdfc7eSAndroid Build Coastguard Worker }
353*49cdfc7eSAndroid Build Coastguard Worker yielder_main(NULL);
354*49cdfc7eSAndroid Build Coastguard Worker } /* End Function run_yielder */
355*49cdfc7eSAndroid Build Coastguard Worker
yielder_main(void * arg)356*49cdfc7eSAndroid Build Coastguard Worker static void *yielder_main(void *arg)
357*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Yielder function.
358*49cdfc7eSAndroid Build Coastguard Worker <arg> An arbirtrary pointer. Ignored.
359*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] NULL.
360*49cdfc7eSAndroid Build Coastguard Worker */
361*49cdfc7eSAndroid Build Coastguard Worker {
362*49cdfc7eSAndroid Build Coastguard Worker char ch = 0;
363*49cdfc7eSAndroid Build Coastguard Worker
364*49cdfc7eSAndroid Build Coastguard Worker sched_count = 0;
365*49cdfc7eSAndroid Build Coastguard Worker write(pipe_write_fd, &ch, 1);
366*49cdfc7eSAndroid Build Coastguard Worker while (TRUE) {
367*49cdfc7eSAndroid Build Coastguard Worker if (pipe_read_fd >= 0) {
368*49cdfc7eSAndroid Build Coastguard Worker read(pipe_read_fd, &ch, 1);
369*49cdfc7eSAndroid Build Coastguard Worker write(pipe_write_fd, &ch, 1);
370*49cdfc7eSAndroid Build Coastguard Worker } else
371*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
372*49cdfc7eSAndroid Build Coastguard Worker ++sched_count;
373*49cdfc7eSAndroid Build Coastguard Worker }
374*49cdfc7eSAndroid Build Coastguard Worker return (NULL);
375*49cdfc7eSAndroid Build Coastguard Worker } /* End Function yielder_main */
376*49cdfc7eSAndroid Build Coastguard Worker
s_term_handler()377*49cdfc7eSAndroid Build Coastguard Worker static void s_term_handler()
378*49cdfc7eSAndroid Build Coastguard Worker {
379*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Number of yields: %u\n", sched_count);
380*49cdfc7eSAndroid Build Coastguard Worker exit(0);
381*49cdfc7eSAndroid Build Coastguard Worker } /* End Function s_term_handler */
382*49cdfc7eSAndroid Build Coastguard Worker
run_low_priority(unsigned int num,int read_fd)383*49cdfc7eSAndroid Build Coastguard Worker static void run_low_priority(unsigned int num, int read_fd)
384*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Run low priority processes.
385*49cdfc7eSAndroid Build Coastguard Worker <num> Number of processes.
386*49cdfc7eSAndroid Build Coastguard Worker <read_fd> The pipe to read the synchronisation byte from.
387*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] Nothing.
388*49cdfc7eSAndroid Build Coastguard Worker */
389*49cdfc7eSAndroid Build Coastguard Worker {
390*49cdfc7eSAndroid Build Coastguard Worker char ch = 0;
391*49cdfc7eSAndroid Build Coastguard Worker
392*49cdfc7eSAndroid Build Coastguard Worker for (; num > 0; --num) {
393*49cdfc7eSAndroid Build Coastguard Worker switch (fork()) {
394*49cdfc7eSAndroid Build Coastguard Worker case 0:
395*49cdfc7eSAndroid Build Coastguard Worker /* Child */
396*49cdfc7eSAndroid Build Coastguard Worker if (geteuid() == 0) {
397*49cdfc7eSAndroid Build Coastguard Worker struct sched_param sp;
398*49cdfc7eSAndroid Build Coastguard Worker
399*49cdfc7eSAndroid Build Coastguard Worker memset(&sp, 0, sizeof sp);
400*49cdfc7eSAndroid Build Coastguard Worker sp.sched_priority = 0;
401*49cdfc7eSAndroid Build Coastguard Worker if (sched_setscheduler(0, SCHED_OTHER, &sp) !=
402*49cdfc7eSAndroid Build Coastguard Worker 0) {
403*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
404*49cdfc7eSAndroid Build Coastguard Worker "Error changing to SCHED_OTHER class\t%s\n",
405*49cdfc7eSAndroid Build Coastguard Worker ERRSTRING);
406*49cdfc7eSAndroid Build Coastguard Worker exit(1);
407*49cdfc7eSAndroid Build Coastguard Worker }
408*49cdfc7eSAndroid Build Coastguard Worker }
409*49cdfc7eSAndroid Build Coastguard Worker if (nice(20) != 0) {
410*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error nicing\t%s\n",
411*49cdfc7eSAndroid Build Coastguard Worker ERRSTRING);
412*49cdfc7eSAndroid Build Coastguard Worker kill(0, SIGTERM);
413*49cdfc7eSAndroid Build Coastguard Worker }
414*49cdfc7eSAndroid Build Coastguard Worker write(pipe_write_fd, &ch, 1);
415*49cdfc7eSAndroid Build Coastguard Worker while (TRUE)
416*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
417*49cdfc7eSAndroid Build Coastguard Worker break;
418*49cdfc7eSAndroid Build Coastguard Worker case -1:
419*49cdfc7eSAndroid Build Coastguard Worker /* Error */
420*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error forking\t%s\n", ERRSTRING);
421*49cdfc7eSAndroid Build Coastguard Worker kill(0, SIGTERM);
422*49cdfc7eSAndroid Build Coastguard Worker break;
423*49cdfc7eSAndroid Build Coastguard Worker default:
424*49cdfc7eSAndroid Build Coastguard Worker /* Parent */
425*49cdfc7eSAndroid Build Coastguard Worker read(read_fd, &ch, 1);
426*49cdfc7eSAndroid Build Coastguard Worker break;
427*49cdfc7eSAndroid Build Coastguard Worker }
428*49cdfc7eSAndroid Build Coastguard Worker }
429*49cdfc7eSAndroid Build Coastguard Worker } /* End Function run_low_priority */
430*49cdfc7eSAndroid Build Coastguard Worker
compute_median(unsigned long values[MAX_ITERATIONS],unsigned long max_value)431*49cdfc7eSAndroid Build Coastguard Worker static unsigned long compute_median(unsigned long values[MAX_ITERATIONS],
432*49cdfc7eSAndroid Build Coastguard Worker unsigned long max_value)
433*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Compute the median from an array of values.
434*49cdfc7eSAndroid Build Coastguard Worker <values> The array of values.
435*49cdfc7eSAndroid Build Coastguard Worker <max_value> The maximum value in the array.
436*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] The median value.
437*49cdfc7eSAndroid Build Coastguard Worker */
438*49cdfc7eSAndroid Build Coastguard Worker {
439*49cdfc7eSAndroid Build Coastguard Worker unsigned long count;
440*49cdfc7eSAndroid Build Coastguard Worker unsigned long median = 0;
441*49cdfc7eSAndroid Build Coastguard Worker unsigned long peak = 0;
442*49cdfc7eSAndroid Build Coastguard Worker unsigned long *table;
443*49cdfc7eSAndroid Build Coastguard Worker
444*49cdfc7eSAndroid Build Coastguard Worker /* Crude but effective */
445*49cdfc7eSAndroid Build Coastguard Worker if ((table = calloc(max_value + 1, sizeof *table)) == NULL) {
446*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Error allocating median table\n");
447*49cdfc7eSAndroid Build Coastguard Worker exit(1);
448*49cdfc7eSAndroid Build Coastguard Worker }
449*49cdfc7eSAndroid Build Coastguard Worker for (count = 0; count < MAX_ITERATIONS; ++count) {
450*49cdfc7eSAndroid Build Coastguard Worker ++table[values[count]];
451*49cdfc7eSAndroid Build Coastguard Worker }
452*49cdfc7eSAndroid Build Coastguard Worker /* Now search for peak. Position of peak is median */
453*49cdfc7eSAndroid Build Coastguard Worker for (count = 0; count < max_value + 1; ++count) {
454*49cdfc7eSAndroid Build Coastguard Worker if (table[count] < peak)
455*49cdfc7eSAndroid Build Coastguard Worker continue;
456*49cdfc7eSAndroid Build Coastguard Worker peak = table[count];
457*49cdfc7eSAndroid Build Coastguard Worker median = count;
458*49cdfc7eSAndroid Build Coastguard Worker }
459*49cdfc7eSAndroid Build Coastguard Worker free(table);
460*49cdfc7eSAndroid Build Coastguard Worker return (median);
461*49cdfc7eSAndroid Build Coastguard Worker } /* End Function compute_median */
462*49cdfc7eSAndroid Build Coastguard Worker
get_run_queue_size()463*49cdfc7eSAndroid Build Coastguard Worker static unsigned int get_run_queue_size()
464*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Compute the current size of the run queue.
465*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] The length of the run queue.
466*49cdfc7eSAndroid Build Coastguard Worker */
467*49cdfc7eSAndroid Build Coastguard Worker {
468*49cdfc7eSAndroid Build Coastguard Worker int dummy_i;
469*49cdfc7eSAndroid Build Coastguard Worker unsigned int length = 0;
470*49cdfc7eSAndroid Build Coastguard Worker FILE *fp;
471*49cdfc7eSAndroid Build Coastguard Worker DIR *dp;
472*49cdfc7eSAndroid Build Coastguard Worker struct dirent *de;
473*49cdfc7eSAndroid Build Coastguard Worker char txt[64], dummy_str[64];
474*49cdfc7eSAndroid Build Coastguard Worker
475*49cdfc7eSAndroid Build Coastguard Worker if ((dp = opendir("/proc")) == NULL)
476*49cdfc7eSAndroid Build Coastguard Worker return (0);
477*49cdfc7eSAndroid Build Coastguard Worker while ((de = readdir(dp)) != NULL) {
478*49cdfc7eSAndroid Build Coastguard Worker if (!isdigit(de->d_name[0]))
479*49cdfc7eSAndroid Build Coastguard Worker continue;
480*49cdfc7eSAndroid Build Coastguard Worker sprintf(txt, "/proc/%s/stat", de->d_name);
481*49cdfc7eSAndroid Build Coastguard Worker if ((fp = fopen(txt, "r")) == NULL)
482*49cdfc7eSAndroid Build Coastguard Worker return (length);
483*49cdfc7eSAndroid Build Coastguard Worker fscanf(fp, "%d %s %s", &dummy_i, dummy_str, txt);
484*49cdfc7eSAndroid Build Coastguard Worker if (txt[0] == 'R')
485*49cdfc7eSAndroid Build Coastguard Worker ++length;
486*49cdfc7eSAndroid Build Coastguard Worker fclose(fp);
487*49cdfc7eSAndroid Build Coastguard Worker }
488*49cdfc7eSAndroid Build Coastguard Worker closedir(dp);
489*49cdfc7eSAndroid Build Coastguard Worker return (length);
490*49cdfc7eSAndroid Build Coastguard Worker } /* End Function get_run_queue_size */
491*49cdfc7eSAndroid Build Coastguard Worker
get_num_switches()492*49cdfc7eSAndroid Build Coastguard Worker static unsigned long get_num_switches()
493*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Get the number of context switches.
494*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] The number of context switches on success, else 0.
495*49cdfc7eSAndroid Build Coastguard Worker */
496*49cdfc7eSAndroid Build Coastguard Worker {
497*49cdfc7eSAndroid Build Coastguard Worker unsigned long val;
498*49cdfc7eSAndroid Build Coastguard Worker FILE *fp;
499*49cdfc7eSAndroid Build Coastguard Worker char line[256], name[64];
500*49cdfc7eSAndroid Build Coastguard Worker
501*49cdfc7eSAndroid Build Coastguard Worker if ((fp = fopen("/proc/stat", "r")) == NULL)
502*49cdfc7eSAndroid Build Coastguard Worker return (0);
503*49cdfc7eSAndroid Build Coastguard Worker
504*49cdfc7eSAndroid Build Coastguard Worker while (fgets(line, sizeof line, fp) != NULL) {
505*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(line, "%s %lu", name, &val) != 2)
506*49cdfc7eSAndroid Build Coastguard Worker continue;
507*49cdfc7eSAndroid Build Coastguard Worker
508*49cdfc7eSAndroid Build Coastguard Worker if (strcasecmp(name, "ctxt") != 0)
509*49cdfc7eSAndroid Build Coastguard Worker continue;
510*49cdfc7eSAndroid Build Coastguard Worker
511*49cdfc7eSAndroid Build Coastguard Worker fclose(fp);
512*49cdfc7eSAndroid Build Coastguard Worker return (val);
513*49cdfc7eSAndroid Build Coastguard Worker }
514*49cdfc7eSAndroid Build Coastguard Worker fclose(fp);
515*49cdfc7eSAndroid Build Coastguard Worker return (0);
516*49cdfc7eSAndroid Build Coastguard Worker } /* End Function get_num_switches */
517*49cdfc7eSAndroid Build Coastguard Worker
use_fpu_value(double val)518*49cdfc7eSAndroid Build Coastguard Worker static void use_fpu_value(double val)
519*49cdfc7eSAndroid Build Coastguard Worker /* [SUMMARY] Dummy function to consume FPU value. Fools compiler.
520*49cdfc7eSAndroid Build Coastguard Worker <val> The value.
521*49cdfc7eSAndroid Build Coastguard Worker [RETURNS] Nothing.
522*49cdfc7eSAndroid Build Coastguard Worker */
523*49cdfc7eSAndroid Build Coastguard Worker {
524*49cdfc7eSAndroid Build Coastguard Worker } /* End Function use_fpu_value */
525