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