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_tc4                              |
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_tc4 sched_tc4.c -L. -lpsc                  |
33|                                                                      |
34| Usage:        sched_tc4 [-t priority_type] [-p priority]             |
35|                         [-l log] [-v] [-d]                           |
36|                                                                      |
37| Last update:   Ver. 1.3, 4/10/94 23:05:02                           |
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   <sys/times.h>
48#include <sys/resource.h>
49#include <sys/types.h>
50#include <sys/stat.h>
51#include <fcntl.h>
52#include   <stdlib.h>
53#include   "sched.h"
54
55/*
56 * Defines:
57 *
58 * USAGE: usage statement
59 *
60 * DEFAULT_PRIORITY_TYPE: default priority
61 *
62 * BLOCK_SIZE: block size (in bytes) for raw I/O
63 *
64 * TIMES: number of times to read raw I/O device (~25MB)
65 *
66 */
67#define DEFAULT_PRIORITY_TYPE	"variable"
68#define DEFAULT_LOGFILE		"sched_tc4.log"
69#define BLOCK_SIZE		512
70#define TIMES			5000
71#define USAGE "Usage:  %s  [-l log] [-t type] [-p priority] [-v] [-d]\n" \
72              "        -l log      log file                             \n" \
73              "        -t type     priority type 'variable' or 'fixed'  \n" \
74              "        -p priority priority value                       \n" \
75              "        -v          verbose                              \n" \
76              "        -d          enable debugging messages            \n"
77
78/*
79 * Function prototypes:
80 *
81 * process_file: reads data file
82 *
83 * parse_args: parse command line arguments
84 */
85void parse_args(int, char **);
86void read_raw_device();
87
88/*
89 * Global variables:
90 *
91 * verbose: enable normal messages
92 *
93 * debug: enable debugging messages
94 *
95 * priority: process type (fixed priority, variable priority)
96 */
97int verbose = 0;
98int debug = 0;
99int priority = DEFAULT_PRIORITY;
100char *logfile = DEFAULT_LOGFILE;
101char *priority_type = DEFAULT_PRIORITY_TYPE;
102
103/*---------------------------------------------------------------------+
104|                                 main                                 |
105| ==================================================================== |
106|                                                                      |
107| Function:  ...                                                       |
108|                                                                      |
109+---------------------------------------------------------------------*/
110int main(int argc, char **argv)
111{
112	FILE *statfile;
113	clock_t start_time;	/* start & stop times */
114	clock_t stop_time;
115	float elapsed_time;
116	struct tms timer_info;	/* time accounting info */
117
118	/*
119	 * Process command line arguments...
120	 */
121	parse_args(argc, argv);
122	if (verbose)
123		printf("%s: Scheduler TestSuite program\n\n", *argv);
124	if (debug) {
125		printf("\tpriority type:  %s\n", priority_type);
126		printf("\tpriority:       %d\n", priority);
127		printf("\tlogfile:        %s\n", logfile);
128	}
129
130	/*
131	 * Adjust the priority of this process if the real time flag is set
132	 */
133	if (!strcmp(priority_type, "fixed")) {
134#ifndef __linux__
135		if (setpri(0, DEFAULT_PRIORITY) < 0)
136			sys_error("setpri failed", __FILE__, __LINE__);
137#else
138		if (setpriority(PRIO_PROCESS, 0, 0) < 0)
139			sys_error("setpri failed", __FILE__, __LINE__);
140#endif
141	} else {
142		if (nice((priority - 50) - (nice(0) + 20)) < 0 && errno != 0)
143			sys_error("nice failed", __FILE__, __LINE__);
144	}
145
146	/*
147	 * Read from raw I/O device and record elapsed time...
148	 */
149	start_time = time((time_t *) & timer_info);
150
151	read_raw_device();
152
153	stop_time = time((time_t *) & timer_info);
154	elapsed_time = (float)(stop_time - start_time) / 100.0;
155
156	if ((statfile = fopen(logfile, "w")) == NULL)
157		sys_error("fopen failed", __FILE__, __LINE__);
158
159	fprintf(statfile, "%f\n", elapsed_time);
160	if (debug)
161		printf("\n\telapsed time: %f\n", elapsed_time);
162
163	if (fclose(statfile) < 0)
164		sys_error("fclose failed", __FILE__, __LINE__);
165
166	/*
167	 * Exit with success!
168	 */
169	if (verbose)
170		printf("\nsuccessful!\n");
171	return (0);
172}
173
174/*---------------------------------------------------------------------+
175|                          read_raw_device ()                          |
176| ==================================================================== |
177|                                                                      |
178| Function:  o  opens raw disk device                                  |
179|            o  reads block of size BLOCK_SIZE n times                 |
180|            o  lseeks back to beginning of file                       |
181|            o  closes raw device                                      |
182|                                                                      |
183+---------------------------------------------------------------------*/
184void read_raw_device()
185{
186	char readbuf[BLOCK_SIZE + 1];	/* buffer to store bytes read */
187	int fd;			/* file descriptor */
188	int i;			/* loop counter */
189	int blocks = 0;		/* number of blocks read */
190#ifndef __linux__
191	char raw_dev[50] = "/dev/hd2";	/* name of raw device file */
192#else
193	char *raw_dev;		/* name of raw device file  */
194
195	if ((raw_dev = getenv("RAWDEV")) == NULL) {
196		errno = ENODATA;
197		sys_error("environment variable RAWDEV not set", __FILE__,
198			  __LINE__);
199	}
200#endif
201
202	/*
203	 * Open the raw disk file
204	 */
205	if ((fd = open(raw_dev, 0)) < 0)
206		sys_error("open failed", __FILE__, __LINE__);
207
208	/*
209	 * Read through predefined number of blocks TIMES number of times.
210	 * (Seek back to beginning of raw device after reading 10MB)
211	 */
212	for (i = 0; i < TIMES; i++) {
213		if (read(fd, readbuf, BLOCK_SIZE) != BLOCK_SIZE)
214			sys_error("read failed", __FILE__, __LINE__);
215		if (blocks == 10000)
216			if (lseek(fd, 0, 0) < 0)
217				sys_error("lseek failed", __FILE__, __LINE__);
218	}
219
220	/*
221	 * Close the raw disk file
222	 */
223	if (close(fd) < 0)
224		sys_error("close failed", __FILE__, __LINE__);
225}
226
227/*---------------------------------------------------------------------+
228|                             parse_args ()                            |
229| ==================================================================== |
230|                                                                      |
231| Function:  Parse the command line arguments & initialize global      |
232|            variables.                                                |
233|                                                                      |
234| Updates:   (command line options)                                    |
235|                                                                      |
236|            [-t] type:     priority type "fixed" or "variable"        |
237|            [-p] priority: priority value                             |
238|            [-l] logfile:  log file name                              |
239|            [-v]           verbose                                    |
240|            [-d]           enable debugging messages                  |
241|                                                                      |
242+---------------------------------------------------------------------*/
243void parse_args(int argc, char **argv)
244{
245	int opt;
246	int lflg = 0, pflg = 0, tflg = 0;
247	int errflag = 0;
248	char *program_name = *argv;
249	extern char *optarg;	/* Command line option */
250
251	/*
252	 * Parse command line options.
253	 */
254	if (argc < 2) {
255		fprintf(stderr, USAGE, program_name);
256		exit(0);
257	}
258
259	while ((opt = getopt(argc, argv, "l:t:p:vd")) != EOF) {
260		switch (opt) {
261		case 'l':	/* log file */
262			lflg++;
263			logfile = optarg;
264			break;
265		case 't':	/* process type */
266			tflg++;
267			priority_type = optarg;
268			break;
269		case 'p':	/* process priority */
270			pflg++;
271			priority = atoi(optarg);
272			break;
273		case 'v':	/* verbose */
274			verbose++;
275			break;
276		case 'd':	/* enable debugging messages */
277			verbose++;
278			debug++;
279			break;
280		default:
281			errflag++;
282			break;
283		}
284	}
285
286	/*
287	 * Check percentage and process slots...
288	 */
289	if (tflg) {
290		if (strcmp(priority_type, "fixed") &&
291		    strcmp(priority_type, "variable")) {
292			errflag++;
293			fprintf(stderr, "Error: priority type must be: "
294				"\'fixed\' or \'variable\'\n");
295		}
296	}
297	if (pflg) {
298		if (priority < 50 || priority > 100) {
299			errflag++;
300			fprintf(stderr, "Error: priority range [50..100]\n");
301		}
302	}
303	if (errflag) {
304		fprintf(stderr, USAGE, program_name);
305		exit(2);
306	}
307}
308