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., 59
15 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17
18
19 * This sample test aims to check the following assertion:
20 * If the mutex type is PTHREAD_MUTEX_RECURSIVE,
21 * and a thread attempts to unlock a mutex that it does not own,
22 * an error is returned.
23
24 * The steps are:
25 *  -> Initialize and lock a recursive mutex
26 *  -> create a child thread which tries to unlock this mutex. *
27 */
28
29 /*
30  * - adam.li@intel.com 2004-05-20
31  *   Add to PTS. Please refer to http://nptl.bullopensource.org/phpBB/
32  *   for general information
33  */
34
35 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
36 #define _POSIX_C_SOURCE 200112L
37
38 /* We enable the following line to have mutex attributes defined */
39#ifndef WITHOUT_XOPEN
40 #define _XOPEN_SOURCE	600
41
42/********************************************************************************************/
43/****************************** standard includes *****************************************/
44/********************************************************************************************/
45 #include <pthread.h>
46 #include <unistd.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <stdarg.h>
50
51 #include <errno.h> /* needed for EPERM test */
52
53/********************************************************************************************/
54/******************************   Test framework   *****************************************/
55/********************************************************************************************/
56 #include "testfrmw.h"
57 #include "testfrmw.c"
58 /* This header is responsible for defining the following macros:
59  * UNRESOLVED(ret, descr);
60  *    where descr is a description of the error and ret is an int (error code for example)
61  * FAILED(descr);
62  *    where descr is a short text saying why the test has failed.
63  * PASSED();
64  *    No parameter.
65  *
66  * Both three macros shall terminate the calling process.
67  * The testcase shall not terminate in any other maneer.
68  *
69  * The other file defines the functions
70  * void output_init()
71  * void output(char * string, ...)
72  *
73  * Those may be used to output information.
74  */
75
76/********************************************************************************************/
77/********************************** Configuration ******************************************/
78/********************************************************************************************/
79#ifndef VERBOSE
80#define VERBOSE 1
81#endif
82
83/********************************************************************************************/
84/***********************************    Test case   *****************************************/
85/********************************************************************************************/
86
87pthread_mutex_t m;
88
89/** child thread function **/
90void * threaded(void * arg)
91{
92	int ret;
93	ret = pthread_mutex_unlock(&m);
94	if (ret == 0)
95	{  UNRESOLVED(ret, "Unlocking a not owned recursive mutex succeeded");  }
96
97	if (ret != EPERM) /* This is a "may" assertion */
98		output("Unlocking a not owned recursive mutex did not return EPERM\n");
99
100	return NULL;
101}
102
103/** parent thread function **/
104int main(int argc, char * argv[])
105{
106	int ret;
107	pthread_mutexattr_t ma;
108	pthread_t  th;
109
110	output_init();
111
112	#if VERBOSE >1
113	output("Initialize the PTHREAD_MUTEX_RECURSIVE mutex\n");
114	#endif
115
116	ret = pthread_mutexattr_init(&ma);
117	if (ret != 0)
118	{  UNRESOLVED(ret, "Mutex attribute init failed");  }
119
120	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
121	if (ret != 0)
122	{  UNRESOLVED(ret, "Set type recursive failed");  }
123
124	ret = pthread_mutex_init(&m, &ma);
125	if (ret != 0)
126	{  UNRESOLVED(ret, "Mutex init failed");  }
127
128	#if VERBOSE >1
129	output("Lock the mutex\n");
130	#endif
131
132	ret = pthread_mutex_lock(&m);
133	if (ret != 0)
134	{  UNRESOLVED(ret, "Mutex lock failed");  }
135
136	/* destroy the mutex attribute object */
137	ret = pthread_mutexattr_destroy(&ma);
138	if (ret != 0)
139	{  UNRESOLVED(ret, "Mutex attribute destroy failed");  }
140
141	#if VERBOSE >1
142	output("Create the thread\n");
143	#endif
144
145	ret = pthread_create(&th, NULL, threaded, NULL);
146	if (ret != 0)
147	{  UNRESOLVED(ret, "Thread creation failed");  }
148
149	/* Let the thread terminate */
150	ret = pthread_join(th, NULL);
151	if (ret != 0)
152	{  UNRESOLVED(ret, "Thread join failed");  }
153
154	#if VERBOSE >1
155	output("Joined the thread\n");
156	#endif
157
158	/* We can clean everything and exit */
159	ret = pthread_mutex_unlock(&m);
160	if (ret != 0)
161	{  UNRESOLVED(ret, "Mutex unlock failed. Mutex got corrupted?");  }
162
163	PASSED;
164}
165#else /* WITHOUT_XOPEN */
166int main(int argc, char * argv[])
167{
168	output_init();
169	UNTESTED("This test requires XSI features");
170}
171#endif
172
173