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