diff options
author | rpj <rpj> | 2005-05-06 07:27:10 +0000 |
---|---|---|
committer | rpj <rpj> | 2005-05-06 07:27:10 +0000 |
commit | 7523c7c4d75652f67cd31cb123e1268790394c8b (patch) | |
tree | 0920ebf089ccb971e0878542f85486171a541a8a /tests | |
parent | cf42850c77554311e62d3780f6a36cbc38e5e002 (diff) |
''
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Bmakefile | 15 | ||||
-rw-r--r-- | tests/GNUmakefile | 32 | ||||
-rw-r--r-- | tests/Makefile | 76 | ||||
-rw-r--r-- | tests/cancel4.c | 4 | ||||
-rw-r--r-- | tests/condvar2.c | 2 | ||||
-rw-r--r-- | tests/semaphore1.c | 4 | ||||
-rw-r--r-- | tests/stress1.c | 271 | ||||
-rw-r--r-- | tests/test.h | 18 | ||||
-rw-r--r-- | tests/tsd1.c | 38 |
9 files changed, 398 insertions, 62 deletions
diff --git a/tests/Bmakefile b/tests/Bmakefile index 285239a..60b0a75 100644 --- a/tests/Bmakefile +++ b/tests/Bmakefile @@ -91,11 +91,12 @@ PASSES= loadfree.pass \ mutex6s.pass mutex6es.pass mutex6rs.pass \ mutex7.pass mutex7n.pass mutex7e.pass mutex7r.pass \ mutex8.pass mutex8n.pass mutex8e.pass mutex8r.pass \ - count1.pass once1.pass once2.pass once3.pass once4.pass tsd1.pass \ + count1.pass once1.pass once2.pass once3.pass once4.pass \ self2.pass \ cancel1.pass cancel2.pass \ semaphore4.pass semaphore4t.pass \ - delay1.pass delay2.pass eyal1.pass \ + barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ + tsd1.pass delay1.pass delay2.pass eyal1.pass \ condvar3.pass condvar3_1.pass condvar3_2.pass condvar3_3.pass \ condvar4.pass condvar5.pass condvar6.pass \ condvar7.pass condvar8.pass condvar9.pass \ @@ -108,9 +109,8 @@ PASSES= loadfree.pass \ cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \ priority1.pass priority2.pass inherit1.pass \ spin1.pass spin2.pass spin3.pass spin4.pass \ - barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ exception1.pass exception2.pass exception3.pass \ - cancel9.pass create3.pass + cancel9.pass create3.pass stress1.pass BENCHRESULTS = \ benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench @@ -220,7 +220,7 @@ benchtest2.bench: benchtest3.bench: benchtest4.bench: benchtest5.bench: -barrier1.pass: +barrier1.pass: semaphore4.pass barrier2.pass: barrier1.pass barrier3.pass: barrier2.pass barrier4.pass: barrier3.pass @@ -234,6 +234,7 @@ cancel6a.pass: cancel3.pass cancel6d.pass: cancel3.pass cancel7.pass: kill1.pass cancel8.pass: cancel7.pass +cancel9.pass: cancel8.pass cleanup0.pass: cancel5.pass cleanup1.pass: cleanup0.pass cleanup2.pass: cleanup1.pass @@ -339,7 +340,7 @@ spin1.pass: spin2.pass: spin1.pass spin3.pass: spin2.pass spin4.pass: spin3.pass -tsd1.pass: join1.pass +stress1.pass: barrier5.pass +tsd1.pass: barrier5.pass join1.pass valid1.pass: join1.pass valid2.pass: valid1.pass -cancel9.pass: cancel8.pass diff --git a/tests/GNUmakefile b/tests/GNUmakefile index a789e19..641164d 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -86,10 +86,11 @@ TESTS = sizes loadfree \ mutex4 mutex6 mutex6n mutex6e mutex6r \ mutex6s mutex6es mutex6rs \ mutex7 mutex7n mutex7e mutex7r mutex8 mutex8n mutex8e mutex8r \ - count1 once1 once2 once3 once4 tsd1 self2 \ + count1 once1 once2 once3 once4 self2 \ cancel1 cancel2 \ semaphore4 semaphore4t \ - delay1 delay2 eyal1 \ + barrier1 barrier2 barrier3 barrier4 barrier5 \ + tsd1 delay1 delay2 eyal1 \ condvar3 condvar3_1 condvar3_2 condvar3_3 \ condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \ errno1 \ @@ -100,10 +101,12 @@ TESTS = sizes loadfree \ cleanup0 cleanup1 cleanup2 cleanup3 \ priority1 priority2 inherit1 \ spin1 spin2 spin3 spin4 \ - barrier1 barrier2 barrier3 barrier4 barrier5 \ exception1 exception2 exception3 \ cancel9 create3 +STRESSTESTS = \ + stress1 + BENCHTESTS = \ benchtest1 benchtest2 benchtest3 benchtest4 benchtest5 @@ -112,6 +115,7 @@ STATICTESTS = \ PASSES = $(TESTS:%=%.pass) BENCHRESULTS = $(BENCHTESTS:%=%.bench) +STRESSRESULTS = $(STRESSTESTS:%=%.pass) STATICRESULTS = $(STATICTESTS:%=%.pass) help: @@ -121,6 +125,8 @@ help: @ $(ECHO) "make clean GCE (to test using GCE dll with C++ (EH) applications)" @ $(ECHO) "make clean GC-bench (to benchtest using GNU C dll with C cleanup code)" @ $(ECHO) "make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling)" + @ $(ECHO) "make clean GC-stress (to stresstest using GNU C dll with C cleanup code)" + @ $(ECHO) "make clean GCE-stress (to stresstest using GNU C dll with C++ exception handling)" @ $(ECHO) "make clean GC-static (to test using GC static lib with C (no EH) applications)" all: @@ -146,12 +152,24 @@ GCE-bench: GC-static: $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C -DPTW32_STATIC_LIB" DLL="" all-static +GC-stress: + $(ECHO) Stress tests can take a long time since they are trying to + $(ECHO) expose weaknesses that may be intermittant or statistically rare. + $(ECHO) A pass does not prove correctness, but may give greater confidence. + $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" all-stress + +GCE-stress: + $(MAKE) TEST=GCE CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" all-stress + all-pass: $(PASSES) @ $(ECHO) ALL TESTS PASSED! Congratulations! all-bench: $(BENCHRESULTS) @ $(ECHO) BENCH TESTS COMPLETED. +all-stress: $(STRESSRESULTS) + @ $(ECHO) STRESS TESTS COMPLETED. + all-static: $(STATICRESULTS) @ $(ECHO) ALL STATIC TESTS PASSED! Congratulations! @ $(ECHO) Build and test the DLL to run all tests. @@ -163,7 +181,9 @@ benchtest3.bench: benchtest4.bench: benchtest5.bench: -barrier1.pass: +stress1.pass: + +barrier1.pass: semaphore4.pass barrier2.pass: barrier1.pass barrier3.pass: barrier2.pass barrier4.pass: barrier3.pass @@ -178,6 +198,7 @@ cancel6a.pass: cancel3.pass cancel6d.pass: cancel3.pass cancel7.pass: kill1.pass cancel8.pass: cancel7.pass +cancel9.pass: cancel8.pass cleanup0.pass: cancel5.pass cleanup1.pass: cleanup0.pass cleanup2.pass: cleanup1.pass @@ -283,10 +304,9 @@ spin1.pass: spin2.pass: spin1.pass spin3.pass: spin2.pass spin4.pass: spin3.pass -tsd1.pass: join1.pass +tsd1.pass: barrier5.pass join1.pass valid1.pass: join1.pass valid2.pass: valid1.pass -cancel9.pass: cancel8.pass sizes.pass: sizes.exe @ $(ECHO) Running $* diff --git a/tests/Makefile b/tests/Makefile index 5c73009..8fa72b4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -95,11 +95,12 @@ PASSES= sizes.pass loadfree.pass \ mutex6s.pass mutex6es.pass mutex6rs.pass \ mutex7.pass mutex7n.pass mutex7e.pass mutex7r.pass \ mutex8.pass mutex8n.pass mutex8e.pass mutex8r.pass \ - count1.pass once1.pass once2.pass once3.pass once4.pass tsd1.pass \ + count1.pass once1.pass once2.pass once3.pass once4.pass \ self2.pass \ cancel1.pass cancel2.pass \ semaphore4.pass semaphore4t.pass \ - delay1.pass delay2.pass eyal1.pass \ + barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ + tsd1.pass delay1.pass delay2.pass eyal1.pass \ condvar3.pass condvar3_1.pass condvar3_2.pass condvar3_3.pass \ condvar4.pass condvar5.pass condvar6.pass \ condvar7.pass condvar8.pass condvar9.pass \ @@ -113,27 +114,33 @@ PASSES= sizes.pass loadfree.pass \ cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \ priority1.pass priority2.pass inherit1.pass \ spin1.pass spin2.pass spin3.pass spin4.pass \ - barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ exception1.pass exception2.pass exception3.pass \ - cancel9.pass create3.pass + cancel9.pass create3.pass BENCHRESULTS = \ benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench +STRESSRESULTS = \ + stress1.pass + STATICRESULTS = \ self1.pass help: @ $(ECHO) Run one of the following command lines: - @ $(ECHO) nmake clean VC (to test using VC dll with VC (no EH) applications) - @ $(ECHO) nmake clean VCX (to test using VC dll with VC++ (EH) applications) - @ $(ECHO) nmake clean VCE (to test using the VCE dll with VC++ EH applications) - @ $(ECHO) nmake clean VSE (to test using VSE dll with VC (SEH) applications) - @ $(ECHO) nmake clean VC-bench (to benchtest using VC dll with C bench app) - @ $(ECHO) nmake clean VCX-bench (to benchtest using VC dll with C++ bench app) - @ $(ECHO) nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app) - @ $(ECHO) nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app) - @ $(ECHO) nmake clean VC-static (to test using VC static lib with VC (no EH) applications) + @ $(ECHO) nmake clean VC (to test using VC dll with VC (no EH) apps) + @ $(ECHO) nmake clean VC-bench (to benchtest using VC dll with C bench apps) + @ $(ECHO) nmake clean VC-stress (to stresstest using VC dll with C stress apps) + @ $(ECHO) nmake clean VC-static (to test using VC static lib with VC (no EH) apps) + @ $(ECHO) nmake clean VCX (to test using VC dll with VC++ (EH) applications) + @ $(ECHO) nmake clean VCX-bench (to benchtest using VC dll with C++ bench apps) + @ $(ECHO) nmake clean VCX-stress (to stresstest using VC dll with C++ stress apps) + @ $(ECHO) nmake clean VCE (to test using the VCE dll with VC++ EH applications) + @ $(ECHO) nmake clean VCE-bench (to benchtest using VCE dll with C++ bench apps) + @ $(ECHO) nmake clean VCE-stress (to stresstest using VCE dll with C++ stress apps) + @ $(ECHO) nmake clean VSE (to test using VSE dll with VC (SEH) apps) + @ $(ECHO) nmake clean VSE-bench (to benchtest using VSE dll with SEH bench apps) + @ $(ECHO) nmake clean VSE-stress (to stresstest using VSE dll with SEH stress apps) all: @ nmake clean VC @@ -141,6 +148,7 @@ all: @ nmake clean VCE @ nmake clean VSE @ nmake clean VC-bench + @ nmake clean VC-stress # This allows an individual test application to be made using the default lib. # e.g. nmake clean test cancel3.exe @@ -152,6 +160,9 @@ tests: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) $(PASSES) benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(XXLIBS) $(BENCHRESULTS) @ $(ECHO) ALL BENCH TESTS DONE. +stresstests: $(CPLIB) $(CPDLL) $(CPHDR) $(STRESSRESULTS) + @ $(ECHO) ALL STRESS TESTS DONE. + statictests: $(CPLIB) $(CPDLL) $(CPHDR) $(STATICRESULTS) @ $(ECHO) ALL STATIC TESTS DONE. @ $(ECHO) Build and test the DLL to run all tests. @@ -176,30 +187,48 @@ $(BENCHRESULTS): $*.exe @ $(ECHO) ...... Done @ $(TOUCH) $*.bench +$(STRESSRESULTS): $*.exe + @ $(ECHO) ... Running $(TEST) stresstest: $*.exe + @ .\$*.exe + @ $(ECHO) ...... Done + @ $(TOUCH) $*.pass + +VC: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests + VCE: @ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" tests VSE: @ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" tests -VC: - @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests - VCX: @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" tests +VC-bench: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" XXLIBS="benchlib.o" benchtests + VCE-bench: @ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" XXLIBS="benchlib.o" benchtests VSE-bench: @ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" XXLIBS="benchlib.o" benchtests -VC-bench: - @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" XXLIBS="benchlib.o" benchtests - VCX-bench: @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" XXLIBS="benchlib.o" benchtests +VC-stress: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" stresstests + +VCE-stress: + @ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" stresstests + +VSE-stress: + @ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" stresstests + +VCX-stress: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" stresstests + VC-static: @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="" EHFLAGS="$(VCFLAGS) /DPTW32_STATIC_LIB" statictests @@ -244,7 +273,10 @@ benchtest2.bench: benchtest3.bench: benchtest4.bench: benchtest5.bench: -barrier1.pass: + +stress1.pass: + +barrier1.pass: semaphore4.pass barrier2.pass: barrier1.pass barrier3.pass: barrier2.pass barrier4.pass: barrier3.pass @@ -258,6 +290,7 @@ cancel6a.pass: cancel3.pass cancel6d.pass: cancel3.pass cancel7.pass: kill1.pass cancel8.pass: cancel7.pass +cancel9.pass: cancel8.pass cleanup0.pass: cancel5.pass cleanup1.pass: cleanup0.pass cleanup2.pass: cleanup1.pass @@ -363,7 +396,6 @@ spin1.pass: spin2.pass: spin1.pass spin3.pass: spin2.pass spin4.pass: spin3.pass -tsd1.pass: join1.pass +tsd1.pass: barrier5.pass join1.pass valid1.pass: join1.pass valid2.pass: valid1.pass -cancel9.pass: cancel8.pass diff --git a/tests/cancel4.c b/tests/cancel4.c index 1561ea6..6d6d3dc 100644 --- a/tests/cancel4.c +++ b/tests/cancel4.c @@ -112,10 +112,10 @@ mythread(void * arg) assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); /* - * We wait up to 10 seconds, waking every 0.1 seconds, + * We wait up to 2 seconds, waking every 0.1 seconds, * for a cancelation to be applied to us. */ - for (bag->count = 0; bag->count < 100; bag->count++) + for (bag->count = 0; bag->count < 20; bag->count++) Sleep(100); return (void *) result; diff --git a/tests/condvar2.c b/tests/condvar2.c index cfc68af..33f1d3f 100644 --- a/tests/condvar2.c +++ b/tests/condvar2.c @@ -102,7 +102,7 @@ main() abstime.tv_sec = currSysTime.time; abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; - abstime.tv_sec += 5; + abstime.tv_sec += 1; assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT); diff --git a/tests/semaphore1.c b/tests/semaphore1.c index b5b2050..4327e73 100644 --- a/tests/semaphore1.c +++ b/tests/semaphore1.c @@ -86,7 +86,7 @@ thr(void * arg) if ( result == -1 ) { int err = errno; - perror("thread: sem_trywait 1: expected error"); // No error + perror("thread: sem_trywait 1: expect an EAGAIN error"); // No error assert(err == EAGAIN); } else @@ -131,7 +131,7 @@ main() if ( result == -1 ) { int err = errno; - perror("main: sem_trywait 1: expected error"); // No error + perror("main: sem_trywait 1: expect an EAGAIN error"); // No error assert(err == EAGAIN); } else diff --git a/tests/stress1.c b/tests/stress1.c new file mode 100644 index 0000000..b8d1c77 --- /dev/null +++ b/tests/stress1.c @@ -0,0 +1,271 @@ +/* + * stress1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Stress test condition variables, mutexes, semaphores. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - Correct accounting of semaphore and condition variable waiters. + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * Attempting to expose race conditions in cond vars, semaphores etc. + * - Master attempts to signal slave close to when timeout is due. + * - Master and slave do battle continuously until main tells them to stop. + * - Afterwards, the CV must be successfully destroyed (will return an + * error if there are waiters (including any internal semaphore waiters, + * which, if there are, cannot not be real waiters). + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - CV is successfully destroyed. + * + * Fail Criteria: + * - CV destroy fails. + */ + +#include "test.h" +#include <string.h> +#include <sys/timeb.h> + + +const unsigned int ITERATIONS = 1000; + +static pthread_t master, slave; +typedef struct { + int value; + pthread_cond_t cv; + pthread_mutex_t mx; +} mysig_t; + +static int allExit; +static mysig_t control = {0, PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}; +static pthread_barrier_t startBarrier, readyBarrier, holdBarrier; +static int timeoutCount = 0; +static int signalsTakenCount = 0; +static int signalsSent = 0; +static int bias = 0; +static int timeout = 10;
// Must be > 0 + +enum { + CTL_STOP = -1 +}; + +/* + * Returns abstime 'milliseconds' from 'now'. + */ +struct timespec * +millisecondsFromNow (struct timespec * time, int millisecs) +{ + struct _timeb currSysTime; + int64_t nanosecs, secs; + const int64_t NANOSEC_PER_MILLISEC = 1000000; + const int64_t NANOSEC_PER_SEC = 1000000000; + + /* get current system time and add millisecs */ + _ftime(&currSysTime); + + nanosecs = ((int64_t) (millisecs + currSysTime.millitm)) * NANOSEC_PER_MILLISEC; + if (nanosecs >= NANOSEC_PER_SEC) + { + secs = currSysTime.time + 1; + nanosecs %= NANOSEC_PER_SEC; + } + else + { + secs = currSysTime.time; + } + + time->tv_nsec = (long)nanosecs; + time->tv_sec = (long)secs; + + return time; +} + +void * +masterThread (void * arg) +{ + int dither = (int) arg; + + timeout = (int) arg; + + pthread_barrier_wait(&startBarrier); + + do + { + int sleepTime; + + assert(pthread_mutex_lock(&control.mx) == 0); + control.value = timeout; + assert(pthread_mutex_unlock(&control.mx) == 0); + + /* + * We are attempting to send the signal close to when the slave + * is due to timeout. We feel around by adding some [non-random] dither. + * + * with dither added, sleep time range is 2*timeout peak-to-peak centred on timeout, + * e.g. + * if timeout = 10 then dither = 20 and + * sleep millisecs is: 5 <= ms <= 15 + * + * The bias value attempts to apply some negative feedback to keep + * the ratio of timeouts to signals taken close to 1:1. + * bias changes more slowly than dither so as to average more. + */ + if (signalsSent % timeout == 0) + { + if (timeoutCount > signalsTakenCount) + { + bias++; + } + else if (timeoutCount < signalsTakenCount) + { + bias--; + } + if (bias < -timeout || bias > timeout) + { + timeout++; + } + } + dither = (dither + 1 ) % (timeout * 2); + sleepTime = (timeout - bias + dither) / 2; + Sleep(sleepTime); + assert(pthread_cond_signal(&control.cv) == 0); + signalsSent++; + + pthread_barrier_wait(&holdBarrier); + pthread_barrier_wait(&readyBarrier); + } + while (!allExit); + + return NULL; +} + +void * +slaveThread (void * arg) +{ + struct timespec time; + + pthread_barrier_wait(&startBarrier); + + do + { + assert(pthread_mutex_lock(&control.mx) == 0); + if (pthread_cond_timedwait(&control.cv, + &control.mx, + millisecondsFromNow(&time, control.value)) == ETIMEDOUT) + { + timeoutCount++; + } + else + { + signalsTakenCount++; + } + assert(pthread_mutex_unlock(&control.mx) == 0); + + pthread_barrier_wait(&holdBarrier); + pthread_barrier_wait(&readyBarrier); + } + while (!allExit); + + return NULL; +} + +int +main () +{ + unsigned int i; + + assert(pthread_barrier_init(&startBarrier, NULL, 3) == 0); + assert(pthread_barrier_init(&readyBarrier, NULL, 3) == 0); + assert(pthread_barrier_init(&holdBarrier, NULL, 3) == 0); + + assert(pthread_create(&master, NULL, masterThread, (void *) timeout) == 0); + assert(pthread_create(&slave, NULL, slaveThread, NULL) == 0); + + allExit = FALSE; + + pthread_barrier_wait(&startBarrier); + + for (i = 1; !allExit; i++) + { + pthread_barrier_wait(&holdBarrier); + if (i >= ITERATIONS) + { + allExit = TRUE; + } + pthread_barrier_wait(&readyBarrier); + } + + assert(pthread_join(slave, NULL) == 0); + assert(pthread_join(master, NULL) == 0); + + printf("Signals sent = %d\nWait timeouts = %d\nSignals taken = %d\nBias = %d\nTimeout = %d\n", + signalsSent, + timeoutCount, + signalsTakenCount, + (int) bias, + timeout); + + /* Cleanup */ + assert(pthread_barrier_destroy(&holdBarrier) == 0); + assert(pthread_barrier_destroy(&readyBarrier) == 0); + assert(pthread_barrier_destroy(&startBarrier) == 0); + assert(pthread_cond_destroy(&control.cv) == 0); + assert(pthread_mutex_destroy(&control.mx) == 0); + + /* Success. */ + return 0; +} diff --git a/tests/test.h b/tests/test.h index 11498cd..3132c69 100644 --- a/tests/test.h +++ b/tests/test.h @@ -47,6 +47,15 @@ #define PTW32_THREAD_NULL_ID {NULL,0} +#if defined(__MINGW32__) +#include <stdint.h> +#elif defined(__BORLANDC__) +#define int64_t ULONGLONG +#else +#define int64_t _int64 +#endif + + char * error_string[] = { "ZERO_or_EOK", "EPERM", @@ -109,13 +118,8 @@ char * error_string[] = { # define ASSERT_TRACE 1 #endif -/* - * Trick to force the compiler to not optimise out dead or obvious expressions. - */ -int ptw32_assert_force = 1; - # define assert(e) \ - (ptw32_assert_force && (e) ? ((ASSERT_TRACE) ? fprintf(stderr, \ + ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \ "Assertion succeeded: (%s), file %s, line %d\n", \ #e, __FILE__, (int) __LINE__), \ fflush(stderr) : \ @@ -125,7 +129,7 @@ int ptw32_assert_force = 1; int assertE; # define assert_e(e, o, r) \ - (ptw32_assert_force && ((assertE = e) o (r)) ? ((ASSERT_TRACE) ? fprintf(stderr, \ + (((assertE = e) o (r)) ? ((ASSERT_TRACE) ? fprintf(stderr, \ "Assertion succeeded: (%s), file %s, line %d\n", \ #e, __FILE__, (int) __LINE__), \ fflush(stderr) : \ diff --git a/tests/tsd1.c b/tests/tsd1.c index 6e21d2a..4d89165 100644 --- a/tests/tsd1.c +++ b/tests/tsd1.c @@ -34,6 +34,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * + * -------------------------------------------------------------------------- + * * Description: * - * @@ -77,10 +79,15 @@ #include <sched.h> #include "test.h" +enum { + NUM_THREADS = 100 +}; + static pthread_key_t key = NULL; -static int accesscount[10]; -static int thread_set[10]; -static int thread_destroyed[10]; +static int accesscount[NUM_THREADS]; +static int thread_set[NUM_THREADS]; +static int thread_destroyed[NUM_THREADS]; +static pthread_barrier_t startBarrier; static void destroy_key(void * arg) @@ -117,10 +124,7 @@ setkey(void * arg) static void * mythread(void * arg) { - while (key == NULL) - { - sched_yield(); - } + (void) pthread_barrier_wait(&startBarrier); setkey(arg); @@ -134,22 +138,24 @@ main() { int i; int fail = 0; - pthread_t thread[10]; + pthread_t thread[NUM_THREADS]; - for (i = 1; i < 5; i++) + assert(pthread_barrier_init(&startBarrier, NULL, NUM_THREADS/2) == 0); + + for (i = 1; i < NUM_THREADS/2; i++) { accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); } - Sleep(2000); - /* * Here we test that existing threads will get a key created * for them. */ assert(pthread_key_create(&key, destroy_key) == 0); + (void) pthread_barrier_wait(&startBarrier); + /* * Test main thread key. */ @@ -160,16 +166,16 @@ main() * Here we test that new threads will get a key created * for them. */ - for (i = 5; i < 10; i++) + for (i = NUM_THREADS/2; i < NUM_THREADS; i++) { - accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); } /* * Wait for all threads to complete. */ - for (i = 1; i < 10; i++) + for (i = 1; i < NUM_THREADS; i++) { int result = 0; @@ -178,7 +184,9 @@ main() assert(pthread_key_delete(key) == 0); - for (i = 1; i < 10; i++) + assert(pthread_barrier_destroy(&startBarrier) == 0); + + for (i = 1; i < NUM_THREADS; i++) { /* * The counter is incremented once when the key is set to |