summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog87
-rw-r--r--dll.c13
-rw-r--r--global.c7
-rw-r--r--implement.h5
-rw-r--r--mutex.c508
-rw-r--r--private.c14
-rw-r--r--pthread.h20
-rw-r--r--tests/eyal1.c1
8 files changed, 613 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index fde297e..9460c56 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Wed Jan 20 09:31:28 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_mutexattr_t): Changed to a pointer.
+
+ * mutex.c (pthread_mutex_init): Conditionally create Win32 mutex
+ - from John Bossom's implementation.
+ (pthread_mutex_destroy): Conditionally close Win32 mutex
+ - from John Bossom's implementation.
+ (pthread_mutexattr_init): Replaced by John Bossom's version.
+ (pthread_mutexattr_destroy): Ditto.
+ (pthread_mutexattr_getpshared): New function from John Bossom's
+ implementation.
+ (pthread_mutexattr_setpshared): New function from John Bossom's
+ implementation.
+
Tue Jan 19 18:27:42 1999 Ross Johnson <rpj@swan.canberra.edu.au>
* pthread.h (pthreadCancelableTimedWait): New prototype.
@@ -16,6 +31,78 @@ Tue Jan 19 18:27:42 1999 Ross Johnson <rpj@swan.canberra.edu.au>
pthreadCancelableTimedWait().
- Scott Lightner <scott@curriculum.com>
+Tue Jan 19 10:27:39 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_mutexattr_setforcecs_np): New prototype.
+
+ * mutex.c (pthread_mutexattr_init): Init 'pshared' and 'forcecs'
+ attributes to 0.
+ (pthread_mutexattr_setforcecs_np): New function (not portable).
+
+ * pthread.h (pthread_mutex_t):
+ Add 'mutex' element. Set to NULL in PTHREAD_MUTEX_INITIALIZER.
+ The pthread_mutex_*() routines will try to optimise performance
+ by choosing either mutexes or critical sections as the basis
+ for pthread mutexes for each indevidual mutex.
+ (pthread_mutexattr_t_): Add 'forcecs' element.
+ Some applications may choose to force use of critical sections
+ if they know that:-
+ the mutex is PROCESS_PRIVATE and,
+ either the OS supports TryEnterCriticalSection() or
+ pthread_mutex_trylock() will never be called on the mutex.
+ This attribute will be setable via a non-portable routine.
+
+ Note: We don't yet support PROCESS_SHARED mutexes, so the
+ implementation as it stands will default to Win32 mutexes only if
+ the OS doesn't support TryEnterCriticalSection. On Win9x, and early
+ versions of NT 'forcecs' will need to be set in order to get
+ critical section based mutexes.
+
+Sun Jan 17 12:01:26 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * pthread.h (PTHREAD_MUTEX_INITIALIZER): Init new 'staticinit'
+ value to '1' and existing 'valid' value to '1'.
+
+ * global.c (_pthread_mutex_test_init_lock): Add.
+
+ * implement.h (_pthread_mutex_test_init_lock.): Add extern.
+
+ * private.c (_pthread_processInitialize): Init critical section for
+ global lock used by _mutex_check_need_init().
+ (_pthread_processTerminate): Ditto (:s/Init/Destroy/).
+
+ * dll.c (dllMain): Move call to FreeLibrary() so that it is only
+ called once when the process detaches.
+
+ * mutex.c (_mutex_check_need_init): New static function to test
+ and init PTHREAD_MUTEX_INITIALIZER mutexes. Provides serialised
+ access to the internal state of the uninitialised static mutex.
+ Called from pthread_mutex_trylock() and pthread_mutex_lock() which
+ do a quick unguarded test to check if _mutex_check_need_init()
+ needs to be called. This is safe as the test is conservative
+ and is repeated inside the guarded section of
+ _mutex_check_need_init(). Thus in all calls except the first
+ calls to lock static mutexes, the additional overhead to lock any
+ mutex is a single memory fetch and test for zero.
+
+ * pthread.h (pthread_mutex_t_): Add 'staticinit' member. Mutexes
+ initialised by PTHREAD_MUTEX_INITIALIZER aren't really initialised
+ until the first attempt to lock it. Using the 'valid'
+ flag (which flags the mutex as destroyed or not) to record this
+ information would be messy. It is possible for a statically
+ initialised mutex such as this to be destroyed before ever being
+ used.
+
+ * mutex.c (pthread_mutex_trylock): Call _mutex_check_need_init()
+ to test/init PTHREAD_MUTEX_INITIALIZER mutexes.
+ (pthread_mutex_lock): Ditto.
+ (pthread_mutex_unlock): Add check to ensure we don't try to unlock
+ an unitialised static mutex.
+ (pthread_mutex_destroy): Add check to ensure we don't try to delete
+ a critical section that we never created. Allows us to destroy
+ a static mutex that has never been locked (and hence initialised).
+ (pthread_mutex_init): Set 'staticinit' flag to 0 for the new mutex.
+
Sun Jan 17 12:01:26 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* private.c (_pthread_sem_timedwait): Move from semaphore.c.
diff --git a/dll.c b/dll.c
index d26f8fd..f2b3505 100644
--- a/dll.c
+++ b/dll.c
@@ -10,12 +10,17 @@
#include "implement.h"
-/* Function pointer to TryEnterCriticalSection if it exists; otherwise NULL */
+/*
+ * Function pointer to TryEnterCriticalSection if it exists; otherwise NULL
+ */
BOOL (WINAPI *_pthread_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL;
-/* Handle to kernel32.dll */
+/*
+ * Handle to kernel32.dll
+ */
static HINSTANCE _pthread_h_kernel32;
+
#ifdef _MSC_VER
/*
* lpvReserved yields an unreferenced formal parameter;
@@ -89,11 +94,11 @@ DllMain (
* The DLL is being unmapped into the process's address space
*/
_pthread_processTerminate ();
+
+ (void) FreeLibrary(_pthread_h_kernel32);
}
}
- (void) FreeLibrary(_pthread_h_kernel32);
-
result = TRUE;
}
break;
diff --git a/global.c b/global.c
index 56a26f3..a8bd69a 100644
--- a/global.c
+++ b/global.c
@@ -14,4 +14,11 @@ int _pthread_processInitialized = FALSE;
pthread_key_t _pthread_selfThreadKey = NULL;
pthread_key_t _pthread_cleanupKey = NULL;
+/*
+ * Global lock for testing internal state of PTHREAD_MUTEX_INITIALIZER
+ * created mutexes.
+ */
+CRITICAL_SECTION _pthread_mutex_test_init_lock;
+
+
diff --git a/implement.h b/implement.h
index be71b7e..f897033 100644
--- a/implement.h
+++ b/implement.h
@@ -135,6 +135,7 @@ extern BOOL (WINAPI *_pthread_try_enter_critical_section)(LPCRITICAL_SECTION);
extern int _pthread_processInitialized;
extern pthread_key_t _pthread_selfThreadKey;
extern pthread_key_t _pthread_cleanupKey;
+extern CRITICAL_SECTION _pthread_mutex_test_init_lock;
#ifdef __cplusplus
@@ -183,7 +184,8 @@ int _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime);
*/
#if defined(__CYGWIN32__) || defined(__CYGWIN__)
-/* Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
+/*
+ * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
* in order to avoid warnings because of return type
*/
@@ -206,3 +208,4 @@ int _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime);
#endif /* _IMPLEMENT_H */
+
diff --git a/mutex.c b/mutex.c
index aabee9e..b800512 100644
--- a/mutex.c
+++ b/mutex.c
@@ -10,85 +10,505 @@
#include "pthread.h"
#include "implement.h"
+
+static int
+_mutex_check_need_init(pthread_mutex_t *mutex)
+{
+ int result = 0;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised mutexes (via PTHREAD_MUTEX_INITIALIZER).
+ *
+ * Note that by not providing this synchronisation we risk
+ * introducing race conditions into applications which are
+ * correctly written.
+ *
+ * Approach
+ * --------
+ * We know that static mutexes will not be PROCESS_SHARED
+ * so we can serialise access to internal state using
+ * Win32 Critical Sections rather than Win32 Mutexes.
+ *
+ * We still have a problem in that we would like a per-mutex
+ * lock, but attempting to create one will again lead
+ * to a race condition. We are forced to use a global
+ * lock in this instance.
+ *
+ * If using a single global lock slows applications down too much,
+ * multiple global locks could be created and hashed on some random
+ * value associated with each mutex, the pointer perhaps. At a guess,
+ * a good value for the optimal number of global locks might be
+ * the number of processors + 1.
+ *
+ * We need to maintain the following per-mutex state independently:
+ * - mutex staticinit (true iff static mutex and still
+ * needs to be initialised)
+ * - mutex valid (false iff mutex has been destroyed)
+ *
+ * For example, a mutex initialised by PTHREAD_MUTEX_INITIALIZER
+ * in this implementation will be valid but uninitialised until the thread
+ * attempts to lock it. It can also be destroyed (made invalid) before
+ * ever being locked.
+ */
+ EnterCriticalSection(&_pthread_mutex_test_init_lock);
+
+ /*
+ * We got here because staticinit tested true.
+ * Check staticinit again inside the critical section
+ * and only initialise if the mutex is valid (not been destroyed).
+ * If a static mutex has been destroyed, the application can
+ * re-initialise it only by calling pthread_mutex_init()
+ * explicitly.
+ */
+ if (mutex->staticinit && mutex->valid)
+ {
+ result = pthread_mutex_init(mutex, NULL);
+ }
+
+ LeaveCriticalSection(&_pthread_mutex_test_init_lock);
+
+ return(result);
+}
+
int
pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
{
+ int result = 0;
+
if (mutex == NULL)
{
return EINVAL;
}
- /* Create a critical section. */
- InitializeCriticalSection(&mutex->cs);
+ mutex->mutex = 0;
- /* Mark as valid. */
- mutex->valid = 1;
+ /*
+ * Assuming any race condition here is harmless.
+ */
+ if (mutex->valid && !mutex->staticinit)
+ {
+ return EBUSY;
+ }
- return 0;
+ if (attr != NULL
+ && *attr != NULL
+ && (*attr)->pshared == PTHREAD_PROCESS_SHARED
+ )
+ {
+ /*
+ * 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.
+
+ mutex->mutex = CreateMutex (
+ NULL,
+ FALSE,
+ ????);
+ result = (mutex->mutex == 0) ? EAGAIN : 0;
+
+#else
+
+ result = ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+ }
+ else
+ {
+ if (_pthread_try_enter_critical_section != NULL
+ || (attr != NULL
+ && *attr != NULL
+ && (*attr)->forcecs == 1)
+ )
+ {
+ /*
+ * Create a critical section.
+ */
+ InitializeCriticalSection(&mutex->cs);
+ }
+ else
+ {
+ /*
+ * Create a mutex that can only be used within the
+ * current process
+ */
+ mutex->mutex = CreateMutex (NULL,
+ FALSE,
+ NULL);
+ result = (mutex->mutex == 0) ? EAGAIN : 0;
+ }
+ }
+
+ if (result == 0)
+ {
+ mutex->staticinit = 0;
+
+ /* Mark as valid. */
+ mutex->valid = 1;
+ }
+
+ return(result);
}
int
pthread_mutex_destroy(pthread_mutex_t *mutex)
{
+ int result = 0;
+
if (mutex == NULL)
{
return EINVAL;
}
- DeleteCriticalSection(&mutex->cs);
-
- /* Mark as invalid. */
- mutex->valid = 0;
+ /*
+ * Check to see if we have something to delete.
+ */
+ if (!mutex->staticinit)
+ {
+ if (mutex->mutex == 0)
+ {
+ DeleteCriticalSection(&mutex->cs);
+ }
+ else
+ {
+ result = (CloseHandle (mutex->mutex) ? 0 : EINVAL);
+ }
+ }
- return 0;
+ if (result == 0)
+ {
+ mutex->mutex = 0;
+
+ /* Mark as invalid. */
+ mutex->valid = 0;
+ }
+
+ return(result);
}
int
-pthread_mutexattr_init(pthread_mutexattr_t *attr)
+pthread_mutexattr_init (pthread_mutexattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a mutex attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a mutex attributes object with default
+ * attributes.
+ *
+ * NOTES:
+ * 1) Used to define mutex types
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_mutexattr_t attr_result;
+ int result = 0;
+
+ attr_result = calloc (1, sizeof (*attr_result));
+
+ result = (attr_result == NULL)
+ ? ENOMEM
+ : 0;
+
+ *attr = attr_result;
+
+ return (result);
+
+} /* pthread_mutexattr_init */
+
+
+int
+pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a mutex attributes object. The object can
+ * no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a mutex attributes object. The object can
+ * no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect mutexes created using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+
+ }
+ else
+ {
+ free (*attr);
+
+ *attr = NULL;
+ result = 0;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_destroy */
+
+
+int
+pthread_mutexattr_setforcecs_np(pthread_mutexattr_t *attr,
+ int forcecs)
{
- if (attr == NULL)
+ if (attr == NULL || *attr == NULL)
{
/* This is disallowed. */
return EINVAL;
}
- /* None of the optional attributes are supported yet. */
+ (*attr)->forcecs = forcecs;
+
return 0;
}
+
int
-pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
+pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr,
+ int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether mutexes created with 'attr' can be
+ * shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' is invalid,
+ *
+ * ------------------------------------------------------
+ */
{
- /* Nothing to do. */
- return 0;
-}
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ *pshared = PTHREAD_PROCESS_PRIVATE;
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_getpshared */
+
+
+int
+pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Mutexes created with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((pshared == PTHREAD_PROCESS_SHARED) ||
+ (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_setpshared */
+
int
pthread_mutex_lock(pthread_mutex_t *mutex)
{
- if (!mutex->valid)
+ int result = 0;
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check 'staticinit'
+ * again inside the guarded section of _mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (mutex->staticinit)
{
- pthread_mutex_init(mutex, NULL);
+ result = _mutex_check_need_init(mutex);
}
- EnterCriticalSection(&mutex->cs);
- return 0;
+
+ if (result == 0)
+ {
+ if (mutex->mutex == 0)
+ {
+ EnterCriticalSection(&mutex->cs);
+ }
+ else
+ {
+ result = (WaitForSingleObject(mutex->mutex, INFINITE)
+ == WAIT_OBJECT_0)
+ ? 0
+ : EINVAL;
+ }
+ }
+
+ return(result);
}
int
pthread_mutex_unlock(pthread_mutex_t *mutex)
{
- if (!mutex->valid)
+ int result = 0;
+
+ /*
+ * If the thread calling us holds the mutex then there is no
+ * race condition. If another thread holds the
+ * lock then we shouldn't be in here.
+ */
+ if (!mutex->staticinit && mutex->valid)
{
- return EINVAL;
+ if (mutex->mutex == 0)
+ {
+ LeaveCriticalSection(&mutex->cs);
+ }
+ else
+ {
+ result = (ReleaseMutex (mutex->mutex) ? 0 : EINVAL);
+ }
}
- LeaveCriticalSection(&mutex->cs);
- return 0;
+ else
+ {
+ result = EINVAL;
+ }
+
+ return(result);
}
int
pthread_mutex_trylock(pthread_mutex_t *mutex)
{
- if (_pthread_try_enter_critical_section == NULL)
+ int result = 0;
+
+ if (mutex->mutex == 0 && _pthread_try_enter_critical_section == NULL)
{
/* TryEnterCriticalSection does not exist in the OS; return ENOSYS. */
return ENOSYS;
@@ -99,10 +519,40 @@ pthread_mutex_trylock(pthread_mutex_t *mutex)
return EINVAL;
}
- if (!mutex->valid)
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check 'staticinit'
+ * again inside the guarded section of _mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (mutex->staticinit)
+ {
+ result = _mutex_check_need_init(mutex);
+ }
+
+ if (result == 0)
{
- pthread_mutex_init(mutex, NULL);
+ if (mutex->mutex == 0)
+ {
+ if ((*_pthread_try_enter_critical_section)(&mutex->cs) != TRUE)
+ {
+ result = EBUSY;
+ }
+ }
+ else
+ {
+ DWORD status;
+
+ status = WaitForSingleObject (mutex->mutex, 0);
+
+ if (status != WAIT_OBJECT_0)
+ {
+ result = ((status == WAIT_TIMEOUT)
+ ? EBUSY
+ : EINVAL);
+ }
+ }
}
- return ((*_pthread_try_enter_critical_section)(&mutex->cs) != TRUE) ? EBUSY : 0;
+ return(result);
}
diff --git a/private.c b/private.c
index 1039d81..dd32ccd 100644
--- a/private.c
+++ b/private.c
@@ -9,6 +9,8 @@
#include "pthread.h"
#include "implement.h"
+#include <sys/timeb.h>
+
/*
* Code contributed by John E. Bossom <JEB>.
*/
@@ -49,6 +51,11 @@ _pthread_processInitialize (void)
_pthread_processTerminate ();
}
+ /*
+ * Set up the global mutex test and init check lock.
+ */
+ InitializeCriticalSection(&_pthread_mutex_test_init_lock);
+
return (_pthread_processInitialized);
} /* processInitialize */
@@ -99,6 +106,11 @@ _pthread_processTerminate (void)
_pthread_cleanupKey = NULL;
}
+ /*
+ * Destroy up the global mutex test and init check lock.
+ */
+ DeleteCriticalSection(&_pthread_mutex_test_init_lock);
+
_pthread_processInitialized = FALSE;
}
@@ -483,7 +495,7 @@ _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime)
if (abstime == NULL)
{
- msecs = INFINITE;
+ milliseconds = INFINITE;
}
else
{
diff --git a/pthread.h b/pthread.h
index aa48b32..29e691f 100644
--- a/pthread.h
+++ b/pthread.h
@@ -415,7 +415,7 @@ extern "C"
typedef struct pthread_once_t_ pthread_once_t;
typedef struct pthread_key_t_ *pthread_key_t;
typedef struct pthread_mutex_t_ pthread_mutex_t;
- typedef struct pthread_mutexattr_t_ pthread_mutexattr_t;
+ typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t;
typedef struct pthread_cond_t_ *pthread_cond_t;
typedef struct pthread_condattr_t_ *pthread_condattr_t;
@@ -460,10 +460,10 @@ extern "C"
* ====================
*/
-/* FIXME: Replace the NULL with a valid critical section initializer
- * and then also change the 0 (first element) to 1.
+/*
+ *
*/
-#define PTHREAD_MUTEX_INITIALIZER { 0, NULL }
+#define PTHREAD_MUTEX_INITIALIZER { 1, 1, 0, NULL }
/*
@@ -569,13 +569,16 @@ struct pthread_attr_t_ {
struct pthread_mutex_t_ {
- int valid;
- CRITICAL_SECTION cs;
- };
+ int staticinit;
+ int valid;
+ HANDLE mutex;
+ CRITICAL_SECTION cs;
+};
struct pthread_mutexattr_t_ {
int pshared;
+ int forcecs;
};
@@ -838,6 +841,9 @@ int pthread_mutexattr_getpshared (const pthread_mutexattr_t
int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
int pshared);
+int pthread_mutexattr_setforcecs_np(pthread_mutexattr_t *attr,
+ int forcecs);
+
/*
* Mutex Functions
*/
diff --git a/tests/eyal1.c b/tests/eyal1.c
index e32d29e..f51bc9c 100644
--- a/tests/eyal1.c
+++ b/tests/eyal1.c
@@ -161,6 +161,7 @@ print_server (void *ptr)
*/
if (pthread_mutex_lock (&mutex_todo))
return (-6);
+
mywork = todo;
if (todo >= 0) {
++todo;