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_timedwait()
9  *   shall be equivalent to pthread_cond_wait(), except that an error is returned
10  *   if the absolute time specified by abstime passes before the condition cond is
11  *   signaled or broadcasted, or if the absolute time specified by abstime has
12  *   already been passed at the time of the call.
13  *
14  * Case 2-1
15  *   Upon successful return, the mutex shall have been locked and shall
16  *   be owned by the calling thread.
17  */
18 
19 
20 #include <pthread.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <errno.h>
26 #include "posixtest.h"
27 
28 #define INTERVAL  1
29 #define TIMEOUT   5
30 
31 static struct testdata {
32     pthread_mutex_t mutex;
33     pthread_cond_t cond;
34 } td;
35 
36 static int t1_start = 0;
37 static int signaled = 0;
38 
t1_func(void * arg)39 static void *t1_func(void *arg)
40 {
41     int rc;
42     struct timespec timeout;
43     struct timeval curtime;
44 
45     (void) arg;
46 
47     if (pthread_mutex_lock(&td.mutex) != 0) {
48         fprintf(stderr, "Thread1 failed to acquire the mutex\n");
49         exit(PTS_UNRESOLVED);
50     }
51     fprintf(stderr, "Thread1 started\n");
52     t1_start = 1;       /* let main thread continue */
53 
54     if (gettimeofday(&curtime, NULL) != 0) {
55         fprintf(stderr, "Fail to get current time\n");
56         exit(PTS_UNRESOLVED);
57     }
58     timeout.tv_sec = curtime.tv_sec + TIMEOUT;
59     timeout.tv_nsec = curtime.tv_usec * 1000;
60 
61     fprintf(stderr, "Thread1 is waiting for the cond\n");
62     rc = pthread_cond_timedwait(&td.cond, &td.mutex, &timeout);
63     if (rc != 0) {
64         if (rc == ETIMEDOUT) {
65             fprintf(stderr,
66                 "Thread1 stops waiting when time is out\n");
67             exit(PTS_UNRESOLVED);
68         } else {
69             fprintf(stderr, "pthread_cond_timedwait return %d\n",
70                 rc);
71             exit(PTS_UNRESOLVED);
72         }
73     }
74 
75     fprintf(stderr, "Thread1 wakened\n");
76     if (signaled == 0) {
77         fprintf(stderr, "Thread1 did not block on the cond at all\n");
78         exit(PTS_UNRESOLVED);
79     }
80 
81     if (pthread_mutex_trylock(&td.mutex) == 0) {
82         fprintf(stderr,
83             "Thread1 should not be able to lock the mutex again\n");
84         printf("Test FAILED\n");
85         exit(PTS_FAIL);
86     }
87     fprintf(stderr, "Thread1 failed to trylock the mutex (as expected)\n");
88 
89     if (pthread_mutex_unlock(&td.mutex) != 0) {
90         fprintf(stderr, "Thread1 failed to release the mutex\n");
91         printf("Test FAILED\n");
92         exit(PTS_FAIL);
93     }
94     fprintf(stderr, "Thread1 released the mutex\n");
95     return NULL;
96 }
97 
posix_testcase(void)98 static int posix_testcase(void)
99 {
100     pthread_t thread1;
101     struct timespec thread_start_ts = {0, 100000};
102 
103     if (pthread_mutex_init(&td.mutex, NULL) != 0) {
104         fprintf(stderr, "Fail to initialize mutex\n");
105         return PTS_UNRESOLVED;
106     }
107     if (pthread_cond_init(&td.cond, NULL) != 0) {
108         fprintf(stderr, "Fail to initialize cond\n");
109         return PTS_UNRESOLVED;
110     }
111 
112     if (pthread_create(&thread1, NULL, t1_func, NULL) != 0) {
113         fprintf(stderr, "Fail to create thread 1\n");
114         return PTS_UNRESOLVED;
115     }
116     while (!t1_start)   /* wait for thread1 started */
117         nanosleep(&thread_start_ts, NULL);
118 
119     /* acquire the mutex released by pthread_cond_wait() within thread 1 */
120     if (pthread_mutex_lock(&td.mutex) != 0) {
121         fprintf(stderr, "Main failed to acquire mutex\n");
122         return PTS_UNRESOLVED;
123     }
124     if (pthread_mutex_unlock(&td.mutex) != 0) {
125         fprintf(stderr, "Main failed to release mutex\n");
126         return PTS_UNRESOLVED;
127     }
128     sleep(INTERVAL);
129 
130     fprintf(stderr, "Time to wake up thread1 by signaling a condition\n");
131     signaled = 1;
132     if (pthread_cond_signal(&td.cond) != 0) {
133         fprintf(stderr, "Main failed to signal the condition\n");
134         return PTS_UNRESOLVED;
135     }
136 
137     pthread_join(thread1, NULL);
138     printf("Test PASSED\n");
139     return PTS_PASS;
140 }
141 #include <rtt_utest_internal.h>
142 UTEST_TC_EXPORT(testcase, "posix.pthread_cond_timedwait.2-1.c", RT_NULL, RT_NULL, 10);
143 
144