summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/ChangeLog7
-rw-r--r--tests/GNUmakefile3
-rw-r--r--tests/Makefile3
-rw-r--r--tests/rwlock6.c110
-rw-r--r--tests/rwlock7.c173
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;
+}