1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  */
9 /* ex7
10  *
11  * Test case that illustrates a timed wait on a condition variable.
12  */
13 
14 #include <sys/errno.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <pthread.h>
18 #include <sys/time.h>
19 #include <unistd.h>
20 
21 #define usleep rt_thread_delay
22 
23 /* Our event variable using a condition variable contruct. */
24 typedef struct {
25     pthread_mutex_t mutex;
26     pthread_cond_t cond;
27     int flag;
28 } event_t;
29 
30 /* Global event to signal main thread the timeout of the child thread. */
31 event_t main_event;
32 
test_thread(void * ms_param)33 static void *test_thread(void *ms_param) {
34     int status = 0;
35     event_t foo;
36     struct timespec time;
37     struct timeval now;
38     long ms = (long) ms_param;
39 
40     /* initialize cond var */
41     pthread_cond_init(&foo.cond, NULL);
42     pthread_mutex_init(&foo.mutex, NULL);
43     foo.flag = 0;
44 
45     /* set the time out value */
46     printf("waiting %ld ms ...\n", ms);
47     gettimeofday(&now, NULL);
48     time.tv_sec = now.tv_sec + ms / 1000 + (now.tv_usec + (ms % 1000) * 1000)
49             / 1000000;
50     time.tv_nsec = ((now.tv_usec + (ms % 1000) * 1000) % 1000000) * 1000;
51 
52     /* Just use this to test the time out. The cond var is never signaled. */
53     pthread_mutex_lock(&foo.mutex);
54     while (foo.flag == 0 && status != ETIMEDOUT) {
55         status = pthread_cond_timedwait(&foo.cond, &foo.mutex, &time);
56     }
57     pthread_mutex_unlock(&foo.mutex);
58 
59     /* post the main event */
60     pthread_mutex_lock(&main_event.mutex);
61     main_event.flag = 1;
62     pthread_cond_signal(&main_event.cond);
63     pthread_mutex_unlock(&main_event.mutex);
64 
65     /* that's it, bye */
66     return (void*) status;
67 }
68 
libc_ex7(void)69 int libc_ex7(void) {
70     unsigned long count;
71 
72     setvbuf(stdout, NULL, _IONBF, 0);
73 
74     /* initialize main event cond var */
75     pthread_cond_init(&main_event.cond, NULL);
76     pthread_mutex_init(&main_event.mutex, NULL);
77     main_event.flag = 0;
78 
79     for (count = 0; count < 20; ++count) {
80         pthread_t thread;
81         int status;
82 
83         /* pass down the milli-second timeout in the void* param */
84         status = pthread_create(&thread, NULL, test_thread, (void*) (count
85                 * 100));
86         if (status != 0) {
87             printf("status = %d, count = %lu: %s\n", status, count, strerror(
88                     errno));
89             return 1;
90         } else {
91 
92             /* wait for the event posted by the child thread */
93             pthread_mutex_lock(&main_event.mutex);
94             while (main_event.flag == 0) {
95                 pthread_cond_wait(&main_event.cond, &main_event.mutex);
96             }
97             main_event.flag = 0;
98             pthread_mutex_unlock(&main_event.mutex);
99 
100             printf("count = %lu\n", count);
101         }
102 
103         usleep(10);
104     }
105 
106     return 0;
107 }
108 #include <finsh.h>
109 FINSH_FUNCTION_EXPORT(libc_ex7, example 7 for libc);
110