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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18/*
19 * FUNCTIONS: Scheduler Test Suite
20 */
21
22/*---------------------------------------------------------------------+
23|                               sched_tc5                              |
24| ==================================================================== |
25|                                                                      |
26| Description:  Creates short-term disk I/O bound process              |
27|                                                                      |
28| Algorithm:    o  Set process priority                                |
29|               o  Continuously multiply matrices together until       |
30|                  interrupted.                                        |
31|                                                                      |
32| To compile:   cc -o sched_tc5 sched_tc5.c -L. -lpsc                  |
33|                                                                      |
34| Usage:        sched_tc5 [-t priority_type] [-p priority]             |
35|                         [-l log] [-v] [-d]                           |
36|                                                                      |
37| Last update:   Ver. 1.3, 4/10/94 23:05:03                           |
38|                                                                      |
39| Change Activity                                                      |
40|                                                                      |
41|   Version  Date    Name  Reason                                      |
42|    0.1     050689  CTU   Initial version                             |
43|    0.2     010402  Manoj Iyer Ported to Linux		               |
44|                                                                      |
45+---------------------------------------------------------------------*/
46
47#include   <stdio.h>
48#include   <stdlib.h>
49#include   <sys/times.h>
50#include <sys/resource.h>
51#include   "sched.h"
52
53/*
54 * Defines:
55 *
56 * USAGE: usage statement
57 *
58 * DEFAULT_PRIORITY_TYPE: default priority
59 *
60 * BLOCK_SIZE: block size (in bytes) for raw I/O
61 *
62 * TIMES: number of times preform calculations
63 *
64 */
65#define DEFAULT_PRIORITY_TYPE	"variable"
66#define DEFAULT_LOGFILE		"sched_tc5.log"
67#define TIMES			20
68#define MATRIX_SIZE    		50
69#define USAGE "Usage:  %s  [-l log] [-t type] [-p priority] [-v] [-d]\n" \
70              "        -l log      log file                             \n" \
71              "        -t type     priority type 'variable' or 'fixed'  \n" \
72              "        -p priority priority value                       \n" \
73              "        -v          verbose                              \n" \
74              "        -d          enable debugging messages            \n"
75
76/*
77 * Function prototypes:
78 *
79 * parse_args: parse command line arguments
80 */
81void parse_args(int, char **);
82void invert_matrix();
83
84/*
85 * Global variables:
86 *
87 * verbose: enable normal messages
88 *
89 * debug: enable debugging messages
90 *
91 * priority: process type (fixed priority, variable priority)
92 */
93int verbose = 0;
94int debug = 0;
95int priority = DEFAULT_PRIORITY;
96char *logfile = DEFAULT_LOGFILE;
97char *priority_type = DEFAULT_PRIORITY_TYPE;
98
99/*---------------------------------------------------------------------+
100|                                 main                                 |
101| ==================================================================== |
102|                                                                      |
103| Function:  ...                                                       |
104|                                                                      |
105+---------------------------------------------------------------------*/
106int main(int argc, char **argv)
107{
108	FILE *statfile;
109	int i;
110	clock_t start_time;	/* start & stop times */
111	clock_t stop_time;
112	float elapsed_time;
113	struct tms timer_info;	/* time accounting info */
114
115	/*
116	 * Process command line arguments...
117	 */
118	parse_args(argc, argv);
119	if (verbose)
120		printf("%s: Scheduler TestSuite program\n\n", *argv);
121	if (debug) {
122		printf("\tpriority type:  %s\n", priority_type);
123		printf("\tpriority:       %d\n", priority);
124		printf("\tlogfile:        %s\n", logfile);
125	}
126
127	/*
128	 * Adjust the priority of this process if the real time flag is set
129	 */
130	if (!strcmp(priority_type, "fixed")) {
131#ifndef __linux__
132		if (setpri(0, DEFAULT_PRIORITY) < 0)
133			sys_error("setpri failed", __FILE__, __LINE__);
134#else
135		if (setpriority(PRIO_PROCESS, 0, 0) < 0)
136			sys_error("setpri failed", __FILE__, __LINE__);
137#endif
138	} else {
139		if (nice((priority - 50) - (nice(0) + 20)) < 0 && errno != 0)
140			sys_error("nice failed", __FILE__, __LINE__);
141	}
142
143	/*
144	 * Read from raw I/O device and record elapsed time...
145	 */
146	start_time = time((time_t *) & timer_info);
147
148	for (i = 0; i < TIMES; i++)
149		invert_matrix();
150
151	stop_time = time((time_t *) & timer_info);
152	elapsed_time = (float)(stop_time - start_time) / 100.0;
153
154	if ((statfile = fopen(logfile, "w")) == NULL)
155		sys_error("fopen failed", __FILE__, __LINE__);
156
157	fprintf(statfile, "%f\n", elapsed_time);
158	if (debug)
159		printf("\n\telapsed time: %f\n", elapsed_time);
160
161	if (fclose(statfile) < 0)
162		sys_error("fclose failed", __FILE__, __LINE__);
163
164	/*
165	 * Exit with success!
166	 */
167	if (verbose)
168		printf("\nsuccessful!\n");
169	return (0);
170}
171
172/*---------------------------------------------------------------------+
173|                           invert_matrix ()                           |
174| ==================================================================== |
175|                                                                      |
176| Function:  o  Randomly assign values to a matrix and then calculate  |
177|               inverse..                                              |
178|                                                                      |
179+---------------------------------------------------------------------*/
180void invert_matrix()
181{
182	int i, j, k;
183	float t1;
184	float matrix_1[MATRIX_SIZE][MATRIX_SIZE];
185	float matrix_2[MATRIX_SIZE][MATRIX_SIZE];
186
187	/*
188	 * Fill the first matrix to be inverted with random values
189	 */
190	printf("sched_tc5: invert_matrix: before first matrix inversion\n");
191	for (i = 0; i < MATRIX_SIZE; i++)
192		for (j = 0; j < MATRIX_SIZE; j++) {
193			matrix_1[i][j] = (float)(rand() % 100);
194		}
195
196	/*
197	 * Now calculate the inverse of the random matrix first, create an
198	 * identity matrix in the result matrix
199	 */
200	printf("sched_tc5: invert_matrix: before second matrix inversion\n");
201	for (i = 0; i < MATRIX_SIZE; i++)
202		for (j = 0; j < MATRIX_SIZE; j++)
203			if (i == j)
204				matrix_2[i][j] = 1;
205			else
206				matrix_2[i][j] = 0;
207
208	printf("sched_tc5: invert_matrix: before form identity matrix\n");
209	/*
210	 * Form an identity matrix in the random matrix
211	 */
212	for (i = 0; i < MATRIX_SIZE; i++) {
213		t1 = matrix_1[i][i];
214		for (j = 0; j < MATRIX_SIZE; j++) {
215			matrix_1[i][j] /= t1;
216			matrix_2[i][j] /= t1;
217		}
218		for (j = 0; j < MATRIX_SIZE; j++)
219			if (i != j) {
220				t1 = -matrix_1[j][i];
221				for (k = 0; k < MATRIX_SIZE; k++) {
222					matrix_1[j][k] += (matrix_1[i][k] * t1);
223					matrix_2[j][k] += (matrix_2[i][k] * t1);
224				}
225			}
226	}
227	printf("sched_tc5: invert_matrix: after form identity matrix\n");
228}
229
230/*---------------------------------------------------------------------+
231|                             parse_args ()                            |
232| ==================================================================== |
233|                                                                      |
234| Function:  Parse the command line arguments & initialize global      |
235|            variables.                                                |
236|                                                                      |
237| Updates:   (command line options)                                    |
238|                                                                      |
239|            [-t] type:     priority type "fixed" or "variable"        |
240|            [-p] priority: priority value                             |
241|            [-l] logfile:  log file name                              |
242|            [-v]           verbose                                    |
243|            [-d]           enable debugging messages                  |
244|                                                                      |
245+---------------------------------------------------------------------*/
246void parse_args(int argc, char **argv)
247{
248	int opt;
249	int lflg = 0, pflg = 0, tflg = 0;
250	int errflag = 0;
251	char *program_name = *argv;
252	extern char *optarg;	/* Command line option */
253
254	/*
255	 * Parse command line options.
256	 */
257	if (argc < 2) {
258		fprintf(stderr, USAGE, program_name);
259		exit(0);
260	}
261
262	while ((opt = getopt(argc, argv, "l:t:p:vd")) != EOF) {
263		switch (opt) {
264		case 'l':	/* log file */
265			lflg++;
266			logfile = optarg;
267			break;
268		case 't':	/* process type */
269			tflg++;
270			priority_type = optarg;
271			break;
272		case 'p':	/* process priority */
273			pflg++;
274			priority = atoi(optarg);
275			break;
276		case 'v':	/* verbose */
277			verbose++;
278			break;
279		case 'd':	/* enable debugging messages */
280			verbose++;
281			debug++;
282			break;
283		default:
284			errflag++;
285			break;
286		}
287	}
288	debug = 1;
289
290	/*
291	 * Check percentage and process slots...
292	 */
293	if (tflg) {
294		if (strcmp(priority_type, "fixed") &&
295		    strcmp(priority_type, "variable"))
296			errflag++;
297	}
298	if (pflg) {
299		if (priority < 50 || priority > 100)
300			errflag++;
301	}
302	if (errflag) {
303		fprintf(stderr, USAGE, program_name);
304		exit(2);
305	}
306}
307