Home | History | Annotate | Download | only in pthread_cond_signal
      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  *   shall unblock at least one of the threads currently blocked on
     10  *   the specified condition variable cond.
     11  */
     12 
     13 #define _XOPEN_SOURCE 600
     14 
     15 #include <pthread.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <unistd.h>
     19 #include <signal.h>
     20 #include "posixtest.h"
     21 
     22 #define THREAD_NUM  3
     23 
     24 struct testdata {
     25 	pthread_mutex_t mutex;
     26 	pthread_cond_t cond;
     27 } td;
     28 
     29 pthread_t thread[THREAD_NUM];
     30 
     31 int start_num = 0;
     32 int waken_num = 0;
     33 
     34 /* Alarm handler */
     35 void alarm_handler(int signo)
     36 {
     37 	int i;
     38 	printf("Error: failed to wakeup all threads\n");
     39 	for (i = 0; i < THREAD_NUM; i++) {	/* cancel threads */
     40 		pthread_cancel(thread[i]);
     41 	}
     42 
     43 	exit(PTS_UNRESOLVED);
     44 }
     45 
     46 void *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",
     53 			(void *)self);
     54 		exit(PTS_UNRESOLVED);
     55 	}
     56 	start_num++;
     57 	fprintf(stderr, "[Thread 0x%p] started and locked the mutex\n",
     58 		(void *)self);
     59 
     60 	fprintf(stderr, "[Thread 0x%p] is waiting for the cond\n",
     61 		(void *)self);
     62 	rc = pthread_cond_wait(&td.cond, &td.mutex);
     63 	if (rc != 0) {
     64 		fprintf(stderr, "pthread_cond_wait return %d\n", rc);
     65 		exit(PTS_UNRESOLVED);
     66 	}
     67 	waken_num++;
     68 	fprintf(stderr,
     69 		"[Thread 0x%p] was wakened and acquired the mutex again\n",
     70 		(void *)self);
     71 
     72 	if (pthread_mutex_unlock(&td.mutex) != 0) {
     73 		fprintf(stderr, "[Thread 0x%p] failed to release the mutex\n",
     74 			(void *)self);
     75 		exit(PTS_UNRESOLVED);
     76 	}
     77 	fprintf(stderr, "[Thread 0x%p] released the mutex\n", (void *)self);
     78 	return NULL;
     79 }
     80 
     81 int main(void)
     82 {
     83 	int i, rc;
     84 	struct sigaction act;
     85 
     86 	if (pthread_mutex_init(&td.mutex, NULL) != 0) {
     87 		fprintf(stderr, "Fail to initialize mutex\n");
     88 		return PTS_UNRESOLVED;
     89 	}
     90 	if (pthread_cond_init(&td.cond, NULL) != 0) {
     91 		fprintf(stderr, "Fail to initialize cond\n");
     92 		return PTS_UNRESOLVED;
     93 	}
     94 
     95 	for (i = 0; i < THREAD_NUM; i++) {	/* create THREAD_NUM threads */
     96 		if (pthread_create(&thread[i], NULL, thr_func, NULL) != 0) {
     97 			fprintf(stderr, "Fail to create thread[%d]\n", i);
     98 			exit(PTS_UNRESOLVED);
     99 		}
    100 	}
    101 	while (start_num < THREAD_NUM)	/* waiting for all threads started */
    102 		usleep(100);
    103 
    104 	/* Acquire the mutex to make sure that all waiters are currently
    105 	   blocked on pthread_cond_wait */
    106 	if (pthread_mutex_lock(&td.mutex) != 0) {
    107 		fprintf(stderr, "Main: Fail to acquire mutex\n");
    108 		exit(PTS_UNRESOLVED);
    109 	}
    110 	if (pthread_mutex_unlock(&td.mutex) != 0) {
    111 		fprintf(stderr, "Main: Fail to release mutex\n");
    112 		exit(PTS_UNRESOLVED);
    113 	}
    114 
    115 	/* signal once and check if at least one waiter is wakened */
    116 	fprintf(stderr, "[Main thread] signals a condition\n");
    117 	rc = pthread_cond_signal(&td.cond);
    118 	if (rc != 0) {
    119 		fprintf(stderr,
    120 			"[Main thread] failed to signal the condition\n");
    121 		exit(PTS_UNRESOLVED);
    122 	}
    123 	sleep(1);
    124 	if (waken_num <= 0) {
    125 		fprintf(stderr, "[Main thread] but no waiters were wakened\n");
    126 		printf("Test FAILED\n");
    127 		/* Cancel the threads */
    128 		for (i = 0; i < THREAD_NUM; i++) {	/* cancel threads */
    129 			pthread_cancel(thread[i]);
    130 		}
    131 		exit(PTS_FAIL);
    132 	}
    133 	fprintf(stderr, "[Main thread] %d waiters were wakened\n", waken_num);
    134 
    135 	/* Setup alarm handler */
    136 	act.sa_handler = alarm_handler;
    137 	act.sa_flags = 0;
    138 	sigemptyset(&act.sa_mask);
    139 	sigaction(SIGALRM, &act, 0);
    140 	alarm(5);
    141 
    142 	/* loop to wake up the rest threads */
    143 	for (i = 1; i < THREAD_NUM; i++) {
    144 		fprintf(stderr,
    145 			"[Main thread] signals to wake up the next thread\n");
    146 		if (pthread_cond_signal(&td.cond) != 0) {
    147 			fprintf(stderr,
    148 				"Main failed to signal the condition\n");
    149 			exit(PTS_UNRESOLVED);
    150 		}
    151 		usleep(100);
    152 	}
    153 
    154 	/* join all secondary threads */
    155 	for (i = 0; i < THREAD_NUM; i++) {
    156 		if (pthread_join(thread[i], NULL) != 0) {
    157 			fprintf(stderr, "Fail to join thread[%d]\n", i);
    158 			exit(PTS_UNRESOLVED);
    159 		}
    160 	}
    161 	printf("Test PASSED\n");
    162 	return PTS_PASS;
    163 }
    164