1f08c3bdfSopenharmony_ci/******************************************************************************/
2f08c3bdfSopenharmony_ci/*									      */
3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines  Corp., 2001		      */
4f08c3bdfSopenharmony_ci/*									      */
5f08c3bdfSopenharmony_ci/* This program is free software;  you can redistribute it and/or modify      */
6f08c3bdfSopenharmony_ci/* it under the terms of the GNU General Public License as published by       */
7f08c3bdfSopenharmony_ci/* the Free Software Foundation; either version 2 of the License, or          */
8f08c3bdfSopenharmony_ci/* (at your option) any later version.					      */
9f08c3bdfSopenharmony_ci/*									      */
10f08c3bdfSopenharmony_ci/* This program is distributed in the hope that it will be useful,	      */
11f08c3bdfSopenharmony_ci/* but WITHOUT ANY WARRANTY;  without even the implied warranty of	      */
12f08c3bdfSopenharmony_ci/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	              */
13f08c3bdfSopenharmony_ci/* the GNU General Public License for more details.			      */
14f08c3bdfSopenharmony_ci/*									      */
15f08c3bdfSopenharmony_ci/* You should have received a copy of the GNU General Public License	      */
16f08c3bdfSopenharmony_ci/* along with this program;  if not, write to the Free Software		      */
17f08c3bdfSopenharmony_ci/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
18f08c3bdfSopenharmony_ci/*									      */
19f08c3bdfSopenharmony_ci/******************************************************************************/
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci/******************************************************************************/
22f08c3bdfSopenharmony_ci/*			                                                      */
23f08c3bdfSopenharmony_ci/* History:	Feb - 21 - 2002 Created - Manoj Iyer, IBM Austin TX.          */
24f08c3bdfSopenharmony_ci/*				          email: manjo@austin.ibm.com.        */
25f08c3bdfSopenharmony_ci/*			                                                      */
26f08c3bdfSopenharmony_ci/* 		Feb - 25 - 2002 Modified - Manoj Iyer, IBM Austin TX.         */
27f08c3bdfSopenharmony_ci/*		                - Added structure thread_sched_t.             */
28f08c3bdfSopenharmony_ci/*				- Added logic to specify scheduling policy.   */
29f08c3bdfSopenharmony_ci/*			                                                      */
30f08c3bdfSopenharmony_ci/*		Feb - 25 - 2002 Modified - Manoj Iyer, IBM Austin TX.         */
31f08c3bdfSopenharmony_ci/*				- Added header file string.h.	              */
32f08c3bdfSopenharmony_ci/*				- Removed dead variable ppid from thread_func.*/
33f08c3bdfSopenharmony_ci/*				- Fixed date from 2001 to 2002 in History.    */
34f08c3bdfSopenharmony_ci/*			                                                      */
35f08c3bdfSopenharmony_ci/* File:	trace_sched.c						      */
36f08c3bdfSopenharmony_ci/*			                                                      */
37f08c3bdfSopenharmony_ci/* Description:	This utility spawns N tasks, each task sets its priority by   */
38f08c3bdfSopenharmony_ci/*		making a system call to the scheduler. The thread function    */
39f08c3bdfSopenharmony_ci/*		reads the priority that tbe schedular sets for this task and  */
40f08c3bdfSopenharmony_ci/*		also reads from /proc the processor this task last executed on*/
41f08c3bdfSopenharmony_ci/*		the information that is gathered by the thread function may   */
42f08c3bdfSopenharmony_ci/*		be in real-time. Its only an approximation.                   */
43f08c3bdfSopenharmony_ci/*			                                                      */
44f08c3bdfSopenharmony_ci/******************************************************************************/
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci#include <fcntl.h>
47f08c3bdfSopenharmony_ci#include <limits.h>
48f08c3bdfSopenharmony_ci#include <pthread.h>
49f08c3bdfSopenharmony_ci#include <stdio.h>
50f08c3bdfSopenharmony_ci#include <stdlib.h>
51f08c3bdfSopenharmony_ci#include <sched.h>
52f08c3bdfSopenharmony_ci#include <sys/types.h>
53f08c3bdfSopenharmony_ci#include <sys/stat.h>
54f08c3bdfSopenharmony_ci#include <sys/wait.h>
55f08c3bdfSopenharmony_ci#include <sys/time.h>
56f08c3bdfSopenharmony_ci#include <unistd.h>
57f08c3bdfSopenharmony_ci#include <string.h>
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_civoid noprintf(char *string, ...)
60f08c3bdfSopenharmony_ci{
61f08c3bdfSopenharmony_ci}
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_ci#ifdef DEBUG			/* compile with this flag for debug, use dprt in code */
64f08c3bdfSopenharmony_ci#define dprt    printf
65f08c3bdfSopenharmony_ci#else
66f08c3bdfSopenharmony_ci#define dprt    noprintf
67f08c3bdfSopenharmony_ci#endif
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci#ifndef PID_MAX
70f08c3bdfSopenharmony_ci#define PID_MAX 0x8000
71f08c3bdfSopenharmony_ci#endif
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci#define MAXT 100
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci#ifdef PTHREAD_THREADS_MAX
76f08c3bdfSopenharmony_ci#define PIDS PTHREAD_THREADS_MAX	/* maximum thread allowed.                     */
77f08c3bdfSopenharmony_ci#elif defined(PID_MAX_DEFAULT)
78f08c3bdfSopenharmony_ci#define PIDS PID_MAX_DEFAULT	/* maximum pids allowed.                       */
79f08c3bdfSopenharmony_ci#else
80f08c3bdfSopenharmony_ci#define PIDS PID_MAX		/* alternative way maximum pids may be defined */
81f08c3bdfSopenharmony_ci#endif
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci#define UP   1			/* assume UP if no SMP value is specified.     */
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ci#define OPT_MISSING(prog, opt)   do{\
86f08c3bdfSopenharmony_ci                               fprintf(stderr, "%s: option -%c ", prog, opt); \
87f08c3bdfSopenharmony_ci                               fprintf(stderr, "requires an argument\n"); \
88f08c3bdfSopenharmony_ci                               usage(prog); \
89f08c3bdfSopenharmony_ci                                   } while (0)
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci#define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_citypedef struct {		/* contains priority and CPU info of the task.        */
94f08c3bdfSopenharmony_ci	int exp_prio;		/* priority that we wish to set.                      */
95f08c3bdfSopenharmony_ci	int act_prio;		/* priority set by the scheduler.                     */
96f08c3bdfSopenharmony_ci	int proc_num;		/* last processor on which this task executed.        */
97f08c3bdfSopenharmony_ci	int procs_id;		/* pid of this task.                                  */
98f08c3bdfSopenharmony_ci	int s_policy;		/* scheduling policy for the task.                    */
99f08c3bdfSopenharmony_ci} thread_sched_t;
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ciint verbose = 0;		/* set verbose printing, makes output look ugly!      */
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci/******************************************************************************/
104f08c3bdfSopenharmony_ci/*                                                                            */
105f08c3bdfSopenharmony_ci/* Function:    usage                                                         */
106f08c3bdfSopenharmony_ci/*                                                                            */
107f08c3bdfSopenharmony_ci/* Description: Print the usage message.                                      */
108f08c3bdfSopenharmony_ci/*                                                                            */
109f08c3bdfSopenharmony_ci/* Return:      exits with -1                                                 */
110f08c3bdfSopenharmony_ci/*                                                                            */
111f08c3bdfSopenharmony_ci/******************************************************************************/
112f08c3bdfSopenharmony_civoid usage(char *progname)
113f08c3bdfSopenharmony_ci{				/* name of this program                                 */
114f08c3bdfSopenharmony_ci	fprintf(stderr,
115f08c3bdfSopenharmony_ci		"Usage: %s -c NCPU -h -p [fifo:rr:other] -t THREADS -v\n"
116f08c3bdfSopenharmony_ci		"\t -c Number of CUPS in the machine. User MUST provide\n"
117f08c3bdfSopenharmony_ci		"\t -h Help!\n"
118f08c3bdfSopenharmony_ci		"\t -p Scheduling policy, choice: fifo, rr, other. Default: fifo\n"
119f08c3bdfSopenharmony_ci		"\t -t Number of threads to create.                Default: %d\n"
120f08c3bdfSopenharmony_ci		"\t -v Verbose out put, print ugly!.               Default: OFF\n",
121f08c3bdfSopenharmony_ci		progname, MAXT);
122f08c3bdfSopenharmony_ci	exit(-1);
123f08c3bdfSopenharmony_ci}
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_ci/******************************************************************************/
126f08c3bdfSopenharmony_ci/*                                                                            */
127f08c3bdfSopenharmony_ci/* Function:    get_proc_num                                                  */
128f08c3bdfSopenharmony_ci/*                                                                            */
129f08c3bdfSopenharmony_ci/* Description: Function reads the proc filesystem file /proc/<PID>/stat      */
130f08c3bdfSopenharmony_ci/*		gets the CPU number this process last executed on and returns */
131f08c3bdfSopenharmony_ci/*		Some hard assumptions were made regarding buffer sizes.       */
132f08c3bdfSopenharmony_ci/*                                                                            */
133f08c3bdfSopenharmony_ci/* Return:      exits with -1 - on error                                      */
134f08c3bdfSopenharmony_ci/*              CPU number - on success				              */
135f08c3bdfSopenharmony_ci/*                                                                            */
136f08c3bdfSopenharmony_ci/******************************************************************************/
137f08c3bdfSopenharmony_cistatic int get_proc_num(void)
138f08c3bdfSopenharmony_ci{
139f08c3bdfSopenharmony_ci	int fd = -1;		/* file descriptor of the /proc/<pid>/stat file.      */
140f08c3bdfSopenharmony_ci	int fsize = -1;		/* size of the /proc/<pid>/stat file.                 */
141f08c3bdfSopenharmony_ci	char filename[256];	/* buffer to hold the string /proc/<pid>/stat.        */
142f08c3bdfSopenharmony_ci	char fbuff[512];	/* contains the contents of the stat file.            */
143f08c3bdfSopenharmony_ci
144f08c3bdfSopenharmony_ci	/* get the name of the stat file for this process */
145f08c3bdfSopenharmony_ci	sprintf(filename, "/proc/%d/stat", getpid());
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ci	/* open the stat file and read the contents to a buffer */
148f08c3bdfSopenharmony_ci	if ((fd = open(filename, O_RDONLY)) == -1) {
149f08c3bdfSopenharmony_ci		perror("get_proc_num(): open()");
150f08c3bdfSopenharmony_ci		return -1;
151f08c3bdfSopenharmony_ci	}
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci	usleep(6);
154f08c3bdfSopenharmony_ci	sched_yield();
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ci	if ((fsize = read(fd, fbuff, 512)) == -1) {
157f08c3bdfSopenharmony_ci		perror("main(): read()");
158f08c3bdfSopenharmony_ci		return -1;
159f08c3bdfSopenharmony_ci	}
160f08c3bdfSopenharmony_ci
161f08c3bdfSopenharmony_ci	close(fd);
162f08c3bdfSopenharmony_ci	/* return the processor number last executed on. */
163f08c3bdfSopenharmony_ci	return atoi(&fbuff[fsize - 2]);
164f08c3bdfSopenharmony_ci}
165f08c3bdfSopenharmony_ci
166f08c3bdfSopenharmony_ci/******************************************************************************/
167f08c3bdfSopenharmony_ci/*                                                                            */
168f08c3bdfSopenharmony_ci/* Function:    thread_func                                                   */
169f08c3bdfSopenharmony_ci/*                                                                            */
170f08c3bdfSopenharmony_ci/* Description: This function is executed in the context of the new task that */
171f08c3bdfSopenharmony_ci/*		pthread_createi() will spawn. The (thread) task will get the  */
172f08c3bdfSopenharmony_ci/*		minimum and maximum static priority for this system, set the  */
173f08c3bdfSopenharmony_ci/*		priority of the current task to a random priority value if    */
174f08c3bdfSopenharmony_ci/*		the policy set if SCHED_FIFO or SCHED_RR. The priority if this*/
175f08c3bdfSopenharmony_ci/*		task that was assigned by the scheduler is got from making the*/
176f08c3bdfSopenharmony_ci/*		system call to sched_getscheduler(). The CPU number on which  */
177f08c3bdfSopenharmony_ci/*		the task was last seen is also recorded. All the above data is*/
178f08c3bdfSopenharmony_ci/*		returned to the calling routine in a structure thread_sched_t.*/
179f08c3bdfSopenharmony_ci/*                                                                            */
180f08c3bdfSopenharmony_ci/* Input:       thread_sched_t 						      */
181f08c3bdfSopenharmony_ci/*		    s_policy - scheduling policy for the task.                */
182f08c3bdfSopenharmony_ci/*                                                                            */
183f08c3bdfSopenharmony_ci/* Return:      thread_sched_t - on success.				      */
184f08c3bdfSopenharmony_ci/*		    exp_prio - random priority value to set.                  */
185f08c3bdfSopenharmony_ci/*		    act_prio - priority set by the scheduler.                 */
186f08c3bdfSopenharmony_ci/*		    proc_num - CPU number on which this task last executed.   */
187f08c3bdfSopenharmony_ci/*		    procs_id -  pid of this task.                             */
188f08c3bdfSopenharmony_ci/*                                                                            */
189f08c3bdfSopenharmony_ci/*		-1 	       - on error.                                    */
190f08c3bdfSopenharmony_ci/*                                                                            */
191f08c3bdfSopenharmony_ci/******************************************************************************/
192f08c3bdfSopenharmony_civoid *thread_func(void *args)
193f08c3bdfSopenharmony_ci{				/* arguments to the thread function           */
194f08c3bdfSopenharmony_ci	static int max_priority;	/* max possible priority for a process.       */
195f08c3bdfSopenharmony_ci	static int min_priority;	/* min possible priority for a process.       */
196f08c3bdfSopenharmony_ci	static int set_priority;	/* set the priority of the proc by this value. */
197f08c3bdfSopenharmony_ci	static int get_priority;	/* get the priority that is set for this proc. */
198f08c3bdfSopenharmony_ci	static int procnum;	/* processor number last executed on.         */
199f08c3bdfSopenharmony_ci	static int sched_policy;	/* scheduling policy as set by user/default   */
200f08c3bdfSopenharmony_ci	struct sched_param ssp;	/* set schedule priority.                     */
201f08c3bdfSopenharmony_ci	struct sched_param gsp;	/* gsp schedule priority.                     */
202f08c3bdfSopenharmony_ci	struct timeval tptr;	/* tptr.tv_usec will be used to seed srand.   */
203f08c3bdfSopenharmony_ci	thread_sched_t *locargptr =	/* local ptr to the arguments.                */
204f08c3bdfSopenharmony_ci	    (thread_sched_t *) args;
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci	/* Get the system max and min static priority for a process. */
207f08c3bdfSopenharmony_ci	if (((max_priority = sched_get_priority_max(SCHED_FIFO)) == -1) ||
208f08c3bdfSopenharmony_ci	    ((min_priority = sched_get_priority_min(SCHED_FIFO)) == -1)) {
209f08c3bdfSopenharmony_ci		fprintf(stderr, "failed to get static priority range\n");
210f08c3bdfSopenharmony_ci		dprt("pid[%d]: exiting with -1\n", getpid());
211f08c3bdfSopenharmony_ci		pthread_exit((void *)-1);
212f08c3bdfSopenharmony_ci	}
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ci	if ((sched_policy = locargptr->s_policy) == SCHED_OTHER)
215f08c3bdfSopenharmony_ci		ssp.sched_priority = 0;
216f08c3bdfSopenharmony_ci	else {
217f08c3bdfSopenharmony_ci		/* Set a random value between max_priority and min_priority */
218f08c3bdfSopenharmony_ci		gettimeofday(&tptr, NULL);
219f08c3bdfSopenharmony_ci		srand((unsigned int)tptr.tv_usec);
220f08c3bdfSopenharmony_ci		set_priority = (min_priority + (int)((float)max_priority
221f08c3bdfSopenharmony_ci						     * rand() / (RAND_MAX +
222f08c3bdfSopenharmony_ci								 1.0)));
223f08c3bdfSopenharmony_ci		ssp.sched_priority = set_priority;
224f08c3bdfSopenharmony_ci	}
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_ci	/* give other threads a chance */
227f08c3bdfSopenharmony_ci	usleep(8);
228f08c3bdfSopenharmony_ci
229f08c3bdfSopenharmony_ci	/* set a random priority value and check if this value was honoured. */
230f08c3bdfSopenharmony_ci	if ((sched_setscheduler(getpid(), sched_policy, &ssp)) == -1) {
231f08c3bdfSopenharmony_ci		perror("main(): sched_setscheduler()");
232f08c3bdfSopenharmony_ci		dprt("pid[%d]: exiting with -1\n", getpid());
233f08c3bdfSopenharmony_ci		pthread_exit((void *)-1);
234f08c3bdfSopenharmony_ci	}
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci	/* processor number this process last executed on */
237f08c3bdfSopenharmony_ci	if ((procnum = get_proc_num()) == -1) {
238f08c3bdfSopenharmony_ci		fprintf(stderr, "main(): get_proc_num() failed\n");
239f08c3bdfSopenharmony_ci		dprt("pid[%d]: exiting with -1\n", getpid());
240f08c3bdfSopenharmony_ci		pthread_exit((void *)-1);
241f08c3bdfSopenharmony_ci	}
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci	if ((get_priority = sched_getparam(getpid(), &gsp)) == -1) {
244f08c3bdfSopenharmony_ci		perror("main(): sched_setscheduler()");
245f08c3bdfSopenharmony_ci		dprt("pid[%d]: exiting with -1\n", getpid());
246f08c3bdfSopenharmony_ci		pthread_exit((void *)-1);
247f08c3bdfSopenharmony_ci	}
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ci	/* processor number this process last executed on */
250f08c3bdfSopenharmony_ci	if ((procnum = get_proc_num()) == -1) {
251f08c3bdfSopenharmony_ci		fprintf(stderr, "main(): get_proc_num() failed\n");
252f08c3bdfSopenharmony_ci		dprt("pid[%d]: exiting with -1\n", getpid());
253f08c3bdfSopenharmony_ci		pthread_exit((void *)-1);
254f08c3bdfSopenharmony_ci	}
255f08c3bdfSopenharmony_ci
256f08c3bdfSopenharmony_ci	if (verbose) {
257f08c3bdfSopenharmony_ci		fprintf(stdout,
258f08c3bdfSopenharmony_ci			"PID of this task         = %d\n"
259f08c3bdfSopenharmony_ci			"Max priority             = %d\n"
260f08c3bdfSopenharmony_ci			"Min priority             = %d\n"
261f08c3bdfSopenharmony_ci			"Expected priority        = %d\n"
262f08c3bdfSopenharmony_ci			"Actual assigned priority = %d\n"
263f08c3bdfSopenharmony_ci			"Processor last execed on = %d\n\n", getpid(),
264f08c3bdfSopenharmony_ci			max_priority, min_priority, set_priority,
265f08c3bdfSopenharmony_ci			gsp.sched_priority, procnum);
266f08c3bdfSopenharmony_ci	}
267f08c3bdfSopenharmony_ci
268f08c3bdfSopenharmony_ci	locargptr->exp_prio = set_priority;
269f08c3bdfSopenharmony_ci	locargptr->act_prio = gsp.sched_priority;
270f08c3bdfSopenharmony_ci	locargptr->proc_num = procnum;
271f08c3bdfSopenharmony_ci	locargptr->procs_id = getpid();
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_ci	dprt("pid[%d]: exiting with %ld\n", getpid(), locargptr);
274f08c3bdfSopenharmony_ci	pthread_exit((void *)locargptr);
275f08c3bdfSopenharmony_ci}
276f08c3bdfSopenharmony_ci
277f08c3bdfSopenharmony_ci/******************************************************************************/
278f08c3bdfSopenharmony_ci/*                                                                            */
279f08c3bdfSopenharmony_ci/* Function:    main						              */
280f08c3bdfSopenharmony_ci/*                                                                            */
281f08c3bdfSopenharmony_ci/* Description: Entry point of the program, parse options, check for their    */
282f08c3bdfSopenharmony_ci/*		validity, spawn N tasks, wait for them to return, in the end  */
283f08c3bdfSopenharmony_ci/*		print all the data that the thiread function collected.       */
284f08c3bdfSopenharmony_ci/*                                                                            */
285f08c3bdfSopenharmony_ci/* Return:      exits with -1 - on error.                                     */
286f08c3bdfSopenharmony_ci/*		exits with  0 - on success.				      */
287f08c3bdfSopenharmony_ci/*                                                                            */
288f08c3bdfSopenharmony_ci/******************************************************************************/
289f08c3bdfSopenharmony_ciint main(int argc,		/* number of input parameters.                        */
290f08c3bdfSopenharmony_ci	 char **argv)
291f08c3bdfSopenharmony_ci{				/* pointer to the command line arguments.       */
292f08c3bdfSopenharmony_ci	int c;			/* command line options.                      */
293f08c3bdfSopenharmony_ci	int proc_ndx;		/* number of time to repete the loop.         */
294f08c3bdfSopenharmony_ci	int pid_ndx;		/* number of time to repete the loop.         */
295f08c3bdfSopenharmony_ci	int num_cpus = UP;	/* assume machine is an UP machine.           */
296f08c3bdfSopenharmony_ci	int num_thrd = MAXT;	/* number of threads to create.               */
297f08c3bdfSopenharmony_ci	int thrd_ndx;		/* index into the array of threads.           */
298f08c3bdfSopenharmony_ci	int exp_prio[PIDS];	/* desired priority, random value.            */
299f08c3bdfSopenharmony_ci	int act_prio[PIDS];	/* priority actually set.                     */
300f08c3bdfSopenharmony_ci	int gen_pid[PIDS];	/* pid of the processes on this processor.    */
301f08c3bdfSopenharmony_ci	int proc_id[PIDS];	/* id of the processor last execed on.        */
302f08c3bdfSopenharmony_ci	int spcy = SCHED_FIFO;	/* scheduling policy for the tasks.           */
303f08c3bdfSopenharmony_ci	pthread_t thid[PIDS];	/* pids of process or threads spawned         */
304f08c3bdfSopenharmony_ci	thread_sched_t *chld_args;	/* arguments to funcs execed by child process. */
305f08c3bdfSopenharmony_ci	thread_sched_t *status;	/* exit status for light weight process.      */
306f08c3bdfSopenharmony_ci	extern char *optarg;	/* arguments passed to each option.           */
307f08c3bdfSopenharmony_ci	thread_sched_t **args_table;	/* pointer table of arguments address         */
308f08c3bdfSopenharmony_ci	thread_sched_t **status_table;	/*pointer table of status address          */
309f08c3bdfSopenharmony_ci
310f08c3bdfSopenharmony_ci	if (getuid() != 0) {
311f08c3bdfSopenharmony_ci		fprintf(stderr,
312f08c3bdfSopenharmony_ci			"ERROR: Only root user can run this program.\n");
313f08c3bdfSopenharmony_ci		usage(argv[0]);
314f08c3bdfSopenharmony_ci	}
315f08c3bdfSopenharmony_ci
316f08c3bdfSopenharmony_ci	if (argc < 2) {
317f08c3bdfSopenharmony_ci		fprintf(stderr,
318f08c3bdfSopenharmony_ci			"ERROR: Enter a value for the number of CPUS\n");
319f08c3bdfSopenharmony_ci		usage(argv[0]);
320f08c3bdfSopenharmony_ci	}
321f08c3bdfSopenharmony_ci
322f08c3bdfSopenharmony_ci	while ((c = getopt(argc, argv, "c:hp:t:v")) != -1) {
323f08c3bdfSopenharmony_ci		switch (c) {
324f08c3bdfSopenharmony_ci		case 'c':	/* number of processors. no default. */
325f08c3bdfSopenharmony_ci			if ((num_cpus = atoi(optarg)) == 0)
326f08c3bdfSopenharmony_ci				OPT_MISSING(argv[0], optopt);
327f08c3bdfSopenharmony_ci			else if (num_cpus < 0) {
328f08c3bdfSopenharmony_ci				fprintf(stdout,
329f08c3bdfSopenharmony_ci					"WARNING: Bad argument -p %d. Using default\n",
330f08c3bdfSopenharmony_ci					num_cpus);
331f08c3bdfSopenharmony_ci				num_cpus = UP;
332f08c3bdfSopenharmony_ci			}
333f08c3bdfSopenharmony_ci			/* MAXT threads per cpu. */
334f08c3bdfSopenharmony_ci			num_thrd = num_thrd * num_cpus;
335f08c3bdfSopenharmony_ci			break;
336f08c3bdfSopenharmony_ci		case 'h':	/* usage message */
337f08c3bdfSopenharmony_ci			usage(argv[0]);
338f08c3bdfSopenharmony_ci			break;
339f08c3bdfSopenharmony_ci		case 'p':	/* schedular policy. default SCHED_FIFO */
340f08c3bdfSopenharmony_ci			if (strncmp(optarg, "fifo", 4) == 0)
341f08c3bdfSopenharmony_ci				spcy = SCHED_FIFO;
342f08c3bdfSopenharmony_ci			else if (strncmp(optarg, "rr", 2) == 0)
343f08c3bdfSopenharmony_ci				spcy = SCHED_RR;
344f08c3bdfSopenharmony_ci			else if (strncmp(optarg, "other", 5) == 0)
345f08c3bdfSopenharmony_ci				spcy = SCHED_OTHER;
346f08c3bdfSopenharmony_ci			else {
347f08c3bdfSopenharmony_ci				fprintf(stderr,
348f08c3bdfSopenharmony_ci					"ERROR: Unrecognized scheduler policy, "
349f08c3bdfSopenharmony_ci					"using default\n");
350f08c3bdfSopenharmony_ci				usage(argv[0]);
351f08c3bdfSopenharmony_ci			}
352f08c3bdfSopenharmony_ci			break;
353f08c3bdfSopenharmony_ci		case 't':	/* input how many threads to create */
354f08c3bdfSopenharmony_ci			if ((num_thrd = atoi(optarg)) == 0)
355f08c3bdfSopenharmony_ci				OPT_MISSING(argv[0], optopt);
356f08c3bdfSopenharmony_ci			else if (num_thrd < 0) {
357f08c3bdfSopenharmony_ci				fprintf(stderr,
358f08c3bdfSopenharmony_ci					"WARNING: Bad argument -t %d. Using default\n",
359f08c3bdfSopenharmony_ci					num_thrd);
360f08c3bdfSopenharmony_ci				num_thrd = MAXT;
361f08c3bdfSopenharmony_ci			} else if (num_thrd > PIDS) {
362f08c3bdfSopenharmony_ci				fprintf(stderr,
363f08c3bdfSopenharmony_ci					"WARNING: -t %d exceeds maximum number of allowed pids"
364f08c3bdfSopenharmony_ci					" %d\n Setting number of threads to %d\n",
365f08c3bdfSopenharmony_ci					num_thrd, PIDS, PIDS - 1000);
366f08c3bdfSopenharmony_ci				num_thrd = (PIDS - 1000);
367f08c3bdfSopenharmony_ci			}
368f08c3bdfSopenharmony_ci			break;
369f08c3bdfSopenharmony_ci		case 'v':	/* verbose out put, make output look ugly! */
370f08c3bdfSopenharmony_ci			verbose = 1;
371f08c3bdfSopenharmony_ci			break;
372f08c3bdfSopenharmony_ci		default:
373f08c3bdfSopenharmony_ci			usage(argv[0]);
374f08c3bdfSopenharmony_ci			break;
375f08c3bdfSopenharmony_ci		}
376f08c3bdfSopenharmony_ci	}
377f08c3bdfSopenharmony_ci
378f08c3bdfSopenharmony_ci	/* create num_thrd number of threads. */
379f08c3bdfSopenharmony_ci	args_table = malloc(num_thrd * sizeof(thread_sched_t *));
380f08c3bdfSopenharmony_ci	if (!args_table) {
381f08c3bdfSopenharmony_ci		perror("main(): malloc failed");
382f08c3bdfSopenharmony_ci		exit(-1);
383f08c3bdfSopenharmony_ci	}
384f08c3bdfSopenharmony_ci	for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
385f08c3bdfSopenharmony_ci		args_table[thrd_ndx] = malloc(sizeof(thread_sched_t));
386f08c3bdfSopenharmony_ci		if (!args_table[thrd_ndx]) {
387f08c3bdfSopenharmony_ci			perror("main(): malloc failed");
388f08c3bdfSopenharmony_ci			exit(-1);
389f08c3bdfSopenharmony_ci		}
390f08c3bdfSopenharmony_ci		chld_args = args_table[thrd_ndx];
391f08c3bdfSopenharmony_ci		chld_args->s_policy = spcy;
392f08c3bdfSopenharmony_ci		if (pthread_create(&thid[thrd_ndx], NULL, thread_func,
393f08c3bdfSopenharmony_ci				   chld_args)) {
394f08c3bdfSopenharmony_ci			fprintf(stderr, "ERROR: creating task number: %d\n",
395f08c3bdfSopenharmony_ci				thrd_ndx);
396f08c3bdfSopenharmony_ci			perror("main(): pthread_create()");
397f08c3bdfSopenharmony_ci			exit(-1);
398f08c3bdfSopenharmony_ci		}
399f08c3bdfSopenharmony_ci		if (verbose)
400f08c3bdfSopenharmony_ci			fprintf(stdout, "Created thread[%d]\n", thrd_ndx);
401f08c3bdfSopenharmony_ci		usleep(9);
402f08c3bdfSopenharmony_ci		sched_yield();
403f08c3bdfSopenharmony_ci	}
404f08c3bdfSopenharmony_ci
405f08c3bdfSopenharmony_ci	/* wait for the children to terminate */
406f08c3bdfSopenharmony_ci	status_table = malloc(num_thrd * sizeof(thread_sched_t *));
407f08c3bdfSopenharmony_ci	if (!status_table) {
408f08c3bdfSopenharmony_ci		perror("main(): malloc failed");
409f08c3bdfSopenharmony_ci		exit(-1);
410f08c3bdfSopenharmony_ci	}
411f08c3bdfSopenharmony_ci	for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
412f08c3bdfSopenharmony_ci		status_table[thrd_ndx] = malloc(sizeof(thread_sched_t));
413f08c3bdfSopenharmony_ci		if (!status_table[thrd_ndx]) {
414f08c3bdfSopenharmony_ci			perror("main(): malloc failed");
415f08c3bdfSopenharmony_ci			exit(-1);
416f08c3bdfSopenharmony_ci		}
417f08c3bdfSopenharmony_ci		status = status_table[thrd_ndx];
418f08c3bdfSopenharmony_ci		if (pthread_join(thid[thrd_ndx], (void **)&status)) {
419f08c3bdfSopenharmony_ci			perror("main(): pthread_join()");
420f08c3bdfSopenharmony_ci			exit(-1);
421f08c3bdfSopenharmony_ci		} else {
422f08c3bdfSopenharmony_ci			if (status == (thread_sched_t *) - 1) {
423f08c3bdfSopenharmony_ci				fprintf(stderr,
424f08c3bdfSopenharmony_ci					"thread [%d] - process exited with exit code -1\n",
425f08c3bdfSopenharmony_ci					thrd_ndx);
426f08c3bdfSopenharmony_ci				exit(-1);
427f08c3bdfSopenharmony_ci			} else {
428f08c3bdfSopenharmony_ci				exp_prio[thrd_ndx] = status->exp_prio;
429f08c3bdfSopenharmony_ci				act_prio[thrd_ndx] = status->act_prio;
430f08c3bdfSopenharmony_ci				proc_id[thrd_ndx] = status->proc_num;
431f08c3bdfSopenharmony_ci				gen_pid[thrd_ndx] = status->procs_id;
432f08c3bdfSopenharmony_ci			}
433f08c3bdfSopenharmony_ci		}
434f08c3bdfSopenharmony_ci		SAFE_FREE(args_table[thrd_ndx]);
435f08c3bdfSopenharmony_ci		SAFE_FREE(status_table[thrd_ndx]);
436f08c3bdfSopenharmony_ci		usleep(10);
437f08c3bdfSopenharmony_ci	}
438f08c3bdfSopenharmony_ci
439f08c3bdfSopenharmony_ci	if (verbose) {
440f08c3bdfSopenharmony_ci		fprintf(stdout,
441f08c3bdfSopenharmony_ci			"Number of tasks spawned: %d\n"
442f08c3bdfSopenharmony_ci			"Number of CPUs:          %d\n"
443f08c3bdfSopenharmony_ci			"Scheduling policy:       %d\n", num_thrd, num_cpus,
444f08c3bdfSopenharmony_ci			spcy);
445f08c3bdfSopenharmony_ci	}
446f08c3bdfSopenharmony_ci
447f08c3bdfSopenharmony_ci	SAFE_FREE(args_table);
448f08c3bdfSopenharmony_ci	SAFE_FREE(status_table);
449f08c3bdfSopenharmony_ci
450f08c3bdfSopenharmony_ci	for (proc_ndx = 0; proc_ndx < num_cpus; proc_ndx++) {
451f08c3bdfSopenharmony_ci		fprintf(stdout, "For processor number = %d\n", proc_ndx);
452f08c3bdfSopenharmony_ci		fprintf(stdout, "%s\n", "===========================");
453f08c3bdfSopenharmony_ci		for (pid_ndx = 0; pid_ndx < num_thrd; pid_ndx++) {
454f08c3bdfSopenharmony_ci			if (proc_id[pid_ndx] == proc_ndx)
455f08c3bdfSopenharmony_ci				fprintf(stdout,
456f08c3bdfSopenharmony_ci					"pid of task = %d priority requested = %d"
457f08c3bdfSopenharmony_ci					" priority assigned by scheduler = %d\n",
458f08c3bdfSopenharmony_ci					gen_pid[pid_ndx], exp_prio[pid_ndx],
459f08c3bdfSopenharmony_ci					act_prio[pid_ndx]);
460f08c3bdfSopenharmony_ci		}
461f08c3bdfSopenharmony_ci	}
462f08c3bdfSopenharmony_ci	exit(0);
463f08c3bdfSopenharmony_ci}
464