| 145 | | pthread_cond_destroy(cond); |
| 146 | | return 0; |
| 147 | | } |
| 148 | | |
| 149 | | int gen_win_cond_wait(HANDLE cond, HANDLE mut) |
| | 149 | |
| | 150 | if (*cond != GEN_COND_INITIALIZER) |
| | 151 | { |
| | 152 | EnterCriticalSection(cond_list_lock); |
| | 153 | |
| | 154 | cv = *cond; |
| | 155 | |
| | 156 | if (WaitForSingleObject(&(cv->semBlockLock), INFINITE) != WAIT_OBJECT_0) |
| | 157 | { |
| | 158 | return GetLastError(); |
| | 159 | } |
| | 160 | |
| | 161 | if ((result = gen_mutex_trylock(&(cv->mtxUnblockLock))) != 0) |
| | 162 | { |
| | 163 | ReleaseSemaphore(&(cv->semBlockLock), 1, NULL); |
| | 164 | return result; |
| | 165 | } |
| | 166 | |
| | 167 | if (cv->nWaitersBlocked > cv->nWaitersGone) |
| | 168 | { |
| | 169 | if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) |
| | 170 | { |
| | 171 | result = GetLastError(); |
| | 172 | } |
| | 173 | result1 = gen_mutex_unlock(&(cv->mtxUnblockLock)); |
| | 174 | result2 = EBUSY; |
| | 175 | } |
| | 176 | else |
| | 177 | { |
| | 178 | /* Now it is safe to destroy */ |
| | 179 | *cond = NULL; |
| | 180 | |
| | 181 | if (CloseHandle(&(cv->semBlockLock)) != 0) |
| | 182 | { |
| | 183 | result = GetLastError(); |
| | 184 | } |
| | 185 | if (CloseHandle(&(cv->semBlockQueue)) != 0) |
| | 186 | { |
| | 187 | result1 = GetLastError(); |
| | 188 | } |
| | 189 | if ((result2 = gen_mutex_unlock(&(cv->mtxUnblockLock))) == 0) |
| | 190 | { |
| | 191 | result2 = gen_mutex_destroy(&(cv->mtxUnblockLock)); |
| | 192 | } |
| | 193 | |
| | 194 | /* Unlink the CV from the list */ |
| | 195 | if (cond_list_head == cv) |
| | 196 | { |
| | 197 | cond_list_head = cv->next; |
| | 198 | } |
| | 199 | else |
| | 200 | { |
| | 201 | cv->prev->next = cv->next; |
| | 202 | } |
| | 203 | |
| | 204 | if (cond_list_tail == cv) |
| | 205 | { |
| | 206 | cond_list_tail = cv->prev; |
| | 207 | } |
| | 208 | else { |
| | 209 | cv->next->prev = cv->prev; |
| | 210 | } |
| | 211 | |
| | 212 | free(cv); |
| | 213 | } |
| | 214 | |
| | 215 | LeaveCriticalSection(cond_list_lock); |
| | 216 | } |
| | 217 | else |
| | 218 | { |
| | 219 | EnterCriticalSection(cond_test_init_lock); |
| | 220 | |
| | 221 | if (*cond == GEN_COND_INITIALIZER) |
| | 222 | { |
| | 223 | *cond = NULL; |
| | 224 | } |
| | 225 | else |
| | 226 | { |
| | 227 | result = EBUSY; |
| | 228 | } |
| | 229 | |
| | 230 | LeaveCriticalSection(cond_test_init_lock); |
| | 231 | } |
| | 232 | |
| | 233 | return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); |
| | 234 | } |
| | 235 | |
| | 236 | typedef struct |
| | 237 | { |
| | 238 | gen_mutex_t *mutexPtr; |
| | 239 | pgen_cond_t cv; |
| | 240 | int *resultPtr; |
| | 241 | } cond_wait_cleanup_args_t; |
| | 242 | |
| | 243 | static void __cdecl cond_wait_cleanup(void *args) |
| | 244 | { |
| | 245 | cond_wait_cleanup_args_t *cleanup_args = (cond_wait_cleanup_args_t *) args; |
| | 246 | pgen_cond_t cv = cleanup_args->cv; |
| | 247 | int *resultPtr = cleanup_args->resultPtr; |
| | 248 | int nSignalsWasLeft; |
| | 249 | int result; |
| | 250 | |
| | 251 | if ((result = gen_mutex_lock(&(cv->mtxUnblockLock))) != 0) |
| | 252 | { |
| | 253 | *resultPtr = result; |
| | 254 | return; |
| | 255 | } |
| | 256 | |
| | 257 | if ((nSignalsWasLeft = cv->nWaitersToUnblock) != 0) |
| | 258 | { |
| | 259 | --(cv->nWaitersToUnblock); |
| | 260 | } |
| | 261 | else if (INT_MAX / 2 == ++(cv->nWaitersGone)) |
| | 262 | { |
| | 263 | if (WaitForSingleObject(&(cv->semBlockLock), INFINITE) != 0) |
| | 264 | { |
| | 265 | *resultPtr = (int) GetLastError(); |
| | 266 | return; |
| | 267 | } |
| | 268 | cv->nWaitersBlocked -= cv->nWaitersGone; |
| | 269 | if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) |
| | 270 | { |
| | 271 | *resultPtr = (int) GetLastError(); |
| | 272 | return; |
| | 273 | } |
| | 274 | cv->nWaitersGone = 0; |
| | 275 | } |
| | 276 | |
| | 277 | if ((result = gen_mutex_unlock(&(cv->mtxUnblockLock))) != 0) |
| | 278 | { |
| | 279 | *resultPtr = result; |
| | 280 | return; |
| | 281 | } |
| | 282 | |
| | 283 | if (nSignalsWasLeft == 1) |
| | 284 | { |
| | 285 | if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) |
| | 286 | { |
| | 287 | *resultPtr = (int) GetLastError(); |
| | 288 | return; |
| | 289 | } |
| | 290 | } |
| | 291 | |
| | 292 | if ((result = gen_mutex_lock(cleanup_args->mutexPtr)) != 0) |
| | 293 | { |
| | 294 | *resultPtr = result; |
| | 295 | } |
| | 296 | |
| | 297 | } |
| | 298 | |
| | 299 | static __inline int cond_timedwait(pgen_cond_t *cond, |
| | 300 | HANDLE *mutex, const struct timespec *abstime) |
| | 301 | { |
| | 302 | int result = 0; |
| | 303 | pgen_cond_t cv; |
| | 304 | cond_wait_cleanup_args_t cleanup_args; |
| | 305 | |
| | 306 | if (cond == NULL || *cond == NULL) |
| | 307 | { |
| | 308 | return EINVAL; |
| | 309 | } |
| | 310 | |
| | 311 | if (*cond == GEN_COND_INITIALIZER) |
| | 312 | { |
| | 313 | result = cond_check_need_init(cond); |
| | 314 | } |
| | 315 | |
| | 316 | if (result != 0 && result != EBUSY) |
| | 317 | { |
| | 318 | return result; |
| | 319 | } |
| | 320 | |
| | 321 | cv = *cond; |
| | 322 | |
| | 323 | if (WaitForSingleObject(&(cv->semBlockLock), INFINITE) != 0) |
| | 324 | { |
| | 325 | return (int) GetLastError(); |
| | 326 | } |
| | 327 | |
| | 328 | ++(cv->nWaitersBlocked); |
| | 329 | |
| | 330 | if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) |
| | 331 | { |
| | 332 | return (int) GetLastError(); |
| | 333 | } |
| | 334 | |
| | 335 | cleanup_args.mutexPtr = mutex; |
| | 336 | cleanup_args.cv = cv; |
| | 337 | cleanup_args.resultPtr = &result; |
| | 338 | |
| | 339 | // TODO: pthread_cleanup_push(cond_wait_cleanup, (void*) &cleanup_args); |
| | 340 | |
| | 341 | /* Now we can release mutex and... */ |
| | 342 | if ((result = gen_mutex_unlock(mutex)) == 0) |
| | 343 | { |
| | 344 | |
| | 345 | } |
| | 346 | |
| | 347 | return result; |
| | 348 | } |
| | 349 | |
| | 350 | int gen_win_cond_wait(pgen_cond_t *cond, HANDLE *mut) |