diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | condvar.c | 62 | ||||
-rw-r--r-- | misc.c | 6 | ||||
-rw-r--r-- | pthread.h | 2 | ||||
-rw-r--r-- | semaphore.c | 4 |
5 files changed, 54 insertions, 34 deletions
@@ -1,10 +1,24 @@ 2000-09-02 Ross Johnson <rpj@special.ise.canberra.edu.au> + * condvar.c (ptw32_cond_wait_cleanup): Ensure that all + waking threads check if they are the last, and notify + the broadcaster if so - even if an error occurs in the + waiter. + + * semaphore.c (_decrease_semaphore): Should be + a call to ptw32_decrease_semaphore. + (_increase_semaphore): Should be a call to + ptw32_increase_semaphore. + + * misc.c (ptw32_cancelable_wait): Renamed from + CancelableWait. * rwlock.c (_rwlock_check*): Renamed to ptw32_rwlock_check*. * mutex.c (_mutex_check*): Renamed to ptw32_mutex_check*. * condvar.c (cond_timed*): Renamed to ptw32_cond_timed*. (_cond_check*): Renamed to ptw32_cond_check*. + (cond_wait_cleanup*): Rename to ptw32_cond_wait_cleanup*. + (ptw32_cond_timedwait): Add comments. 2000-08-22 Ross Johnson <rpj@setup1.ise.canberra.edu.au> @@ -530,19 +530,23 @@ typedef struct { pthread_mutex_t * mutexPtr; pthread_cond_t cv; int * resultPtr; -} cond_wait_cleanup_args_t; +} ptw32_cond_wait_cleanup_args_t; static void -cond_wait_cleanup(void * args) +ptw32_cond_wait_cleanup(void * args) { - cond_wait_cleanup_args_t * cleanup_args = (cond_wait_cleanup_args_t *) args; + ptw32_cond_wait_cleanup_args_t * cleanup_args = (ptw32_cond_wait_cleanup_args_t *) args; pthread_mutex_t * mutexPtr = cleanup_args->mutexPtr; pthread_cond_t cv = cleanup_args->cv; int * resultPtr = cleanup_args->resultPtr; - int lock_result; int lastWaiter = FALSE; - if ((lock_result = pthread_mutex_lock (&(cv->waitersLock))) == 0) + /* + * Whether we got here legitimately or because of an error we + * indicate that we are no longer waiting. The alternative + * will result in never signaling the broadcasting thread. + */ + if (pthread_mutex_lock (&(cv->waitersLock)) == 0) { /* * The waiter is responsible for decrementing @@ -558,40 +562,42 @@ cond_wait_cleanup(void * args) cv->wasBroadcast = FALSE; } - lock_result = pthread_mutex_unlock (&(cv->waitersLock)); + (void) pthread_mutex_unlock (&(cv->waitersLock)); } - if ((*resultPtr == 0 || *resultPtr == ETIMEDOUT) && lock_result == 0) + /* + * If we are the last waiter on this broadcast + * let the thread doing the broadcast proceed + */ + if (lastWaiter && !SetEvent (cv->waitersDone)) { - if (lastWaiter) - { - /* - * If we are the last waiter on this broadcast - * let the thread doing the broadcast proceed - */ - if (!SetEvent (cv->waitersDone)) - { - *resultPtr = EINVAL; - } - } + *resultPtr = EINVAL; } /* * We must always regain the external mutex, even when * errors occur, because that's the guarantee that we give - * to our callers + * to our callers. + * + * Note that the broadcasting thread may already own the lock. + * The standard actually requires that the signaling thread hold + * the lock at the time that it signals if the developer wants + * predictable scheduling behaviour. It's up to the developer. + * In that case all waiting threads will block here until + * the broadcasting thread releases the lock, having been + * notified by the last waiting thread (SetEvent call above). */ (void) pthread_mutex_lock (mutexPtr); } static int ptw32_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime) + pthread_mutex_t * mutex, + const struct timespec *abstime) { int result = 0; pthread_cond_t cv; - cond_wait_cleanup_args_t cleanup_args; + ptw32_cond_wait_cleanup_args_t cleanup_args; if (cond == NULL || *cond == NULL) { @@ -644,15 +650,15 @@ ptw32_cond_timedwait (pthread_cond_t * cond, cleanup_args.cv = cv; cleanup_args.resultPtr = &result; - pthread_cleanup_push (cond_wait_cleanup, (void *) &cleanup_args); + pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args); if ((result = pthread_mutex_unlock (mutex)) == 0) { /* * Wait to be awakened by * pthread_cond_signal, or - * pthread_cond_broadcast - * timeout + * pthread_cond_broadcast, or + * a timeout * * Note: * ptw32_sem_timedwait is a cancelation point, @@ -668,7 +674,7 @@ ptw32_cond_timedwait (pthread_cond_t * cond, } } - pthread_cleanup_pop (1); + pthread_cleanup_pop (1); /* Always cleanup */ /* * "result" can be modified by the cleanup handler. @@ -737,8 +743,8 @@ pthread_cond_wait (pthread_cond_t * cond, int pthread_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime) + pthread_mutex_t * mutex, + const struct timespec *abstime) /* * ------------------------------------------------------ * DOCPUBLIC @@ -237,7 +237,7 @@ pthread_equal (pthread_t t1, pthread_t t2) static int -CancelableWait (HANDLE waitHandle, DWORD timeout) +ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout) /* * ------------------------------------------------------------------- * This provides an extra hook into the pthread_cancel @@ -346,13 +346,13 @@ CancelableWait (HANDLE waitHandle, DWORD timeout) int pthreadCancelableWait (HANDLE waitHandle) { - return (CancelableWait(waitHandle, INFINITE)); + return (ptw32_cancelable_wait(waitHandle, INFINITE)); } int pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout) { - return (CancelableWait(waitHandle, timeout)); + return (ptw32_cancelable_wait(waitHandle, timeout)); } @@ -686,7 +686,7 @@ struct ptw32_cleanup_t { if ( executeIt && ((void *) cleanUpRout != NULL) ) { - (void) (*cleanUpRout)( obj ); + (void) (*cleanUpRout)( obj ); } } diff --git a/semaphore.c b/semaphore.c index 366c2de..b388887 100644 --- a/semaphore.c +++ b/semaphore.c @@ -382,7 +382,7 @@ sem_wait (sem_t * sem) #ifdef NEED_SEM - _decrease_semaphore(sem); + ptw32_decrease_semaphore(sem); #endif /* NEED_SEM */ @@ -426,7 +426,7 @@ sem_post (sem_t * sem) #ifdef NEED_SEM - else if (! _increase_semaphore (sem, 1)) + else if (! ptw32_increase_semaphore (sem, 1)) #else /* NEED_SEM */ |