xref: /aosp_15_r20/external/ltp/testcases/realtime/lib/librttest.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************
2*49cdfc7eSAndroid Build Coastguard Worker  *
3*49cdfc7eSAndroid Build Coastguard Worker  *   Copyright © International Business Machines  Corp., 2006-2008
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  *   This program is free software;  you can redistribute it and/or modify
6*49cdfc7eSAndroid Build Coastguard Worker  *   it under the terms of the GNU General Public License as published by
7*49cdfc7eSAndroid Build Coastguard Worker  *   the Free Software Foundation; either version 2 of the License, or
8*49cdfc7eSAndroid Build Coastguard Worker  *   (at your option) any later version.
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  *   This program is distributed in the hope that it will be useful,
11*49cdfc7eSAndroid Build Coastguard Worker  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12*49cdfc7eSAndroid Build Coastguard Worker  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13*49cdfc7eSAndroid Build Coastguard Worker  *   the GNU General Public License for more details.
14*49cdfc7eSAndroid Build Coastguard Worker  *
15*49cdfc7eSAndroid Build Coastguard Worker  *   You should have received a copy of the GNU General Public License
16*49cdfc7eSAndroid Build Coastguard Worker  *   along with this program;  if not, write to the Free Software
17*49cdfc7eSAndroid Build Coastguard Worker  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*49cdfc7eSAndroid Build Coastguard Worker  *
19*49cdfc7eSAndroid Build Coastguard Worker  * NAME
20*49cdfc7eSAndroid Build Coastguard Worker  *       librttest.c
21*49cdfc7eSAndroid Build Coastguard Worker  *
22*49cdfc7eSAndroid Build Coastguard Worker  * DESCRIPTION
23*49cdfc7eSAndroid Build Coastguard Worker  *      A set of commonly used convenience functions for writing
24*49cdfc7eSAndroid Build Coastguard Worker  *      threaded realtime test cases.
25*49cdfc7eSAndroid Build Coastguard Worker  *
26*49cdfc7eSAndroid Build Coastguard Worker  * USAGE:
27*49cdfc7eSAndroid Build Coastguard Worker  *       To be included in testcases.
28*49cdfc7eSAndroid Build Coastguard Worker  *
29*49cdfc7eSAndroid Build Coastguard Worker  * AUTHOR
30*49cdfc7eSAndroid Build Coastguard Worker  *	Darren Hart <[email protected]>
31*49cdfc7eSAndroid Build Coastguard Worker  *
32*49cdfc7eSAndroid Build Coastguard Worker  * HISTORY
33*49cdfc7eSAndroid Build Coastguard Worker  *      2006-Apr-26: Initial version by Darren Hart
34*49cdfc7eSAndroid Build Coastguard Worker  *      2006-May-08: Added atomic_{inc,set,get}, thread struct, debug function,
35*49cdfc7eSAndroid Build Coastguard Worker  *		      rt_init, buffered printing -- Vernon Mauery
36*49cdfc7eSAndroid Build Coastguard Worker  *      2006-May-09: improved command line argument handling
37*49cdfc7eSAndroid Build Coastguard Worker  *      2007-Jul-12: Added latency tracing functions and I/O helper functions
38*49cdfc7eSAndroid Build Coastguard Worker  *					      -- Josh triplett
39*49cdfc7eSAndroid Build Coastguard Worker  *	2008-Jan-10: Added RR thread support to tests -- Chirag Jog
40*49cdfc7eSAndroid Build Coastguard Worker  *
41*49cdfc7eSAndroid Build Coastguard Worker  *****************************************************************************/
42*49cdfc7eSAndroid Build Coastguard Worker 
43*49cdfc7eSAndroid Build Coastguard Worker #include <librttest.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <libstats.h>
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
47*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
48*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
49*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
50*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
51*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
52*49cdfc7eSAndroid Build Coastguard Worker #include <sched.h>
53*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
54*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
55*49cdfc7eSAndroid Build Coastguard Worker #include <getopt.h>
56*49cdfc7eSAndroid Build Coastguard Worker #include <sys/prctl.h>
57*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
58*49cdfc7eSAndroid Build Coastguard Worker #include <sys/syscall.h>
59*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
60*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
61*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
62*49cdfc7eSAndroid Build Coastguard Worker #include <math.h>
63*49cdfc7eSAndroid Build Coastguard Worker 
64*49cdfc7eSAndroid Build Coastguard Worker static LIST_HEAD(_threads);
65*49cdfc7eSAndroid Build Coastguard Worker static atomic_t _thread_count = { -1 };
66*49cdfc7eSAndroid Build Coastguard Worker static unsigned long iters_per_us;
67*49cdfc7eSAndroid Build Coastguard Worker 
68*49cdfc7eSAndroid Build Coastguard Worker pthread_mutex_t _buffer_mutex;
69*49cdfc7eSAndroid Build Coastguard Worker char *_print_buffer = NULL;
70*49cdfc7eSAndroid Build Coastguard Worker int _print_buffer_offset = 0;
71*49cdfc7eSAndroid Build Coastguard Worker int _dbg_lvl = 0;
72*49cdfc7eSAndroid Build Coastguard Worker double pass_criteria;
73*49cdfc7eSAndroid Build Coastguard Worker 
74*49cdfc7eSAndroid Build Coastguard Worker static int _use_pi = 1;
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker /* function implementations */
rt_help(void)77*49cdfc7eSAndroid Build Coastguard Worker void rt_help(void)
78*49cdfc7eSAndroid Build Coastguard Worker {
79*49cdfc7eSAndroid Build Coastguard Worker 	printf("librt standard options:\n");
80*49cdfc7eSAndroid Build Coastguard Worker 	printf
81*49cdfc7eSAndroid Build Coastguard Worker 	    ("  -b(0,1)	1:enable buffered output, 0:diable buffered output\n");
82*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -p(0,1)	0:don't use pi mutexes, 1:use pi mutexes\n");
83*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -m		use mlockall\n");
84*49cdfc7eSAndroid Build Coastguard Worker 	printf
85*49cdfc7eSAndroid Build Coastguard Worker 	    ("  -v[0-4]	0:no debug, 1:DBG_ERR, 2:DBG_WARN, 3:DBG_INFO, 4:DBG_DEBUG\n");
86*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -s		Enable saving stats data (default disabled)\n");
87*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -c		Set pass criteria\n");
88*49cdfc7eSAndroid Build Coastguard Worker }
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker /* Calibrate the busy work loop */
calibrate_busyloop(void)91*49cdfc7eSAndroid Build Coastguard Worker void calibrate_busyloop(void)
92*49cdfc7eSAndroid Build Coastguard Worker {
93*49cdfc7eSAndroid Build Coastguard Worker 	volatile int i = CALIBRATE_LOOPS;
94*49cdfc7eSAndroid Build Coastguard Worker 	nsec_t start, end;
95*49cdfc7eSAndroid Build Coastguard Worker 
96*49cdfc7eSAndroid Build Coastguard Worker 	start = rt_gettime();
97*49cdfc7eSAndroid Build Coastguard Worker 	while (--i > 0) {
98*49cdfc7eSAndroid Build Coastguard Worker 		continue;
99*49cdfc7eSAndroid Build Coastguard Worker 	}
100*49cdfc7eSAndroid Build Coastguard Worker 	end = rt_gettime();
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker 	iters_per_us = (CALIBRATE_LOOPS * NS_PER_US) / (end - start);
103*49cdfc7eSAndroid Build Coastguard Worker }
104*49cdfc7eSAndroid Build Coastguard Worker 
rt_init_long(const char * options,const struct option * longopts,int (* parse_arg)(int option,char * value),int argc,char * argv[])105*49cdfc7eSAndroid Build Coastguard Worker int rt_init_long(const char *options, const struct option *longopts,
106*49cdfc7eSAndroid Build Coastguard Worker 		 int (*parse_arg) (int option, char *value), int argc,
107*49cdfc7eSAndroid Build Coastguard Worker 		 char *argv[])
108*49cdfc7eSAndroid Build Coastguard Worker {
109*49cdfc7eSAndroid Build Coastguard Worker 	const struct option *cur_opt;
110*49cdfc7eSAndroid Build Coastguard Worker 	int use_buffer = 1;
111*49cdfc7eSAndroid Build Coastguard Worker 	char *longopt_vals;
112*49cdfc7eSAndroid Build Coastguard Worker 	size_t i;
113*49cdfc7eSAndroid Build Coastguard Worker 	int c;
114*49cdfc7eSAndroid Build Coastguard Worker 	opterr = 0;
115*49cdfc7eSAndroid Build Coastguard Worker 	int mlock = 0;
116*49cdfc7eSAndroid Build Coastguard Worker 	char *all_options;
117*49cdfc7eSAndroid Build Coastguard Worker 
118*49cdfc7eSAndroid Build Coastguard Worker 	if (asprintf(&all_options, ":b:mp:v:sc:%s", options) == -1) {
119*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr,
120*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to allocate string for option string\n");
121*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
122*49cdfc7eSAndroid Build Coastguard Worker 	}
123*49cdfc7eSAndroid Build Coastguard Worker 
124*49cdfc7eSAndroid Build Coastguard Worker 	/* Check for duplicate options in optstring */
125*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < strlen(all_options); i++) {
126*49cdfc7eSAndroid Build Coastguard Worker 		char opt = all_options[i];
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker 		if (opt == ':')
129*49cdfc7eSAndroid Build Coastguard Worker 			continue;
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 		/* Search ahead */
132*49cdfc7eSAndroid Build Coastguard Worker 		if (strchr(&all_options[i + 1], opt)) {
133*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
134*49cdfc7eSAndroid Build Coastguard Worker 				"Programmer error -- argument -%c already used at least twice\n",
135*49cdfc7eSAndroid Build Coastguard Worker 				opt);
136*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
137*49cdfc7eSAndroid Build Coastguard Worker 		}
138*49cdfc7eSAndroid Build Coastguard Worker 	}
139*49cdfc7eSAndroid Build Coastguard Worker 
140*49cdfc7eSAndroid Build Coastguard Worker 	/* Ensure each long options has a known unique short option in val. */
141*49cdfc7eSAndroid Build Coastguard Worker 	longopt_vals = "";
142*49cdfc7eSAndroid Build Coastguard Worker 	cur_opt = longopts;
143*49cdfc7eSAndroid Build Coastguard Worker 	while (cur_opt && cur_opt->name) {
144*49cdfc7eSAndroid Build Coastguard Worker 		if (cur_opt->flag) {
145*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Programmer error -- argument --%s flag"
146*49cdfc7eSAndroid Build Coastguard Worker 				" is non-null\n", cur_opt->name);
147*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
148*49cdfc7eSAndroid Build Coastguard Worker 		}
149*49cdfc7eSAndroid Build Coastguard Worker 		if (!strchr(all_options, cur_opt->val)) {
150*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Programmer error -- argument --%s "
151*49cdfc7eSAndroid Build Coastguard Worker 				"shortopt -%c wasn't listed in options (%s)\n",
152*49cdfc7eSAndroid Build Coastguard Worker 				cur_opt->name, cur_opt->val, all_options);
153*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
154*49cdfc7eSAndroid Build Coastguard Worker 		}
155*49cdfc7eSAndroid Build Coastguard Worker 		if (strchr(longopt_vals, cur_opt->val)) {
156*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Programmer error -- argument --%s "
157*49cdfc7eSAndroid Build Coastguard Worker 				"shortopt -%c is used more than once\n",
158*49cdfc7eSAndroid Build Coastguard Worker 				cur_opt->name, cur_opt->val);
159*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
160*49cdfc7eSAndroid Build Coastguard Worker 		}
161*49cdfc7eSAndroid Build Coastguard Worker 		if (asprintf(&longopt_vals, "%s%c", longopt_vals, cur_opt->val)
162*49cdfc7eSAndroid Build Coastguard Worker 		    < 0) {
163*49cdfc7eSAndroid Build Coastguard Worker 			perror("asprintf");
164*49cdfc7eSAndroid Build Coastguard Worker 			exit(2);
165*49cdfc7eSAndroid Build Coastguard Worker 		}
166*49cdfc7eSAndroid Build Coastguard Worker 		cur_opt++;
167*49cdfc7eSAndroid Build Coastguard Worker 	}
168*49cdfc7eSAndroid Build Coastguard Worker 
169*49cdfc7eSAndroid Build Coastguard Worker 	while ((c = getopt_long(argc, argv, all_options, longopts, NULL)) != -1) {
170*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
171*49cdfc7eSAndroid Build Coastguard Worker 		case 'c':
172*49cdfc7eSAndroid Build Coastguard Worker 			pass_criteria = atof(optarg);
173*49cdfc7eSAndroid Build Coastguard Worker 			break;
174*49cdfc7eSAndroid Build Coastguard Worker 		case 'b':
175*49cdfc7eSAndroid Build Coastguard Worker 			use_buffer = atoi(optarg);
176*49cdfc7eSAndroid Build Coastguard Worker 			break;
177*49cdfc7eSAndroid Build Coastguard Worker 		case 'p':
178*49cdfc7eSAndroid Build Coastguard Worker 			_use_pi = atoi(optarg);
179*49cdfc7eSAndroid Build Coastguard Worker 			break;
180*49cdfc7eSAndroid Build Coastguard Worker 		case 'm':
181*49cdfc7eSAndroid Build Coastguard Worker 			mlock = 1;
182*49cdfc7eSAndroid Build Coastguard Worker 			break;
183*49cdfc7eSAndroid Build Coastguard Worker 		case 'v':
184*49cdfc7eSAndroid Build Coastguard Worker 			_dbg_lvl = atoi(optarg);
185*49cdfc7eSAndroid Build Coastguard Worker 			break;
186*49cdfc7eSAndroid Build Coastguard Worker 		case 's':
187*49cdfc7eSAndroid Build Coastguard Worker 			save_stats = 1;
188*49cdfc7eSAndroid Build Coastguard Worker 			break;
189*49cdfc7eSAndroid Build Coastguard Worker 		case ':':
190*49cdfc7eSAndroid Build Coastguard Worker 			if (optopt == '-')
191*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "long option missing arg\n");
192*49cdfc7eSAndroid Build Coastguard Worker 			else
193*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "option -%c: missing arg\n",
194*49cdfc7eSAndroid Build Coastguard Worker 					optopt);
195*49cdfc7eSAndroid Build Coastguard Worker 			parse_arg('h', optarg);	/* Just to display usage */
196*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);	/* Just in case. (should normally be done by usage()) */
197*49cdfc7eSAndroid Build Coastguard Worker 		case '?':
198*49cdfc7eSAndroid Build Coastguard Worker 			if (optopt == '-')
199*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "unrecognized long option\n");
200*49cdfc7eSAndroid Build Coastguard Worker 			else
201*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "option -%c not recognized\n",
202*49cdfc7eSAndroid Build Coastguard Worker 					optopt);
203*49cdfc7eSAndroid Build Coastguard Worker 			parse_arg('h', optarg);	/* Just to display usage */
204*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);	/* Just in case. (should normally be done by usage()) */
205*49cdfc7eSAndroid Build Coastguard Worker 		default:
206*49cdfc7eSAndroid Build Coastguard Worker 			if (parse_arg && parse_arg(c, optarg))
207*49cdfc7eSAndroid Build Coastguard Worker 				break;	/* Application option */
208*49cdfc7eSAndroid Build Coastguard Worker 
209*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
210*49cdfc7eSAndroid Build Coastguard Worker 				"Programmer error -- option -%c defined but not handled\n",
211*49cdfc7eSAndroid Build Coastguard Worker 				c);
212*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
213*49cdfc7eSAndroid Build Coastguard Worker 		}
214*49cdfc7eSAndroid Build Coastguard Worker 	}
215*49cdfc7eSAndroid Build Coastguard Worker 	if (!_use_pi)
216*49cdfc7eSAndroid Build Coastguard Worker 		printf
217*49cdfc7eSAndroid Build Coastguard Worker 		    ("Priority Inheritance has been disabled for this run.\n");
218*49cdfc7eSAndroid Build Coastguard Worker 	if (use_buffer)
219*49cdfc7eSAndroid Build Coastguard Worker 		buffer_init();
220*49cdfc7eSAndroid Build Coastguard Worker 	if (mlock) {
221*49cdfc7eSAndroid Build Coastguard Worker 		if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
222*49cdfc7eSAndroid Build Coastguard Worker 			perror("failed to lock memory\n");
223*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
224*49cdfc7eSAndroid Build Coastguard Worker 		}
225*49cdfc7eSAndroid Build Coastguard Worker 	}
226*49cdfc7eSAndroid Build Coastguard Worker 
227*49cdfc7eSAndroid Build Coastguard Worker 	calibrate_busyloop();
228*49cdfc7eSAndroid Build Coastguard Worker 
229*49cdfc7eSAndroid Build Coastguard Worker 	free(all_options);
230*49cdfc7eSAndroid Build Coastguard Worker 
231*49cdfc7eSAndroid Build Coastguard Worker 	/*
232*49cdfc7eSAndroid Build Coastguard Worker 	 * atexit() order matters here - buffer_print() will be called before
233*49cdfc7eSAndroid Build Coastguard Worker 	 * buffer_fini().
234*49cdfc7eSAndroid Build Coastguard Worker 	 */
235*49cdfc7eSAndroid Build Coastguard Worker 	atexit(buffer_fini);
236*49cdfc7eSAndroid Build Coastguard Worker 	atexit(buffer_print);
237*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
238*49cdfc7eSAndroid Build Coastguard Worker }
239*49cdfc7eSAndroid Build Coastguard Worker 
rt_init(const char * options,int (* parse_arg)(int option,char * value),int argc,char * argv[])240*49cdfc7eSAndroid Build Coastguard Worker int rt_init(const char *options, int (*parse_arg) (int option, char *value),
241*49cdfc7eSAndroid Build Coastguard Worker 	    int argc, char *argv[])
242*49cdfc7eSAndroid Build Coastguard Worker {
243*49cdfc7eSAndroid Build Coastguard Worker 	return rt_init_long(options, NULL, parse_arg, argc, argv);
244*49cdfc7eSAndroid Build Coastguard Worker }
245*49cdfc7eSAndroid Build Coastguard Worker 
buffer_init(void)246*49cdfc7eSAndroid Build Coastguard Worker void buffer_init(void)
247*49cdfc7eSAndroid Build Coastguard Worker {
248*49cdfc7eSAndroid Build Coastguard Worker 	_print_buffer = malloc(PRINT_BUFFER_SIZE);
249*49cdfc7eSAndroid Build Coastguard Worker 	if (!_print_buffer)
250*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr,
251*49cdfc7eSAndroid Build Coastguard Worker 			"insufficient memory for print buffer - printing directly to stderr\n");
252*49cdfc7eSAndroid Build Coastguard Worker 	else
253*49cdfc7eSAndroid Build Coastguard Worker 		memset(_print_buffer, 0, PRINT_BUFFER_SIZE);
254*49cdfc7eSAndroid Build Coastguard Worker }
255*49cdfc7eSAndroid Build Coastguard Worker 
buffer_print(void)256*49cdfc7eSAndroid Build Coastguard Worker void buffer_print(void)
257*49cdfc7eSAndroid Build Coastguard Worker {
258*49cdfc7eSAndroid Build Coastguard Worker 	if (_print_buffer) {
259*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "%s", _print_buffer);
260*49cdfc7eSAndroid Build Coastguard Worker 		memset(_print_buffer, 0, PRINT_BUFFER_SIZE);
261*49cdfc7eSAndroid Build Coastguard Worker 		_print_buffer_offset = 0;
262*49cdfc7eSAndroid Build Coastguard Worker 	}
263*49cdfc7eSAndroid Build Coastguard Worker }
264*49cdfc7eSAndroid Build Coastguard Worker 
buffer_fini(void)265*49cdfc7eSAndroid Build Coastguard Worker void buffer_fini(void)
266*49cdfc7eSAndroid Build Coastguard Worker {
267*49cdfc7eSAndroid Build Coastguard Worker 	if (_print_buffer)
268*49cdfc7eSAndroid Build Coastguard Worker 		free(_print_buffer);
269*49cdfc7eSAndroid Build Coastguard Worker 	_print_buffer = NULL;
270*49cdfc7eSAndroid Build Coastguard Worker }
271*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(int i)272*49cdfc7eSAndroid Build Coastguard Worker void cleanup(int i)
273*49cdfc7eSAndroid Build Coastguard Worker {
274*49cdfc7eSAndroid Build Coastguard Worker 	printf("Test terminated with asynchronous signal\n");
275*49cdfc7eSAndroid Build Coastguard Worker 	buffer_print();
276*49cdfc7eSAndroid Build Coastguard Worker 	buffer_fini();
277*49cdfc7eSAndroid Build Coastguard Worker 	if (i)
278*49cdfc7eSAndroid Build Coastguard Worker 		exit(i);
279*49cdfc7eSAndroid Build Coastguard Worker }
280*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)281*49cdfc7eSAndroid Build Coastguard Worker void setup(void)
282*49cdfc7eSAndroid Build Coastguard Worker {
283*49cdfc7eSAndroid Build Coastguard Worker 	signal(SIGINT, cleanup);
284*49cdfc7eSAndroid Build Coastguard Worker 	signal(SIGQUIT, cleanup);
285*49cdfc7eSAndroid Build Coastguard Worker 	signal(SIGTERM, cleanup);
286*49cdfc7eSAndroid Build Coastguard Worker }
287*49cdfc7eSAndroid Build Coastguard Worker 
create_thread(void * (* func)(void *),void * arg,int prio,int policy)288*49cdfc7eSAndroid Build Coastguard Worker int create_thread(void *(*func) (void *), void *arg, int prio, int policy)
289*49cdfc7eSAndroid Build Coastguard Worker {
290*49cdfc7eSAndroid Build Coastguard Worker 	struct sched_param param;
291*49cdfc7eSAndroid Build Coastguard Worker 	int id, ret;
292*49cdfc7eSAndroid Build Coastguard Worker 	struct thread *thread;
293*49cdfc7eSAndroid Build Coastguard Worker 
294*49cdfc7eSAndroid Build Coastguard Worker 	id = atomic_inc(&_thread_count);
295*49cdfc7eSAndroid Build Coastguard Worker 
296*49cdfc7eSAndroid Build Coastguard Worker 	thread = malloc(sizeof(struct thread));
297*49cdfc7eSAndroid Build Coastguard Worker 	if (!thread)
298*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
299*49cdfc7eSAndroid Build Coastguard Worker 
300*49cdfc7eSAndroid Build Coastguard Worker 	list_add_tail(&thread->_threads, &_threads);
301*49cdfc7eSAndroid Build Coastguard Worker 	pthread_cond_init(&thread->cond, NULL);	// Accept the defaults
302*49cdfc7eSAndroid Build Coastguard Worker 	init_pi_mutex(&thread->mutex);
303*49cdfc7eSAndroid Build Coastguard Worker 	thread->id = id;
304*49cdfc7eSAndroid Build Coastguard Worker 	thread->priority = prio;
305*49cdfc7eSAndroid Build Coastguard Worker 	thread->policy = policy;
306*49cdfc7eSAndroid Build Coastguard Worker 	thread->flags = 0;
307*49cdfc7eSAndroid Build Coastguard Worker 	thread->arg = arg;
308*49cdfc7eSAndroid Build Coastguard Worker 	thread->func = func;
309*49cdfc7eSAndroid Build Coastguard Worker 	param.sched_priority = prio;
310*49cdfc7eSAndroid Build Coastguard Worker 
311*49cdfc7eSAndroid Build Coastguard Worker 	pthread_attr_init(&thread->attr);
312*49cdfc7eSAndroid Build Coastguard Worker 	pthread_attr_setinheritsched(&thread->attr, PTHREAD_EXPLICIT_SCHED);
313*49cdfc7eSAndroid Build Coastguard Worker 	pthread_attr_setschedpolicy(&thread->attr, thread->policy);
314*49cdfc7eSAndroid Build Coastguard Worker 	pthread_attr_setschedparam(&thread->attr, &param);
315*49cdfc7eSAndroid Build Coastguard Worker 
316*49cdfc7eSAndroid Build Coastguard Worker 	if ((ret =
317*49cdfc7eSAndroid Build Coastguard Worker 	     pthread_create(&thread->pthread, &thread->attr, func,
318*49cdfc7eSAndroid Build Coastguard Worker 			    (void *)thread))) {
319*49cdfc7eSAndroid Build Coastguard Worker 		printf("pthread_create failed: %d (%s)\n", ret, strerror(ret));
320*49cdfc7eSAndroid Build Coastguard Worker 		list_del(&thread->_threads);
321*49cdfc7eSAndroid Build Coastguard Worker 		pthread_attr_destroy(&thread->attr);
322*49cdfc7eSAndroid Build Coastguard Worker 		free(thread);
323*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
324*49cdfc7eSAndroid Build Coastguard Worker 	}
325*49cdfc7eSAndroid Build Coastguard Worker 	pthread_attr_destroy(&thread->attr);
326*49cdfc7eSAndroid Build Coastguard Worker 
327*49cdfc7eSAndroid Build Coastguard Worker 	return id;
328*49cdfc7eSAndroid Build Coastguard Worker }
329*49cdfc7eSAndroid Build Coastguard Worker 
create_fifo_thread(void * (* func)(void *),void * arg,int prio)330*49cdfc7eSAndroid Build Coastguard Worker int create_fifo_thread(void *(*func) (void *), void *arg, int prio)
331*49cdfc7eSAndroid Build Coastguard Worker {
332*49cdfc7eSAndroid Build Coastguard Worker 	return create_thread(func, arg, prio, SCHED_FIFO);
333*49cdfc7eSAndroid Build Coastguard Worker }
334*49cdfc7eSAndroid Build Coastguard Worker 
create_rr_thread(void * (* func)(void *),void * arg,int prio)335*49cdfc7eSAndroid Build Coastguard Worker int create_rr_thread(void *(*func) (void *), void *arg, int prio)
336*49cdfc7eSAndroid Build Coastguard Worker {
337*49cdfc7eSAndroid Build Coastguard Worker 	return create_thread(func, arg, prio, SCHED_RR);
338*49cdfc7eSAndroid Build Coastguard Worker }
339*49cdfc7eSAndroid Build Coastguard Worker 
create_other_thread(void * (* func)(void *),void * arg)340*49cdfc7eSAndroid Build Coastguard Worker int create_other_thread(void *(*func) (void *), void *arg)
341*49cdfc7eSAndroid Build Coastguard Worker {
342*49cdfc7eSAndroid Build Coastguard Worker 	return create_thread(func, arg, 0, SCHED_OTHER);
343*49cdfc7eSAndroid Build Coastguard Worker }
344*49cdfc7eSAndroid Build Coastguard Worker 
set_thread_priority(pthread_t pthread,int prio)345*49cdfc7eSAndroid Build Coastguard Worker int set_thread_priority(pthread_t pthread, int prio)
346*49cdfc7eSAndroid Build Coastguard Worker {
347*49cdfc7eSAndroid Build Coastguard Worker 	struct sched_param sched_param;
348*49cdfc7eSAndroid Build Coastguard Worker 	sched_param.sched_priority = prio;
349*49cdfc7eSAndroid Build Coastguard Worker 	int policy;
350*49cdfc7eSAndroid Build Coastguard Worker 
351*49cdfc7eSAndroid Build Coastguard Worker 	policy = (prio > 0) ? SCHED_FIFO : SCHED_OTHER;
352*49cdfc7eSAndroid Build Coastguard Worker 
353*49cdfc7eSAndroid Build Coastguard Worker 	return pthread_setschedparam(pthread, policy, &sched_param);
354*49cdfc7eSAndroid Build Coastguard Worker }
355*49cdfc7eSAndroid Build Coastguard Worker 
set_priority(int prio)356*49cdfc7eSAndroid Build Coastguard Worker int set_priority(int prio)
357*49cdfc7eSAndroid Build Coastguard Worker {
358*49cdfc7eSAndroid Build Coastguard Worker 	struct sched_param sp;
359*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
360*49cdfc7eSAndroid Build Coastguard Worker 
361*49cdfc7eSAndroid Build Coastguard Worker 	sp.sched_priority = prio;
362*49cdfc7eSAndroid Build Coastguard Worker 	if (sched_setscheduler(0, SCHED_FIFO, &sp) != 0) {
363*49cdfc7eSAndroid Build Coastguard Worker 		perror("sched_setscheduler");
364*49cdfc7eSAndroid Build Coastguard Worker 		ret = -1;
365*49cdfc7eSAndroid Build Coastguard Worker 	}
366*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
367*49cdfc7eSAndroid Build Coastguard Worker }
368*49cdfc7eSAndroid Build Coastguard Worker 
join_thread(int i)369*49cdfc7eSAndroid Build Coastguard Worker void join_thread(int i)
370*49cdfc7eSAndroid Build Coastguard Worker {
371*49cdfc7eSAndroid Build Coastguard Worker 	struct thread *p, *t = NULL;
372*49cdfc7eSAndroid Build Coastguard Worker 	list_for_each_entry(p, &_threads, _threads) {
373*49cdfc7eSAndroid Build Coastguard Worker 		if (p->id == i) {
374*49cdfc7eSAndroid Build Coastguard Worker 			t = p;
375*49cdfc7eSAndroid Build Coastguard Worker 			break;
376*49cdfc7eSAndroid Build Coastguard Worker 		}
377*49cdfc7eSAndroid Build Coastguard Worker 	}
378*49cdfc7eSAndroid Build Coastguard Worker 	if (t) {
379*49cdfc7eSAndroid Build Coastguard Worker 		t->flags |= THREAD_QUIT;
380*49cdfc7eSAndroid Build Coastguard Worker 		if (t->pthread)
381*49cdfc7eSAndroid Build Coastguard Worker 			pthread_join(t->pthread, NULL);
382*49cdfc7eSAndroid Build Coastguard Worker 		list_del(&t->_threads);
383*49cdfc7eSAndroid Build Coastguard Worker 		free(t);
384*49cdfc7eSAndroid Build Coastguard Worker 	}
385*49cdfc7eSAndroid Build Coastguard Worker }
386*49cdfc7eSAndroid Build Coastguard Worker 
all_threads_quit(void)387*49cdfc7eSAndroid Build Coastguard Worker void all_threads_quit(void)
388*49cdfc7eSAndroid Build Coastguard Worker {
389*49cdfc7eSAndroid Build Coastguard Worker 	struct thread *p;
390*49cdfc7eSAndroid Build Coastguard Worker 	list_for_each_entry(p, &_threads, _threads) {
391*49cdfc7eSAndroid Build Coastguard Worker 		p->flags |= THREAD_QUIT;
392*49cdfc7eSAndroid Build Coastguard Worker 	}
393*49cdfc7eSAndroid Build Coastguard Worker }
394*49cdfc7eSAndroid Build Coastguard Worker 
join_threads(void)395*49cdfc7eSAndroid Build Coastguard Worker void join_threads(void)
396*49cdfc7eSAndroid Build Coastguard Worker {
397*49cdfc7eSAndroid Build Coastguard Worker 	all_threads_quit();
398*49cdfc7eSAndroid Build Coastguard Worker 	struct thread *p, *t;
399*49cdfc7eSAndroid Build Coastguard Worker 	list_for_each_entry_safe(p, t, &_threads, _threads) {
400*49cdfc7eSAndroid Build Coastguard Worker 		if (p->pthread)
401*49cdfc7eSAndroid Build Coastguard Worker 			pthread_join(p->pthread, NULL);
402*49cdfc7eSAndroid Build Coastguard Worker 		list_del(&p->_threads);
403*49cdfc7eSAndroid Build Coastguard Worker 		free(p);
404*49cdfc7eSAndroid Build Coastguard Worker 	}
405*49cdfc7eSAndroid Build Coastguard Worker }
406*49cdfc7eSAndroid Build Coastguard Worker 
get_thread(int i)407*49cdfc7eSAndroid Build Coastguard Worker struct thread *get_thread(int i)
408*49cdfc7eSAndroid Build Coastguard Worker {
409*49cdfc7eSAndroid Build Coastguard Worker 	struct thread *p;
410*49cdfc7eSAndroid Build Coastguard Worker 	list_for_each_entry(p, &_threads, _threads) {
411*49cdfc7eSAndroid Build Coastguard Worker 		if (p->id == i) {
412*49cdfc7eSAndroid Build Coastguard Worker 			return p;
413*49cdfc7eSAndroid Build Coastguard Worker 		}
414*49cdfc7eSAndroid Build Coastguard Worker 	}
415*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
416*49cdfc7eSAndroid Build Coastguard Worker }
417*49cdfc7eSAndroid Build Coastguard Worker 
ts_minus(struct timespec * ts_end,struct timespec * ts_start,struct timespec * ts_delta)418*49cdfc7eSAndroid Build Coastguard Worker void ts_minus(struct timespec *ts_end, struct timespec *ts_start,
419*49cdfc7eSAndroid Build Coastguard Worker 	      struct timespec *ts_delta)
420*49cdfc7eSAndroid Build Coastguard Worker {
421*49cdfc7eSAndroid Build Coastguard Worker 	if (ts_end == NULL || ts_start == NULL || ts_delta == NULL) {
422*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: one or more of the timespecs is NULL",
423*49cdfc7eSAndroid Build Coastguard Worker 		       __FUNCTION__);
424*49cdfc7eSAndroid Build Coastguard Worker 		return;
425*49cdfc7eSAndroid Build Coastguard Worker 	}
426*49cdfc7eSAndroid Build Coastguard Worker 
427*49cdfc7eSAndroid Build Coastguard Worker 	ts_delta->tv_sec = ts_end->tv_sec - ts_start->tv_sec;
428*49cdfc7eSAndroid Build Coastguard Worker 	ts_delta->tv_nsec = ts_end->tv_nsec - ts_start->tv_nsec;
429*49cdfc7eSAndroid Build Coastguard Worker 	ts_normalize(ts_delta);
430*49cdfc7eSAndroid Build Coastguard Worker }
431*49cdfc7eSAndroid Build Coastguard Worker 
ts_plus(struct timespec * ts_a,struct timespec * ts_b,struct timespec * ts_sum)432*49cdfc7eSAndroid Build Coastguard Worker void ts_plus(struct timespec *ts_a, struct timespec *ts_b,
433*49cdfc7eSAndroid Build Coastguard Worker 	     struct timespec *ts_sum)
434*49cdfc7eSAndroid Build Coastguard Worker {
435*49cdfc7eSAndroid Build Coastguard Worker 	if (ts_a == NULL || ts_b == NULL || ts_sum == NULL) {
436*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: one or more of the timespecs is NULL",
437*49cdfc7eSAndroid Build Coastguard Worker 		       __FUNCTION__);
438*49cdfc7eSAndroid Build Coastguard Worker 		return;
439*49cdfc7eSAndroid Build Coastguard Worker 	}
440*49cdfc7eSAndroid Build Coastguard Worker 
441*49cdfc7eSAndroid Build Coastguard Worker 	ts_sum->tv_sec = ts_a->tv_sec + ts_b->tv_sec;
442*49cdfc7eSAndroid Build Coastguard Worker 	ts_sum->tv_nsec = ts_a->tv_nsec + ts_b->tv_nsec;
443*49cdfc7eSAndroid Build Coastguard Worker 	ts_normalize(ts_sum);
444*49cdfc7eSAndroid Build Coastguard Worker }
445*49cdfc7eSAndroid Build Coastguard Worker 
ts_normalize(struct timespec * ts)446*49cdfc7eSAndroid Build Coastguard Worker void ts_normalize(struct timespec *ts)
447*49cdfc7eSAndroid Build Coastguard Worker {
448*49cdfc7eSAndroid Build Coastguard Worker 	if (ts == NULL) {
449*49cdfc7eSAndroid Build Coastguard Worker 		/* FIXME: write a real error logging system */
450*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: ts is NULL\n", __FUNCTION__);
451*49cdfc7eSAndroid Build Coastguard Worker 		return;
452*49cdfc7eSAndroid Build Coastguard Worker 	}
453*49cdfc7eSAndroid Build Coastguard Worker 
454*49cdfc7eSAndroid Build Coastguard Worker 	/* get the abs(nsec) < NS_PER_SEC */
455*49cdfc7eSAndroid Build Coastguard Worker 	while (ts->tv_nsec > NS_PER_SEC) {
456*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_sec++;
457*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_nsec -= NS_PER_SEC;
458*49cdfc7eSAndroid Build Coastguard Worker 	}
459*49cdfc7eSAndroid Build Coastguard Worker 	while (ts->tv_nsec < -NS_PER_SEC) {
460*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_sec--;
461*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_nsec += NS_PER_SEC;
462*49cdfc7eSAndroid Build Coastguard Worker 	}
463*49cdfc7eSAndroid Build Coastguard Worker 
464*49cdfc7eSAndroid Build Coastguard Worker 	/* get the values to the same polarity */
465*49cdfc7eSAndroid Build Coastguard Worker 	if (ts->tv_sec > 0 && ts->tv_nsec < 0) {
466*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_sec--;
467*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_nsec += NS_PER_SEC;
468*49cdfc7eSAndroid Build Coastguard Worker 	}
469*49cdfc7eSAndroid Build Coastguard Worker 	if (ts->tv_sec < 0 && ts->tv_nsec > 0) {
470*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_sec++;
471*49cdfc7eSAndroid Build Coastguard Worker 		ts->tv_nsec -= NS_PER_SEC;
472*49cdfc7eSAndroid Build Coastguard Worker 	}
473*49cdfc7eSAndroid Build Coastguard Worker }
474*49cdfc7eSAndroid Build Coastguard Worker 
ts_to_nsec(struct timespec * ts,nsec_t * ns)475*49cdfc7eSAndroid Build Coastguard Worker int ts_to_nsec(struct timespec *ts, nsec_t * ns)
476*49cdfc7eSAndroid Build Coastguard Worker {
477*49cdfc7eSAndroid Build Coastguard Worker 	struct timespec t;
478*49cdfc7eSAndroid Build Coastguard Worker 	if (ts == NULL) {
479*49cdfc7eSAndroid Build Coastguard Worker 		/* FIXME: write a real error logging system */
480*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: ts is NULL\n", __FUNCTION__);
481*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
482*49cdfc7eSAndroid Build Coastguard Worker 	}
483*49cdfc7eSAndroid Build Coastguard Worker 	t.tv_sec = ts->tv_sec;
484*49cdfc7eSAndroid Build Coastguard Worker 	t.tv_nsec = ts->tv_nsec;
485*49cdfc7eSAndroid Build Coastguard Worker 	ts_normalize(&t);
486*49cdfc7eSAndroid Build Coastguard Worker 
487*49cdfc7eSAndroid Build Coastguard Worker 	if (t.tv_sec <= 0 && t.tv_nsec < 0) {
488*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: ts is negative\n", __FUNCTION__);
489*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
490*49cdfc7eSAndroid Build Coastguard Worker 	}
491*49cdfc7eSAndroid Build Coastguard Worker 
492*49cdfc7eSAndroid Build Coastguard Worker 	*ns = (nsec_t) ts->tv_sec * NS_PER_SEC + ts->tv_nsec;
493*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
494*49cdfc7eSAndroid Build Coastguard Worker }
495*49cdfc7eSAndroid Build Coastguard Worker 
nsec_to_ts(nsec_t ns,struct timespec * ts)496*49cdfc7eSAndroid Build Coastguard Worker void nsec_to_ts(nsec_t ns, struct timespec *ts)
497*49cdfc7eSAndroid Build Coastguard Worker {
498*49cdfc7eSAndroid Build Coastguard Worker 	if (ts == NULL) {
499*49cdfc7eSAndroid Build Coastguard Worker 		/* FIXME: write a real error logging system */
500*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: ts is NULL\n", __FUNCTION__);
501*49cdfc7eSAndroid Build Coastguard Worker 		return;
502*49cdfc7eSAndroid Build Coastguard Worker 	}
503*49cdfc7eSAndroid Build Coastguard Worker 	ts->tv_sec = ns / NS_PER_SEC;
504*49cdfc7eSAndroid Build Coastguard Worker 	ts->tv_nsec = ns % NS_PER_SEC;
505*49cdfc7eSAndroid Build Coastguard Worker }
506*49cdfc7eSAndroid Build Coastguard Worker 
507*49cdfc7eSAndroid Build Coastguard Worker /* return difference in microseconds */
tsc_minus(unsigned long long tsc_start,unsigned long long tsc_end)508*49cdfc7eSAndroid Build Coastguard Worker unsigned long long tsc_minus(unsigned long long tsc_start,
509*49cdfc7eSAndroid Build Coastguard Worker 			     unsigned long long tsc_end)
510*49cdfc7eSAndroid Build Coastguard Worker {
511*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long delta;
512*49cdfc7eSAndroid Build Coastguard Worker 	if (tsc_start <= tsc_end)
513*49cdfc7eSAndroid Build Coastguard Worker 		delta = tsc_end - tsc_start;
514*49cdfc7eSAndroid Build Coastguard Worker 	else {
515*49cdfc7eSAndroid Build Coastguard Worker 		delta = ULL_MAX - (tsc_end - tsc_start) + 1;
516*49cdfc7eSAndroid Build Coastguard Worker 		printf("TSC wrapped, delta=%llu\n", delta);
517*49cdfc7eSAndroid Build Coastguard Worker 	}
518*49cdfc7eSAndroid Build Coastguard Worker 	return delta;
519*49cdfc7eSAndroid Build Coastguard Worker }
520*49cdfc7eSAndroid Build Coastguard Worker 
rt_nanosleep_until(nsec_t ns)521*49cdfc7eSAndroid Build Coastguard Worker void rt_nanosleep_until(nsec_t ns)
522*49cdfc7eSAndroid Build Coastguard Worker {
523*49cdfc7eSAndroid Build Coastguard Worker 	struct timespec ts_sleep, ts_rem;
524*49cdfc7eSAndroid Build Coastguard Worker 	int rc;
525*49cdfc7eSAndroid Build Coastguard Worker 	nsec_to_ts(ns, &ts_sleep);
526*49cdfc7eSAndroid Build Coastguard Worker 	rc = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts_sleep,
527*49cdfc7eSAndroid Build Coastguard Worker 			     &ts_rem);
528*49cdfc7eSAndroid Build Coastguard Worker 	/* FIXME: when should we display the remainder ? */
529*49cdfc7eSAndroid Build Coastguard Worker 	if (rc != 0) {
530*49cdfc7eSAndroid Build Coastguard Worker 		printf("WARNING: rt_nanosleep() returned early by %d s %d ns\n",
531*49cdfc7eSAndroid Build Coastguard Worker 		       (int)ts_rem.tv_sec, (int)ts_rem.tv_nsec);
532*49cdfc7eSAndroid Build Coastguard Worker 	}
533*49cdfc7eSAndroid Build Coastguard Worker }
534*49cdfc7eSAndroid Build Coastguard Worker 
rt_nanosleep(nsec_t ns)535*49cdfc7eSAndroid Build Coastguard Worker void rt_nanosleep(nsec_t ns)
536*49cdfc7eSAndroid Build Coastguard Worker {
537*49cdfc7eSAndroid Build Coastguard Worker 	struct timespec ts_sleep, ts_rem;
538*49cdfc7eSAndroid Build Coastguard Worker 	int rc;
539*49cdfc7eSAndroid Build Coastguard Worker 	nsec_to_ts(ns, &ts_sleep);
540*49cdfc7eSAndroid Build Coastguard Worker 	rc = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts_sleep, &ts_rem);
541*49cdfc7eSAndroid Build Coastguard Worker 	/* FIXME: when should we display the remainder ? */
542*49cdfc7eSAndroid Build Coastguard Worker 	if (rc != 0) {
543*49cdfc7eSAndroid Build Coastguard Worker 		printf("WARNING: rt_nanosleep() returned early by %d s %d ns\n",
544*49cdfc7eSAndroid Build Coastguard Worker 		       (int)ts_rem.tv_sec, (int)ts_rem.tv_nsec);
545*49cdfc7eSAndroid Build Coastguard Worker 	}
546*49cdfc7eSAndroid Build Coastguard Worker }
547*49cdfc7eSAndroid Build Coastguard Worker 
rt_gettime(void)548*49cdfc7eSAndroid Build Coastguard Worker nsec_t rt_gettime(void)
549*49cdfc7eSAndroid Build Coastguard Worker {
550*49cdfc7eSAndroid Build Coastguard Worker 	struct timespec ts;
551*49cdfc7eSAndroid Build Coastguard Worker 	nsec_t ns;
552*49cdfc7eSAndroid Build Coastguard Worker 	int rc;
553*49cdfc7eSAndroid Build Coastguard Worker 
554*49cdfc7eSAndroid Build Coastguard Worker 	rc = clock_gettime(CLOCK_MONOTONIC, &ts);
555*49cdfc7eSAndroid Build Coastguard Worker 	if (rc != 0) {
556*49cdfc7eSAndroid Build Coastguard Worker 		printf("ERROR in %s: clock_gettime() returned %d\n",
557*49cdfc7eSAndroid Build Coastguard Worker 		       __FUNCTION__, rc);
558*49cdfc7eSAndroid Build Coastguard Worker 		perror("clock_gettime() failed");
559*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
560*49cdfc7eSAndroid Build Coastguard Worker 	}
561*49cdfc7eSAndroid Build Coastguard Worker 
562*49cdfc7eSAndroid Build Coastguard Worker 	ts_to_nsec(&ts, &ns);
563*49cdfc7eSAndroid Build Coastguard Worker 	return ns;
564*49cdfc7eSAndroid Build Coastguard Worker }
565*49cdfc7eSAndroid Build Coastguard Worker 
busy_work_ms(int ms)566*49cdfc7eSAndroid Build Coastguard Worker void *busy_work_ms(int ms)
567*49cdfc7eSAndroid Build Coastguard Worker {
568*49cdfc7eSAndroid Build Coastguard Worker 	busy_work_us(ms * US_PER_MS);
569*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
570*49cdfc7eSAndroid Build Coastguard Worker }
571*49cdfc7eSAndroid Build Coastguard Worker 
busy_work_us(int us)572*49cdfc7eSAndroid Build Coastguard Worker void *busy_work_us(int us)
573*49cdfc7eSAndroid Build Coastguard Worker {
574*49cdfc7eSAndroid Build Coastguard Worker 	volatile int i;
575*49cdfc7eSAndroid Build Coastguard Worker 	nsec_t start, now;
576*49cdfc7eSAndroid Build Coastguard Worker 	int delta;		/* time in us */
577*49cdfc7eSAndroid Build Coastguard Worker 
578*49cdfc7eSAndroid Build Coastguard Worker 	i = us * iters_per_us;
579*49cdfc7eSAndroid Build Coastguard Worker 
580*49cdfc7eSAndroid Build Coastguard Worker 	start = rt_gettime();
581*49cdfc7eSAndroid Build Coastguard Worker 	while (--i > 0) {
582*49cdfc7eSAndroid Build Coastguard Worker 		continue;
583*49cdfc7eSAndroid Build Coastguard Worker 	}
584*49cdfc7eSAndroid Build Coastguard Worker 	now = rt_gettime();
585*49cdfc7eSAndroid Build Coastguard Worker 
586*49cdfc7eSAndroid Build Coastguard Worker 	delta = (now - start) / NS_PER_US;
587*49cdfc7eSAndroid Build Coastguard Worker 	/* uncomment to tune to your machine */
588*49cdfc7eSAndroid Build Coastguard Worker 	/* printf("busy_work_us requested: %dus  actual: %dus\n", us, delta); */
589*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
590*49cdfc7eSAndroid Build Coastguard Worker }
591*49cdfc7eSAndroid Build Coastguard Worker 
init_pi_mutex(pthread_mutex_t * m)592*49cdfc7eSAndroid Build Coastguard Worker void init_pi_mutex(pthread_mutex_t * m)
593*49cdfc7eSAndroid Build Coastguard Worker {
594*49cdfc7eSAndroid Build Coastguard Worker #if HAS_PRIORITY_INHERIT
595*49cdfc7eSAndroid Build Coastguard Worker 	pthread_mutexattr_t attr;
596*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
597*49cdfc7eSAndroid Build Coastguard Worker 	int protocol;
598*49cdfc7eSAndroid Build Coastguard Worker 
599*49cdfc7eSAndroid Build Coastguard Worker 	if ((ret = pthread_mutexattr_init(&attr)) != 0) {
600*49cdfc7eSAndroid Build Coastguard Worker 		printf("Failed to init mutexattr: %d (%s)\n", ret,
601*49cdfc7eSAndroid Build Coastguard Worker 		       strerror(ret));
602*49cdfc7eSAndroid Build Coastguard Worker 	};
603*49cdfc7eSAndroid Build Coastguard Worker 	if (_use_pi
604*49cdfc7eSAndroid Build Coastguard Worker 	    && (ret =
605*49cdfc7eSAndroid Build Coastguard Worker 		pthread_mutexattr_setprotocol(&attr,
606*49cdfc7eSAndroid Build Coastguard Worker 					      PTHREAD_PRIO_INHERIT)) != 0) {
607*49cdfc7eSAndroid Build Coastguard Worker 		printf("Can't set protocol prio inherit: %d (%s)\n", ret,
608*49cdfc7eSAndroid Build Coastguard Worker 		       strerror(ret));
609*49cdfc7eSAndroid Build Coastguard Worker 	}
610*49cdfc7eSAndroid Build Coastguard Worker 	if ((ret = pthread_mutexattr_getprotocol(&attr, &protocol)) != 0) {
611*49cdfc7eSAndroid Build Coastguard Worker 		printf("Can't get mutexattr protocol: %d (%s)\n", ret,
612*49cdfc7eSAndroid Build Coastguard Worker 		       strerror(ret));
613*49cdfc7eSAndroid Build Coastguard Worker 	}
614*49cdfc7eSAndroid Build Coastguard Worker 	if ((ret = pthread_mutex_init(m, &attr)) != 0) {
615*49cdfc7eSAndroid Build Coastguard Worker 		printf("Failed to init mutex: %d (%s)\n", ret, strerror(ret));
616*49cdfc7eSAndroid Build Coastguard Worker 	}
617*49cdfc7eSAndroid Build Coastguard Worker #endif
618*49cdfc7eSAndroid Build Coastguard Worker 
619*49cdfc7eSAndroid Build Coastguard Worker 	/* FIXME: does any of this need to be destroyed ? */
620*49cdfc7eSAndroid Build Coastguard Worker }
621*49cdfc7eSAndroid Build Coastguard Worker 
622*49cdfc7eSAndroid Build Coastguard Worker /* Write the entirety of data.  Complain if unable to do so. */
write_or_complain(int fd,const void * data,size_t len)623*49cdfc7eSAndroid Build Coastguard Worker static void write_or_complain(int fd, const void *data, size_t len)
624*49cdfc7eSAndroid Build Coastguard Worker {
625*49cdfc7eSAndroid Build Coastguard Worker 	const char *remaining = data;
626*49cdfc7eSAndroid Build Coastguard Worker 
627*49cdfc7eSAndroid Build Coastguard Worker 	while (len > 0) {
628*49cdfc7eSAndroid Build Coastguard Worker 		ssize_t ret = write(fd, remaining, len);
629*49cdfc7eSAndroid Build Coastguard Worker 		if (ret <= 0) {
630*49cdfc7eSAndroid Build Coastguard Worker 			if (errno != EAGAIN && errno != EINTR) {
631*49cdfc7eSAndroid Build Coastguard Worker 				perror("write");
632*49cdfc7eSAndroid Build Coastguard Worker 				return;
633*49cdfc7eSAndroid Build Coastguard Worker 			}
634*49cdfc7eSAndroid Build Coastguard Worker 		} else {
635*49cdfc7eSAndroid Build Coastguard Worker 			remaining += ret;
636*49cdfc7eSAndroid Build Coastguard Worker 			len -= ret;
637*49cdfc7eSAndroid Build Coastguard Worker 		}
638*49cdfc7eSAndroid Build Coastguard Worker 	}
639*49cdfc7eSAndroid Build Coastguard Worker }
640*49cdfc7eSAndroid Build Coastguard Worker 
641*49cdfc7eSAndroid Build Coastguard Worker /* Write the given data to the existing file specified by pathname.  Complain
642*49cdfc7eSAndroid Build Coastguard Worker  * if unable to do so. */
write_file(const char * pathname,const void * data,size_t len)643*49cdfc7eSAndroid Build Coastguard Worker static void write_file(const char *pathname, const void *data, size_t len)
644*49cdfc7eSAndroid Build Coastguard Worker {
645*49cdfc7eSAndroid Build Coastguard Worker 	int fd = open(pathname, O_WRONLY);
646*49cdfc7eSAndroid Build Coastguard Worker 	if (fd < 0) {
647*49cdfc7eSAndroid Build Coastguard Worker 		printf("Failed to open file \"%s\": %d (%s)\n",
648*49cdfc7eSAndroid Build Coastguard Worker 		       pathname, errno, strerror(errno));
649*49cdfc7eSAndroid Build Coastguard Worker 		return;
650*49cdfc7eSAndroid Build Coastguard Worker 	}
651*49cdfc7eSAndroid Build Coastguard Worker 
652*49cdfc7eSAndroid Build Coastguard Worker 	write_or_complain(fd, data, len);
653*49cdfc7eSAndroid Build Coastguard Worker 
654*49cdfc7eSAndroid Build Coastguard Worker 	if (close(fd) < 0) {
655*49cdfc7eSAndroid Build Coastguard Worker 		printf("Failed to close file \"%s\": %d (%s)\n",
656*49cdfc7eSAndroid Build Coastguard Worker 		       pathname, errno, strerror(errno));
657*49cdfc7eSAndroid Build Coastguard Worker 	}
658*49cdfc7eSAndroid Build Coastguard Worker }
659*49cdfc7eSAndroid Build Coastguard Worker 
660*49cdfc7eSAndroid Build Coastguard Worker /* Write the given '\0'-terminated string to the existing file specified by
661*49cdfc7eSAndroid Build Coastguard Worker  * pathname.  Complain if unable to do so. */
write_string_to_file(const char * pathname,const char * string)662*49cdfc7eSAndroid Build Coastguard Worker static void write_string_to_file(const char *pathname, const char *string)
663*49cdfc7eSAndroid Build Coastguard Worker {
664*49cdfc7eSAndroid Build Coastguard Worker 	write_file(pathname, string, strlen(string));
665*49cdfc7eSAndroid Build Coastguard Worker }
666*49cdfc7eSAndroid Build Coastguard Worker 
read_and_print(const char * pathname,int output_fd)667*49cdfc7eSAndroid Build Coastguard Worker static void read_and_print(const char *pathname, int output_fd)
668*49cdfc7eSAndroid Build Coastguard Worker {
669*49cdfc7eSAndroid Build Coastguard Worker 	char data[4096];
670*49cdfc7eSAndroid Build Coastguard Worker 	int fd = open(pathname, O_RDONLY);
671*49cdfc7eSAndroid Build Coastguard Worker 	if (fd < 0) {
672*49cdfc7eSAndroid Build Coastguard Worker 		printf("Failed to open file \"%s\": %d (%s)\n",
673*49cdfc7eSAndroid Build Coastguard Worker 		       pathname, errno, strerror(errno));
674*49cdfc7eSAndroid Build Coastguard Worker 		return;
675*49cdfc7eSAndroid Build Coastguard Worker 	}
676*49cdfc7eSAndroid Build Coastguard Worker 
677*49cdfc7eSAndroid Build Coastguard Worker 	while (1) {
678*49cdfc7eSAndroid Build Coastguard Worker 		ssize_t ret = read(fd, data, sizeof(data));
679*49cdfc7eSAndroid Build Coastguard Worker 		if (ret < 0) {
680*49cdfc7eSAndroid Build Coastguard Worker 			if (errno != EAGAIN && errno != EINTR) {
681*49cdfc7eSAndroid Build Coastguard Worker 				printf
682*49cdfc7eSAndroid Build Coastguard Worker 				    ("Failed to read from file \"%s\": %d (%s)\n",
683*49cdfc7eSAndroid Build Coastguard Worker 				     pathname, errno, strerror(errno));
684*49cdfc7eSAndroid Build Coastguard Worker 				break;
685*49cdfc7eSAndroid Build Coastguard Worker 			}
686*49cdfc7eSAndroid Build Coastguard Worker 		} else if (ret == 0)
687*49cdfc7eSAndroid Build Coastguard Worker 			break;
688*49cdfc7eSAndroid Build Coastguard Worker 		else
689*49cdfc7eSAndroid Build Coastguard Worker 			write_or_complain(output_fd, data, ret);
690*49cdfc7eSAndroid Build Coastguard Worker 	}
691*49cdfc7eSAndroid Build Coastguard Worker 
692*49cdfc7eSAndroid Build Coastguard Worker 	if (close(fd) < 0) {
693*49cdfc7eSAndroid Build Coastguard Worker 		printf("Failed to close file \"%s\": %d (%s)\n",
694*49cdfc7eSAndroid Build Coastguard Worker 		       pathname, errno, strerror(errno));
695*49cdfc7eSAndroid Build Coastguard Worker 	}
696*49cdfc7eSAndroid Build Coastguard Worker }
697*49cdfc7eSAndroid Build Coastguard Worker 
latency_trace_enable(void)698*49cdfc7eSAndroid Build Coastguard Worker void latency_trace_enable(void)
699*49cdfc7eSAndroid Build Coastguard Worker {
700*49cdfc7eSAndroid Build Coastguard Worker 	printf("Enabling latency tracer.\n");
701*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_use_raw_cycles", "1");
702*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_all_cpus", "1");
703*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_enabled", "1");
704*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_freerunning", "1");
705*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_print_on_crash", "0");
706*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_user_triggered", "1");
707*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_user_trigger_irq", "-1");
708*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/trace_verbose", "0");
709*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/preempt_thresh", "0");
710*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/wakeup_timing", "0");
711*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/mcount_enabled", "1");
712*49cdfc7eSAndroid Build Coastguard Worker 	write_string_to_file("/proc/sys/kernel/preempt_max_latency", "0");
713*49cdfc7eSAndroid Build Coastguard Worker }
714*49cdfc7eSAndroid Build Coastguard Worker 
715*49cdfc7eSAndroid Build Coastguard Worker #ifndef PR_SET_TRACING
716*49cdfc7eSAndroid Build Coastguard Worker #define PR_SET_TRACING 0
717*49cdfc7eSAndroid Build Coastguard Worker #endif
718*49cdfc7eSAndroid Build Coastguard Worker 
latency_trace_start(void)719*49cdfc7eSAndroid Build Coastguard Worker void latency_trace_start(void)
720*49cdfc7eSAndroid Build Coastguard Worker {
721*49cdfc7eSAndroid Build Coastguard Worker 	if (prctl(PR_SET_TRACING, 1) < 0)
722*49cdfc7eSAndroid Build Coastguard Worker 		perror("Failed to start tracing");
723*49cdfc7eSAndroid Build Coastguard Worker }
724*49cdfc7eSAndroid Build Coastguard Worker 
latency_trace_stop(void)725*49cdfc7eSAndroid Build Coastguard Worker void latency_trace_stop(void)
726*49cdfc7eSAndroid Build Coastguard Worker {
727*49cdfc7eSAndroid Build Coastguard Worker 	if (prctl(PR_SET_TRACING, 0) < 0)
728*49cdfc7eSAndroid Build Coastguard Worker 		perror("Failed to stop tracing");
729*49cdfc7eSAndroid Build Coastguard Worker }
730*49cdfc7eSAndroid Build Coastguard Worker 
latency_trace_print(void)731*49cdfc7eSAndroid Build Coastguard Worker void latency_trace_print(void)
732*49cdfc7eSAndroid Build Coastguard Worker {
733*49cdfc7eSAndroid Build Coastguard Worker 	read_and_print("/proc/latency_trace", STDOUT_FILENO);
734*49cdfc7eSAndroid Build Coastguard Worker }
735