summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpj <rpj>2004-10-01 07:17:09 +0000
committerrpj <rpj>2004-10-01 07:17:09 +0000
commitb0cf9efa6afeb8a7dbddf124dae173a2d633c801 (patch)
tree8f208f15bd63cf69ae9e2ceb2d523296db8bca76
parent531ca4db4794aab863a898b4d079ccd59b424b25 (diff)
Mutex speedups
-rw-r--r--ChangeLog42
-rw-r--r--implement.h7
-rw-r--r--pthread_mutex_destroy.c9
-rw-r--r--pthread_mutex_init.c2
-rw-r--r--pthread_mutex_lock.c64
-rw-r--r--pthread_mutex_timedlock.c244
-rw-r--r--pthread_mutex_trylock.c47
-rw-r--r--pthread_mutex_unlock.c72
-rw-r--r--tests/GNUmakefile2
-rw-r--r--tests/benchlib.c25
-rw-r--r--tests/benchtest.h3
-rw-r--r--tests/benchtest1.c42
-rw-r--r--tests/mutex4.c6
13 files changed, 341 insertions, 224 deletions
diff --git a/ChangeLog b/ChangeLog
index 7ce169c..9a3cd4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,23 +1,39 @@
+2004-09-27 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_mutex_lock.c (pthread_mutex_lock): Separate PTHREAD_MUTEX_NORMAL
+ logic since we do not need to keep or check some state required by other
+ mutex types; do not check mutex pointer arg for validity - leave this to
+ the system since we are only checking for NULL pointers. This should improve
+ speed of NORMAL mutexes and marginally improve speed of other type.
+ * pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
+ * pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise; also avoid
+ entering the critical section for the no-waiters case, with approx. 30%
+ reduction in lock/unlock overhead for this case..
+ * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise; also
+ no longer keeps mutex if post-timeout second attempt succeeds - this will
+ assist applications that wish to impose strict lock deadlines, rather than
+ simply to escape from frozen locks.
+
2004-09-09 Tristan Savatier <tristan at mpegtv.com>
- * pthread.h (struct pthread_once_t_): Qualify the 'done' element
- as 'volatile'.
- * pthread_once.c: Concerned about possible race condition,
- specifically on MPU systems re concurrent access to multibyte types.
- [Maintainer's note: the race condition is harmless on SPU systems
- and only a problem on MPU systems if concurrent access results in an
- exception (presumably generated by a hardware interrupt). There are
- other instances of similar harmless race conditions that have not been
- identified as issues.]
+ * pthread.h (struct pthread_once_t_): Qualify the 'done' element
+ as 'volatile'.
+ * pthread_once.c: Concerned about possible race condition,
+ specifically on MPU systems re concurrent access to multibyte types.
+ [Maintainer's note: the race condition is harmless on SPU systems
+ and only a problem on MPU systems if concurrent access results in an
+ exception (presumably generated by a hardware interrupt). There are
+ other instances of similar harmless race conditions that have not been
+ identified as issues.]
2004-09-09 Ross Johnson <rpj at callisto.canberra.edu.au>
- * pthread.h: Declare additional types as volatile.
+ * pthread.h: Declare additional types as volatile.
2004-08-27 Ross Johnson <rpj at callisto.canberra.edu.au>
- * pthread_barrier_wait.c (pthread_barrier_wait): Remove excessive code
- by substituting the internal non-cancelable version of sem_wait
- (ptw32_semwait).
+ * pthread_barrier_wait.c (pthread_barrier_wait): Remove excessive code
+ by substituting the internal non-cancelable version of sem_wait
+ (ptw32_semwait).
2004-08-25 Ross Johnson <rpj at callisto.canberra.edu.au>
diff --git a/implement.h b/implement.h
index 95308f5..400598c 100644
--- a/implement.h
+++ b/implement.h
@@ -423,13 +423,6 @@ struct ThreadKeyAssoc
#define PTW32_EPS_EXIT (1)
#define PTW32_EPS_CANCEL (2)
-/* Mutex constants */
-enum
-{
- PTW32_MUTEX_LOCK_IDX_INIT = -1,
- PTW32_MUTEX_OWNER_ANONYMOUS = 1
-};
-
/* Useful macros */
#define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
diff --git a/pthread_mutex_destroy.c b/pthread_mutex_destroy.c
index a777598..c2289d0 100644
--- a/pthread_mutex_destroy.c
+++ b/pthread_mutex_destroy.c
@@ -44,10 +44,9 @@ pthread_mutex_destroy (pthread_mutex_t * mutex)
int result = 0;
pthread_mutex_t mx;
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
+ /*
+ * Let the system deal with invalid pointers.
+ */
/*
* Check to see if we have something to delete.
@@ -64,7 +63,7 @@ pthread_mutex_destroy (pthread_mutex_t * mutex)
*/
if (result == 0)
{
- if (1 == mx->recursive_count)
+ if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count)
{
/*
* FIXME!!!
diff --git a/pthread_mutex_init.c b/pthread_mutex_init.c
index ebf26d5..93504ad 100644
--- a/pthread_mutex_init.c
+++ b/pthread_mutex_init.c
@@ -80,7 +80,7 @@ pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
}
else
{
- mx->lock_idx = PTW32_MUTEX_LOCK_IDX_INIT;
+ mx->lock_idx = -1;
mx->recursive_count = 0;
mx->kind = (attr == NULL || *attr == NULL
? PTHREAD_MUTEX_DEFAULT : (*attr)->kind);
diff --git a/pthread_mutex_lock.c b/pthread_mutex_lock.c
index f92b39b..b733801 100644
--- a/pthread_mutex_lock.c
+++ b/pthread_mutex_lock.c
@@ -46,11 +46,9 @@ pthread_mutex_lock (pthread_mutex_t * mutex)
int result = 0;
pthread_mutex_t mx;
-
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
+ /*
+ * Let the system deal with invalid pointers.
+ */
/*
* We do a quick check to see if we need to do more work
@@ -68,41 +66,51 @@ pthread_mutex_lock (pthread_mutex_t * mutex)
mx = *mutex;
- if (0 == InterlockedIncrement (&mx->lock_idx))
+ if (mx->kind == PTHREAD_MUTEX_NORMAL)
{
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self ()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ if (0 != InterlockedIncrement (&mx->lock_idx))
+ {
+ if (ptw32_semwait (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
+ }
}
else
{
- if (mx->kind != PTHREAD_MUTEX_FAST_NP &&
- pthread_equal (mx->ownerThread, pthread_self ()))
+ if (0 == InterlockedIncrement (&mx->lock_idx))
{
- (void) InterlockedDecrement (&mx->lock_idx);
-
- if (mx->kind == PTHREAD_MUTEX_RECURSIVE_NP)
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
+ mx->recursive_count = 1;
+ mx->ownerThread = pthread_self ();
}
else
{
- if (ptw32_semwait (&mx->wait_sema) == 0)
+ pthread_t self = pthread_self();
+
+ if (pthread_equal (mx->ownerThread, self))
{
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self ()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ (void) InterlockedDecrement (&mx->lock_idx);
+
+ if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
}
else
{
- result = errno;
+ if (ptw32_semwait (&mx->wait_sema) == 0)
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
+ }
+ else
+ {
+ result = errno;
+ }
}
}
}
diff --git a/pthread_mutex_timedlock.c b/pthread_mutex_timedlock.c
index a5d6b59..58f5613 100644
--- a/pthread_mutex_timedlock.c
+++ b/pthread_mutex_timedlock.c
@@ -214,10 +214,9 @@ pthread_mutex_timedlock (pthread_mutex_t * mutex,
return -1;
#endif
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
+ /*
+ * Let the system deal with invalid pointers.
+ */
/*
* We do a quick check to see if we need to do more work
@@ -235,142 +234,135 @@ pthread_mutex_timedlock (pthread_mutex_t * mutex,
mx = *mutex;
- if (0 == InterlockedIncrement (&mx->lock_idx))
+ if (mx->kind == PTHREAD_MUTEX_NORMAL)
{
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self ()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ if (0 != InterlockedIncrement (&mx->lock_idx))
+ {
+ switch (ptw32_timed_semwait (&mx->wait_sema, abstime))
+ {
+ case 0: /* We got the mutex. */
+ {
+ break;
+ }
+ case 1: /* Timed out. */
+ case 2: /* abstime passed before we started to wait. */
+ {
+ /*
+ * If we timeout, it is up to us to adjust lock_idx to say
+ * we're no longer waiting.
+ *
+ * The owner thread may still have posted wait_sema thinking
+ * we were waiting. We must check but then NOT do any
+ * programmed work if we have acquired the mutex because
+ * we don't know how long ago abstime was. We MUST just release it
+ * immediately.
+ */
+ EnterCriticalSection (&mx->wait_cs);
+
+ result = ETIMEDOUT;
+
+ if (-1 == sem_trywait (&mx->wait_sema))
+ {
+ (void) InterlockedDecrement (&mx->lock_idx);
+ }
+ else
+ {
+ if (InterlockedDecrement (&mx->lock_idx) >= 0)
+ {
+ /* Someone else is waiting on that mutex */
+ if (sem_post (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
+ }
+ }
+
+ LeaveCriticalSection (&mx->wait_cs);
+ break;
+ }
+ default:
+ {
+ result = errno;
+ break;
+ }
+ }
+ }
}
else
{
- if (mx->kind != PTHREAD_MUTEX_FAST_NP &&
- pthread_equal (mx->ownerThread, pthread_self ()))
- {
- (void) InterlockedDecrement (&mx->lock_idx);
+ pthread_t self = pthread_self();
- if (mx->kind == PTHREAD_MUTEX_RECURSIVE_NP)
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
+ if (0 == InterlockedIncrement (&mx->lock_idx))
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
}
else
{
- if (abstime == NULL)
+ if (pthread_equal (mx->ownerThread, self))
{
- result = EINVAL;
+ (void) InterlockedDecrement (&mx->lock_idx);
+
+ if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
}
else
{
switch (ptw32_timed_semwait (&mx->wait_sema, abstime))
{
- case 0: /* We got the mutex. */
- {
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self ()
- : (pthread_t)
- PTW32_MUTEX_OWNER_ANONYMOUS);
- break;
- }
- case 1: /* Timedout, try a second grab. */
- {
- int busy;
-
- EnterCriticalSection (&mx->wait_cs);
-
- /*
- * If we timeout, it is up to us to adjust lock_idx to say
- * we're no longer waiting. If the mutex was also unlocked
- * while we were timing out, and we simply return ETIMEDOUT,
- * then wait_sema would be left in a state that is not consistent
- * with the state of lock_idx.
- *
- * We must check to see if wait_sema has just been posted
- * but we can't just call sem_getvalue - we must compete for
- * the semaphore using sem_trywait(), otherwise we would need
- * additional critical sections elsewhere, which would make the
- * logic too inefficient.
- *
- * If sem_trywait returns EAGAIN then either wait_sema
- * was given directly to another waiting thread or
- * another thread has called sem_*wait() before us and
- * taken the lock. Then we MUST decrement lock_idx and return
- * ETIMEDOUT.
- *
- * Otherwise we MUST return success (because we have effectively
- * acquired the lock that would have been ours had we not
- * timed out), and NOT decrement lock_idx.
- *
- * We can almost guarrantee that EAGAIN is the only
- * possible error, so no need to test errno.
- */
-
- if (-1 == (busy = sem_trywait (&mx->wait_sema)))
- {
- (void) InterlockedDecrement (&mx->lock_idx);
- result = ETIMEDOUT;
- }
-
- LeaveCriticalSection (&mx->wait_cs);
-
- if (!busy)
- {
- /*
- * We have acquired the lock on second grab - keep it.
- */
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self ()
- : (pthread_t)
- PTW32_MUTEX_OWNER_ANONYMOUS);
- }
- break;
- }
- case 2: /* abstime passed before we started to wait. */
- {
- /*
- * If we timeout, it is up to us to adjust lock_idx to say
- * we're no longer waiting.
- *
- * The owner thread may still have posted wait_sema thinking
- * we were waiting. I believe we must check but then NOT do any
- * programmed work if we have acquired the mutex because
- * we don't how long ago abstime was. We MUST just release it
- * immediately.
- */
- EnterCriticalSection (&mx->wait_cs);
-
- result = ETIMEDOUT;
-
- if (-1 == sem_trywait (&mx->wait_sema))
- {
- (void) InterlockedDecrement (&mx->lock_idx);
- }
- else
- {
- if (InterlockedDecrement (&mx->lock_idx) >= 0)
- {
- /* Someone else is waiting on that mutex */
- if (sem_post (&mx->wait_sema) != 0)
- {
- result = errno;
- }
- }
- }
-
- LeaveCriticalSection (&mx->wait_cs);
- break;
- }
- default:
- {
- result = errno;
- break;
- }
+ case 0: /* We got the mutex. */
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
+ break;
+ }
+ case 1: /* Timedout. */
+ case 2: /* abstime passed before we started to wait. */
+ {
+ /*
+ * If we timeout, it is up to us to adjust lock_idx to say
+ * we're no longer waiting.
+ *
+ * The owner thread may still have posted wait_sema thinking
+ * we were waiting. We must check but then NOT do any
+ * programmed work if we have acquired the mutex because
+ * we don't know how long ago abstime was. We MUST just release it
+ * immediately.
+ */
+ EnterCriticalSection (&mx->wait_cs);
+
+ result = ETIMEDOUT;
+
+ if (-1 == sem_trywait (&mx->wait_sema))
+ {
+ (void) InterlockedDecrement (&mx->lock_idx);
+ }
+ else
+ {
+ if (InterlockedDecrement (&mx->lock_idx) >= 0)
+ {
+ /* Someone else is waiting on that mutex */
+ if (sem_post (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
+ }
+ }
+
+ LeaveCriticalSection (&mx->wait_cs);
+ break;
+ }
+ default:
+ {
+ result = errno;
+ break;
+ }
}
}
}
diff --git a/pthread_mutex_trylock.c b/pthread_mutex_trylock.c
index 6f137f0..bba8ed2 100644
--- a/pthread_mutex_trylock.c
+++ b/pthread_mutex_trylock.c
@@ -44,10 +44,9 @@ pthread_mutex_trylock (pthread_mutex_t * mutex)
int result = 0;
pthread_mutex_t mx;
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
+ /*
+ * Let the system deal with invalid pointers.
+ */
/*
* We do a quick check to see if we need to do more work
@@ -57,36 +56,36 @@ pthread_mutex_trylock (pthread_mutex_t * mutex)
*/
if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
{
- result = ptw32_mutex_check_need_init (mutex);
+ if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+ {
+ return (result);
+ }
}
mx = *mutex;
- if (result == 0)
+ if ((PTW32_INTERLOCKED_LONG) -1 ==
+ ptw32_interlocked_compare_exchange ((PTW32_INTERLOCKED_LPLONG) &
+ mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 0,
+ (PTW32_INTERLOCKED_LONG) -1))
{
- if ((PTW32_INTERLOCKED_LONG) PTW32_MUTEX_LOCK_IDX_INIT ==
- ptw32_interlocked_compare_exchange ((PTW32_INTERLOCKED_LPLONG) &
- mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 0,
- (PTW32_INTERLOCKED_LONG)
- PTW32_MUTEX_LOCK_IDX_INIT))
+ if (mx->kind != PTHREAD_MUTEX_NORMAL)
{
mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self ()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ mx->ownerThread = pthread_self ();
+ }
+ }
+ else
+ {
+ if (mx->kind == PTHREAD_MUTEX_RECURSIVE &&
+ pthread_equal (mx->ownerThread, pthread_self ()))
+ {
+ mx->recursive_count++;
}
else
{
- if (mx->kind == PTHREAD_MUTEX_RECURSIVE_NP &&
- pthread_equal (mx->ownerThread, pthread_self ()))
- {
- mx->recursive_count++;
- }
- else
- {
- result = EBUSY;
- }
+ result = EBUSY;
}
}
diff --git a/pthread_mutex_unlock.c b/pthread_mutex_unlock.c
index 05677c8..7b20d79 100644
--- a/pthread_mutex_unlock.c
+++ b/pthread_mutex_unlock.c
@@ -44,10 +44,9 @@ pthread_mutex_unlock (pthread_mutex_t * mutex)
int result = 0;
pthread_mutex_t mx;
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
+ /*
+ * Let the system deal with invalid pointers.
+ */
mx = *mutex;
@@ -58,30 +57,67 @@ pthread_mutex_unlock (pthread_mutex_t * mutex)
*/
if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
{
- if (mx->ownerThread == (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS
- || pthread_equal (mx->ownerThread, pthread_self ()))
+ if (mx->kind == PTHREAD_MUTEX_NORMAL)
{
- if (mx->kind != PTHREAD_MUTEX_RECURSIVE_NP
- || 0 == --mx->recursive_count)
- {
- mx->ownerThread = NULL;
- EnterCriticalSection (&mx->wait_cs);
+ LONG idx;
+
+ idx = (LONG) ptw32_interlocked_compare_exchange ((PTW32_INTERLOCKED_LPLONG)
+ &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1,
+ (PTW32_INTERLOCKED_LONG) 0);
- if (InterlockedDecrement (&mx->lock_idx) >= 0)
+ if (idx != 0)
+ {
+ if (idx > 0)
{
- /* Someone is waiting on that mutex */
- if (sem_post (&mx->wait_sema) != 0)
+ EnterCriticalSection (&mx->wait_cs);
+
+ if (InterlockedDecrement (&mx->lock_idx) >= 0)
{
- result = errno;
+ /* Someone is waiting on that mutex */
+ if (sem_post (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
}
- }
- LeaveCriticalSection (&mx->wait_cs);
+ LeaveCriticalSection (&mx->wait_cs);
+ }
+ else
+ {
+ /*
+ * Was not locked (so can't be owned by us).
+ */
+ result = EPERM;
+ }
}
}
else
{
- result = EPERM;
+ if (pthread_equal (mx->ownerThread, pthread_self ()))
+ {
+ if (mx->kind != PTHREAD_MUTEX_RECURSIVE
+ || 0 == --mx->recursive_count)
+ {
+ mx->ownerThread = NULL;
+ EnterCriticalSection (&mx->wait_cs);
+
+ if (InterlockedDecrement (&mx->lock_idx) >= 0)
+ {
+ /* Someone is waiting on that mutex */
+ if (sem_post (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
+ }
+
+ LeaveCriticalSection (&mx->wait_cs);
+ }
+ }
+ else
+ {
+ result = EPERM;
+ }
}
}
else
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index 04f9943..cc36b53 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -273,7 +273,7 @@ sizes.pass: sizes.exe
@ $(ECHO) Passed
@ $(TOUCH) $@
-%.bench: $(XXLIBS) %.exe
+%.bench: $(LIB) $(DLL) $(HDR) $(QAPC) $(XXLIBS) %.exe
@ $(ECHO) Running $*
$*
@ $(ECHO) Done
diff --git a/tests/benchlib.c b/tests/benchlib.c
index 78ec3c8..3fa7171 100644
--- a/tests/benchlib.c
+++ b/tests/benchlib.c
@@ -51,6 +51,31 @@ int old_mutex_use = OLD_WIN32CS;
BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL;
HINSTANCE ptw32_h_kernel32;
+void
+dummy_call(int * a)
+{
+}
+
+void
+interlocked_inc_with_conditionals(int * a)
+{
+ if (a != NULL)
+ if (InterlockedIncrement((long *) a) == -1)
+ {
+ *a = 0;
+ }
+}
+
+void
+interlocked_dec_with_conditionals(int * a)
+{
+ if (a != NULL)
+ if (InterlockedDecrement((long *) a) == -1)
+ {
+ *a = 0;
+ }
+}
+
int
old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr)
{
diff --git a/tests/benchtest.h b/tests/benchtest.h
index 2401622..64af6c8 100644
--- a/tests/benchtest.h
+++ b/tests/benchtest.h
@@ -59,6 +59,9 @@ extern HINSTANCE ptw32_h_kernel32;
#define PTW32_OBJECT_AUTO_INIT ((void *) -1)
+void dummy_call(int * a);
+void interlocked_inc_with_conditionals(int *a);
+void interlocked_dec_with_conditionals(int *a);
int old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr);
int old_mutex_lock(old_mutex_t *mutex);
int old_mutex_unlock(old_mutex_t *mutex);
diff --git a/tests/benchtest1.c b/tests/benchtest1.c
index 1a553dc..ce45cf2 100644
--- a/tests/benchtest1.c
+++ b/tests/benchtest1.c
@@ -101,6 +101,7 @@ runTest (char * testNameString, int mType)
int
main (int argc, char *argv[])
{
+ int i = 0;
CRITICAL_SECTION cs;
old_mutex_t ox;
pthread_mutexattr_init(&ma);
@@ -127,6 +128,45 @@ main (int argc, char *argv[])
overHeadMilliSecs = durationMilliSecs;
+ TESTSTART
+ assert((dummy_call(&i), 1) == one);
+ assert((dummy_call(&i), 1) == one);
+ TESTSTOP
+
+ durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+ printf( "%-45s %15ld %15.3f\n",
+ "Dummy call x 2",
+ durationMilliSecs,
+ (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+ TESTSTART
+ assert((interlocked_inc_with_conditionals(&i), 1) == one);
+ assert((interlocked_dec_with_conditionals(&i), 1) == one);
+ TESTSTOP
+
+ durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+ printf( "%-45s %15ld %15.3f\n",
+ "Dummy call -> Interlocked with cond x 2",
+ durationMilliSecs,
+ (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+ TESTSTART
+ assert((InterlockedIncrement(&i), 1) == one);
+ assert((InterlockedDecrement(&i), 1) == one);
+ TESTSTOP
+
+ durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+ printf( "%-45s %15ld %15.3f\n",
+ "InterlockedOp x 2",
+ durationMilliSecs,
+ (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
InitializeCriticalSection(&cs);
TESTSTART
@@ -139,7 +179,7 @@ main (int argc, char *argv[])
durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
printf( "%-45s %15ld %15.3f\n",
- "Simple Critical Section",
+ "Simple Critical Section x 2",
durationMilliSecs,
(float) durationMilliSecs * 1E3 / ITERATIONS);
diff --git a/tests/mutex4.c b/tests/mutex4.c
index 74ec159..75880fd 100644
--- a/tests/mutex4.c
+++ b/tests/mutex4.c
@@ -69,6 +69,9 @@ main()
assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_DEFAULT) == 0);
assert(pthread_mutex_init(&mutex1, &ma) == 0);
assert(pthread_mutex_lock(&mutex1) == 0);
+ /*
+ * NORMAL (fast) mutexes don't check ownership.
+ */
assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0);
assert(pthread_join(t, NULL) == 0);
assert(pthread_mutex_unlock(&mutex1) == EPERM);
@@ -78,6 +81,9 @@ main()
assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_NORMAL) == 0);
assert(pthread_mutex_init(&mutex1, &ma) == 0);
assert(pthread_mutex_lock(&mutex1) == 0);
+ /*
+ * NORMAL (fast) mutexes don't check ownership.
+ */
assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0);
assert(pthread_join(t, NULL) == 0);
assert(pthread_mutex_unlock(&mutex1) == EPERM);