aboutsummaryrefslogtreecommitdiff
path: root/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_broadcast/4-1.c
blob: 8ddd5cd569e5957d57c2b73ecf5a3a49b3c1bbfa (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
/*
 * 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_broadcast()
 *   Upon successful completion, a value of zero shall be returned.
 */


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

#define THREAD_NUM  5

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

static int start_num;
static int waken_num;

static 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);
	}
	fprintf(stderr, "[Thread 0x%p] was wakened\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);
		exit(PTS_UNRESOLVED);
	}
	return NULL;
}

int main(void)
{
	struct timespec completion_wait_ts = {0, 100000};
	int i, rc;
	pthread_t thread[THREAD_NUM];

	if (pthread_mutex_init(&td.mutex, NULL) != 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)
		nanosleep(&completion_wait_ts, NULL);

	/* Acquire the mutex to make sure that all waiters are currently
	   blocked on pthread_cond_wait */
	if (pthread_mutex_lock(&td.mutex) != 0) {
		fprintf(stderr, "Main: Fail to acquire mutex\n");
		return PTS_UNRESOLVED;
	}
	if (pthread_mutex_unlock(&td.mutex) != 0) {
		fprintf(stderr, "Main: Fail to release mutex\n");
		return PTS_UNRESOLVED;
	}
	sleep(1);

	/* broadcast the condition to wake up all waiters */
	fprintf(stderr, "[Main thread] broadcast the condition\n");
	rc = pthread_cond_broadcast(&td.cond);
	if (rc != 0) {
		if (rc == EINVAL) {
			fprintf(stderr, "pthread_cond_broadcast "
				"returns EINVAL\n");
			return PTS_UNRESOLVED;
		} else if (rc != 0) {
			fprintf(stderr, "pthread_cond_broadcast returns %d\n",
				rc);
			printf("Test FAILED\n");
			return PTS_FAIL;
		}
	}
	fprintf(stderr, "[Main thread] pthread_cond_broadcast() returned 0\n");
	sleep(1);
	if (waken_num < THREAD_NUM) {
		fprintf(stderr, "[Main thread] Not all waiters were wakened\n");
		for (i = 0; i < THREAD_NUM; i++)
			pthread_cancel(thread[i]);

		return PTS_UNRESOLVED;
	}
	fprintf(stderr, "[Main thread] all waiters were wakened\n");

	/* join all secondary threads */
	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;
}