1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  bing.wei.liu REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7
8 * Test that pthread_cond_signal()
9 *   Upon successful completion, a value of zero shall be returned.
10 */
11
12#define _XOPEN_SOURCE 600
13
14#include <pthread.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <errno.h>
19#include <signal.h>
20#include "posixtest.h"
21
22#define THREAD_NUM  5
23
24struct testdata
25{
26	pthread_mutex_t mutex;
27	pthread_cond_t  cond;
28} td;
29
30pthread_t  thread[THREAD_NUM];
31
32int start_num = 0;
33int waken_num = 0;
34
35/* Alarm handler */
36void alarm_handler(int signo)
37{
38	int i;
39	printf("Error: failed to wakeup all threads\n");
40	for (i=0; i<THREAD_NUM; i++) {	/* cancel threads */
41	    	pthread_cancel(thread[i]);
42	}
43
44	exit(PTS_UNRESOLVED);
45}
46void *thr_func(void *arg)
47{
48	int rc;
49	pthread_t self = pthread_self();
50
51	if (pthread_mutex_lock(&td.mutex) != 0) {
52		fprintf(stderr,"[Thread 0x%p] failed to acquire the mutex\n", (void*)self);
53		exit(PTS_UNRESOLVED);
54	}
55	fprintf(stderr,"[Thread 0x%p] started\n", (void*)self);
56	start_num ++;
57
58	fprintf(stderr,"[Thread 0x%p] is waiting for the cond\n", (void*)self);
59	rc = pthread_cond_wait(&td.cond, &td.mutex);
60	if(rc != 0) {
61		fprintf(stderr,"pthread_cond_wait return %d\n", rc);
62                exit(PTS_UNRESOLVED);
63	}
64	fprintf(stderr,"[Thread 0x%p] was wakened\n", (void*)self);
65	waken_num ++;
66
67	if (pthread_mutex_unlock(&td.mutex) != 0) {
68		fprintf(stderr,"[Thread 0x%p] failed to release the mutex\n", (void*)self);
69		exit(PTS_UNRESOLVED);
70	}
71	return NULL;
72}
73
74int main()
75{
76	int i, rc;
77	struct sigaction act;
78
79	if (pthread_mutex_init(&td.mutex, NULL) != 0) {
80		fprintf(stderr,"Fail to initialize mutex\n");
81		return PTS_UNRESOLVED;
82	}
83	if (pthread_cond_init(&td.cond, NULL) != 0) {
84		fprintf(stderr,"Fail to initialize cond\n");
85		return PTS_UNRESOLVED;
86	}
87
88	for (i=0; i<THREAD_NUM; i++) {
89	    	if (pthread_create(&thread[i], NULL, thr_func, NULL) != 0) {
90			fprintf(stderr,"Fail to create thread[%d]\n", i);
91			exit(PTS_UNRESOLVED);
92		}
93	}
94	while (start_num < THREAD_NUM)	/* waiting for all threads started */
95		usleep(100);
96
97	/* Setup alarm handler */
98	act.sa_handler=alarm_handler;
99	act.sa_flags=0;
100	sigemptyset(&act.sa_mask);
101	sigaction(SIGALRM, &act, 0);
102	alarm(5);
103
104	while (waken_num < THREAD_NUM) { /* loop to wake up all waiter threads */
105		fprintf(stderr,"[Main thread] signals a condition\n");
106		rc = pthread_cond_signal(&td.cond);
107		if (rc == EINVAL) {
108			fprintf(stderr,"pthread_cond_signal returns EINVAL\n");
109			exit(PTS_UNRESOLVED);
110		}
111		else if (rc != 0) {
112			fprintf(stderr,"pthread_cond_signal returns %d\n",rc);
113  	              	printf("Test FAILED\n");
114			exit(PTS_FAIL);
115		}
116		usleep(100);
117	}
118
119	for (i=0; i<THREAD_NUM; i++) {
120	    	if (pthread_join(thread[i], NULL) != 0) {
121			fprintf(stderr,"Fail to join thread[%d]\n", i);
122			exit(PTS_UNRESOLVED);
123		}
124	}
125	printf("Test PASSED\n");
126	return PTS_PASS;
127}
128