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  */
81 void parse_args(int, char **);
82 void 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  */
93 int verbose = 0;
94 int debug = 0;
95 int priority = DEFAULT_PRIORITY;
96 char *logfile = DEFAULT_LOGFILE;
97 char *priority_type = DEFAULT_PRIORITY_TYPE;
98 
99 /*---------------------------------------------------------------------+
100 |                                 main                                 |
101 | ==================================================================== |
102 |                                                                      |
103 | Function:  ...                                                       |
104 |                                                                      |
105 +---------------------------------------------------------------------*/
main(int argc,char ** argv)106 int 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 +---------------------------------------------------------------------*/
invert_matrix()180 void 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 +---------------------------------------------------------------------*/
parse_args(int argc,char ** argv)246 void 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