xref: /relibc/pthreads-emb/tests/condvar6.c (revision 714af18cbe52336f4ff71fe91bfb035d5efaef7d)
1 
2 /*
3  * File: condvar6.c
4  *
5  *
6  * --------------------------------------------------------------------------
7  *
8  *      Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
9  *      Copyright(C) 2008 Jason Schmidlapp
10  *
11  *      Contact Email: jschmidlapp@users.sourceforge.net
12  *
13  *
14  *      Based upon Pthreads-win32 - POSIX Threads Library for Win32
15  *      Copyright(C) 1998 John E. Bossom
16  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
17  *
18  *      Contact Email: rpj@callisto.canberra.edu.au
19  *
20  *      The original list of contributors to the Pthreads-win32 project
21  *      is contained in the file CONTRIBUTORS.ptw32 included with the
22  *      source code distribution. The list can also be seen at the
23  *      following World Wide Web location:
24  *      http://sources.redhat.com/pthreads-win32/contributors.html
25  *
26  *      This library is free software; you can redistribute it and/or
27  *      modify it under the terms of the GNU Lesser General Public
28  *      License as published by the Free Software Foundation; either
29  *      version 2 of the License, or (at your option) any later version.
30  *
31  *      This library is distributed in the hope that it will be useful,
32  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
33  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
34  *      Lesser General Public License for more details.
35  *
36  *      You should have received a copy of the GNU Lesser General Public
37  *      License along with this library in the file COPYING.LIB;
38  *      if not, write to the Free Software Foundation, Inc.,
39  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
40  *
41  * --------------------------------------------------------------------------
42  *
43  * Test Synopsis:
44  * - Test pthread_cond_broadcast.
45  *
46  * Test Method (Validation or Falsification):
47  * - Validation
48  *
49  * Requirements Tested:
50  * -
51  *
52  * Features Tested:
53  * -
54  *
55  * Cases Tested:
56  * -
57  *
58  * Description:
59  * - Test broadcast with NUMTHREADS (=5) waiting CVs.
60  *
61  * Environment:
62  * -
63  *
64  * Input:
65  * - None.
66  *
67  * Output:
68  * - File name, Line number, and failed expression on failure.
69  * - No output on success.
70  *
71  * Assumptions:
72  * -
73  *
74  * Pass Criteria:
75  * - Process returns zero exit status.
76  *
77  * Fail Criteria:
78  * - Process returns non-zero exit status.
79  */
80 
81 #include "test.h"
82 
83 
84 /*
85  * Create NUMTHREADS threads in addition to the Main thread.
86  */
87 enum
88 {
89   NUMTHREADS = 5
90 };
91 
92 typedef struct bag_t_ bag_t;
93 struct bag_t_
94   {
95     int threadnum;
96     int started;
97     /* Add more per-thread state variables here */
98   };
99 
100 static bag_t threadbag[NUMTHREADS + 1];
101 
102 typedef struct cvthing_t_ cvthing_t;
103 
104 struct cvthing_t_
105   {
106     pthread_cond_t notbusy;
107     pthread_mutex_t lock;
108     int shared;
109   };
110 
111 static cvthing_t cvthing =
112 {
113   PTHREAD_COND_INITIALIZER,
114   PTHREAD_MUTEX_INITIALIZER,
115   0
116 };
117 
118 static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
119 
120 static struct timespec abstime =
121   {
122     0, 0
123   };
124 
125 static int awoken;
126 
127 static void *
128 mythread(void * arg)
129 {
130   bag_t * bag = (bag_t *) arg;
131   struct _timeb currSysTime;
132   const unsigned int NANOSEC_PER_MILLISEC = 1000000;
133 
134   assert(bag == &threadbag[bag->threadnum]);
135   assert(bag->started == 0);
136   bag->started = 1;
137 
138   /* Wait for the start gun */
139   assert(pthread_mutex_lock(&start_flag) == 0);
140   assert(pthread_mutex_unlock(&start_flag) == 0);
141 
142   assert(pthread_mutex_lock(&cvthing.lock) == 0);
143 
144   while (! (cvthing.shared > 0))
145     {
146       _ftime(&currSysTime);
147 
148       abstime.tv_sec = currSysTime.time;
149       abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
150 
151       abstime.tv_sec += 5;
152 
153       assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
154     }
155 
156   assert(cvthing.shared > 0);
157 
158   awoken++;
159 
160   assert(pthread_mutex_unlock(&cvthing.lock) == 0);
161 
162   return (void *) 0;
163 }
164 
165 int pthread_test_condvar6()
166 {
167   int failed = 0;
168   int i;
169   pthread_t t[NUMTHREADS + 1];
170 
171 
172   start_flag = PTHREAD_MUTEX_INITIALIZER;
173   cvthing.notbusy = PTHREAD_COND_INITIALIZER;
174   cvthing.lock = PTHREAD_MUTEX_INITIALIZER;
175 
176   cvthing.shared = 0;
177 
178   assert((t[0] = pthread_self()).p != NULL);
179 
180   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
181 
182   assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
183 
184   assert(pthread_mutex_lock(&start_flag) == 0);
185 
186 
187 
188   assert((t[0] = pthread_self()).p != NULL);
189 
190   awoken = 0;
191 
192   for (i = 1; i <= NUMTHREADS; i++)
193     {
194       threadbag[i].started = 0;
195       threadbag[i].threadnum = i;
196       assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
197     }
198 
199   /*
200    * Code to control or munipulate child threads should probably go here.
201    */
202 
203   assert(pthread_mutex_unlock(&start_flag) == 0);
204 
205   /*
206    * Give threads time to start.
207    */
208   pte_osThreadSleep(1000);
209 
210   assert(pthread_mutex_lock(&cvthing.lock) == 0);
211   cvthing.shared++;
212   assert(pthread_mutex_unlock(&cvthing.lock) == 0);
213 
214   assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
215 
216   /*
217    * Give threads time to complete.
218    */
219   for (i = 1; i <= NUMTHREADS; i++)
220     {
221       assert(pthread_join(t[i], NULL) == 0);
222     }
223 
224   /*
225    * Cleanup the CV.
226    */
227 
228   assert(pthread_mutex_destroy(&cvthing.lock) == 0);
229 
230   assert(cvthing.lock == NULL);
231 
232   assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
233 
234   assert(cvthing.notbusy == NULL);
235 
236   /*
237    * Standard check that all threads started.
238    */
239   for (i = 1; i <= NUMTHREADS; i++)
240     {
241       failed = !threadbag[i].started;
242     }
243 
244   assert(!failed);
245 
246   /*
247    * Check any results here.
248    */
249 
250   assert(awoken == NUMTHREADS);
251 
252   assert(pthread_mutex_destroy(&start_flag) == 0);
253 
254   /*
255    * Success.
256    */
257   return 0;
258 }
259 
260 
261