sched_driver.c revision da0cc970b6adc42679cf947c6a7326c3bc6d7fc9
1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2001
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program;  if not, write to the Free Software
17 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* @BULL_COPYRIGHT@ */
21
22/*
23 *
24 *   FUNCTIONS: none
25 *
26 *   ORIGINS: 27
27 *
28 *   IBM CONFIDENTIAL -- (IBM Confidential Restricted when
29 *   combined with the aggregated modules for this product)
30 *   OBJECT CODE ONLY SOURCE MATERIALS
31 *
32 *   (C) COPYRIGHT International Business Machines Corp. 1993
33 *   All Rights Reserved
34 *   US Government Users Restricted Rights - Use, duplication or
35 *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
36 */
37
38/*---------------------------------------------------------------------+
39|                             sched_driver                             |
40| ==================================================================== |
41|                                                                      |
42| Description:  This program uses system calls to change the           |
43|               priorities of the throughput measurement testcases.    |
44|               When real-time is in effect, priorities 50 through 64  |
45|               are used.  (MAX_PRI and MIN_PRI)  When user-time       |
46|               (normal) is in effect, 0-14 (corresponding to nice()   |
47|               calls) is used.  The driver only keeps track of        |
48|               values from 50 to 64, and the testcases will scale     |
49|               them down to 0 to 14 when needed, to change the        |
50|               priority of a user-time process.                       |
51|                                                                      |
52| Algorithm:    o  Parse command line arguments                        |
53|               o  Set current priority                                |
54|               o  Calcucations (process slots, short/long term slots) |
55|               o  Perform throughput tests with high priority         |
56|               o  Start long-term testcases                           |
57|               o  While time remains                                  |
58|                  - Start short-term tests                            |
59|                  - Perform throughput tests with new priority        |
60|                  - Kill short-term tests                             |
61|                  - Increase priority                                 |
62|                                                                      |
63| Usage:        sched_driver [-s n] [-p n] [-t n] [-d] [-v]            |
64|                                                                      |
65|               where:                                                 |
66|                 -s n  stress percentage                              |
67|                 -p n  process slots                                  |
68|                 -t n  execution time in hours                        |
69|                 -d    enable debugging messages                      |
70|                 -v    Turn on verbose mode                           |
71|                                                                      |
72| Last update:   Ver. 1.15, 4/10/94 23:04:23                           |
73|                                                                      |
74| Change Activity                                                      |
75|                                                                      |
76|   Version  Date    Name  Reason                                      |
77|    0.1     072889  GEB   Initial draft                               |
78|    1.2     120793  JAT   Changes for AIX 4.1                         |
79|    1.3     041094  DJK   Rewrote protions...                         |
80|    1.4     010402  Manoj Iyer Ported to Linux                        |
81|                                                                      |
82+---------------------------------------------------------------------*/
83
84#include <sys/types.h>
85#include <unistd.h>
86#include <wait.h>
87#include <string.h>
88#include <stdlib.h>
89#include <signal.h>
90#include <pwd.h>
91#include <time.h>
92#include "sched.h"
93
94/*
95 * Defines:
96 *
97 * MAXPROCS: maximum number of processes
98 *
99 * PRIINC: priority step value
100 *
101 * MAX_PRI: highest priority to use
102 *
103 * MIN_PRI: lowest priority to use
104 *
105 * DEFAULT_STRESS_PERCENTAGE: stress percentage (process slot multiplier)
106 *
107 * DEFAULT_PROCESS_SLOTS: number of processes test driver will try and create
108 *
109 * DEFAULT_TIME: time (hours) for which this test driver will run
110 *
111 * USAGE: usage statement
112 */
113#define MAXPROCS   100
114#define PRIINC     2
115#define MAX_PRI    55    /* was 50 */
116#define MIN_PRI    75    /* was 64 */
117#define DEFAULT_STRESS_PERCENTAGE	0.5
118#define DEFAULT_PROCESS_SLOTS		16
119#define DEFAULT_TIME			1.00
120#define USAGE "Usage:  %s  [-s n] [-p n] [-t n] [-d] [-v]              \n" \
121              "        -s n   stress percentage [0.0<n<1.0] (default 0.5) \n" \
122              "        -p n   process slots (default 16)                  \n" \
123              "        -t n   execution time in hours (default 1.0 hrs)   \n" \
124              "        -d     enable debugging messages                   \n" \
125              "        -v     Turn on verbose mode 	                  \n"
126
127/*
128 * Global variables:
129 *
130 * stress_percent: stress percentage
131 *
132 * :
133 *
134 * execution_time: execution time in hours
135 *
136 * debug: (option flag) enables debugging messages
137 */
138int	numprocs,          /* number of process id's in table             */
139	procs[MAXPROCS],   /* array of process id's for killing           */
140	long_running,      /* number of long term testcases running       */
141	short_running;     /* number of short term testcases running      */
142float	e4user,            /* previous elapsed seconds for tc 4-user      */
143	e4real,            /* previous elapsed seconds for tc 4-real      */
144	e5user,            /* previous elapsed seconds for tc 5-user      */
145	e5real,            /* previous elapsed seconds for tc 5-real      */
146	e6user0,           /* previous elapsed seconds for tc 6-user,nf   */
147	e6real0,           /* previous elapsed seconds for tc 6-real,nf   */
148	e6user1,           /* previous elapsed seconds for tc 6-user,f    */
149	e6child;           /* previous elapsed seconds for tc 6-child     */
150double	stress_percent = DEFAULT_STRESS_PERCENTAGE;
151double	execution_time = DEFAULT_TIME;
152int	process_slots  = DEFAULT_PROCESS_SLOTS;
153int	debug = 0;
154
155
156/*
157 * Function prototypes
158 */
159void  startup (long);
160int   start_testcase (char *, char *, char *, char *, char *, char *);
161int   process_slots_in_use ();
162int   available_user_process_slots ();
163float measure_test (char *, char *, char *, char *, float *);
164void  display_line (char *, int, int, float, float *, int);
165void  perform_throughput_tests (int);
166void  start_long_term_testcases (int, char *);
167void  kill_short_term_testcases ();
168void  start_short_term_testcases (int, double, int);
169void  finishup (long);
170void  parse_args (int, char **);
171
172
173/*---------------------------------------------------------------------+
174|                               main ()                                |
175| ==================================================================== |
176|                                                                      |
177| Function:  Main program                                              |
178|                                                                      |
179+---------------------------------------------------------------------*/
180int main (int argc, char **argv)
181{
182	long    runseconds,              /* number of seconds to run */
183		start_time;              /* time at start of driver */
184	int     current_priority,        /* current priority level for nice */
185		workslots,               /* number of free workslots */
186		long_term_slot_total,    /* workslots for long-term processes */
187		short_term_slot_total;   /* workslots for short-term */
188
189	/*
190	 * Parse command line arguments & printer program header...
191	 */
192	parse_args (argc, argv);
193	printf ("Scheduler Testsuite Program\n\n");
194	fflush (stdout);
195
196	/*
197	 * Calculate number of seconds to run, then print out start info
198	 */
199	runseconds = (long)  (execution_time * 60.0 * 60.0);
200	start_time = time ((long *) 0);
201
202	startup (start_time);
203
204	/*
205	 * Calculate available workslots, long-term, and short-term slots
206	 */
207	workslots = available_user_process_slots() * stress_percent;
208	long_term_slot_total = workslots / 2;
209	if (debug) {
210		printf ("available slots:      %d\n", available_user_process_slots ());
211		printf ("workslots available:  %d\n", workslots);
212		printf ("stress_percent:       %f\n", stress_percent);
213		printf ("run-hours:            %f (hrs)\n", execution_time);
214		 		 printf ("runseconds:           %ld (sec)\n", runseconds);
215	}
216
217	/*
218	 * Run the first set of tests with an average priority
219	 */
220	perform_throughput_tests ( (MAX_PRI + MIN_PRI) / 2);
221	fflush (stdout);
222
223	/*
224	 * Start the long-term testcases running
225	 */
226	start_long_term_testcases (long_term_slot_total, argv[2]);
227	short_term_slot_total = workslots / 2;
228	fflush (stdout);
229
230	/*
231	 * Loop while there is still time
232	 */
233	current_priority=MAX_PRI;
234	while ((time(0) - start_time) < runseconds) {
235
236		if (debug) printf ("current priority: %d\n", current_priority);
237		if (debug) printf ("starting short term tests\n");
238
239		start_short_term_testcases (short_term_slot_total,
240			stress_percent, current_priority);
241		fflush (stdout);
242
243		perform_throughput_tests (current_priority);
244		fflush (stdout);
245
246		if (debug) printf ("killing short term tests\n");
247
248		kill_short_term_testcases ();
249		fflush (stdout);
250
251		if (current_priority + PRIINC > MIN_PRI)
252			current_priority = MAX_PRI;
253		else
254			current_priority += PRIINC;
255	}
256
257	/*
258	 * Exit with success...
259	 */
260	finishup (start_time);
261	printf ("\nsuccessful!\n");
262	fflush (stdout);
263	return (0);
264}
265
266
267/*------------------------------ startup() ------------------------------*/
268/* This procedure opens the , and then outputs some starting	 *
269 * information to the screen and .  It also initializes the	 *
270 * process id list and other global variables.	 			 *
271 *-----------------------------------------------------------------------*/
272void startup (long start_time)
273{
274	char   tempbuffer[50];   /* temporary buffer to hold names */
275
276	/*
277	 * Now output some diagnostic information
278	 */
279	printf ("start time    = %s\n", ctime (&start_time));
280
281	gethostname (tempbuffer, 40);
282	printf ("host name     = %s\n", tempbuffer);
283
284	printf ("user name     = %s\n", getpwuid(geteuid())->pw_name);
285
286	printf ("test duration = %4.2f (hours)\n", execution_time);
287
288	printf ("test stress   = %4.2f%%%%\n\n", 100 * stress_percent);
289
290	/*
291	 * Initialize the global variables
292	 */
293	numprocs = 0;
294	long_running = 0;
295	short_running = 0;
296	e4user = 0.0;
297	e4real = 0.0;
298	e5user = 0.0;
299	e5real = 0.0;
300	e6user0 = 0.0;
301	e6real0 = 0.0;
302	e6user1 = 0.0;
303	e6child = 0.0;
304}
305
306
307/*--------------------------- start_testcase() --------------------------*/
308/* This procedure will run a specified testcase by forking a process, and*
309 * then running the testcase with it.  It will also store the process id *
310 * number in the process id table.  The process id of the child process  *
311 * is returned to the calling program.					 *
312 *	name1     pathname of testcase to run			         *
313 *	name2     filename of testcase to run			         *
314 *	param1    parameters to pass to the testcase			 *
315 *	param2 			         			         *
316 *	param3 			         			         *
317 *	param4    if sched_tc6:  fork flag:  0=false, 1=true             *
318 *-----------------------------------------------------------------------*/
319
320int start_testcase (char *name1, char *name2, char *param1, char *param2, char *param3, char *param4)
321{
322	int   pid,        /* pid of currently running process */
323	pid_save;   /* saved pid of process */
324
325	/*
326	 * Fork a process that will run testcase and save the pid
327	 */
328	if (debug)
329		printf ("test: %s %s p1[%s] p2[%s] p3[%s] p4[%s]\n",
330			name1, name2, param1, param2, param3, param4);
331
332	pid_save = pid = fork();
333
334	/*
335	 * If the pid returned is -1, fork failed.  If the pid returned is
336	 * 0, then the process running is the child process, and we need
337	 * to do an 'execl' to run the testcase.  If the pid returned is
338	 * anything else, then the parent is running, and we return.
339	 */
340	switch (pid) {
341		case -1 :
342			exit (-1);
343		case 0 :
344			execl (name1, name2, param1, param2, param3, param4, NULL);
345			printf ("ERROR: start_testcase():  execl failed.\n");
346			exit (-1);
347		default :
348			break;
349	}
350	if (debug)
351		printf ("testcase %s started -- pid is %d\n", name2, pid_save);
352
353	/*
354	 * If the process just forked is for a short-term testcase, then
355	 * add the process id to the table.
356	 */
357	if (debug) printf ("new process: %s ", name2);
358	if  (strstr (name2, "tc1") || strstr (name2, "tc3")) {
359		procs[ numprocs ] = pid_save;
360		numprocs++;
361		short_running++;
362		if (debug) printf ("(%d short term)", short_running);
363	}
364	if  (strstr (name2, "tc0") || strstr (name2, "tc2")) {
365		long_running++;
366		if (debug) printf ("(%d long term)", long_running);
367	}
368	if (debug) printf ("\n");
369
370	return (pid_save);
371}
372
373
374/*------------------------- process_slots_in_use() ----------------------*/
375/* This function will return the number of process slots currently in use*
376 * by executing the 'ps' command.					 *
377 *-----------------------------------------------------------------------*/
378int process_slots_in_use()
379{
380	FILE   *psfile;     /* temporary file to hold output of 'ps' command */
381	int    usedslots;   /* holds the number of used process slots */
382
383	/*
384	 * Call the 'ps' command and write the number of process slots to a file
385	 */
386	if  (system ("ps -e | wc -l > ps.out") < 0)
387		sys_error ("system failed", __FILE__, __LINE__);
388
389	/*
390	 * Open the output file
391	 */
392	if  ( (psfile = fopen ("ps.out", "r")) == (FILE *) NULL) {
393		exit (-1);
394	}
395
396	/*
397	 * Read the number of process slots in use from the file
398	 */
399	fscanf (psfile, "%d", &usedslots);
400
401	/*
402	 * Close the output file
403	 */
404	if  (fclose (psfile) == -1) {
405		exit (-1);
406	}
407
408	/*
409	 * Remove the output file
410	 */
411	if  (system ("/bin/rm ps.out") < 0)
412		sys_error ("system failed", __FILE__, __LINE__);
413
414	return (usedslots - 1);
415}
416
417
418/*----------------------- available_user_process_slots() ----------------*/
419/* This function returns the total number of available user process slots*
420 * by subtracting the process slots currently in use from the maximum	 *
421 * possible process slots.						 *
422 *-----------------------------------------------------------------------*/
423int available_user_process_slots ()
424{
425	int num = process_slots_in_use ();
426
427	return ( (process_slots < num) ? process_slots : process_slots - num);
428}
429
430/*---------------------------- measure_test() ---------------------------*/
431/* This function executes a throughput measurement process and waits for *
432 * that process to finish.  When finished, it reads the result from a 	 *
433 * file and returns that result to the caller.  The file is then deleted.*
434 * If sched_tc6 is called, then the second time is also read from the	 *
435 * results file and returned to the caller.				 *
436 *-----------------------------------------------------------------------*/
437float measure_test (name, param1, param2, param3, t2)
438char 	*name,     /* filename of testcase to run */
439	*param1,   /* user flag:  0=user, 1=real time */
440	*param2,   /* priority to run the throughput test at */
441	*param3;   /* if sched_tc6:  fork flag, 0=false, 1=true */
442float *t2;       /* if sched_tc6:  second time returned from testcase */
443{
444	char	temp[50],	/* holds pathname and returned floating number */
445		t2asc[50];   	/* holds second returned floating number */
446	int	saved_pid;	/* process id of forked process */
447	FILE	*datafile;	/* file pointer for temporary file */
448
449	/*
450	 * Create the path name to be passed to the start_testcase() function
451	 */
452	sprintf (temp, "./%s", name);
453
454	/*
455	 * Send all the parameters, and start the testcase
456	 */
457	saved_pid = start_testcase (temp, name, param1,
458        	"-lsch.measure", param2, param3);
459
460	/*
461	 * Wait for the testcase to finish
462	 */
463	if (debug) printf ("waiting on child %d\n", saved_pid);
464	while (wait((void *) 0) != saved_pid) ;
465
466	/*
467	 * Open the temporary file to get the returned number of seconds
468	 */
469
470	if ( (datafile = fopen ("sch.measure", "r")) == (FILE *) NULL) {
471		sys_error ("cannot open sch.measure", __FILE__, __LINE__);
472	}
473
474	/*
475	 * Read the number of seconds
476	 */
477	fgets (temp, 50, datafile);
478	/*added by mpt
479	printf("sched+driver: measure_test: number of seconds=%s\n",temp)
480         *********** */
481
482	/*
483	 * If this is sched_tc6, then there is another number we must return
484	 */
485
486	if (strcmp (name, "sched_tc6") == 0) {
487		fgets (t2asc, 50, datafile);
488		*t2 = atof (t2asc);
489	}
490
491	/*
492	 * Close the temporary file
493	 */
494	if  (fclose (datafile) != 0) {
495		exit (-1);
496	}
497
498	/*
499	 * Now try to remove the temporary file
500	 */
501	/*added by MPT
502	printf("measure_test:  REMOVING sch.measure\n");
503	fflush(stdout);
504	if  (system ("rm sch.measure") < 0)
505		sys_error ("system failed", __FILE__, __LINE__);
506	*/
507	return (atof (temp));
508}
509
510/*------------------------- display_line() ------------------------------*/
511/* This procedure displays a line of output given the results of a	 *
512 * throughput test.  It displays the testcase name, the current priority *
513 * level, the user/real time flag, and the elapsed time in seconds, as	 *
514 * well as the percent change between the current and previous times.	 *
515 * It then updates the previous elapsed time to be the current one.	 *
516 *-----------------------------------------------------------------------*/
517void display_line (char *tcname, int pri, int f, float et, float *pet, int ff)
518{
519	static  int display_header = 0;
520	float	pc;               /* holds percent change */
521
522
523	/*
524	 * Print header every eight lines...
525	 */
526	if (display_header-- == 0) {
527		printf ("\n  Test                Processes              "   \
528			"  Time        Notes\n"                           \
529			"---------   ---------------------------   "      \
530			"---------------  -------\n"                      \
531			"name        long  short  priority  mode   "      \
532			"elapsed  %%%%delta\n\n");
533		display_header = 6;
534	}
535
536	/*
537	 * Calculate the percent change in time
538	 */
539	pc = (*pet == 0.0)? 0.0 : 100.0 *  ( (et - *pet) / *pet) + 0.05;
540
541	printf ("%-12s %2d    %2d      %2d      %4s   %06.4f  %+06.4f  %s\n",
542		tcname, long_running, short_running, pri,
543		(f == 0) ? "user" : "real",
544		et, pc,
545		(ff) ? "forked child" : " ");
546
547	fflush (stdout);
548
549	*pet = et;
550}
551
552
553/*------------------------- perform_throughput_tests() ------------------*/
554/* This procedure is called each time throughput tests are to be	 *
555 * performed.  This procedure executes each of the throughput tests, and *
556 * records the results of each to the .	 			 *
557 *-----------------------------------------------------------------------*/
558void perform_throughput_tests (int current_priority)
559{
560	float   esecs,        /* elapsed seconds returned from each testcase */
561		esecs2,       /* elapsed seconds (second part) for sched_tc6 */
562		pc;           /* percent change for sched_tc6 */
563	char    pristr[10];   /* holds ascii value of priority as parameter */
564
565	sprintf (pristr, "-p%d", current_priority);
566
567#if defined(_IA64) && !defined(__64BIT__)
568	esecs = measure_test ("sched_tc4.32", "-tvariable", pristr, NULL, &esecs2);
569	display_line ("sched_tc4.32", current_priority, 0, esecs, &e4user, 2);
570	esecs = measure_test ("sched_tc4.32", "-tfixed", pristr, NULL, &esecs2);
571	display_line ("sched_tc4.32", current_priority, 1, esecs, &e4real, 2);
572	esecs = measure_test ("sched_tc5.32", "-tvariable", pristr, NULL, &esecs2);
573	display_line ("sched_tc5.32", current_priority, 0, esecs, &e5user, 2);
574	esecs = measure_test ("sched_tc5.32", "-tfixed", pristr, NULL, &esecs2);
575	display_line ("sched_tc5.32", current_priority, 1, esecs, &e5real, 2);
576	esecs = measure_test ("sched_tc6.32", "-tvariable", pristr, " -d ", &esecs2);
577	display_line ("sched_tc6.32", current_priority, 0, esecs, &e6user0, 0);
578	esecs = measure_test ("sched_tc6.32", "-tfixed", pristr, " -d ", &esecs2);
579	display_line ("sched_tc6.32", current_priority, 1, esecs, &e6real0, 0);
580	esecs = measure_test ("sched_tc6.32", "-tvariable", pristr, " -df ", &esecs2);
581	display_line ("sched_tc6.32", current_priority, 0, esecs, &e6user1, 1);
582#else
583	esecs = measure_test ("sched_tc4", "-tvariable", pristr, NULL, &esecs2);
584	display_line ("sched_tc4", current_priority, 0, esecs, &e4user, 2);
585	esecs = measure_test ("sched_tc4", "-tfixed", pristr, NULL, &esecs2);
586	display_line ("sched_tc4", current_priority, 1, esecs, &e4real, 2);
587	esecs = measure_test ("sched_tc5", "-tvariable", pristr, NULL, &esecs2);
588	display_line ("sched_tc5", current_priority, 0, esecs, &e5user, 2);
589	esecs = measure_test ("sched_tc5", "-tfixed", pristr, NULL, &esecs2);
590	display_line ("sched_tc5", current_priority, 1, esecs, &e5real, 2);
591	esecs = measure_test ("sched_tc6", "-tvariable", pristr, " -d ", &esecs2);
592	display_line ("sched_tc6", current_priority, 0, esecs, &e6user0, 0);
593	esecs = measure_test ("sched_tc6", "-tfixed", pristr, " -d ", &esecs2);
594	display_line ("sched_tc6", current_priority, 1, esecs, &e6real0, 0);
595	esecs = measure_test ("sched_tc6", "-tvariable", pristr, " -df ", &esecs2);
596	display_line ("sched_tc6", current_priority, 0, esecs, &e6user1, 1);
597#endif
598
599	/*
600	 * Manually build the display line for the second part of sched_tc6
601	 */
602
603	/*
604	 * Calculate the percent change in time
605	 */
606	pc = (e6child == 0.0) ? 0.0 : 100 * ((esecs2 - e6child)/e6child) + 0.05;
607	printf ("%-12s forked child          %4s   %06.4f  %+06.4f\n",
608		"sched_tc6", "real", esecs2, pc);
609	e6child = esecs2;
610}
611
612
613/*------------------------ start_long_term_testcases() ------------------*/
614/* This procedure takes the number of long-term process slots available, *
615 * and executes the long term testcases.				 *
616 *-----------------------------------------------------------------------*/
617void start_long_term_testcases (long_term_slot_total, execution_time)
618int long_term_slot_total;    /* total number of long-term slots */
619char *execution_time;              /* runtime hours to pass to each testcase */
620{
621	int   i;   /* counter for loop */
622
623	/*
624	 * Now use up the long_term_slot_total by starting testcases call
625	 * half with real-time flag '1' set, other half user flag '0'
626	 */
627	if (debug)
628		printf ("long-term slots available:  %d\n", long_term_slot_total);
629
630	for  (i = 0; i <  (long_term_slot_total/4); i++) {
631#if defined(_IA64) && !defined(__64BIT__)
632		start_testcase ("./sched_tc0.32", "sched_tc0 -t", execution_time, " -p1", NULL, NULL);
633		start_testcase ("./sched_tc2.32", "sched_tc2", execution_time, "1", NULL, NULL);
634		start_testcase ("./sched_tc0.32", "sched_tc0 -t", execution_time, " -p0", NULL, NULL);
635		start_testcase ("./sched_tc2.32", "sched_tc2", execution_time, "0", NULL, NULL);
636#else
637		start_testcase ("./sched_tc0", "sched_tc0 -t", execution_time, " -p1", NULL, NULL);
638		start_testcase ("./sched_tc2", "sched_tc2", execution_time, "1", NULL, NULL);
639		start_testcase ("./sched_tc0", "sched_tc0 -t", execution_time, " -p0", NULL, NULL);
640		start_testcase ("./sched_tc2", "sched_tc2", execution_time, "0", NULL, NULL);
641#endif
642	}
643}
644
645
646/*---------------------------------------------------------------------+
647|                     start_short_term_testcases ()                    |
648| ==================================================================== |
649|                                                                      |
650| Function:  Starts short term testcases (one for each process slot)   |
651|                                                                      |
652+---------------------------------------------------------------------*/
653void start_short_term_testcases (int short_term_slot_total, double stress_percent, int pri)
654{
655	int	i;                  /* counter for loop */
656	int	short_term_slots;   /* number of slots to use */
657
658	/*
659	 * Set up the short_term_slot_total by starting testcases call
660	 * half with real-time flag '1' set, other half user flag '0'
661	 */
662	if  (available_user_process_slots() < short_term_slot_total)
663		short_term_slots = available_user_process_slots() * stress_percent / 2;
664	else
665		short_term_slots = short_term_slot_total;
666
667	printf ("\n<< Starting %d short-term testcases>> \n\n", short_term_slots);
668	if (debug)
669		printf ("short-term slots available:  %d\n", short_term_slots);
670
671	for  (i = 0; i <  (short_term_slots/4); i++) {
672#if defined(_IA64) && !defined(__64BIT__)
673		start_testcase ("./sched_tc1.32", "sched_tc1", "1", NULL, NULL, NULL);
674		start_testcase ("./sched_tc3.32", "sched_tc3", "1", NULL, NULL, NULL);
675		start_testcase ("./sched_tc1.32", "sched_tc1", "0", NULL, NULL, NULL);
676		start_testcase ("./sched_tc3.32", "sched_tc3", "0", NULL, NULL, NULL);
677#else
678		start_testcase ("./sched_tc1", "sched_tc1", "1", NULL, NULL, NULL);
679		start_testcase ("./sched_tc3", "sched_tc3", "1", NULL, NULL, NULL);
680		start_testcase ("./sched_tc1", "sched_tc1", "0", NULL, NULL, NULL);
681		start_testcase ("./sched_tc3", "sched_tc3", "0", NULL, NULL, NULL);
682#endif
683#if 0
684		perform_throughput_tests (pri);
685#endif
686	}
687}
688
689/*------------------------ kill_short_term_testcases() ------------------*/
690/* This procedure goes through the process id table, and sends each	 *
691 * process id number found in the table a signal in order to terminate	 *
692 * it.  The signal sent is SIGUSR1.  It also re-initializes the table.	 *
693 *-----------------------------------------------------------------------*/
694void kill_short_term_testcases()
695{
696	int   i;   /* loop counter to step through the list of process id's */
697
698        /*
699	 * Loop through the array of process id's one at a time, and
700	 * attempt to kill each one.  If kill fails, report error and
701	 * continue.
702	 */
703	if (debug)
704		printf ("killing short-term processes...\n");
705	for  (i = 0; i < numprocs; i++) {
706		if (debug) printf ("killing process [%d]\n", procs [i]);
707		kill (procs[i], SIGUSR1);
708	}
709
710	/*
711	 * Adjust the number of short_term_testcases
712	 */
713	short_running -= numprocs;
714
715	/*
716	 * Clear the table by setting number of entries to zero
717	 */
718	numprocs = 0;
719}
720
721
722/*----------------------------- finishup() ------------------------------*/
723/* This procedure closing information to the about ending	 *
724 * times, elapsed times, etc.  This procedure then closes the file*
725 *-----------------------------------------------------------------------*/
726void finishup (start_time)
727long start_time;   /* starting time to calculate elapsed time */
728{
729	long   end_time;       /* time when program finished */
730
731	/*
732	 * Get the end time and calculate elapsed time; write all this out
733	 */
734	end_time = time ((long *) 0);
735
736	printf ("\nend time = %s\n", ctime (&end_time));
737
738	printf ("elapsed time = %4.2f hours\n",
739		( (end_time - start_time) / 3600.0));
740}
741
742
743/*---------------------------------------------------------------------+
744|                             parse_args ()                            |
745| ==================================================================== |
746|                                                                      |
747| Function:  Parse the command line arguments & initialize global      |
748|            variables.                                                |
749|                                                                      |
750| Updates:   (command line options)                                    |
751|                                                                      |
752|            [-s] size: shared memory segment size                     |
753|                                                                      |
754+---------------------------------------------------------------------*/
755void parse_args (int argc, char **argv)
756{
757	int	opt;
758	int 	sflg = 0, pflg = 0, tflg = 0;
759	int	errflag = 0;
760	char	*program_name = *argv;
761	extern char 	*optarg;	/* Command line option */
762
763	/*
764	 * Parse command line options.
765	 */
766	while ((opt = getopt(argc, argv, "vs:p:t:l:d")) != EOF)
767	{
768		switch (opt)
769		{
770		case 's':	/* stress percentage */
771			sflg++;
772			stress_percent = atof (optarg);
773			break;
774		case 'p':	/* process slots */
775			pflg++;
776			process_slots = atof (optarg);
777			break;
778		case 't':	/* time (hours) */
779			tflg++;
780			execution_time = atof (optarg);
781			break;
782		case 'd':	/* Enable debugging messages */
783			debug++;
784			break;
785		case 'v':	/* Enable verbose mode=debug mode */
786			debug++;
787			break;
788		default:
789			errflag++;
790			break;
791		}
792	}
793
794	/*
795	 * Check percentage, execution time and process slots...
796 	 */
797	if (sflg) {
798		if (stress_percent < 0.0 || stress_percent > 1.0)
799			errflag++;
800	}
801	if (pflg) {
802		if (process_slots < 0 || process_slots > MAXPROCS)
803			errflag++;
804	}
805	if (tflg) {
806		if (execution_time < 0.0 || execution_time > 100.0)
807			errflag++;
808	}
809	if (debug)
810		printf ("\n(debugging messages enabled)\n\n");
811	if (errflag) {
812		fprintf (stderr, USAGE, program_name);
813		exit (2);
814	}
815}
816