diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/ChangeLog | 19 | ||||
| -rw-r--r-- | tests/GNUmakefile | 45 | ||||
| -rw-r--r-- | tests/Makefile | 39 | ||||
| -rw-r--r-- | tests/benchtest.h | 314 | ||||
| -rw-r--r-- | tests/benchtest1.c | 116 | ||||
| -rw-r--r-- | tests/benchtest2.c | 198 | ||||
| -rw-r--r-- | tests/benchtest3.c | 169 | ||||
| -rw-r--r-- | tests/benchtest4.c | 150 | ||||
| -rw-r--r-- | tests/condvar3.c | 8 | ||||
| -rw-r--r-- | tests/condvar3_1.c | 26 | ||||
| -rw-r--r-- | tests/condvar3_3.c | 100 | 
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; +} | 
