From 19299847fdd32094b28377db1aea61b0f605dc8b Mon Sep 17 00:00:00 2001
From: rpj <rpj>
Date: Sun, 1 Jul 2001 13:49:38 +0000
Subject: 2001-07-01  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>

	Contributed by  - Alexander Terekhov.

	* condvar.c: Fixed lost signal bug reported by Timur Aydin
	(taydin@snet.net).
	[RPJ (me) didn't translate the original algorithm
	correctly.]
	* semaphore.c: Added sem_post_multiple; this is a useful
	routine, but it doesn't appear to be standard. For now it's
	not an exported function.

tests/ChangeLog:
2001-07-01  Ross Johnson  <rpj@special.ise.canberra.edu.au>

	* benchtest3.c: New; timing mutexes.
	* benchtest4.c: New; time mutexes.
	* condvar3_1.c: Fixed bug - Alexander Terekhov
	* condvar3_3.c: New test.

2001-06-25  Ross Johnson  <rpj@special.ise.canberra.edu.au>

	* priority1.c: New test.
	* priority2.c: New test.
	* inherit1.c: New test.
	* benchtest1.c: New; timing mutexes.
	* benchtest2.c: New; timing mutexes.
	* mutex4.c: Modified to test all mutex types.
---
 tests/ChangeLog    |  19 +++-
 tests/GNUmakefile  |  45 ++++++--
 tests/Makefile     |  39 +++++--
 tests/benchtest.h  | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/benchtest1.c | 116 +++++++++++++++-----
 tests/benchtest2.c | 198 ++++++++++++++++++++++++---------
 tests/benchtest3.c | 169 ++++++++++++++++++++++++++++
 tests/benchtest4.c | 150 +++++++++++++++++++++++++
 tests/condvar3.c   |   8 +-
 tests/condvar3_1.c |  26 ++++-
 tests/condvar3_3.c | 100 +++++++++++++++++
 11 files changed, 1072 insertions(+), 112 deletions(-)
 create mode 100644 tests/benchtest.h
 create mode 100644 tests/benchtest3.c
 create mode 100644 tests/benchtest4.c
 create mode 100644 tests/condvar3_3.c

diff --git a/tests/ChangeLog b/tests/ChangeLog
index 231d9fe..f99d1be 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,11 +1,18 @@
+2001-07-01  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* benchtest3.c: New; timing mutexes.
+	* benchtest4.c: New; time mutexes.
+	* condvar3_1.c: Fixed bug - Alexander Terekhov
+	* condvar3_3.c: New test.
+
 2001-06-25  Ross Johnson  <rpj@special.ise.canberra.edu.au>
 
-	priority1.c: New test.
-	priority2.c: New test.
-	inherit1.c: New test.
-	benchtest1.c: New; timing mutexes.
-	benchtest2.c: New; timing mutexes.
-	mutex4.c: Modified to test all mutex types.
+	* priority1.c: New test.
+	* priority2.c: New test.
+	* inherit1.c: New test.
+	* benchtest1.c: New; timing mutexes.
+	* benchtest2.c: New; timing mutexes.
+	* mutex4.c: Modified to test all mutex types.
 
 2001-06-8  Ross Johnson  <rpj@special.ise.canberra.edu.au>
 
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index 2eabdae..b952eed 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -41,41 +41,54 @@ TESTS	= loadfree \
 	  exit2 exit3 \
 	  join0 join1 join2 mutex2 mutex3 mutex4 mutex6 mutex6n mutex6e mutex6r \
 	  count1 once1 tsd1 self2 cancel1 cancel2 eyal1 \
-	  condvar3 condvar3_1 condvar3_2 condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \
+	  condvar3 condvar3_1 condvar3_2 condvar3_3 \
+	  condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \
 	  errno1 \
 	  rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 rwlock7 \
 	  context1 cancel3 cancel4 cancel5 \
 	  cleanup0 cleanup1 cleanup2 cleanup3 \
 	  priority1 priority2 inherit1 \
-	  exception1 exception2 \
-	  benchtest1 benchtest2 \
-	  exception3
+	  exception1 exception2 exception3
 
-PASSES	= $(TESTS:%=%.pass)
+BENCHTESTS = \
+	benchtest1 benchtest2 benchtest3 benchtest4
+
+PASSES		= $(TESTS:%=%.pass)
+BENCHRESULTS	= $(BENCHTESTS:%=%.bench)
 
 default:
 	@ $(ECHO) Run one of the following command lines:
 	@ $(ECHO) nmake clean GCE   (to test using GNU C dll with C++ exception handling)
 	@ $(ECHO) nmake clean GC    (to test using GNU C dll with C cleanup code)
+	@ $(ECHO) nmake clean GCE-bench   (to benchtest using GNU C dll with C++ exception handling)
+	@ $(ECHO) nmake clean GC-bench    (to benchtest using GNU C dll with C cleanup code)
 
 auto:
 	@ $(MAKE) clean GCE
 	@ $(MAKE) clean GC
 
 GC:
-	$(MAKE) GCX=GC XXCFLAGS="-x c" all-GC
+	$(MAKE) GCX=GC XXCFLAGS="-x c" all-pass
 
 GCE:
-	$(MAKE) GCX=GCE XXCFLAGS="-mthreads -x c++" all-GCE
+	$(MAKE) GCX=GCE XXCFLAGS="-mthreads -x c++" all-pass
 
-all-GC: $(PASSES)
-	@ $(ECHO) ALL TESTS PASSED! Congratulations!
+GC-bench:
+	$(MAKE) GCX=GC XXCFLAGS="-x c" all-bench
 
-all-GCE: $(PASSES)
+GCE-bench:
+	$(MAKE) GCX=GCE XXCFLAGS="-mthreads -x c++" all-bench
+
+all-pass: $(PASSES)
 	@ $(ECHO) ALL TESTS PASSED! Congratulations!
 
-benchtest1.pass: mutex3.pass
-benchtest2.pass: benchtest1.pass
+all-bench: $(BENCHRESULTS)
+	@ $(ECHO) BENCH TESTS COMPLETED.
+
+benchtest1.bench:
+benchtest2.bench:
+benchtest3.bench:
+benchtest4.bench:
 cancel1.pass: create1.pass
 cancel2.pass: cancel1.pass
 cancel2_1.pass: cancel2.pass
@@ -92,6 +105,7 @@ condvar2_1.pass: condvar2.pass join2.pass
 condvar3.pass: create1.pass condvar2.pass
 condvar3_1.pass: condvar3.pass join2.pass
 condvar3_2.pass: condvar3_1.pass
+condvar3_3.pass: condvar3_2.pass
 condvar4.pass: create1.pass
 condvar5.pass: condvar4.pass
 condvar6.pass: condvar5.pass
@@ -144,6 +158,12 @@ tsd1.pass: join1.pass
 	@ $(ECHO) Passed
 	@ $(TOUCH) $@
 
+%.bench: %.exe $(LIB) $(DLL) $(HDR)
+	@ $(ECHO) Running $*
+	$*
+	@ $(ECHO) Done
+	@ $(TOUCH) $@
+
 %.exe: %.c
 	@ $(ECHO) Compiling $@
 	@ $(ECHO) $(CC) $(CFLAGS) -o $@ $^ $(INCLUDES) -L. -lpthread$(GCX)
@@ -174,3 +194,4 @@ clean:
 	- $(RM) *.pdb
 	- $(RM) *.exe
 	- $(RM) *.pass
+	- $(RM) *.bench
diff --git a/tests/Makefile b/tests/Makefile
index d7b36b0..7fd32af 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -48,7 +48,8 @@ PASSES= loadfree.pass \
 	  self2.pass  \
 	  cancel1.pass  cancel2.pass  \
 	  eyal1.pass  \
-	  condvar3.pass  condvar3_1.pass  condvar3_2.pass  condvar4.pass  condvar5.pass  condvar6.pass  \
+	  condvar3.pass  condvar3_1.pass  condvar3_2.pass  condvar3_3.pass  \
+	  condvar4.pass  condvar5.pass  condvar6.pass  \
 	  condvar7.pass  condvar8.pass  condvar9.pass  \
 	  errno1.pass  \
 	  rwlock1.pass  rwlock2.pass  rwlock3.pass  rwlock4.pass  rwlock5.pass  rwlock6.pass  rwlock7.pass  \
@@ -56,14 +57,19 @@ PASSES= loadfree.pass \
 	  cancel3.pass  cancel4.pass  cancel5.pass  \
 	  cleanup0.pass  cleanup1.pass  cleanup2.pass  cleanup3.pass  \
 	  priority1.pass priority2.pass inherit1.pass  \
-	  exception1.pass  exception2.pass  \
-	  benchtest1.pass benchtest2.pass exception3.pass  \
+	  exception1.pass  exception2.pass  exception3.pass
+
+BENCHRESULTS = \
+	  benchtest1.pass benchtest2.pass
 
 all:
 	@ $(ECHO) Run one of the following command lines:
 	@ $(ECHO) nmake clean VCE   (to test using MSVC dll with C++ exception handling)
 	@ $(ECHO) nmake clean VSE   (to test using MSVC dll with structured exception handling)
 	@ $(ECHO) nmake clean VC    (to test using MSVC dll with C cleanup code)
+	@ $(ECHO) nmake clean VCE-bench   (to benchtest using MSVC dll with C++ exception handling)
+	@ $(ECHO) nmake clean VSE-bench   (to benchtest using MSVC dll with structured exception handling)
+	@ $(ECHO) nmake clean VC-bench    (to benchtest using MSVC dll with C cleanup code)
 
 auto:
 	@ nmake clean VCE
@@ -73,12 +79,21 @@ auto:
 tests: $(CPLIB) $(CPDLL) $(CPHDR) $(PASSES)
 	@ $(ECHO) ALL TESTS PASSED! Congratulations!
 
+benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(BENCHRESULTS)
+	@ $(ECHO) ALL BENCH TESTS DONE.
+
 $(PASSES): $*.exe
 	@ $(ECHO) ... Running $(TEST) test: $*.exe
 	@ .\$*.exe
 	@ $(ECHO) ...... Passed
 	@ $(TOUCH) $*.pass
 
+$(BENCHRESULTS): $*.exe
+	@ $(ECHO) ... Running $(TEST) benchtest: $*.exe
+	@ .\$*.exe
+	@ $(ECHO) ...... Done
+	@ $(TOUCH) $*.bench
+
 VCE:
 	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" tests
 
@@ -88,6 +103,15 @@ VSE:
 VC:
 	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests
 
+VCE-bench:
+	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" benchtests
+
+VSE-bench:
+	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" benchtests
+
+VC-bench:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" benchtests
+
 .c.exe:
 	@ $(ECHO) Compiling $@
 	@ $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB)
@@ -115,9 +139,11 @@ clean:
 	- $(RM) *.o
 	- $(RM) *.exe
 	- $(RM) *.pass
+	- $(RM) *.bench
 
-benchtest1.pass: mutex3.pass
-benchtest2.pass: benchtest1.pass
+benchtest1.bench:
+benchtest2.bench:
+benchtest3.bench:
 cancel1.pass: create1.pass
 cancel2.pass: cancel1.pass
 cancel3.pass: context1.pass
@@ -133,6 +159,7 @@ condvar2_1.pass: condvar2.pass join2.pass
 condvar3.pass: create1.pass condvar2.pass
 condvar3_1.pass: condvar3.pass join2.pass
 condvar3_2.pass: condvar3_1.pass
+condvar3_3.pass: condvar3_2.pass
 condvar4.pass: create1.pass
 condvar5.pass: condvar4.pass
 condvar6.pass: condvar5.pass
@@ -177,5 +204,3 @@ rwlock7.pass: rwlock6.pass
 self1.pass:
 self2.pass: create1.pass
 tsd1.pass: join1.pass
-
-
diff --git a/tests/benchtest.h b/tests/benchtest.h
new file mode 100644
index 0000000..98d2bbe
--- /dev/null
+++ b/tests/benchtest.h
@@ -0,0 +1,314 @@
+/****************************************************************************************/
+
+#include "../config.h"
+
+enum {
+  OLD_WIN32CS,
+  OLD_WIN32MUTEX
+};
+
+static int old_mutex_use = OLD_WIN32CS;
+
+struct old_mutex_t_ {
+  HANDLE mutex;
+  CRITICAL_SECTION cs;
+};
+
+typedef struct old_mutex_t_ * old_mutex_t;
+
+struct old_mutexattr_t_ {
+  int pshared;
+};
+
+typedef struct old_mutexattr_t_ * old_mutexattr_t;
+
+static BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL;
+static HINSTANCE ptw32_h_kernel32;
+
+#define PTW32_OBJECT_AUTO_INIT ((void *) -1)
+
+static int
+old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  mx = (old_mutex_t) calloc(1, sizeof(*mx));
+
+  if (mx == NULL)
+    {
+      result = ENOMEM;
+      goto FAIL0;
+    }
+
+  mx->mutex = 0;
+
+  if (attr != NULL
+      && *attr != NULL
+      && (*attr)->pshared == PTHREAD_PROCESS_SHARED
+      )
+    {
+      result = ENOSYS;
+    }
+  else
+    {
+        CRITICAL_SECTION cs;
+
+        /*
+         * Load KERNEL32 and try to get address of TryEnterCriticalSection
+         */
+        ptw32_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));
+        ptw32_try_enter_critical_section = (BOOL (WINAPI *)(LPCRITICAL_SECTION))
+
+#if defined(NEED_UNICODE_CONSTS)
+        GetProcAddress(ptw32_h_kernel32,
+                       (const TCHAR *)TEXT("TryEnterCriticalSection"));
+#else
+        GetProcAddress(ptw32_h_kernel32,
+                       (LPCSTR) "TryEnterCriticalSection");
+#endif
+
+        if (ptw32_try_enter_critical_section != NULL)
+          {
+            InitializeCriticalSection(&cs);
+            if ((*ptw32_try_enter_critical_section)(&cs))
+              {
+                LeaveCriticalSection(&cs);
+              }
+            else
+              {
+                /*
+                 * Not really supported (Win98?).
+                 */
+                ptw32_try_enter_critical_section = NULL;
+              }
+            DeleteCriticalSection(&cs);
+          }
+
+        if (ptw32_try_enter_critical_section == NULL)
+          {
+            (void) FreeLibrary(ptw32_h_kernel32);
+            ptw32_h_kernel32 = 0;
+          }
+
+      if (old_mutex_use == OLD_WIN32CS)
+	{
+	  InitializeCriticalSection(&mx->cs);
+	}
+      else if (old_mutex_use == OLD_WIN32MUTEX)
+      {
+	  mx->mutex = CreateMutex (NULL,
+				   FALSE,
+				   NULL);
+
+	  if (mx->mutex == 0)
+	    {
+	      result = EAGAIN;
+	    }
+	}
+      else
+	{
+        result = EINVAL;
+      }
+    }
+
+  if (result != 0 && mx != NULL)
+    {
+      free(mx);
+      mx = NULL;
+    }
+
+FAIL0:
+  *mutex = mx;
+
+  return(result);
+}
+
+
+static int
+old_mutex_lock(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      /*
+       * Don't use initialisers when benchtesting.
+       */
+      result = EINVAL;
+    }
+
+  mx = *mutex;
+
+  if (result == 0)
+    {
+      if (mx->mutex == 0)
+	{
+	  EnterCriticalSection(&mx->cs);
+	}
+      else
+	{
+	  result = (WaitForSingleObject(mx->mutex, INFINITE) 
+		    == WAIT_OBJECT_0)
+	    ? 0
+	    : EINVAL;
+	}
+    }
+
+  return(result);
+}
+
+static int
+old_mutex_unlock(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  mx = *mutex;
+
+  if (mx != (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      if (mx->mutex == 0)
+	{
+	  LeaveCriticalSection(&mx->cs);
+	}
+      else
+	{
+	  result = (ReleaseMutex (mx->mutex) ? 0 : EINVAL);
+	}
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return(result);
+}
+
+
+static int
+old_mutex_trylock(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      /*
+       * Don't use initialisers when benchtesting.
+       */
+      result = EINVAL;
+    }
+
+  mx = *mutex;
+
+  if (result == 0)
+    {
+      if (mx->mutex == 0)
+	{
+	  if (ptw32_try_enter_critical_section == NULL)
+          {
+            result = 0;
+          }
+        else if ((*ptw32_try_enter_critical_section)(&mx->cs) != TRUE)
+	    {
+	      result = EBUSY;
+	    }
+	}
+      else
+	{
+	  DWORD status;
+
+	  status = WaitForSingleObject (mx->mutex, 0);
+
+	  if (status != WAIT_OBJECT_0)
+	    {
+	      result = ((status == WAIT_TIMEOUT)
+			? EBUSY
+			: EINVAL);
+	    }
+	}
+    }
+
+  return(result);
+}
+
+
+static int
+old_mutex_destroy(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL
+      || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*mutex != (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      mx = *mutex;
+
+      if ((result = old_mutex_trylock(&mx)) == 0)
+        {
+          *mutex = NULL;
+
+          (void) old_mutex_unlock(&mx);
+
+          if (mx->mutex == 0)
+            {
+              DeleteCriticalSection(&mx->cs);
+            }
+          else
+            {
+              result = (CloseHandle (mx->mutex) ? 0 : EINVAL);
+            }
+
+          if (result == 0)
+            {
+              mx->mutex = 0;
+              free(mx);
+            }
+          else
+            {
+              *mutex = mx;
+            }
+        }
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  if (ptw32_try_enter_critical_section != NULL)
+    {
+      (void) FreeLibrary(ptw32_h_kernel32);
+      ptw32_h_kernel32 = 0;
+    }
+
+  return(result);
+}
+
+/****************************************************************************************/
diff --git a/tests/benchtest1.c b/tests/benchtest1.c
index 883c24f..8514fa4 100644
--- a/tests/benchtest1.c
+++ b/tests/benchtest1.c
@@ -14,6 +14,9 @@
 #include <stdlib.h>
 #endif
 
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
 #define ITERATIONS      10000000L
 
 pthread_mutex_t mx;
@@ -40,24 +43,22 @@ long overHeadMilliSecs = 0;
 void
 runTest (char * testNameString, int mType)
 {
-#ifdef PTHREAD_MUTEX_DEFAULT
-  pthread_mutexattr_settype(&ma, mType);
+#ifdef PTW32_MUTEX_TYPES
+  assert(pthread_mutexattr_settype(&ma, mType) == 0);
 #endif
-  pthread_mutex_init(&mx, &ma);
+  assert(pthread_mutex_init(&mx, &ma) == 0);
 
   TESTSTART
-  (void) pthread_mutex_lock(&mx);
-  (void) pthread_mutex_unlock(&mx);
+  assert(pthread_mutex_lock(&mx) == 0);
+  assert(pthread_mutex_unlock(&mx) == 0);
   TESTSTOP
 
-  pthread_mutex_destroy(&mx);
+  assert(pthread_mutex_destroy(&mx) == 0);
 
-  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop)
-    - overHeadMilliSecs;
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
 
-  printf( "%-25s %15ld %15ld %15.3f\n",
-          testNameString,
-          ITERATIONS,
+  printf( "%-40s %15ld %15.3f\n",
+	    testNameString,
           durationMilliSecs,
           (float) durationMilliSecs * 1E3 / ITERATIONS);
 }
@@ -66,47 +67,104 @@ runTest (char * testNameString, int mType)
 int
 main (int argc, char *argv[])
 {
+  CRITICAL_SECTION cs;
+  old_mutex_t ox;
+
   pthread_mutexattr_init(&ma);
 
-  printf( "Single thread, non-blocking mutex locks/unlocks.\n\n");
-  printf( "%-25s %15s %15s %15s\n",
-          "Test",
-          "Iterations",
-          "Total(msec)",
-          "lock/unlock(usec)");
+  printf( "========================================================================\n");
+  printf( "\nNon-blocking mutex lock plus unlock.\n%ld iterations\n\n",
+          ITERATIONS);
+  printf( "%-40s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "------------------------------------------------------------------------\n");
 
   /*
    * Time the loop overhead so we can subtract it from the actual test times.
    */
 
   TESTSTART
+  assert(1 == 1);
+  assert(1 == 1);
   TESTSTOP
 
-  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop)
-    - overHeadMilliSecs;
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
 
-  printf( "%-25s %15ld %15ld\n",
-          "Overhead",
-          ITERATIONS,
-          durationMilliSecs);
 
-  overHeadMilliSecs = durationMilliSecs;
+  InitializeCriticalSection(&cs);
+
+  TESTSTART
+  assert((EnterCriticalSection(&cs), 1) == 1);
+  assert((LeaveCriticalSection(&cs), 1) == 1);
+  TESTSTOP
+
+  DeleteCriticalSection(&cs);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-40s %15ld %15.3f\n",
+	    "Simple Critical Section",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox, NULL) == 0);
+
+  TESTSTART
+  assert(old_mutex_lock(&ox) == 0);
+  assert(old_mutex_unlock(&ox) == 0);
+  TESTSTOP
+
+  assert(old_mutex_destroy(&ox) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox, NULL) == 0);
+
+  TESTSTART
+  assert(old_mutex_lock(&ox) == 0);
+  assert(old_mutex_unlock(&ox) == 0);
+  TESTSTOP
+
+  assert(old_mutex_destroy(&ox) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  printf( "........................................................................\n");
 
   /*
    * Now we can start the actual tests
    */
-#ifdef PTHREAD_MUTEX_DEFAULT
-  runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT);
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
 
-  runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL);
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
 
-  runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK);
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
 
-  runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE);
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
 #else
   runTest("Non-blocking lock", 0);
 #endif
 
+  printf( "========================================================================\n");
+
   /*
    * End of tests.
    */
diff --git a/tests/benchtest2.c b/tests/benchtest2.c
index f2932b9..a049961 100644
--- a/tests/benchtest2.c
+++ b/tests/benchtest2.c
@@ -17,9 +17,14 @@
 #include <stdlib.h>
 #endif
 
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
 #define ITERATIONS      100000L
 
 pthread_mutex_t gate1, gate2;
+old_mutex_t ox1, ox2;
+CRITICAL_SECTION cs1, cs2;
 pthread_mutexattr_t ma;
 long durationMilliSecs;
 long overHeadMilliSecs = 0;
@@ -55,6 +60,22 @@ overheadThread(void * arg)
 }
 
 
+void *
+oldThread(void * arg)
+{
+  do
+    {
+      (void) old_mutex_lock(&ox1);
+      (void) old_mutex_lock(&ox2);
+      (void) old_mutex_unlock(&ox1);
+      sched_yield();
+      (void) old_mutex_unlock(&ox2);
+    }
+  while (running);
+
+  return NULL;
+}
+
 void *
 workerThread(void * arg)
 {
@@ -71,22 +92,34 @@ workerThread(void * arg)
   return NULL;
 }
 
+void *
+CSThread(void * arg)
+{
+  do
+    {
+      EnterCriticalSection(&cs1);
+      EnterCriticalSection(&cs2);
+      LeaveCriticalSection(&cs1);
+      sched_yield();
+      LeaveCriticalSection(&cs2);
+    }
+  while (running);
+
+  return NULL;
+}
+
 void
 runTest (char * testNameString, int mType)
 {
-#ifdef PTHREAD_MUTEX_DEFAULT
-  pthread_mutexattr_settype(&ma, mType);
+#ifdef PTW32_MUTEX_TYPES
+  assert(pthread_mutexattr_settype(&ma, mType) == 0);
 #endif
-  pthread_mutex_init(&gate1, &ma);
-  pthread_mutex_init(&gate2, &ma);
-
-  (void) pthread_mutex_lock(&gate1);
-  (void) pthread_mutex_lock(&gate2);
-
+  assert(pthread_mutex_init(&gate1, &ma) == 0);
+  assert(pthread_mutex_init(&gate2, &ma) == 0);
+  assert(pthread_mutex_lock(&gate1) == 0);
+  assert(pthread_mutex_lock(&gate2) == 0);
   running = 1;
-
-  (void) pthread_create(&worker, NULL, workerThread, NULL);
-
+  assert(pthread_create(&worker, NULL, workerThread, NULL) == 0);
   TESTSTART
   (void) pthread_mutex_unlock(&gate1);
   sched_yield();
@@ -94,23 +127,15 @@ runTest (char * testNameString, int mType)
   (void) pthread_mutex_lock(&gate1);
   (void) pthread_mutex_lock(&gate2);
   TESTSTOP
-
   running = 0;
-
-  (void) pthread_mutex_unlock(&gate2);
-  (void) pthread_mutex_unlock(&gate1);
-
-  (void) pthread_join(worker, NULL);
-
-  pthread_mutex_destroy(&gate2);
-  pthread_mutex_destroy(&gate1);
-
-  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop)
-    - overHeadMilliSecs;
-
-  printf( "%-25s %15ld %15ld %15.3f\n",
-          testNameString,
-          ITERATIONS,
+  assert(pthread_mutex_unlock(&gate2) == 0);
+  assert(pthread_mutex_unlock(&gate1) == 0);
+  assert(pthread_join(worker, NULL) == 0);
+  assert(pthread_mutex_destroy(&gate2) == 0);
+  assert(pthread_mutex_destroy(&gate1) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    testNameString,
           durationMilliSecs,
           (float) durationMilliSecs * 1E3 / ITERATIONS / 4   /* Four locks/unlocks per iteration */);
 }
@@ -119,60 +144,131 @@ runTest (char * testNameString, int mType)
 int
 main (int argc, char *argv[])
 {
-  pthread_mutexattr_init(&ma);
+  assert(pthread_mutexattr_init(&ma) == 0);
 
-  printf( "Two threads, blocking mutex locks/unlocks.\n\n");
+  printf( "========================================================================\n");
+  printf( "\nBlocking mutex lock plus unlock.\n");
+  printf("%ld iterations, four locks/unlocks per iteration.\n\n", ITERATIONS);
 
-  printf( "%-25s %15s %15s %15s\n",
-          "Test",
-          "Iterations",
-          "Total(msec)",
-          "lock/unlock(usec)");
+  printf( "%-40s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "------------------------------------------------------------------------\n");
 
   /*
    * Time the loop overhead so we can subtract it from the actual test times.
    */
 
   running = 1;
+  assert(pthread_create(&worker, NULL, overheadThread, NULL) == 0);
+  TESTSTART
+  sched_yield();
+  sched_yield();
+  TESTSTOP
+  running = 0;
+  assert(pthread_join(worker, NULL) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
 
-  (void) pthread_create(&worker, NULL, overheadThread, NULL);
 
+  InitializeCriticalSection(&cs1);
+  InitializeCriticalSection(&cs2);
+  EnterCriticalSection(&cs1);
+  EnterCriticalSection(&cs2);
+  running = 1;
+  assert(pthread_create(&worker, NULL, CSThread, NULL) == 0);
   TESTSTART
+  LeaveCriticalSection(&cs1);
   sched_yield();
+  LeaveCriticalSection(&cs2);
+  EnterCriticalSection(&cs1);
+  EnterCriticalSection(&cs2);
   TESTSTOP
-
   running = 0;
+  LeaveCriticalSection(&cs2);
+  LeaveCriticalSection(&cs1);
+  assert(pthread_join(worker, NULL) == 0);
+  DeleteCriticalSection(&cs2);
+  DeleteCriticalSection(&cs1);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "Simple Critical Section",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4 );
 
-  (void) pthread_join(worker, NULL);
 
-  pthread_mutex_destroy(&gate2);
-  pthread_mutex_destroy(&gate1);
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox1, NULL) == 0);
+  assert(old_mutex_init(&ox2, NULL) == 0);
+  assert(old_mutex_lock(&ox1) == 0);
+  assert(old_mutex_lock(&ox2) == 0);
+  running = 1;
+  assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_unlock(&ox1);
+  sched_yield();
+  (void) old_mutex_unlock(&ox2);
+  (void) old_mutex_lock(&ox1);
+  (void) old_mutex_lock(&ox2);
+  TESTSTOP
+  running = 0;
+  assert(old_mutex_unlock(&ox1) == 0);
+  assert(old_mutex_unlock(&ox2) == 0);
+  assert(pthread_join(worker, NULL) == 0);
+  assert(old_mutex_destroy(&ox2) == 0);
+  assert(old_mutex_destroy(&ox1) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4);
 
-  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop)
-    - overHeadMilliSecs;
 
-  printf( "%-25s %15ld %15ld\n",
-          "Overhead",
-          ITERATIONS,
-          durationMilliSecs);
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox1, NULL) == 0);
+  assert(old_mutex_init(&ox2, NULL) == 0);
+  assert(old_mutex_lock(&ox1) == 0);
+  assert(old_mutex_lock(&ox2) == 0);
+  running = 1;
+  assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_unlock(&ox1);
+  sched_yield();
+  (void) old_mutex_unlock(&ox2);
+  (void) old_mutex_lock(&ox1);
+  (void) old_mutex_lock(&ox2);
+  TESTSTOP
+  running = 0;
+  assert(old_mutex_unlock(&ox1) == 0);
+  assert(old_mutex_unlock(&ox2) == 0);
+  assert(pthread_join(worker, NULL) == 0);
+  assert(old_mutex_destroy(&ox2) == 0);
+  assert(old_mutex_destroy(&ox1) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4);
 
-  overHeadMilliSecs = durationMilliSecs;
+  printf( "........................................................................\n");
 
   /*
    * Now we can start the actual tests
    */
-#ifdef PTHREAD_MUTEX_DEFAULT
-  runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT);
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
 
-  runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL);
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
 
-  runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK);
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
 
-  runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE);
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
 #else
   runTest("Blocking locks", 0);
 #endif
 
+  printf( "========================================================================\n");
   /*
    * End of tests.
    */
diff --git a/tests/benchtest3.c b/tests/benchtest3.c
new file mode 100644
index 0000000..c789fab
--- /dev/null
+++ b/tests/benchtest3.c
@@ -0,0 +1,169 @@
+/*
+ * benchtest3.c
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Mutex
+ *   Single thread iteration over a trylock on a locked mutex for each mutex type.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
+#define ITERATIONS      10000000L
+
+pthread_mutex_t mx;
+old_mutex_t ox;
+pthread_mutexattr_t ma;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void *
+trylockThread (void * arg)
+{
+  TESTSTART
+  (void) pthread_mutex_trylock(&mx);
+  TESTSTOP
+
+  return NULL;
+}
+
+
+void *
+oldTrylockThread (void * arg)
+{
+  TESTSTART
+  (void) old_mutex_trylock(&ox);
+  TESTSTOP
+
+  return NULL;
+}
+
+
+void
+runTest (char * testNameString, int mType)
+{
+  pthread_t t;
+
+#ifdef PTW32_MUTEX_TYPES
+  (void) pthread_mutexattr_settype(&ma, mType);
+#endif
+  assert(pthread_mutex_init(&mx, &ma) == 0);
+  assert(pthread_mutex_lock(&mx) == 0);
+  assert(pthread_create(&t, NULL, trylockThread, 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_mutex_unlock(&mx) == 0);
+  assert(pthread_mutex_destroy(&mx) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-40s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  pthread_t t;
+
+  assert(pthread_mutexattr_init(&ma) == 0);
+
+  printf( "========================================================================\n");
+  printf( "\nTrylock on a locked mutex.\n");
+  printf( "%ld iterations.\n\n", ITERATIONS);
+  printf( "%-40s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  TESTSTART
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  assert(old_mutex_lock(&ox) == 0);
+  assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(old_mutex_unlock(&ox) == 0);
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  assert(old_mutex_lock(&ox) == 0);
+  assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(old_mutex_unlock(&ox) == 0);
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  printf( "........................................................................\n");
+
+  /*
+   * Now we can start the actual tests
+   */
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
+
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
+
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
+
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
+#else
+  runTest("Non-blocking lock", 0);
+#endif
+
+  printf( "========================================================================\n");
+
+  /*
+   * End of tests.
+   */
+
+  pthread_mutexattr_destroy(&ma);
+
+  return 0;
+}
diff --git a/tests/benchtest4.c b/tests/benchtest4.c
new file mode 100644
index 0000000..c343db7
--- /dev/null
+++ b/tests/benchtest4.c
@@ -0,0 +1,150 @@
+/*
+ * benchtest4.c
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Mutex
+ *   Single thread iteration over trylock/unlock for each mutex type.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
+#define ITERATIONS      10000000L
+
+pthread_mutex_t mx;
+old_mutex_t ox;
+pthread_mutexattr_t ma;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void
+oldRunTest (char * testNameString, int mType)
+{
+}
+
+
+void
+runTest (char * testNameString, int mType)
+{
+#ifdef PTW32_MUTEX_TYPES
+  pthread_mutexattr_settype(&ma, mType);
+#endif
+  pthread_mutex_init(&mx, &ma);
+
+  TESTSTART
+  (void) pthread_mutex_trylock(&mx);
+  (void) pthread_mutex_unlock(&mx);
+  TESTSTOP
+
+  pthread_mutex_destroy(&mx);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-40s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  pthread_mutexattr_init(&ma);
+
+  printf( "========================================================================\n");
+  printf( "Non-blocking mutex trylock plus unlock.\n");
+  printf( "%ld iterations.\n\n", ITERATIONS);
+  printf( "%-40s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  TESTSTART
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_trylock(&ox);
+  (void) old_mutex_unlock(&ox);
+  TESTSTOP
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_trylock(&ox);
+  (void) old_mutex_unlock(&ox);
+  TESTSTOP
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-40s %15ld %15.3f\n",
+	    "PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  printf( "........................................................................\n");
+
+  /*
+   * Now we can start the actual tests
+   */
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
+
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
+
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
+
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
+#else
+  runTest("Non-blocking lock", 0);
+#endif
+
+  printf( "========================================================================\n");
+
+  /*
+   * End of tests.
+   */
+
+  pthread_mutexattr_destroy(&ma);
+
+  return 0;
+}
diff --git a/tests/condvar3.c b/tests/condvar3.c
index 673feb5..ef71946 100644
--- a/tests/condvar3.c
+++ b/tests/condvar3.c
@@ -59,13 +59,19 @@ enum {
 void *
 mythread(void * arg)
 {
+  int result = 0;
+
   assert(pthread_mutex_lock(&mutex) == 0);
 
   shared++;
 
   assert(pthread_mutex_unlock(&mutex) == 0);
 
-  assert(pthread_cond_signal(&cv) == 0);
+  if ((result = pthread_cond_signal(&cv)) != 0)
+    {
+      printf("Error = %s\n", error_string[result]);
+    }
+  assert(result == 0);
 
   return (void *) 0;
 }
diff --git a/tests/condvar3_1.c b/tests/condvar3_1.c
index f9bb0c6..ea5f33f 100644
--- a/tests/condvar3_1.c
+++ b/tests/condvar3_1.c
@@ -47,11 +47,13 @@
 #include <sys/timeb.h>
 
 static pthread_cond_t cv;
+static pthread_cond_t cv1;
 static pthread_mutex_t mutex;
 static struct timespec abstime = { 0, 0 };
 static int timedout = 0;
 static int signaled = 0;
 static int awoken = 0;
+static int waiting = 0;
 
 enum {
   NUMTHREADS = 60
@@ -64,6 +66,9 @@ mythread(void * arg)
 
   assert(pthread_mutex_lock(&mutex) == 0);
 
+  if ( ++waiting == NUMTHREADS)
+    assert(pthread_cond_signal(&cv1) == 0);
+
   result = pthread_cond_timedwait(&cv, &mutex, &abstime);
   if (result == ETIMEDOUT)
     {
@@ -91,6 +96,7 @@ main()
   const DWORD NANOSEC_PER_MILLISEC = 1000000;
 
   assert(pthread_cond_init(&cv, NULL) == 0);
+  assert(pthread_cond_init(&cv1, NULL) == 0);
 
   assert(pthread_mutex_init(&mutex, NULL) == 0);
 
@@ -109,6 +115,10 @@ main()
       assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
     }
 
+  do {
+    assert(pthread_cond_wait(&cv1,&mutex) == 0);
+  } while ( NUMTHREADS != waiting );
+
   assert(pthread_mutex_unlock(&mutex) == 0);
 
   for (i = NUMTHREADS/3; i <= 2*NUMTHREADS/3; i++)
@@ -120,9 +130,13 @@ main()
   for (i = 1; i <= NUMTHREADS; i++)
     {
       assert(pthread_join(t[i], (void **) &result) == 0);
-	assert(result == i);
+        assert(result == i);
     }
 
+      fprintf(stderr, "awk = %d\n", awoken);
+      fprintf(stderr, "sig = %d\n", signaled);
+      fprintf(stderr, "tot = %d\n", timedout);
+
   assert(signaled == awoken);
   assert(timedout == NUMTHREADS - signaled);
 
@@ -131,11 +145,11 @@ main()
   if (result != 0)
     {
       fprintf(stderr, "Result = %s\n", error_string[result]);
-	fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked);
-	fprintf(stderr, "\tWaitersUnblocked = %ld\n", cv->nWaitersUnblocked);
-	fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone);
-	fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock);
-	fflush(stderr);
+        fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked);
+        fprintf(stderr, "\tWaitersUnblocked = %ld\n", cv->nWaitersUnblocked);
+        fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone);
+        fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock);
+        fflush(stderr);
     }
   assert(result == 0);
   }
diff --git a/tests/condvar3_3.c b/tests/condvar3_3.c
new file mode 100644
index 0000000..43e6f3a
--- /dev/null
+++ b/tests/condvar3_3.c
@@ -0,0 +1,100 @@
+/*
+ * File: condvar3_3.c
+ *
+ * Test Synopsis:
+ * - Test timeouts and lost signals on a CV.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * -
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait does not return ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+/* Timur Aydin (taydin@snet.net) */
+
+#include "test.h"
+
+#include <sys/timeb.h>
+
+pthread_cond_t cnd;
+pthread_mutex_t mtx;
+
+int main()
+{
+   int rc;
+
+   struct timespec abstime = { 0, 0 };
+   struct _timeb currSysTime;
+   const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+   assert(pthread_cond_init(&cnd, 0) == 0);
+   assert(pthread_mutex_init(&mtx, 0) == 0);
+
+   /* get current system time */
+   _ftime(&currSysTime);
+
+   abstime.tv_sec = currSysTime.time;
+   abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+   abstime.tv_sec += 1;
+
+   /* Here pthread_cond_timedwait should time out after one second. */
+
+   assert(pthread_mutex_lock(&mtx) == 0);
+
+   assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT);
+
+   assert(pthread_mutex_unlock(&mtx) == 0);
+
+   /* Here, the condition variable is signaled, but there are no
+      threads waiting on it. The signal should be lost and
+      the next pthread_cond_timedwait should time out too. */
+
+   assert(pthread_mutex_lock(&mtx) == 0);
+
+   assert((rc = pthread_cond_signal(&cnd)) == 0);
+
+   assert(pthread_mutex_unlock(&mtx) == 0);
+
+   assert(pthread_mutex_lock(&mtx) == 0);
+
+   abstime.tv_sec = currSysTime.time;
+   abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+   abstime.tv_sec += 1;
+
+   assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT);
+
+   assert(pthread_mutex_unlock(&mtx) == 0);
+
+   return 0;
+}
-- 
cgit v1.2.3