int tMPI_Thread_cond_broadcast(tMPI_Thread_cond_t *cond) { /* check whether the condition is initialized */ if (tMPI_Atomic_get( &(cond->initialized) ) == 0) { tMPI_Thread_cond_init_once(cond); } /* The condition variable is now guaranteed to be valid. */ #if 0 /* use this code once Vista is the minimum version required */ WakeAllConditionVariable( &(cond->cv) ); #else EnterCriticalSection(&(cond->condp->wtr_lock)); /* check whether there are any waiters */ if (cond->condp->Nwaiters > 0) { cond->condp->Nrelease=cond->condp->Nwaiters; cond->condp->cycle++; if (!SetEvent(cond->condp->ev)) /* actually release the waiting threads */ { tMPI_Fatal_error(TMPI_FARGS,"Failed SetEvent, error code=%d", GetLastError()); return -1; } } LeaveCriticalSection(&(cond->condp->wtr_lock)); #endif return 0; }
int tMPI_Thread_cond_broadcast(tMPI_Thread_cond_t *cond) { int ret; /* check whether the condition is initialized */ if (tMPI_Atomic_get( &(cond->initialized) ) == 0) { tMPI_Thread_cond_init_once(cond); } ret = pthread_cond_broadcast( &(cond->condp->cond) ); return ret; }
int tMPI_Thread_cond_wait(tMPI_Thread_cond_t *cond, tMPI_Thread_mutex_t *mtx) { int ret; /* check whether the condition is initialized */ if (tMPI_Atomic_get( &(cond->initialized) ) == 0) { tMPI_Thread_cond_init_once(cond); } /* the mutex must have been initialized because it should be locked here */ ret = pthread_cond_wait( &(cond->condp->cond), &(mtx->mutex->mtx) ); return ret; }
int tMPI_Thread_cond_wait(tMPI_Thread_cond_t *cond, tMPI_Thread_mutex_t *mtx) { BOOL wait_done=FALSE; BOOL last_waiter=FALSE; int my_cycle; /* check whether the condition is initialized */ if (tMPI_Atomic_get( &(cond->initialized) ) == 0) { tMPI_Thread_cond_init_once(cond); } /* the mutex must have been initialized because it should be locked here */ #if 0 /* use this code once Vista is the minimum version required */ ret=SleepConditionVariableCS (&(cond->cv), &(mtx->cs), INFINITE); if (!ret) { tMPI_Fatal_error(TMPI_FARGS,"Failed wait for condition, error code=%d", GetLastError()); return -1; } #else /* serially increase waiter count */ EnterCriticalSection(&(cond->condp->wtr_lock)); cond->condp->Nwaiters++; my_cycle = cond->condp->cycle; LeaveCriticalSection(&(cond->condp->wtr_lock)); /* now it's safe to release the mutex from the fn call */ LeaveCriticalSection(&(mtx->mutex->cs)); /* Loop a wait until we found out we've waited for the right event. Note that this loop is potentially a busy-wait loop in bad circumstances (higher priority threads, for example). */ do { /* do the actual waiting */ if (WaitForSingleObject( cond->condp->ev, INFINITE )== WAIT_FAILED) { tMPI_Fatal_error(TMPI_FARGS,"Failed event reset, error code=%d", GetLastError()); return -1; } /* serially check whether we got the right event. */ EnterCriticalSection(&(cond->condp->wtr_lock)); wait_done = (cond->condp->Nrelease > 0) && (cond->condp->cycle!=my_cycle); LeaveCriticalSection(&(cond->condp->wtr_lock)); } while(!wait_done); /* We obtain the mutex from the function call */ EnterCriticalSection(&(mtx->mutex->cs)); /* we serially decrease the waiter count and release count */ EnterCriticalSection(&(cond->condp->wtr_lock)); cond->condp->Nwaiters--; cond->condp->Nrelease--; last_waiter=(cond->condp->Nrelease==0); LeaveCriticalSection(&(cond->condp->wtr_lock)); /* manually release the event if everybody's done with it */ if (last_waiter) { if (!ResetEvent( cond->condp->ev )) { tMPI_Fatal_error(TMPI_FARGS,"Failed event reset, error code=%d", GetLastError()); return -1; } } #endif return 0; }