summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/ChangeLog19
-rw-r--r--tests/GNUmakefile45
-rw-r--r--tests/Makefile39
-rw-r--r--tests/benchtest.h314
-rw-r--r--tests/benchtest1.c116
-rw-r--r--tests/benchtest2.c198
-rw-r--r--tests/benchtest3.c169
-rw-r--r--tests/benchtest4.c150
-rw-r--r--tests/condvar3.c8
-rw-r--r--tests/condvar3_1.c26
-rw-r--r--tests/condvar3_3.c100
11 files changed, 1072 insertions, 112 deletions
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;
@@ -56,6 +61,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)
{
do
@@ -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;
+}