diff options
-rw-r--r-- | implement.h | 24 | ||||
-rw-r--r-- | mutex.c | 125 | ||||
-rw-r--r-- | tests/mutex1.c | 2 |
3 files changed, 69 insertions, 82 deletions
diff --git a/implement.h b/implement.h index 41c220d..1addce6 100644 --- a/implement.h +++ b/implement.h @@ -119,27 +119,27 @@ struct pthread_attr_t_ { */ /* - * The following macros provide exclusive access to an object's pointer. + * The following macros are used to serialise access to an object, + * including possibly before it is initialised. * See mutex.c:pthread_mutex_lock() for an example. */ -#define PTW32_OBJECT_GET(type, ppObject, pDest) \ - while (((pDest) = (type) InterlockedCompareExchangePointer((PVOID *)(ppObject), \ - (PVOID)PTW32_OBJECT_IN_USE, \ - (PVOID)PTW32_OBJECT_IN_USE)) \ +#define PTW32_OBJECT_GET(type, pObject, Dest) \ + while (((Dest) = (type) InterlockedExchange((LPLONG)(pObject), \ + (LONG)PTW32_OBJECT_IN_USE)) \ == (type)PTW32_OBJECT_IN_USE) \ { \ Sleep(0); \ } -#define PTW32_OBJECT_SET(ppObject, value) \ - (void) InterlockedExchangePointer((PVOID *)(ppObject), (PVOID)(value)) +#define PTW32_OBJECT_SET(pObject, value) \ + (void) InterlockedExchange((LPLONG)(pObject), (LONG)(value)) -#define PTW32_OBJECT_TRYGET(type, ppObject, pDest) \ - ((((pDest) = (type) InterlockedExchangePointer((PVOID *)(ppObject), \ - (PVOID)PTW32_OBJECT_IN_USE)) \ - == (type)PTW32_OBJECT_IN_USE) ? ((void) InterlockedExchangePointer((PVOID *)(ppObject), \ - (PVOID)(pDest)) , 0) \ +#define PTW32_OBJECT_TRYGET(type, pObject, Dest) \ + ((((Dest) = (type) InterlockedExchange((LPLONG)(pObject), \ + (LONG)PTW32_OBJECT_IN_USE)) \ + == (type)PTW32_OBJECT_IN_USE) ? ((void) InterlockedExchange((LPLONG)(pObject), \ + (LONG)(Dest)) , 0) \ : 1) #define PTW32_OBJECT_IN_USE ((void *) -2) @@ -67,6 +67,12 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) return EINVAL; } + if (attr != NULL && *attr != NULL && (*attr)->pshared == PTHREAD_PROCESS_SHARED) + { + return ENOSYS; + } + + /* * We need to prevent us from being canceled * unexpectedly leaving the mutex in a corrupted state. @@ -85,12 +91,6 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) */ PTW32_OBJECT_GET(pthread_mutex_t, mutex, mx); - if (mx == NULL) - { - result = EINVAL; - goto FAIL0; - } - /* * We now have exclusive access to the mutex pointer * and structure, whether initialised or not. @@ -100,71 +100,44 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) if (mx == NULL) { result = ENOMEM; - goto FAIL1; + goto FAIL0; } - mx->lock_idx = -1; - mx->try_lock = 0; - mx->owner = NULL; - mx->waiters = 0; - mx->lastOwner = NULL; - mx->lastWaiter = NULL; - if (attr != NULL && *attr != NULL) { - mx->type = (*attr)->type; mx->pshared = (*attr)->pshared; - - if (mx->pshared == PTHREAD_PROCESS_SHARED) + if ((*attr)->type == PTHREAD_MUTEX_DEFAULT) { - /* - * Creating mutex that can be shared between - * processes. - */ - -#if _POSIX_THREAD_PROCESS_SHARED - - /* - * Not implemented yet. - */ - -#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet. - -#else - - result = ENOSYS; - -#endif /* _POSIX_THREAD_PROCESS_SHARED */ + mx->type = ptw32_mutex_mapped_default; + } + else + { + mx->type = (*attr)->type; } } else { - mx->type = PTHREAD_MUTEX_DEFAULT; - mx->pshared = PTHREAD_PROCESS_PRIVATE; - } - - if (mx->type == PTHREAD_MUTEX_DEFAULT) - { mx->type = ptw32_mutex_mapped_default; + mx->pshared = PTHREAD_PROCESS_PRIVATE; } - if (result != 0 && mx != NULL) - { - free(mx); - mx = NULL; - } + mx->lock_idx = -1; + mx->try_lock = 0; + mx->owner = NULL; + mx->waiters = 0; + mx->lastOwner = NULL; + mx->lastWaiter = NULL; - FAIL1: + FAIL0: PTW32_OBJECT_SET(mutex, mx); - FAIL0: - (void) pthread_mutex_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); } - return(result); + return result; } int @@ -259,12 +232,12 @@ pthread_mutex_destroy(pthread_mutex_t *mutex) mx = NULL; } + FAIL0: PTW32_OBJECT_SET(mutex, mx); - FAIL0: - (void) pthread_mutex_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); } @@ -711,7 +684,7 @@ pthread_mutex_lock(pthread_mutex_t *mutex) if (mx == (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { - result = pthread_mutex_init(&mx); + result = pthread_mutex_init(&mx, NULL); } if (result == 0) @@ -774,13 +747,17 @@ WAIT_RECURSIVE: mx->lastWaiter = self; mx->lock_idx--; PTW32_OBJECT_SET(mutex, mx); - (void) pthread_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); + Sleep(0); + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + } + else + { + Sleep(0); } - Sleep(0); - (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); PTW32_OBJECT_GET(pthread_mutex_t, mutex, mx); /* * Thread priorities may have tricked another @@ -846,13 +823,17 @@ WAIT_NORMAL: mx->lastWaiter = self; mx->lock_idx--; PTW32_OBJECT_SET(mutex, mx); - (void) pthread_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); + Sleep(0); + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + } + else + { + Sleep(0); } - Sleep(0); - (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); PTW32_OBJECT_GET(pthread_mutex_t, mutex, mx); /* * Thread priorities may have tricked another @@ -920,13 +901,17 @@ WAIT_ERRORCHECK: mx->lastWaiter = self; mx->lock_idx--; PTW32_OBJECT_SET(mutex, mx); - (void) pthread_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); + Sleep(0); + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + } + else + { + Sleep(0); } - Sleep(0); - (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); PTW32_OBJECT_GET(pthread_mutex_t, mutex, mx); /* * Thread priorities may have tricked another @@ -947,12 +932,12 @@ WAIT_ERRORCHECK: } } + FAIL0: PTW32_OBJECT_SET(mutex, mx); - FAIL0: - (void) pthread_mutex_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); } @@ -1007,7 +992,7 @@ pthread_mutex_unlock(pthread_mutex_t *mutex) * asynch cancelation then we also check if we've * been canceled at the same time. */ - (void) pthread_mutex_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldCancelType); + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldCancelType); /* * This waits until no other thread is looking at the @@ -1052,12 +1037,12 @@ pthread_mutex_unlock(pthread_mutex_t *mutex) result = EPERM; } + FAIL0: PTW32_OBJECT_SET(mutex, mx); - FAIL0: - (void) pthread_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); } @@ -1116,7 +1101,7 @@ pthread_mutex_trylock(pthread_mutex_t *mutex) * asynch cancelation then we also check if we've * been canceled at the same time. */ - (void) pthread_mutex_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldCancelType); + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldCancelType); /* * If no other thread is looking at the @@ -1142,7 +1127,7 @@ pthread_mutex_trylock(pthread_mutex_t *mutex) if (mx == (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { - result = pthread_mutex_init(&mx); + result = pthread_mutex_init(&mx, NULL); } if (result == 0) @@ -1181,9 +1166,9 @@ pthread_mutex_trylock(pthread_mutex_t *mutex) PTW32_OBJECT_SET(mutex, mx); FAIL0: - (void) pthread_setcanceltype(oldCancelType, NULL); if (oldCancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); } diff --git a/tests/mutex1.c b/tests/mutex1.c index c997963..2d11867 100644 --- a/tests/mutex1.c +++ b/tests/mutex1.c @@ -11,6 +11,8 @@ * pthread_mutex_destroy() */ +#define ASSERT_TRACE + #include "test.h" pthread_mutex_t mutex = NULL; |