1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci *   Copyright (c) International Business Machines  Corp., 2001
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
5f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
6f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
7f08c3bdfSopenharmony_ci *   (at your option) any later version.
8f08c3bdfSopenharmony_ci *
9f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
10f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
11f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
15f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
16f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17f08c3bdfSopenharmony_ci */
18f08c3bdfSopenharmony_ci/*
19f08c3bdfSopenharmony_ci * FUNCTIONS: Scheduler Test Suite
20f08c3bdfSopenharmony_ci */
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
23f08c3bdfSopenharmony_ci|                               sched_tc6                              |
24f08c3bdfSopenharmony_ci| ==================================================================== |
25f08c3bdfSopenharmony_ci|                                                                      |
26f08c3bdfSopenharmony_ci| Description:  Creates short-term disk I/O bound process              |
27f08c3bdfSopenharmony_ci|                                                                      |
28f08c3bdfSopenharmony_ci|		Creates a situation where a real time process is       |
29f08c3bdfSopenharmony_ci|		waiting on a file lock owned by a user process.  The   |
30f08c3bdfSopenharmony_ci|		scheduler should elevate the user process priority to  |
31f08c3bdfSopenharmony_ci|		the same level as the real time process to avoid       |
32f08c3bdfSopenharmony_ci|		deadlock situations and to decrease wait time          |
33f08c3bdfSopenharmony_ci|		required of the real time process.                     |
34f08c3bdfSopenharmony_ci|                                                                      |
35f08c3bdfSopenharmony_ci| Algorithm:    o  Set process priority                                |
36f08c3bdfSopenharmony_ci|               o  Continuously multiply matrices together until       |
37f08c3bdfSopenharmony_ci|                  interrupted.                                        |
38f08c3bdfSopenharmony_ci|                                                                      |
39f08c3bdfSopenharmony_ci| To compile:   cc -o sched_tc6 sched_tc6.c -L. -lpsc                  |
40f08c3bdfSopenharmony_ci|                                                                      |
41f08c3bdfSopenharmony_ci| Usage:        sched_tc6 [-t priority_type] [-p priority]             |
42f08c3bdfSopenharmony_ci|                         [-l log] [-f] [-v] [-d]                      |
43f08c3bdfSopenharmony_ci|                                                                      |
44f08c3bdfSopenharmony_ci| Last update:   Ver. 1.3, 4/10/94 23:05:03                           |
45f08c3bdfSopenharmony_ci|                                                                      |
46f08c3bdfSopenharmony_ci| Change Activity                                                      |
47f08c3bdfSopenharmony_ci|                                                                      |
48f08c3bdfSopenharmony_ci|   Version  Date    Name  Reason                                      |
49f08c3bdfSopenharmony_ci|    0.1     050689  CTU   Initial version                             |
50f08c3bdfSopenharmony_ci|    0.2     010402  Manoj Iyer Ported to Linux			       |
51f08c3bdfSopenharmony_ci|                                                                      |
52f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci#include <fcntl.h>
55f08c3bdfSopenharmony_ci#include <stdlib.h>
56f08c3bdfSopenharmony_ci#include <sys/time.h>
57f08c3bdfSopenharmony_ci#include <time.h>
58f08c3bdfSopenharmony_ci#include <sys/resource.h>
59f08c3bdfSopenharmony_ci#include "sched.h"
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci/*
62f08c3bdfSopenharmony_ci * Defines:
63f08c3bdfSopenharmony_ci *
64f08c3bdfSopenharmony_ci * USAGE: usage statement
65f08c3bdfSopenharmony_ci *
66f08c3bdfSopenharmony_ci * DEFAULT_PRIORITY_TYPE: default priority
67f08c3bdfSopenharmony_ci *
68f08c3bdfSopenharmony_ci * BLOCK_SIZE: block size (in bytes) for raw I/O
69f08c3bdfSopenharmony_ci *
70f08c3bdfSopenharmony_ci * TIMES: number of times to read raw I/O device (~25MB)
71f08c3bdfSopenharmony_ci *
72f08c3bdfSopenharmony_ci */
73f08c3bdfSopenharmony_ci#define DEFAULT_PRIORITY_TYPE	"variable"
74f08c3bdfSopenharmony_ci#define DEFAULT_LOGFILE		"sched_tc6.log"
75f08c3bdfSopenharmony_ci#define BLOCK_SIZE		512
76f08c3bdfSopenharmony_ci#define TIMES			10
77f08c3bdfSopenharmony_ci#define MAX_TRIES		20
78f08c3bdfSopenharmony_ci#define NAPTIME			1
79f08c3bdfSopenharmony_ci#define REAL_TIME		"1"
80f08c3bdfSopenharmony_ci#define NO_FORK			"0"
81f08c3bdfSopenharmony_ci#define USAGE "Usage:  %s  [-l log] [-t type] [-p priority] [-f] [-v] [-d]\n" \
82f08c3bdfSopenharmony_ci              "        -l log      log file                             \n" \
83f08c3bdfSopenharmony_ci              "        -t type     priority type 'variable' or 'fixed'  \n" \
84f08c3bdfSopenharmony_ci              "        -p priority priority value                       \n" \
85f08c3bdfSopenharmony_ci              "        -f          fork child                           \n" \
86f08c3bdfSopenharmony_ci              "        -v          verbose                              \n" \
87f08c3bdfSopenharmony_ci              "        -d          enable debugging messages            \n"
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci/*
90f08c3bdfSopenharmony_ci * Function prototypes:
91f08c3bdfSopenharmony_ci *
92f08c3bdfSopenharmony_ci * process_file: reads data file
93f08c3bdfSopenharmony_ci *
94f08c3bdfSopenharmony_ci * parse_args: parse command line arguments
95f08c3bdfSopenharmony_ci */
96f08c3bdfSopenharmony_civoid parse_args(int, char **);
97f08c3bdfSopenharmony_ciint fork_realtime(char **);
98f08c3bdfSopenharmony_ciint read_file(int, char *);
99f08c3bdfSopenharmony_ciint lock_file(int, short, char *);
100f08c3bdfSopenharmony_ciint unlock_file(int, char *);
101f08c3bdfSopenharmony_ciint lock_error(int, char *);
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci/*
104f08c3bdfSopenharmony_ci * Global variables:
105f08c3bdfSopenharmony_ci *
106f08c3bdfSopenharmony_ci * verbose: enable normal messages
107f08c3bdfSopenharmony_ci *
108f08c3bdfSopenharmony_ci * debug: enable debugging messages
109f08c3bdfSopenharmony_ci *
110f08c3bdfSopenharmony_ci * priority: process type (fixed priority, variable priority)
111f08c3bdfSopenharmony_ci */
112f08c3bdfSopenharmony_ciint verbose = 0;
113f08c3bdfSopenharmony_ciint debug = 0;
114f08c3bdfSopenharmony_ciint fork_flag = 0;
115f08c3bdfSopenharmony_ciint priority = DEFAULT_PRIORITY;
116f08c3bdfSopenharmony_cichar *logfile = DEFAULT_LOGFILE;
117f08c3bdfSopenharmony_cichar *priority_type = DEFAULT_PRIORITY_TYPE;
118f08c3bdfSopenharmony_cistruct flock flock_struct;
119f08c3bdfSopenharmony_cistruct flock *flock_ptr = &flock_struct;
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ciint open_file(char *, int);
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
124f08c3bdfSopenharmony_ci|                                 main                                 |
125f08c3bdfSopenharmony_ci| ==================================================================== |
126f08c3bdfSopenharmony_ci|                                                                      |
127f08c3bdfSopenharmony_ci| Function:  ...                                                       |
128f08c3bdfSopenharmony_ci|                                                                      |
129f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
130f08c3bdfSopenharmony_ciint main(int argc, char **argv)
131f08c3bdfSopenharmony_ci{
132f08c3bdfSopenharmony_ci	char *filename = NULL;
133f08c3bdfSopenharmony_ci	FILE *statfile;
134f08c3bdfSopenharmony_ci	pid_t pid = 0;
135f08c3bdfSopenharmony_ci	int fd;
136f08c3bdfSopenharmony_ci	int rc;
137f08c3bdfSopenharmony_ci	clock_t start_time;	/* start & stop times */
138f08c3bdfSopenharmony_ci	clock_t stop_time;
139f08c3bdfSopenharmony_ci	float elapsed_time;
140f08c3bdfSopenharmony_ci#ifdef __linux__
141f08c3bdfSopenharmony_ci	time_t timer_info;
142f08c3bdfSopenharmony_ci#else
143f08c3bdfSopenharmony_ci	struct tms timer_info;	/* time accounting info */
144f08c3bdfSopenharmony_ci#endif
145f08c3bdfSopenharmony_ci
146f08c3bdfSopenharmony_ci	if ((filename = getenv("KERNEL")) == NULL) {
147f08c3bdfSopenharmony_ci		errno = ENODATA;
148f08c3bdfSopenharmony_ci		sys_error("environment variable KERNEL not set", __FILE__,
149f08c3bdfSopenharmony_ci			  __LINE__);
150f08c3bdfSopenharmony_ci	}
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_ci	/* Process command line arguments...  */
153f08c3bdfSopenharmony_ci	parse_args(argc, argv);
154f08c3bdfSopenharmony_ci	if (verbose)
155f08c3bdfSopenharmony_ci		printf("%s: Scheduler TestSuite program\n\n", *argv);
156f08c3bdfSopenharmony_ci	if (debug) {
157f08c3bdfSopenharmony_ci		printf("\tpriority type:  %s\n", priority_type);
158f08c3bdfSopenharmony_ci		printf("\tpriority:       %d\n", priority);
159f08c3bdfSopenharmony_ci		printf("\tlogfile:        %s\n", logfile);
160f08c3bdfSopenharmony_ci	}
161f08c3bdfSopenharmony_ci
162f08c3bdfSopenharmony_ci	/* Adjust the priority of this process if the real time flag is set */
163f08c3bdfSopenharmony_ci	if (!strcmp(priority_type, "fixed")) {
164f08c3bdfSopenharmony_ci#ifndef __linux__
165f08c3bdfSopenharmony_ci		if (setpri(0, DEFAULT_PRIORITY) < 0)
166f08c3bdfSopenharmony_ci			sys_error("setpri failed", __FILE__, __LINE__);
167f08c3bdfSopenharmony_ci#else
168f08c3bdfSopenharmony_ci		if (setpriority(PRIO_PROCESS, 0, 0) < 0)
169f08c3bdfSopenharmony_ci			sys_error("setpri failed", __FILE__, __LINE__);
170f08c3bdfSopenharmony_ci#endif
171f08c3bdfSopenharmony_ci	} else {
172f08c3bdfSopenharmony_ci		if (nice((priority - 50) - (nice(0) + 20)) < 0 && errno != 0)
173f08c3bdfSopenharmony_ci			sys_error("nice failed", __FILE__, __LINE__);
174f08c3bdfSopenharmony_ci	}
175f08c3bdfSopenharmony_ci
176f08c3bdfSopenharmony_ci	/* Read from raw I/O device and record elapsed time...  */
177f08c3bdfSopenharmony_ci	start_time = time(&timer_info);
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ci	/* Open and lock file file...  */
180f08c3bdfSopenharmony_ci	fd = open_file(filename, O_RDWR);
181f08c3bdfSopenharmony_ci	if (!lock_file(fd, F_WRLCK, filename))	/* set exclusive lock */
182f08c3bdfSopenharmony_ci		error("lock_file failed", __FILE__, __LINE__);
183f08c3bdfSopenharmony_ci
184f08c3bdfSopenharmony_ci	/* If fork flag set, fork a real process */
185f08c3bdfSopenharmony_ci	if (fork_flag)
186f08c3bdfSopenharmony_ci		pid = fork_realtime(argv);
187f08c3bdfSopenharmony_ci
188f08c3bdfSopenharmony_ci	/* Read file */
189f08c3bdfSopenharmony_ci	if (debug) {
190f08c3bdfSopenharmony_ci		printf("\tprocess id %d successfully locked %s\n",
191f08c3bdfSopenharmony_ci		       getpid(), filename);
192f08c3bdfSopenharmony_ci		printf("\tprocess id %d starting to read %s\n",
193f08c3bdfSopenharmony_ci		       getpid(), filename);
194f08c3bdfSopenharmony_ci	}
195f08c3bdfSopenharmony_ci
196f08c3bdfSopenharmony_ci	if (!read_file(fd, filename))
197f08c3bdfSopenharmony_ci		error("read_file failed", __FILE__, __LINE__);
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci	/* Stop the timer and calculate the elapsed time */
200f08c3bdfSopenharmony_ci	stop_time = time(&timer_info);
201f08c3bdfSopenharmony_ci	elapsed_time = (float)(stop_time - start_time) / 100.0;
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_ci	/* Write the elapsed time to the temporary file...  */
204f08c3bdfSopenharmony_ci	if ((statfile = fopen(logfile, "w")) == NULL)
205f08c3bdfSopenharmony_ci		sys_error("fopen failed", __FILE__, __LINE__);
206f08c3bdfSopenharmony_ci
207f08c3bdfSopenharmony_ci	fprintf(statfile, "%f\n", elapsed_time);
208f08c3bdfSopenharmony_ci	if (debug)
209f08c3bdfSopenharmony_ci		printf("\n\telapsed time: %f\n", elapsed_time);
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	if (fclose(statfile) < 0)
212f08c3bdfSopenharmony_ci		sys_error("fclose failed", __FILE__, __LINE__);
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ci	/* Unlock file at latest possible time to prevent real time child from
215f08c3bdfSopenharmony_ci	 * writing throughput results before user process parent */
216f08c3bdfSopenharmony_ci	unlock_file(fd, filename);
217f08c3bdfSopenharmony_ci	close(fd);
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ci	if (debug)
220f08c3bdfSopenharmony_ci		printf("\tprocess id %d completed read and unlocked file\n",
221f08c3bdfSopenharmony_ci		       getpid());
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci	/* The parent waits for child process to complete before exiting
224f08c3bdfSopenharmony_ci	 * so the driver will not read the throughput results file before
225f08c3bdfSopenharmony_ci	 * child writes to the file */
226f08c3bdfSopenharmony_ci	if (pid != 0) {		/* if parent process ... *//* wait for child process */
227f08c3bdfSopenharmony_ci		if (debug)
228f08c3bdfSopenharmony_ci			printf
229f08c3bdfSopenharmony_ci			    ("parent waiting on child process %d to complete\n",
230f08c3bdfSopenharmony_ci			     pid);
231f08c3bdfSopenharmony_ci
232f08c3bdfSopenharmony_ci		while ((rc = wait(NULL)) != pid)
233f08c3bdfSopenharmony_ci			if (rc == -1)
234f08c3bdfSopenharmony_ci				sys_error("wait failed", __FILE__, __LINE__);
235f08c3bdfSopenharmony_ci/*
236f08c3bdfSopenharmony_ciDARA: which one to use
237f08c3bdfSopenharmony_ci1st -- hangs
238f08c3bdfSopenharmony_ci2nd -- ERROR message
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ci	    while (wait((void *) 0) != pid) ;
241f08c3bdfSopenharmony_ci	    while ((rc=wait ((void *) 0)) != pid)
242f08c3bdfSopenharmony_ci	       if (rc == -1)
243f08c3bdfSopenharmony_ci	          sys_error ("wait failed", __FILE__, __LINE__);
244f08c3bdfSopenharmony_ci*/
245f08c3bdfSopenharmony_ci	}
246f08c3bdfSopenharmony_ci
247f08c3bdfSopenharmony_ci	/* Exit with success! */
248f08c3bdfSopenharmony_ci	if (verbose)
249f08c3bdfSopenharmony_ci		printf("\nsuccessful!\n");
250f08c3bdfSopenharmony_ci	return (0);
251f08c3bdfSopenharmony_ci}
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
254f08c3bdfSopenharmony_ci|                             open_file ()                             |
255f08c3bdfSopenharmony_ci| ==================================================================== |
256f08c3bdfSopenharmony_ci|                                                                      |
257f08c3bdfSopenharmony_ci| Function:  ...                                                       |
258f08c3bdfSopenharmony_ci|                                                                      |
259f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
260f08c3bdfSopenharmony_ciint open_file(char *file, int open_mode)
261f08c3bdfSopenharmony_ci{
262f08c3bdfSopenharmony_ci	int file_desc;
263f08c3bdfSopenharmony_ci
264f08c3bdfSopenharmony_ci	if ((file_desc = open(file, open_mode)) < 0)
265f08c3bdfSopenharmony_ci		sys_error("open failed", __FILE__, __LINE__);
266f08c3bdfSopenharmony_ci	return (file_desc);
267f08c3bdfSopenharmony_ci}
268f08c3bdfSopenharmony_ci
269f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
270f08c3bdfSopenharmony_ci|                           fork_realtime ()                           |
271f08c3bdfSopenharmony_ci| ==================================================================== |
272f08c3bdfSopenharmony_ci|                                                                      |
273f08c3bdfSopenharmony_ci| Function:  ...                                                       |
274f08c3bdfSopenharmony_ci|                                                                      |
275f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
276f08c3bdfSopenharmony_ciint fork_realtime(char **args)
277f08c3bdfSopenharmony_ci{
278f08c3bdfSopenharmony_ci	int pid;
279f08c3bdfSopenharmony_ci	char *results_file = args[2];
280f08c3bdfSopenharmony_ci	char *priority = args[3];
281f08c3bdfSopenharmony_ci
282f08c3bdfSopenharmony_ci	/* fork process then determine if process is parent or child */
283f08c3bdfSopenharmony_ci	pid = fork();
284f08c3bdfSopenharmony_ci	switch (pid) {
285f08c3bdfSopenharmony_ci		/* fork failed  */
286f08c3bdfSopenharmony_ci	case -1:
287f08c3bdfSopenharmony_ci		sys_error("fork failed", __FILE__, __LINE__);
288f08c3bdfSopenharmony_ci
289f08c3bdfSopenharmony_ci		/* child process */
290f08c3bdfSopenharmony_ci	case 0:
291f08c3bdfSopenharmony_ci		if (execl(*args, *args, REAL_TIME, results_file, priority,
292f08c3bdfSopenharmony_ci			  NO_FORK, NULL) < 0)
293f08c3bdfSopenharmony_ci			sys_error("execl failed", __FILE__, __LINE__);
294f08c3bdfSopenharmony_ci
295f08c3bdfSopenharmony_ci		/* parent process */
296f08c3bdfSopenharmony_ci	default:
297f08c3bdfSopenharmony_ci#ifdef DEBUG
298f08c3bdfSopenharmony_ci		printf("\tparent process id = %d\n", getpid());
299f08c3bdfSopenharmony_ci		printf("\tchild process id = %d\n\n", pid);
300f08c3bdfSopenharmony_ci#endif
301f08c3bdfSopenharmony_ci
302f08c3bdfSopenharmony_ci		break;
303f08c3bdfSopenharmony_ci	}
304f08c3bdfSopenharmony_ci	return (pid);
305f08c3bdfSopenharmony_ci}
306f08c3bdfSopenharmony_ci
307f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
308f08c3bdfSopenharmony_ci|                             read_file ()                             |
309f08c3bdfSopenharmony_ci| ==================================================================== |
310f08c3bdfSopenharmony_ci|                                                                      |
311f08c3bdfSopenharmony_ci| Function:  ...                                                       |
312f08c3bdfSopenharmony_ci|                                                                      |
313f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
314f08c3bdfSopenharmony_ciint read_file(int fd, char *filename)
315f08c3bdfSopenharmony_ci{
316f08c3bdfSopenharmony_ci	int bytes_read;
317f08c3bdfSopenharmony_ci	int loop_count;
318f08c3bdfSopenharmony_ci	long total_bytes;
319f08c3bdfSopenharmony_ci	off_t lseek();
320f08c3bdfSopenharmony_ci	off_t file_offset = 0;
321f08c3bdfSopenharmony_ci	int whence = 0;
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_ci	char buf[BLOCK_SIZE];
324f08c3bdfSopenharmony_ci
325f08c3bdfSopenharmony_ci	/* read file for "TIMES" number of times */
326f08c3bdfSopenharmony_ci	total_bytes = 0;
327f08c3bdfSopenharmony_ci	if (debug)
328f08c3bdfSopenharmony_ci		printf("\n");
329f08c3bdfSopenharmony_ci	for (loop_count = 1; loop_count <= TIMES; loop_count++) {
330f08c3bdfSopenharmony_ci		while ((bytes_read = read(fd, buf, BLOCK_SIZE)) > 0) {
331f08c3bdfSopenharmony_ci			if (bytes_read == -1) {
332f08c3bdfSopenharmony_ci				sys_error("read failed", __FILE__, __LINE__);
333f08c3bdfSopenharmony_ci			} else
334f08c3bdfSopenharmony_ci				total_bytes = total_bytes + bytes_read;
335f08c3bdfSopenharmony_ci		}
336f08c3bdfSopenharmony_ci		if (lseek(fd, file_offset, whence) < 0)
337f08c3bdfSopenharmony_ci			sys_error("lseek failed", __FILE__, __LINE__);
338f08c3bdfSopenharmony_ci
339f08c3bdfSopenharmony_ci		if (debug) {
340f08c3bdfSopenharmony_ci			printf("\r\ttotal bytes read = %ld", total_bytes);
341f08c3bdfSopenharmony_ci			fflush(stdout);
342f08c3bdfSopenharmony_ci		}
343f08c3bdfSopenharmony_ci		total_bytes = 0;
344f08c3bdfSopenharmony_ci	}
345f08c3bdfSopenharmony_ci	if (debug)
346f08c3bdfSopenharmony_ci		printf("\n");
347f08c3bdfSopenharmony_ci	return 1;
348f08c3bdfSopenharmony_ci}
349f08c3bdfSopenharmony_ci
350f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
351f08c3bdfSopenharmony_ci|                             lock_file ()                             |
352f08c3bdfSopenharmony_ci| ==================================================================== |
353f08c3bdfSopenharmony_ci|                                                                      |
354f08c3bdfSopenharmony_ci| Function:  ...                                                       |
355f08c3bdfSopenharmony_ci|                                                                      |
356f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
357f08c3bdfSopenharmony_ciint lock_file(int fd, short lock_type, char *file)
358f08c3bdfSopenharmony_ci{
359f08c3bdfSopenharmony_ci	int lock_attempt = 1;
360f08c3bdfSopenharmony_ci	int lock_mode;
361f08c3bdfSopenharmony_ci
362f08c3bdfSopenharmony_ci#ifdef DEBUG
363f08c3bdfSopenharmony_ci	lock_mode = F_SETLK;	/* return if lock fails        */
364f08c3bdfSopenharmony_ci#else
365f08c3bdfSopenharmony_ci	lock_mode = F_SETLKW;	/* set lock and use system wait */
366f08c3bdfSopenharmony_ci#endif
367f08c3bdfSopenharmony_ci
368f08c3bdfSopenharmony_ci	/* file segment locking set data type flock - information
369f08c3bdfSopenharmony_ci	 * passed to system by user --
370f08c3bdfSopenharmony_ci	 *   l_whence:  starting point of relative offset of file
371f08c3bdfSopenharmony_ci	 *   l_start:   defines relative offset in bytes from l_whence
372f08c3bdfSopenharmony_ci	 *   l_len:     number of consecutive bytes to be locked
373f08c3bdfSopenharmony_ci	 */
374f08c3bdfSopenharmony_ci	flock_ptr->l_whence = 0;
375f08c3bdfSopenharmony_ci	flock_ptr->l_start = 0;
376f08c3bdfSopenharmony_ci	flock_ptr->l_len = 0;
377f08c3bdfSopenharmony_ci	flock_ptr->l_type = lock_type;
378f08c3bdfSopenharmony_ci
379f08c3bdfSopenharmony_ci	while (fcntl(fd, lock_mode, flock_ptr) == -1) {
380f08c3bdfSopenharmony_ci		if (lock_error(fd, file)) {
381f08c3bdfSopenharmony_ci			sleep(NAPTIME);
382f08c3bdfSopenharmony_ci			if (++lock_attempt > MAX_TRIES) {
383f08c3bdfSopenharmony_ci				printf
384f08c3bdfSopenharmony_ci				    ("ERROR: max lock attempts of %d reached\n",
385f08c3bdfSopenharmony_ci				     MAX_TRIES);
386f08c3bdfSopenharmony_ci				return (0);
387f08c3bdfSopenharmony_ci			}
388f08c3bdfSopenharmony_ci		} else
389f08c3bdfSopenharmony_ci			return (0);
390f08c3bdfSopenharmony_ci	}
391f08c3bdfSopenharmony_ci	return (1);
392f08c3bdfSopenharmony_ci}
393f08c3bdfSopenharmony_ci
394f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
395f08c3bdfSopenharmony_ci|                            unlock_file ()                            |
396f08c3bdfSopenharmony_ci| ==================================================================== |
397f08c3bdfSopenharmony_ci|                                                                      |
398f08c3bdfSopenharmony_ci| Function:  ...                                                       |
399f08c3bdfSopenharmony_ci|                                                                      |
400f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
401f08c3bdfSopenharmony_ciint unlock_file(int fd, char *file)
402f08c3bdfSopenharmony_ci{
403f08c3bdfSopenharmony_ci	flock_ptr->l_type = F_UNLCK;
404f08c3bdfSopenharmony_ci
405f08c3bdfSopenharmony_ci	if (fcntl(fd, F_SETLK, flock_ptr) < 0)
406f08c3bdfSopenharmony_ci		sys_error("fcntl failed", __FILE__, __LINE__);
407f08c3bdfSopenharmony_ci
408f08c3bdfSopenharmony_ci	return 1;
409f08c3bdfSopenharmony_ci}
410f08c3bdfSopenharmony_ci
411f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
412f08c3bdfSopenharmony_ci|                                 main                                 |
413f08c3bdfSopenharmony_ci| ==================================================================== |
414f08c3bdfSopenharmony_ci|                                                                      |
415f08c3bdfSopenharmony_ci| Function:  ...                                                       |
416f08c3bdfSopenharmony_ci|                                                                      |
417f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
418f08c3bdfSopenharmony_ciint lock_error(int fd, char *file)
419f08c3bdfSopenharmony_ci{
420f08c3bdfSopenharmony_ci	int ret = 1;
421f08c3bdfSopenharmony_ci
422f08c3bdfSopenharmony_ci	printf("ERROR:  lock failed: %s\n", file);
423f08c3bdfSopenharmony_ci	switch (errno) {
424f08c3bdfSopenharmony_ci	case EACCES:		/* access not allowed */
425f08c3bdfSopenharmony_ci		fcntl(fd, F_GETLK, flock_ptr);
426f08c3bdfSopenharmony_ci#ifndef __linux__
427f08c3bdfSopenharmony_ci		printf("ERROR: lock exists - nid: %lX pid: %ld\n",
428f08c3bdfSopenharmony_ci		       flock_ptr->l_sysid, flock_ptr->l_pid);
429f08c3bdfSopenharmony_ci#else
430f08c3bdfSopenharmony_ci		printf("ERROR: lock exists - nid:\n");
431f08c3bdfSopenharmony_ci#endif
432f08c3bdfSopenharmony_ci		break;
433f08c3bdfSopenharmony_ci
434f08c3bdfSopenharmony_ci		/*
435f08c3bdfSopenharmony_ci		 * This was a DS error code, and DS does not exist V3.1
436f08c3bdfSopenharmony_ci		 */
437f08c3bdfSopenharmony_ci#ifndef __linux__
438f08c3bdfSopenharmony_ci	case EDIST:		/* DS file server blocking requests */
439f08c3bdfSopenharmony_ci		printf("ERROR: errno == EDIST\n");
440f08c3bdfSopenharmony_ci		printf("The server has blocked new inbound requests\n");
441f08c3bdfSopenharmony_ci		printf("or outbound requests are currently blocked.\n");
442f08c3bdfSopenharmony_ci		break;
443f08c3bdfSopenharmony_ci#endif
444f08c3bdfSopenharmony_ci
445f08c3bdfSopenharmony_ci	case EAGAIN:		/* server too busy */
446f08c3bdfSopenharmony_ci		printf("ERROR:  Server too busy to accept the request\n");
447f08c3bdfSopenharmony_ci		break;
448f08c3bdfSopenharmony_ci
449f08c3bdfSopenharmony_ci	case EDEADLK:		/* only when F_SETLKW cmd is used */
450f08c3bdfSopenharmony_ci		printf("ERROR:  Putting the calling process to sleep\n");
451f08c3bdfSopenharmony_ci		printf("would cause a dead lock\n");
452f08c3bdfSopenharmony_ci		ret = 0;
453f08c3bdfSopenharmony_ci		break;
454f08c3bdfSopenharmony_ci
455f08c3bdfSopenharmony_ci	case ENOLCK:		/* out of locks */
456f08c3bdfSopenharmony_ci		printf("ERROR: No more file locks available\n");
457f08c3bdfSopenharmony_ci		ret = 0;
458f08c3bdfSopenharmony_ci		break;
459f08c3bdfSopenharmony_ci
460f08c3bdfSopenharmony_ci	case ENOMEM:		/* out of memory */
461f08c3bdfSopenharmony_ci		printf("ERROR: The server or client does not have enough\n");
462f08c3bdfSopenharmony_ci		printf("memory to service the request.\n");
463f08c3bdfSopenharmony_ci		ret = 0;
464f08c3bdfSopenharmony_ci		break;
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci	default:		/* miscellaneous errors */
467f08c3bdfSopenharmony_ci		printf("ERROR: Unknown lock error\n");
468f08c3bdfSopenharmony_ci		perror("reason");
469f08c3bdfSopenharmony_ci		ret = 0;
470f08c3bdfSopenharmony_ci		break;
471f08c3bdfSopenharmony_ci	}
472f08c3bdfSopenharmony_ci
473f08c3bdfSopenharmony_ci	printf("errno = %d\n", errno);	/* log the errno value */
474f08c3bdfSopenharmony_ci	sleep(10);
475f08c3bdfSopenharmony_ci
476f08c3bdfSopenharmony_ci	return (ret);
477f08c3bdfSopenharmony_ci}
478f08c3bdfSopenharmony_ci
479f08c3bdfSopenharmony_ci/*---------------------------------------------------------------------+
480f08c3bdfSopenharmony_ci|                             parse_args ()                            |
481f08c3bdfSopenharmony_ci| ==================================================================== |
482f08c3bdfSopenharmony_ci|                                                                      |
483f08c3bdfSopenharmony_ci| Function:  Parse the command line arguments & initialize global      |
484f08c3bdfSopenharmony_ci|            variables.                                                |
485f08c3bdfSopenharmony_ci|                                                                      |
486f08c3bdfSopenharmony_ci| Updates:   (command line options)                                    |
487f08c3bdfSopenharmony_ci|                                                                      |
488f08c3bdfSopenharmony_ci|            [-t] type:     priority type "fixed" or "variable"        |
489f08c3bdfSopenharmony_ci|            [-p] priority: priority value                             |
490f08c3bdfSopenharmony_ci|            [-l] logfile:  log file name                              |
491f08c3bdfSopenharmony_ci|            [-v]           verbose                                    |
492f08c3bdfSopenharmony_ci|            [-d]           enable debugging messages                  |
493f08c3bdfSopenharmony_ci|                                                                      |
494f08c3bdfSopenharmony_ci+---------------------------------------------------------------------*/
495f08c3bdfSopenharmony_civoid parse_args(int argc, char **argv)
496f08c3bdfSopenharmony_ci{
497f08c3bdfSopenharmony_ci	int opt;
498f08c3bdfSopenharmony_ci	int lflg = 0, pflg = 0, tflg = 0;
499f08c3bdfSopenharmony_ci	int errflag = 0;
500f08c3bdfSopenharmony_ci	char *program_name = *argv;
501f08c3bdfSopenharmony_ci	extern char *optarg;	/* Command line option */
502f08c3bdfSopenharmony_ci
503f08c3bdfSopenharmony_ci	/*
504f08c3bdfSopenharmony_ci	 * Parse command line options.
505f08c3bdfSopenharmony_ci	 */
506f08c3bdfSopenharmony_ci	while ((opt = getopt(argc, argv, "fl:t:p:vd")) != EOF) {
507f08c3bdfSopenharmony_ci		switch (opt) {
508f08c3bdfSopenharmony_ci		case 'f':	/* fork flag */
509f08c3bdfSopenharmony_ci			fork_flag++;
510f08c3bdfSopenharmony_ci			break;
511f08c3bdfSopenharmony_ci		case 'l':	/* log file */
512f08c3bdfSopenharmony_ci			lflg++;
513f08c3bdfSopenharmony_ci			logfile = optarg;
514f08c3bdfSopenharmony_ci			break;
515f08c3bdfSopenharmony_ci		case 't':	/* process type */
516f08c3bdfSopenharmony_ci			tflg++;
517f08c3bdfSopenharmony_ci			priority_type = optarg;
518f08c3bdfSopenharmony_ci			break;
519f08c3bdfSopenharmony_ci		case 'p':	/* process priority */
520f08c3bdfSopenharmony_ci			pflg++;
521f08c3bdfSopenharmony_ci			priority = atoi(optarg);
522f08c3bdfSopenharmony_ci			break;
523f08c3bdfSopenharmony_ci		case 'v':	/* verbose */
524f08c3bdfSopenharmony_ci			verbose++;
525f08c3bdfSopenharmony_ci			break;
526f08c3bdfSopenharmony_ci		case 'd':	/* enable debugging messages */
527f08c3bdfSopenharmony_ci			verbose++;
528f08c3bdfSopenharmony_ci			debug++;
529f08c3bdfSopenharmony_ci			break;
530f08c3bdfSopenharmony_ci		default:
531f08c3bdfSopenharmony_ci			errflag++;
532f08c3bdfSopenharmony_ci			break;
533f08c3bdfSopenharmony_ci		}
534f08c3bdfSopenharmony_ci	}
535f08c3bdfSopenharmony_ci
536f08c3bdfSopenharmony_ci	/*
537f08c3bdfSopenharmony_ci	 * Check percentage and process slots...
538f08c3bdfSopenharmony_ci	 */
539f08c3bdfSopenharmony_ci	if (tflg) {
540f08c3bdfSopenharmony_ci		if (strcmp(priority_type, "fixed") &&
541f08c3bdfSopenharmony_ci		    strcmp(priority_type, "variable")) {
542f08c3bdfSopenharmony_ci			errflag++;
543f08c3bdfSopenharmony_ci			fprintf(stderr, "Error: priority type must be: "
544f08c3bdfSopenharmony_ci				"\'fixed\' or \'variable\'\n");
545f08c3bdfSopenharmony_ci		}
546f08c3bdfSopenharmony_ci	}
547f08c3bdfSopenharmony_ci	if (pflg) {
548f08c3bdfSopenharmony_ci		if (priority < 50 || priority > 100) {
549f08c3bdfSopenharmony_ci			errflag++;
550f08c3bdfSopenharmony_ci			fprintf(stderr, "Error: priority range [50..100]\n");
551f08c3bdfSopenharmony_ci		}
552f08c3bdfSopenharmony_ci	}
553f08c3bdfSopenharmony_ci	if (errflag) {
554f08c3bdfSopenharmony_ci		fprintf(stderr, USAGE, program_name);
555f08c3bdfSopenharmony_ci		exit(2);
556f08c3bdfSopenharmony_ci	}
557f08c3bdfSopenharmony_ci}
558