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