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