1/*
2 * Copyright (c) 2004, Bull S.A..  All rights reserved.
3 * Created by: Sebastien Decugis
4
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 * This sample test aims to check the following assertion:
18 *
19 * If the current thread has an alternate stack, the new thread does not inherit
20 * this stack
21
22 * The steps are:
23 * -> Create a thread with an alternate stack.
24 * -> From this thread, create another thread.
25 * -> Check that the new thread does not use the same stack.
26
27 */
28
29 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
30#define _POSIX_C_SOURCE 200112L
31
32 /* Some routines are part of the XSI Extensions */
33#ifndef WITHOUT_XOPEN
34#define _XOPEN_SOURCE	600
35#endif
36/********************************************************************************************/
37/****************************** standard includes *****************************************/
38/********************************************************************************************/
39#include <pthread.h>
40#include <stdarg.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46#include <sched.h>
47#include <semaphore.h>
48#include <errno.h>
49#include <assert.h>
50#include <sys/wait.h>
51
52/********************************************************************************************/
53/******************************   Test framework   *****************************************/
54/********************************************************************************************/
55#include "../testfrmw/testfrmw.h"
56#include "../testfrmw/testfrmw.c"
57 /* This header is responsible for defining the following macros:
58  * UNRESOLVED(ret, descr);
59  *    where descr is a description of the error and ret is an int (error code for example)
60  * FAILED(descr);
61  *    where descr is a short text saying why the test has failed.
62  * PASSED();
63  *    No parameter.
64  *
65  * Both three macros shall terminate the calling process.
66  * The testcase shall not terminate in any other maneer.
67  *
68  * The other file defines the functions
69  * void output_init()
70  * void output(char * string, ...)
71  *
72  * Those may be used to output information.
73  */
74
75/********************************************************************************************/
76/********************************** Configuration ******************************************/
77/********************************************************************************************/
78#ifndef VERBOSE
79#define VERBOSE 1
80#endif
81
82/********************************************************************************************/
83/***********************************    Test cases  *****************************************/
84/********************************************************************************************/
85
86#define STD_MAIN
87#include "../testfrmw/threads_scenarii.c"
88
89/* This file will define the following objects:
90 * scenarii: array of struct __scenario type.
91 * NSCENAR : macro giving the total # of scenarii
92 * scenar_init(): function to call before use the scenarii array.
93 * scenar_fini(): function to call after end of use of the scenarii array.
94 */
95
96/********************************************************************************************/
97/***********************************    Real Test   *****************************************/
98/********************************************************************************************/
99
100void *teststack(void *arg)
101{
102	int ret = 0;
103	*(int **)arg = &ret;
104	return NULL;
105}
106
107/* Thread function */
108void *threaded(void *arg)
109{
110	int ret;
111	int *child_stack;
112	pthread_t gchild;
113
114	int sz = sysconf(_SC_THREAD_STACK_MIN);
115
116	if (scenarii[sc].bottom != NULL) {
117#if VERBOSE > 1
118		output("Processing test\n");
119#endif
120
121		/* Create a new thread and get a location inside its stack */
122		ret = pthread_create(&gchild, NULL, teststack, &child_stack);
123		if (ret != 0) {
124			UNRESOLVED(ret,
125				   "Failed to create a thread with default attribute");
126		}
127
128		ret = pthread_join(gchild, NULL);
129		if (ret != 0) {
130			UNRESOLVED(ret, "Failed to join the test thread");
131		}
132
133		/* Check the new thread stack location was outside of the current thread location */
134		/* We convert all the @ to longs */
135#if VERBOSE > 4
136		output("Current stack : %p -> %p\n", scenarii[sc].bottom,
137		       sz + (long)scenarii[sc].bottom);
138		output("Child location: %p\n", child_stack);
139#endif
140
141		if ((((long)scenarii[sc].bottom) < ((long)child_stack))
142		    && (((long)child_stack) <
143			(((long)scenarii[sc].bottom) + sz))) {
144			FAILED
145			    ("The new thread inherited th alternate stack from its parent");
146		}
147	}
148
149	/* Signal we're done (especially in case of a detached thread) */
150	do {
151		ret = sem_post(&scenarii[sc].sem);
152	}
153	while ((ret == -1) && (errno == EINTR));
154	if (ret == -1) {
155		UNRESOLVED(errno, "Failed to wait for the semaphore");
156	}
157
158	/* return */
159	return arg;
160}
161