aboutsummaryrefslogtreecommitdiff
path: root/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_signal/2-1.c
blob: 0a1a0cfdd4ee800e5954216976830d94df21d644 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright (c) 2002, Intel Corporation. All rights reserved.
 * Created by:  bing.wei.liu REMOVE-THIS AT intel DOT com
 * This file is licensed under the GPL license.  For the full content
 * of this license, see the COPYING file at the top level of this
 * source tree.

 * Test that pthread_cond_signal()
 *   When each thread unblocked as a result of pthread_cond_signal()
 *   returns from its call to pthread_cond_wait(), the thread shall
 *   own the mutex with which it called pthread_cond_wait().
 */


#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "posixtest.h"

#define THREAD_NUM  3

struct testdata {
	pthread_mutex_t mutex;
	pthread_cond_t cond;
} td;

pthread_t thread[THREAD_NUM];

int start_num = 0;
int waken_num = 0;

/* Alarm handler */
void alarm_handler(int signo)
{
	int i;
	printf("Error: failed to wakeup all threads\n");
	for (i = 0; i < THREAD_NUM; i++) {	/* cancel threads */
		pthread_cancel(thread[i]);
	}

	exit(PTS_UNRESOLVED);
}

void *thr_func(void *arg)
{
	int rc;
	pthread_t self = pthread_self();

	if (pthread_mutex_lock(&td.mutex) != 0) {
		fprintf(stderr, "[Thread 0x%p] failed to acquire the mutex\n",
			(void *)self);
		exit(PTS_UNRESOLVED);
	}
	fprintf(stderr, "[Thread 0x%p] started and locked the mutex\n",
		(void *)self);
	start_num++;

	fprintf(stderr, "[Thread 0x%p] is waiting for the cond\n",
		(void *)self);
	rc = pthread_cond_wait(&td.cond, &td.mutex);
	if (rc != 0) {
		fprintf(stderr, "pthread_cond_wait return %d\n", rc);
		exit(PTS_UNRESOLVED);
	}

	if (pthread_mutex_trylock(&td.mutex) != 0) {
		fprintf(stderr,
			"[Thread 0x%p] should be able to lock the recursive mutex again\n",
			(void *)self);
		printf("Test FAILED\n");
		exit(PTS_FAIL);
	}
	fprintf(stderr,
		"[Thread 0x%p] was wakened and acquired the mutex again\n",
		(void *)self);
	waken_num++;

	if (pthread_mutex_unlock(&td.mutex) != 0) {
		fprintf(stderr, "[Thread 0x%p] failed to release the mutex\n",
			(void *)self);
		printf("Test FAILED\n");
		exit(PTS_FAIL);
	}
	if (pthread_mutex_unlock(&td.mutex) != 0) {
		fprintf(stderr,
			"[Thread 0x%p] did not owned the mutex after the cond wait\n",
			(void *)self);
		printf("Test FAILED\n");
		exit(PTS_FAIL);
	}
	fprintf(stderr, "[Thread 0x%p] released the mutex\n", (void *)self);
	return NULL;
}

int main(void)
{
	struct timespec completion_wait_ts = {0, 100000};
	int i;
	struct sigaction act;
	pthread_mutexattr_t ma;

	if (pthread_mutexattr_init(&ma) != 0) {
		fprintf(stderr, "Fail to initialize mutex attribute\n");
		return PTS_UNRESOLVED;
	}
	if (pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE) != 0) {
		fprintf(stderr, "Fail to set the mutex attribute\n");
		return PTS_UNRESOLVED;
	}

	if (pthread_mutex_init(&td.mutex, &ma) != 0) {
		fprintf(stderr, "Fail to initialize mutex\n");
		return PTS_UNRESOLVED;
	}
	if (pthread_cond_init(&td.cond, NULL) != 0) {
		fprintf(stderr, "Fail to initialize cond\n");
		return PTS_UNRESOLVED;
	}

	for (i = 0; i < THREAD_NUM; i++) {
		if (pthread_create(&thread[i], NULL, thr_func, NULL) != 0) {
			fprintf(stderr, "Fail to create thread[%d]\n", i);
			return PTS_UNRESOLVED;
		}
	}
	while (start_num < THREAD_NUM)	/* waiting for all threads started */
		nanosleep(&completion_wait_ts, NULL);

	sleep(1);

	/* Setup alarm handler */
	act.sa_handler = alarm_handler;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGALRM, &act, 0);
	alarm(5);

	while (waken_num < THREAD_NUM) {	/* waiting for all threads wakened */
		fprintf(stderr, "[Main thread] signals a condition\n");
		if (pthread_cond_signal(&td.cond) != 0) {
			fprintf(stderr,
				"Main failed to signal the condition\n");
			return PTS_UNRESOLVED;
		}
		nanosleep(&completion_wait_ts, NULL);
	}

	for (i = 0; i < THREAD_NUM; i++) {
		if (pthread_join(thread[i], NULL) != 0) {
			fprintf(stderr, "Fail to join thread[%d]\n", i);
			return PTS_UNRESOLVED;
		}
	}
	printf("Test PASSED\n");
	return PTS_PASS;
}