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
18 * This sample test aims to check the following assertion:
19 * If the mutex type is PTHREAD_MUTEX_RECURSIVE,
20 * and a thread attempts to unlock a mutex that it does not own,
21 * an error is returned.
22
23 * The steps are:
24 *  -> Initialize and lock a recursive mutex
25 *  -> create a child thread which tries to unlock this mutex. *
26 */
27
28 /*
29  * - adam.li@intel.com 2004-05-20
30  *   Add to PTS. Please refer to http://nptl.bullopensource.org/phpBB/
31  *   for general information
32  */
33
34 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
35#define _POSIX_C_SOURCE 200112L
36
37 /* We enable the following line to have mutex attributes defined */
38#ifndef WITHOUT_XOPEN
39#define _XOPEN_SOURCE	600
40
41/********************************************************************************************/
42/****************************** standard includes *****************************************/
43/********************************************************************************************/
44#include <pthread.h>
45#include <unistd.h>
46#include <stdlib.h>
47#include <stdio.h>
48#include <stdarg.h>
49
50#include <errno.h>		/* needed for EPERM test */
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 case   *****************************************/
84/********************************************************************************************/
85
86pthread_mutex_t m;
87
88/** child thread function **/
89void *threaded(void *arg)
90{
91	int ret;
92	ret = pthread_mutex_unlock(&m);
93	if (ret == 0) {
94		UNRESOLVED(ret,
95			   "Unlocking a not owned recursive mutex succeeded");
96	}
97
98	if (ret != EPERM)	/* This is a "may" assertion */
99		output
100		    ("Unlocking a not owned recursive mutex did not return EPERM\n");
101
102	return NULL;
103}
104
105/** parent thread function **/
106int main(void)
107{
108	int ret;
109	pthread_mutexattr_t ma;
110	pthread_t th;
111
112	output_init();
113
114#if VERBOSE >1
115	output("Initialize the PTHREAD_MUTEX_RECURSIVE mutex\n");
116#endif
117
118	ret = pthread_mutexattr_init(&ma);
119	if (ret != 0) {
120		UNRESOLVED(ret, "Mutex attribute init failed");
121	}
122
123	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
124	if (ret != 0) {
125		UNRESOLVED(ret, "Set type recursive failed");
126	}
127
128	ret = pthread_mutex_init(&m, &ma);
129	if (ret != 0) {
130		UNRESOLVED(ret, "Mutex init failed");
131	}
132#if VERBOSE >1
133	output("Lock the mutex\n");
134#endif
135
136	ret = pthread_mutex_lock(&m);
137	if (ret != 0) {
138		UNRESOLVED(ret, "Mutex lock failed");
139	}
140
141	/* destroy the mutex attribute object */
142	ret = pthread_mutexattr_destroy(&ma);
143	if (ret != 0) {
144		UNRESOLVED(ret, "Mutex attribute destroy failed");
145	}
146#if VERBOSE >1
147	output("Create the thread\n");
148#endif
149
150	ret = pthread_create(&th, NULL, threaded, NULL);
151	if (ret != 0) {
152		UNRESOLVED(ret, "Thread creation failed");
153	}
154
155	/* Let the thread terminate */
156	ret = pthread_join(th, NULL);
157	if (ret != 0) {
158		UNRESOLVED(ret, "Thread join failed");
159	}
160#if VERBOSE >1
161	output("Joined the thread\n");
162#endif
163
164	/* We can clean everything and exit */
165	ret = pthread_mutex_unlock(&m);
166	if (ret != 0) {
167		UNRESOLVED(ret, "Mutex unlock failed. Mutex got corrupted?");
168	}
169
170	PASSED;
171}
172#else /* WITHOUT_XOPEN */
173int main(void)
174{
175	output_init();
176	UNTESTED("This test requires XSI features");
177}
178#endif
179