diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/ChangeLog | 7 | ||||
| -rw-r--r-- | tests/GNUmakefile | 3 | ||||
| -rw-r--r-- | tests/Makefile | 3 | ||||
| -rw-r--r-- | tests/rwlock6.c | 110 | ||||
| -rw-r--r-- | tests/rwlock7.c | 173 | 
5 files changed, 239 insertions, 57 deletions
| diff --git a/tests/ChangeLog b/tests/ChangeLog index 92fca1b..66ccff1 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2001-02-08  Ross Johnson  <rpj@special.ise.canberra.edu.au> + +	* Makefile (rwlock7): Add new test. +	* GNUmakefile (rwlock7): Add new test. +	* rwlock7.c: New test. +	* rwlock6.c: Changed to test that writer has priority. +  2000-12-29  Ross Johnson  <rpj@special.ise.canberra.edu.au>  	* GNUmakefile: Add mutex4 test; ensure libpthreadw32.a is diff --git a/tests/GNUmakefile b/tests/GNUmakefile index 33de3ac..007cd7f 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -36,7 +36,7 @@ TESTS	= loadfree \  	  count1 once1 tsd1 self1 self2 cancel1 cancel2 eyal1 \  	  condvar3 condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \  	  errno1 \ -	  rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 \ +	  rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 rwlock7 \  	  context1 cancel3 cancel4 cancel5 \  	  cleanup0 cleanup1 cleanup2 cleanup3 \  	  exception1 exception2 exception3 @@ -83,6 +83,7 @@ rwlock3.pass: rwlock2.pass  rwlock4.pass: rwlock3.pass  rwlock5.pass: rwlock4.pass  rwlock6.pass: rwlock5.pass +rwlock7.pass: rwlock6.pass  context1.pass: cancel2.pass  cancel3.pass: context1.pass  cancel4.pass: cancel3.pass diff --git a/tests/Makefile b/tests/Makefile index 281cd50..f8b846f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -45,7 +45,7 @@ PASSES= loadfree.pass \  	  condvar3.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  \
 +	  rwlock1.pass  rwlock2.pass  rwlock3.pass  rwlock4.pass  rwlock5.pass  rwlock6.pass  rwlock7.pass \
  	  context1.pass  \
  	  cancel3.pass  cancel4.pass  cancel5.pass  \
  	  cleanup0.pass  cleanup1.pass  cleanup2.pass  cleanup3.pass  \
 @@ -138,6 +138,7 @@ rwlock3.pass: rwlock2.pass  rwlock4.pass: rwlock3.pass
  rwlock5.pass: rwlock4.pass
  rwlock6.pass: rwlock5.pass
 +rwlock7.pass: rwlock6.pass
  context1.pass: cancel2.pass
  cancel3.pass: context1.pass
  cancel4.pass: cancel3.pass
 diff --git a/tests/rwlock6.c b/tests/rwlock6.c index 8a75b83..97742b1 100644 --- a/tests/rwlock6.c +++ b/tests/rwlock6.c @@ -1,65 +1,65 @@ -/* 
 - * rwlock6.c
 - *
 - * Check that writer locks have priority.
 - *
 - * Depends on API functions: 
 - *      pthread_rwlock_rdlock()
 - *      pthread_rwlock_wrlock()
 - *      pthread_rwlock_unlock()
 - */
 +/* + * rwlock6.c + * + * Check that writer locks have priority. + * + * Depends on API functions:  + *      pthread_rwlock_rdlock() + *      pthread_rwlock_wrlock() + *      pthread_rwlock_unlock() + */ -#include "test.h"
 - 
 -static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
 +#include "test.h" -static int bankAccount;
 +static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; -void * wrfunc(void * arg)
 -{
 -  assert(pthread_rwlock_wrlock(&rwlock1) == 0);
 -  Sleep(1000);
 -  bankAccount += 10;
 -  assert(pthread_rwlock_unlock(&rwlock1) == 0);
 +static int bankAccount; -  return((void *) bankAccount); 
 -}
 - 
 -void * rdfunc(void * arg)
 -{
 -  int ba = 0;
 +void * wrfunc(void * arg) +{ +  assert(pthread_rwlock_wrlock(&rwlock1) == 0); +  Sleep(1000); +  bankAccount += 10; +  assert(pthread_rwlock_unlock(&rwlock1) == 0); -  assert(pthread_rwlock_rdlock(&rwlock1) == 0);
 -  ba = bankAccount;
 -  assert(pthread_rwlock_unlock(&rwlock1) == 0);
 +  return ((void *) bankAccount); +} -  ba += 10;
 -  return((void *) ba); 
 -}
 - 
 -int
 -main()
 -{
 -  pthread_t wrt1;
 -  pthread_t wrt2;
 -  pthread_t rdt;
 -  int wr1Result = 0;
 -  int wr2Result = 0;
 -  int rdResult = 0;
 +void * rdfunc(void * arg) +{ +  int ba = 0; -  assert(pthread_create(&wrt1, NULL, wrfunc, NULL) == 0);
 -  Sleep(200);
 -  assert(pthread_create(&rdt, NULL, rdfunc, NULL) == 0);
 -  Sleep(200);
 -  assert(pthread_create(&wrt2, NULL, wrfunc, NULL) == 0);
 +  assert(pthread_rwlock_rdlock(&rwlock1) == 0); +  ba = bankAccount; +  assert(pthread_rwlock_unlock(&rwlock1) == 0); -  assert(pthread_join(wrt1, (void **) &wr1Result) == 0);
 -  assert(pthread_join(wrt2, (void **) &wr2Result) == 0);
 -  assert(pthread_join(rdt, (void **) &rdResult) == 0);
 +  ba += 10; +  return ((void *) ba); +} -  assert(wr1Result == 10);
 -  assert(wr2Result == 20);
 -  assert(rdResult == 20);
 +int +main() +{ +  pthread_t wrt1; +  pthread_t wrt2; +  pthread_t rdt; +  int wr1Result = 0; +  int wr2Result = 0; +  int rdResult = 0; -  return 0;
 -}
 +  assert(pthread_create(&wrt1, NULL, wrfunc, NULL) == 0); +  Sleep(200); +  assert(pthread_create(&rdt, NULL, rdfunc, NULL) == 0); +  Sleep(200); +  assert(pthread_create(&wrt2, NULL, wrfunc, NULL) == 0); + +  assert(pthread_join(wrt1, (void **) &wr1Result) == 0); +  assert(pthread_join(wrt2, (void **) &wr2Result) == 0); +  assert(pthread_join(rdt, (void **) &rdResult) == 0); + +  assert(wr1Result == 10); +  assert(wr2Result == 20); +  assert(rdResult == 20); + +  return 0; +} diff --git a/tests/rwlock7.c b/tests/rwlock7.c new file mode 100644 index 0000000..88abcfe --- /dev/null +++ b/tests/rwlock7.c @@ -0,0 +1,173 @@ +/* + * rwlock7.c + * + * Hammer on a bunch of rwlocks to test robustness and fairness. + * Printed stats should be roughly even for each thread. + */ + +#include "test.h" +#include <sys/timeb.h> + +#define THREADS         5 +#define DATASIZE        15 +#define ITERATIONS      10000 + +/* + * Keep statistics for each thread. + */ +typedef struct thread_tag { +  int         thread_num; +  pthread_t   thread_id; +  int         updates; +  int         reads; +  int         interval; +} thread_t; + +/* + * Read-write lock and shared data + */ +typedef struct data_tag { +  rwlock_t    lock; +  int         data; +  int         updates; +} data_t; + +static thread_t threads[THREADS]; +static data_t data[DATASIZE]; + +/* + * Thread start routine that uses read-write locks + */ +void *thread_routine (void *arg) +{ +  thread_t *self = (thread_t*)arg; +  int repeats = 0; +  int iteration; +  int element = 0; + +  for (iteration = 0; iteration < ITERATIONS; iteration++) +    { +      /* +       * Each "self->interval" iterations, perform an +       * update operation (write lock instead of read +       * lock). +       */ +      if ((iteration % self->interval) == 0) +        { +          assert(pthread_rwlock_wrlock (&data[element].lock) == 0); +          data[element].data = self->thread_num; +          data[element].updates++; +          self->updates++; +          assert(pthread_rwlock_unlock (&data[element].lock) == 0); +        } else { +          /* +           * Look at the current data element to see whether +           * the current thread last updated it. Count the +           * times, to report later. +           */ +          assert(pthread_rwlock_rdlock (&data[element].lock) == 0); + +          self->reads++; + +          if (data[element].data == self->thread_num) +            { +              repeats++; +            } + +          assert(pthread_rwlock_unlock (&data[element].lock) == 0); +        } + +      element++; + +      if (element >= DATASIZE) +        { +          element = 0; +        } +    } + +  if (repeats > 0) +    { +      printf ("Thread %d found unchanged elements %d times\n", +              self->thread_num, repeats); +    } + +  return NULL; +} + +int +main (int argc, char *argv[]) +{ +  int count; +  int data_count; +  int status; +  unsigned int seed = 1; +  int thread_updates = 0; +  int data_updates = 0; + +  struct _timeb currSysTime1; +  struct _timeb currSysTime2; + +  /* +   * Initialize the shared data. +   */ +  for (data_count = 0; data_count < DATASIZE; data_count++) +    { +      data[data_count].data = 0; +      data[data_count].updates = 0; + +      assert(pthread_rwlock_init (&data[data_count].lock) == 0); +    } + +  _ftime(&currSysTime1); + +  /* +   * Create THREADS threads to access shared data. +   */ +  for (count = 0; count < THREADS; count++) +    { +      threads[count].thread_num = count; +      threads[count].updates = 0; +      threads[count].reads = 0; +      threads[count].interval = rand_r (&seed) % 71; + +      assert(pthread_create (&threads[count].thread_id, +                             NULL, thread_routine, (void*)&threads[count]) == 0); +    } + +  /* +   * Wait for all threads to complete, and collect +   * statistics. +   */ +  for (count = 0; count < THREADS; count++) +    { +      assert(pthread_join (threads[count].thread_id, NULL) == 0); +      thread_updates += threads[count].updates; +      printf ("%02d: interval %d, updates %d, reads %d\n", +              count, threads[count].interval, +              threads[count].updates, threads[count].reads); +    } + +  /* +   * Collect statistics for the data. +   */ +  for (data_count = 0; data_count < DATASIZE; data_count++) +    { +      data_updates += data[data_count].updates; +      printf ("data %02d: value %d, %d updates\n", +              data_count, data[data_count].data, data[data_count].updates); +      assert(pthread_rwlock_destroy (&data[data_count].lock) == 0); +    } + +  printf ("%d thread updates, %d data updates\n", +          thread_updates, data_updates); + +  _ftime(&currSysTime2); + +  printf( "\nstart: %d/%d, stop: %d/%d, duration:%d\n", +          currSysTime1.time,currSysTime1.millitm, +          currSysTime2.time,currSysTime2.millitm, +          (currSysTime2.time*1000+currSysTime2.millitm) - +          (currSysTime1.time*1000+currSysTime1.millitm)); + +  return 0; +} | 
