diff options
-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; +} |