1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci	* Copyright (C) Bull S.A. 2001
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/* Dec-03-2001  Created: Jacky Malcles & Jean Noel Cordenner		  */
23f08c3bdfSopenharmony_ci/*	      These tests are adapted from AIX float PVT tests.	     */
24f08c3bdfSopenharmony_ci/*									    */
25f08c3bdfSopenharmony_ci/******************************************************************************/
26f08c3bdfSopenharmony_ci#include "tfloat.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#include "test.h"
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci#define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
31f08c3bdfSopenharmony_ci/* LTP status reporting */
32f08c3bdfSopenharmony_cichar *TCID;			/* Test program identifier.    */
33f08c3bdfSopenharmony_ciint TST_TOTAL = 1;		/* Total number of test cases. */
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci/* To avoid extensive modifications to the code, use this bodge */
36f08c3bdfSopenharmony_ci#define exit(x) myexit(x)
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_civoid myexit(int x)
39f08c3bdfSopenharmony_ci{
40f08c3bdfSopenharmony_ci	if (x)
41f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "Test failed");
42f08c3bdfSopenharmony_ci	else
43f08c3bdfSopenharmony_ci		tst_resm(TPASS, "Test passed");
44f08c3bdfSopenharmony_ci	tst_exit();
45f08c3bdfSopenharmony_ci}
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ciTH_DATA *pcom;
48f08c3bdfSopenharmony_ciTH_DATA **tabcom;
49f08c3bdfSopenharmony_ciTH_DATA **tabcour;
50f08c3bdfSopenharmony_ci#ifndef	PATH_MAX
51f08c3bdfSopenharmony_ci#define PATH_MAX		1024
52f08c3bdfSopenharmony_ci#endif
53f08c3bdfSopenharmony_cichar datadir[PATH_MAX];		/* DATA directory */
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci#ifndef PTHREAD_THREADS_MAX
56f08c3bdfSopenharmony_ci#define PTHREAD_THREADS_MAX	1024
57f08c3bdfSopenharmony_ci#endif
58f08c3bdfSopenharmony_ci#define DEFAULT_NUM_THREADS	20
59f08c3bdfSopenharmony_ciint num_threads = DEFAULT_NUM_THREADS;
60f08c3bdfSopenharmony_ciint num_loops = 500;
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ciint sig_cancel = 0;		/* flag set by handle_signals to tell initial thread
63f08c3bdfSopenharmony_ci				   to stop creating new threads (signal caught) */
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ciint indice = 0;			/* # of threads created, to be canceled by handle_signals
66f08c3bdfSopenharmony_ci				   or waited for by initial thread */
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_cipthread_mutex_t sig_mutex;
69f08c3bdfSopenharmony_cipthread_t *threads;
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ciint debug = 0;
72f08c3bdfSopenharmony_ciint true = 1;
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_cistatic void *handle_signals(void *);
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_cistatic void sys_error(const char *, int);
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ciconst double EPS = 0.1e-300;
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ciconst int nb_func = NB_FUNC;
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ciint generate(char *datadir, char *bin_path)
83f08c3bdfSopenharmony_ci{
84f08c3bdfSopenharmony_ci	char *cmdline;
85f08c3bdfSopenharmony_ci	char *fmt = "cd %s; %s/%s %s";
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci	cmdline = malloc(2 * strlen(bin_path) + strlen(datadir) + strlen(GENERATOR) + strlen(fmt));
88f08c3bdfSopenharmony_ci	if (cmdline == NULL)
89f08c3bdfSopenharmony_ci		return (1);
90f08c3bdfSopenharmony_ci	sprintf(cmdline, fmt, datadir, bin_path, GENERATOR, bin_path);
91f08c3bdfSopenharmony_ci	system(cmdline);
92f08c3bdfSopenharmony_ci	free(cmdline);
93f08c3bdfSopenharmony_ci	return (0);
94f08c3bdfSopenharmony_ci}
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_cistatic void cleanup(void)
97f08c3bdfSopenharmony_ci{
98f08c3bdfSopenharmony_ci	tst_rmdir();
99f08c3bdfSopenharmony_ci}
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
102f08c3bdfSopenharmony_ci{
103f08c3bdfSopenharmony_ci	int opt = 0;
104f08c3bdfSopenharmony_ci	pid_t pid;
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci	char *bin_path, *ltproot;
107f08c3bdfSopenharmony_ci	void *exit_value;
108f08c3bdfSopenharmony_ci	pthread_attr_t newattr;
109f08c3bdfSopenharmony_ci	pthread_t sig_hand;
110f08c3bdfSopenharmony_ci	size_t stacksize = 2093056;
111f08c3bdfSopenharmony_ci	int th_num;
112f08c3bdfSopenharmony_ci	int retvalend = 0;
113f08c3bdfSopenharmony_ci	int retval = 0;
114f08c3bdfSopenharmony_ci	int error = 0;
115f08c3bdfSopenharmony_ci	/*int time=1; */
116f08c3bdfSopenharmony_ci	int i;
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	/* Generate test ID from invocation name */
119f08c3bdfSopenharmony_ci	if ((TCID = strrchr(argv[0], '/')) != NULL)
120f08c3bdfSopenharmony_ci		TCID++;
121f08c3bdfSopenharmony_ci	else
122f08c3bdfSopenharmony_ci		TCID = argv[0];
123f08c3bdfSopenharmony_ci	ltproot = getenv("LTPROOT");
124f08c3bdfSopenharmony_ci	if (ltproot == NULL || strlen(ltproot) == 0) {
125f08c3bdfSopenharmony_ci		tst_brkm(TBROK, NULL,
126f08c3bdfSopenharmony_ci			 "You must set $LTPROOT before executing this test");
127f08c3bdfSopenharmony_ci	}
128f08c3bdfSopenharmony_ci	bin_path = malloc(strlen(ltproot) + 16);
129f08c3bdfSopenharmony_ci	if (bin_path == NULL) {
130f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, NULL, "malloc failed");
131f08c3bdfSopenharmony_ci	}
132f08c3bdfSopenharmony_ci	sprintf(bin_path, "%s/testcases/bin", ltproot);
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_ci	tst_tmpdir();
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci	setbuf(stdout, NULL);
137f08c3bdfSopenharmony_ci	setbuf(stderr, NULL);
138f08c3bdfSopenharmony_ci	datadir[0] = '.';
139f08c3bdfSopenharmony_ci	datadir[1] = '\0';
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci	if (argc != 1) {
142f08c3bdfSopenharmony_ci		while ((opt = getopt(argc, argv, "vn:l:D:?")) != EOF) {
143f08c3bdfSopenharmony_ci			switch (opt) {
144f08c3bdfSopenharmony_ci			case 'D':
145f08c3bdfSopenharmony_ci				strncpy(datadir, optarg, PATH_MAX);
146f08c3bdfSopenharmony_ci				break;
147f08c3bdfSopenharmony_ci			case 'l':
148f08c3bdfSopenharmony_ci				num_loops = atoi(optarg);
149f08c3bdfSopenharmony_ci				break;
150f08c3bdfSopenharmony_ci			case 'n':
151f08c3bdfSopenharmony_ci				num_threads = atoi(optarg);
152f08c3bdfSopenharmony_ci				break;
153f08c3bdfSopenharmony_ci			case 'v':
154f08c3bdfSopenharmony_ci				++debug;	/* verbose mode */
155f08c3bdfSopenharmony_ci				break;
156f08c3bdfSopenharmony_ci			default:
157f08c3bdfSopenharmony_ci				fprintf(stderr,
158f08c3bdfSopenharmony_ci					"usage: %s [-n number_of_threads] [-v]\n",
159f08c3bdfSopenharmony_ci					argv[0]);
160f08c3bdfSopenharmony_ci				fprintf(stderr, "[-l number_of_loops] ");
161f08c3bdfSopenharmony_ci				fprintf(stderr, "[-D DATAs absolute path]\n");
162f08c3bdfSopenharmony_ci				exit(1);
163f08c3bdfSopenharmony_ci			}
164f08c3bdfSopenharmony_ci		}
165f08c3bdfSopenharmony_ci	}
166f08c3bdfSopenharmony_ci	switch (pid = fork()) {
167f08c3bdfSopenharmony_ci	case -1:
168f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
169f08c3bdfSopenharmony_ci	case 0:
170f08c3bdfSopenharmony_ci		generate(datadir, bin_path);
171f08c3bdfSopenharmony_ci		exit(0);
172f08c3bdfSopenharmony_ci	default:
173f08c3bdfSopenharmony_ci		waitpid(pid, NULL, 0);
174f08c3bdfSopenharmony_ci	}
175f08c3bdfSopenharmony_ci	SAFE_FREE(bin_path);
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	if (debug) {
178f08c3bdfSopenharmony_ci		tst_resm(TINFO,
179f08c3bdfSopenharmony_ci			 "%s: will run for %d loops; using %s as a data directory",
180f08c3bdfSopenharmony_ci			 argv[0], num_loops, datadir);
181f08c3bdfSopenharmony_ci	}
182f08c3bdfSopenharmony_ci	if (num_threads <= 0) {
183f08c3bdfSopenharmony_ci		tst_resm(TWARN,
184f08c3bdfSopenharmony_ci			 "num_threads undefined or incorrect, using \"1\"");
185f08c3bdfSopenharmony_ci		num_threads = 1;
186f08c3bdfSopenharmony_ci	}
187f08c3bdfSopenharmony_ci
188f08c3bdfSopenharmony_ci	if (nb_func * num_threads > PTHREAD_THREADS_MAX - 2)
189f08c3bdfSopenharmony_ci		while (nb_func * num_threads > PTHREAD_THREADS_MAX - 2)
190f08c3bdfSopenharmony_ci			num_threads--;
191f08c3bdfSopenharmony_ci	if (debug)
192f08c3bdfSopenharmony_ci		tst_resm(TINFO,
193f08c3bdfSopenharmony_ci			 "%s: will run %d functions, %d threads per function",
194f08c3bdfSopenharmony_ci			 argv[0], nb_func, num_threads);
195f08c3bdfSopenharmony_ci
196f08c3bdfSopenharmony_ci	retval = pthread_mutex_init(&sig_mutex, NULL);
197f08c3bdfSopenharmony_ci	if (retval != 0)
198f08c3bdfSopenharmony_ci		sys_error("main : mutex_init(&sig_mutex) FAILED", __LINE__);
199f08c3bdfSopenharmony_ci
200f08c3bdfSopenharmony_ci	retval = pthread_create(&sig_hand, NULL, handle_signals, NULL);
201f08c3bdfSopenharmony_ci	if (retval != 0)
202f08c3bdfSopenharmony_ci		sys_error("main : create(&sig_hand) FAILED", __LINE__);
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_ci	/*
205f08c3bdfSopenharmony_ci	 * Start all calculation threads...
206f08c3bdfSopenharmony_ci	 */
207f08c3bdfSopenharmony_ci	threads = malloc(nb_func * num_threads * sizeof(pthread_t));
208f08c3bdfSopenharmony_ci	if (threads == NULL)
209f08c3bdfSopenharmony_ci		tst_brkm(TFAIL | TERRNO, cleanup, "malloc failed");
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	tabcom = malloc((sizeof(TH_DATA *) * nb_func * num_threads));
212f08c3bdfSopenharmony_ci	if (!tabcom)
213f08c3bdfSopenharmony_ci		tst_brkm(TFAIL | TERRNO, cleanup, "malloc failed");
214f08c3bdfSopenharmony_ci	tabcour = tabcom;
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	retval = pthread_attr_init(&newattr);
217f08c3bdfSopenharmony_ci	if (retval != 0)
218f08c3bdfSopenharmony_ci		sys_error("main : attr_init(&newattr) FAILED", __LINE__);
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	if (pthread_attr_setstacksize(&newattr, stacksize))
221f08c3bdfSopenharmony_ci		sys_error("main: pthread_attr_setstacksize failed", __LINE__);
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci	retval = pthread_attr_setdetachstate(&newattr, PTHREAD_CREATE_JOINABLE);
224f08c3bdfSopenharmony_ci	if (retval != 0)
225f08c3bdfSopenharmony_ci		sys_error("main : attr_setdetachstate(&newattr) FAILED",
226f08c3bdfSopenharmony_ci			  __LINE__);
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci	/* run the nb_func functions on num_threads */
229f08c3bdfSopenharmony_ci
230f08c3bdfSopenharmony_ci	indice = 0;
231f08c3bdfSopenharmony_ci	for (i = 0; i < nb_func; i++) {
232f08c3bdfSopenharmony_ci
233f08c3bdfSopenharmony_ci		for (th_num = 0; th_num < num_threads; th_num++) {
234f08c3bdfSopenharmony_ci
235f08c3bdfSopenharmony_ci			/* allocate struct of commucation  with the thread */
236f08c3bdfSopenharmony_ci			pcom = calloc(1, sizeof(TH_DATA));
237f08c3bdfSopenharmony_ci			if (pcom == NULL)
238f08c3bdfSopenharmony_ci				tst_brkm(TFAIL | TERRNO, cleanup,
239f08c3bdfSopenharmony_ci					 "calloc failed");
240f08c3bdfSopenharmony_ci			*tabcour = (TH_DATA *) pcom;
241f08c3bdfSopenharmony_ci			tabcour++;
242f08c3bdfSopenharmony_ci			/*
243f08c3bdfSopenharmony_ci			 * update structure of communication
244f08c3bdfSopenharmony_ci			 */
245f08c3bdfSopenharmony_ci			pcom->th_num = th_num;
246f08c3bdfSopenharmony_ci			pcom->th_func = th_func[i];
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_ci			pthread_mutex_lock(&sig_mutex);
249f08c3bdfSopenharmony_ci
250f08c3bdfSopenharmony_ci			if (sig_cancel) {	/* stop processing right now! */
251f08c3bdfSopenharmony_ci				pthread_mutex_unlock(&sig_mutex);
252f08c3bdfSopenharmony_ci				goto finished;
253f08c3bdfSopenharmony_ci			}
254f08c3bdfSopenharmony_ci			retval = pthread_create(&threads[indice], &newattr,
255f08c3bdfSopenharmony_ci						thread_code, (void *)pcom);
256f08c3bdfSopenharmony_ci			if (retval != 0)
257f08c3bdfSopenharmony_ci				sys_error("main : create FAILED", __LINE__);
258f08c3bdfSopenharmony_ci			indice++;
259f08c3bdfSopenharmony_ci			pthread_mutex_unlock(&sig_mutex);
260f08c3bdfSopenharmony_ci
261f08c3bdfSopenharmony_ci		}		/* num_threads */
262f08c3bdfSopenharmony_ci	}			/* for i */
263f08c3bdfSopenharmony_ci
264f08c3bdfSopenharmony_ci	/*alarm(60*time); *//* start all threads for TEST_time */
265f08c3bdfSopenharmony_ci
266f08c3bdfSopenharmony_ci	/*
267f08c3bdfSopenharmony_ci	 * Wait for the threads finish their task
268f08c3bdfSopenharmony_ci	 * pthread_join () will block
269f08c3bdfSopenharmony_ci	 */
270f08c3bdfSopenharmony_ci
271f08c3bdfSopenharmony_cifinished:
272f08c3bdfSopenharmony_ci	if (debug) {
273f08c3bdfSopenharmony_ci		tst_resm(TINFO,
274f08c3bdfSopenharmony_ci			 "initial thread: Waiting for %d threads to finish",
275f08c3bdfSopenharmony_ci			 indice);
276f08c3bdfSopenharmony_ci	}
277f08c3bdfSopenharmony_ci	tabcour = tabcom;
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci	for (th_num = 0; th_num < indice; th_num++) {
280f08c3bdfSopenharmony_ci		retvalend = pthread_join(threads[th_num], &exit_value);
281f08c3bdfSopenharmony_ci		if (retvalend != 0)
282f08c3bdfSopenharmony_ci			sys_error("finish : join FAILED", __LINE__);
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci		/* test the result in TH_DATA : communication buffer */
285f08c3bdfSopenharmony_ci		pcom = *tabcour++;
286f08c3bdfSopenharmony_ci		if (pcom->th_result != 0) {
287f08c3bdfSopenharmony_ci			error++;
288f08c3bdfSopenharmony_ci			tst_resm(TFAIL,
289f08c3bdfSopenharmony_ci				 "thread %d (%s) terminated unsuccessfully %d "
290f08c3bdfSopenharmony_ci				 "errors/%d loops\n%s",
291f08c3bdfSopenharmony_ci				 th_num, pcom->th_func.fident, pcom->th_nerror,
292f08c3bdfSopenharmony_ci				 pcom->th_nloop, pcom->detail_data);
293f08c3bdfSopenharmony_ci		} else if (debug) {
294f08c3bdfSopenharmony_ci			tst_resm(TINFO,
295f08c3bdfSopenharmony_ci				 "thread %d (%s) terminated successfully %d loops",
296f08c3bdfSopenharmony_ci				 th_num, pcom->th_func.fident,
297f08c3bdfSopenharmony_ci				 pcom->th_nloop - 1);
298f08c3bdfSopenharmony_ci		}
299f08c3bdfSopenharmony_ci		SAFE_FREE(pcom);
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_ci	}
302f08c3bdfSopenharmony_ci	SAFE_FREE(tabcom);
303f08c3bdfSopenharmony_ci	SAFE_FREE(threads);
304f08c3bdfSopenharmony_ci	tst_rmdir();
305f08c3bdfSopenharmony_ci	if (error)
306f08c3bdfSopenharmony_ci		exit(1);
307f08c3bdfSopenharmony_ci	else
308f08c3bdfSopenharmony_ci		exit(0);
309f08c3bdfSopenharmony_ci	return 0;
310f08c3bdfSopenharmony_ci}
311f08c3bdfSopenharmony_ci
312f08c3bdfSopenharmony_ci/*----------------------------------------------------------------------+
313f08c3bdfSopenharmony_ci|			    handle_signals ()				|
314f08c3bdfSopenharmony_ci| ======================================================================|
315f08c3bdfSopenharmony_ci|									|
316f08c3bdfSopenharmony_ci| Function:  ....							|
317f08c3bdfSopenharmony_ci|	    If SIGALRM or SIGUSR1 or SIGINT : cancel threads		|
318f08c3bdfSopenharmony_ci|									|
319f08c3bdfSopenharmony_ci| Updates:   ....							|
320f08c3bdfSopenharmony_ci|									|
321f08c3bdfSopenharmony_ci+-----------------------------------------------------------------------*/
322f08c3bdfSopenharmony_cistatic void *handle_signals(void *arg)
323f08c3bdfSopenharmony_ci{
324f08c3bdfSopenharmony_ci	sigset_t signals_set;
325f08c3bdfSopenharmony_ci	int thd;
326f08c3bdfSopenharmony_ci	int sig;
327f08c3bdfSopenharmony_ci	int retvalsig = 0;
328f08c3bdfSopenharmony_ci
329f08c3bdfSopenharmony_ci	if (debug)
330f08c3bdfSopenharmony_ci		tst_resm(TINFO, "signal handler %lu started", pthread_self());
331f08c3bdfSopenharmony_ci	/*
332f08c3bdfSopenharmony_ci	 * Set up the signals that we want to handle...
333f08c3bdfSopenharmony_ci	 */
334f08c3bdfSopenharmony_ci	sigemptyset(&signals_set);
335f08c3bdfSopenharmony_ci	sigaddset(&signals_set, SIGINT);
336f08c3bdfSopenharmony_ci	sigaddset(&signals_set, SIGQUIT);
337f08c3bdfSopenharmony_ci	sigaddset(&signals_set, SIGTERM);
338f08c3bdfSopenharmony_ci	sigaddset(&signals_set, SIGUSR1);
339f08c3bdfSopenharmony_ci	sigaddset(&signals_set, SIGALRM);
340f08c3bdfSopenharmony_ci	while (1) {
341f08c3bdfSopenharmony_ci		if (debug)
342f08c3bdfSopenharmony_ci			tst_resm(TINFO, "Signal handler starts waiting...");
343f08c3bdfSopenharmony_ci
344f08c3bdfSopenharmony_ci		sigwait(&signals_set, &sig);
345f08c3bdfSopenharmony_ci		if (debug)
346f08c3bdfSopenharmony_ci			tst_resm(TINFO, "Signal handler caught signal %d", sig);
347f08c3bdfSopenharmony_ci
348f08c3bdfSopenharmony_ci		switch (sig) {
349f08c3bdfSopenharmony_ci		case SIGALRM:
350f08c3bdfSopenharmony_ci		case SIGUSR1:
351f08c3bdfSopenharmony_ci		case SIGINT:
352f08c3bdfSopenharmony_ci			if (sig_cancel)
353f08c3bdfSopenharmony_ci				tst_resm(TINFO,
354f08c3bdfSopenharmony_ci					 "Signal handler: already finished; "
355f08c3bdfSopenharmony_ci					 "ignoring signal");
356f08c3bdfSopenharmony_ci			else {
357f08c3bdfSopenharmony_ci				/*
358f08c3bdfSopenharmony_ci				 * Have to signal all non started threads...
359f08c3bdfSopenharmony_ci				 */
360f08c3bdfSopenharmony_ci
361f08c3bdfSopenharmony_ci				retvalsig = pthread_mutex_lock(&sig_mutex);
362f08c3bdfSopenharmony_ci				if (retvalsig != 0)
363f08c3bdfSopenharmony_ci					sys_error
364f08c3bdfSopenharmony_ci					    ("handle_signal : mutex_lock(&sig_mutex) FAILED",
365f08c3bdfSopenharmony_ci					     __LINE__);
366f08c3bdfSopenharmony_ci
367f08c3bdfSopenharmony_ci				sig_cancel = 1;
368f08c3bdfSopenharmony_ci				retvalsig = pthread_mutex_unlock(&sig_mutex);
369f08c3bdfSopenharmony_ci				if (retvalsig != 0)
370f08c3bdfSopenharmony_ci					sys_error
371f08c3bdfSopenharmony_ci					    ("handle_signal : mutex_unlock(&sig_mutex) FAILED",
372f08c3bdfSopenharmony_ci					     __LINE__);
373f08c3bdfSopenharmony_ci
374f08c3bdfSopenharmony_ci				/*
375f08c3bdfSopenharmony_ci				 * ......... and all started
376f08c3bdfSopenharmony_ci				 */
377f08c3bdfSopenharmony_ci				for (thd = 0; thd < indice; thd++) {
378f08c3bdfSopenharmony_ci					if (debug)
379f08c3bdfSopenharmony_ci						tst_resm(TINFO,
380f08c3bdfSopenharmony_ci							 "signal handler: "
381f08c3bdfSopenharmony_ci							 "cancelling thread (%d of "
382f08c3bdfSopenharmony_ci							 "%d)", thd, indice);
383f08c3bdfSopenharmony_ci					retvalsig =
384f08c3bdfSopenharmony_ci					    pthread_cancel(threads[thd]);
385f08c3bdfSopenharmony_ci					if (retvalsig != 0)
386f08c3bdfSopenharmony_ci						sys_error
387f08c3bdfSopenharmony_ci						    ("handle_signal : cancel FAILED",
388f08c3bdfSopenharmony_ci						     __LINE__);
389f08c3bdfSopenharmony_ci				}
390f08c3bdfSopenharmony_ci			}
391f08c3bdfSopenharmony_ci			break;
392f08c3bdfSopenharmony_ci		case SIGQUIT:
393f08c3bdfSopenharmony_ci			tst_resm(TINFO,
394f08c3bdfSopenharmony_ci				 "Signal handler: Caught SIGQUIT; doing nothing");
395f08c3bdfSopenharmony_ci			break;
396f08c3bdfSopenharmony_ci		case SIGTERM:
397f08c3bdfSopenharmony_ci			tst_resm(TINFO,
398f08c3bdfSopenharmony_ci				 "Signal handler: Caught SIGTERM; doing nothing");
399f08c3bdfSopenharmony_ci			break;
400f08c3bdfSopenharmony_ci		default:
401f08c3bdfSopenharmony_ci			exit(1);
402f08c3bdfSopenharmony_ci		}
403f08c3bdfSopenharmony_ci	}
404f08c3bdfSopenharmony_ci	return NULL;
405f08c3bdfSopenharmony_ci}
406f08c3bdfSopenharmony_ci
407f08c3bdfSopenharmony_ci/*----------------------------------------------------------------------+
408f08c3bdfSopenharmony_ci |				error ()				|
409f08c3bdfSopenharmony_ci | =====================================================================|
410f08c3bdfSopenharmony_ci |									|
411f08c3bdfSopenharmony_ci | Function:  Prints out message and exits...				|
412f08c3bdfSopenharmony_ci |									|
413f08c3bdfSopenharmony_ci +----------------------------------------------------------------------*/
414f08c3bdfSopenharmony_cistatic void error(const char *msg, int line)
415f08c3bdfSopenharmony_ci{
416f08c3bdfSopenharmony_ci	tst_brkm(TFAIL, cleanup, "ERROR [line: %d] %s", line, msg);
417f08c3bdfSopenharmony_ci}
418f08c3bdfSopenharmony_ci
419f08c3bdfSopenharmony_ci/*----------------------------------------------------------------------+
420f08c3bdfSopenharmony_ci |			     sys_error ()				|
421f08c3bdfSopenharmony_ci | =====================================================================|
422f08c3bdfSopenharmony_ci |									|
423f08c3bdfSopenharmony_ci | Function:  Creates system error message and calls error ()		|
424f08c3bdfSopenharmony_ci |									|
425f08c3bdfSopenharmony_ci +----------------------------------------------------------------------*/
426f08c3bdfSopenharmony_ci/*
427f08c3bdfSopenharmony_ci * XXX (garrcoop): the way that this is being called is just plain wrong.
428f08c3bdfSopenharmony_ci * pthread(5) returns 0 or errnos, not necessarily sets errno to a sensible
429f08c3bdfSopenharmony_ci * value.
430f08c3bdfSopenharmony_ci */
431f08c3bdfSopenharmony_cistatic void sys_error(const char *msg, int line)
432f08c3bdfSopenharmony_ci{
433f08c3bdfSopenharmony_ci	char syserr_msg[256];
434f08c3bdfSopenharmony_ci
435f08c3bdfSopenharmony_ci	sprintf(syserr_msg, "%s: %s", msg, strerror(errno));
436f08c3bdfSopenharmony_ci	error(syserr_msg, line);
437f08c3bdfSopenharmony_ci}
438