summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpj <rpj>2001-05-31 02:05:25 +0000
committerrpj <rpj>2001-05-31 02:05:25 +0000
commita8744086b476e4007c1d8fc0fae84ecfcade99ba (patch)
tree69bd3bd925233e00d960f3de5a5f3953db235da7
parente121b938c9f012958196a3141f04a3fd4f58bdb9 (diff)
New test.
-rw-r--r--tests/mutex1e.c42
-rw-r--r--tests/mutex1n.c42
-rw-r--r--tests/mutex1r.c42
-rw-r--r--tests/mutex5.c31
-rw-r--r--tests/mutex6.c51
-rw-r--r--tests/mutex6e.c70
-rw-r--r--tests/mutex6n.c61
-rw-r--r--tests/mutex6r.c68
-rw-r--r--tests/rwlock7.c185
9 files changed, 592 insertions, 0 deletions
diff --git a/tests/mutex1e.c b/tests/mutex1e.c
new file mode 100644
index 0000000..2feb16c
--- /dev/null
+++ b/tests/mutex1e.c
@@ -0,0 +1,42 @@
+/*
+ * mutex1e.c
+ *
+ * As for mutex1.c but with type set to PTHREAD_MUTEX_ERRORCHECK.
+ *
+ * Create a simple mutex object, lock it, unlock it, then destroy it.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ * pthread_mutexattr_settype()
+ * pthread_mutex_init()
+ * pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+
+ assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0);
+
+ assert(mutex == NULL);
+
+ assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+ assert(mutex != NULL);
+
+ assert(pthread_mutex_lock(&mutex) == 0);
+
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ assert(pthread_mutex_destroy(&mutex) == 0);
+
+ assert(mutex == NULL);
+
+ return 0;
+}
diff --git a/tests/mutex1n.c b/tests/mutex1n.c
new file mode 100644
index 0000000..9af3d5f
--- /dev/null
+++ b/tests/mutex1n.c
@@ -0,0 +1,42 @@
+/*
+ * mutex1n.c
+ *
+ * As for mutex1.c but with type set to PTHREAD_MUTEX_NORMAL.
+ *
+ * Create a simple mutex object, lock it, unlock it, then destroy it.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ * pthread_mutexattr_settype()
+ * pthread_mutex_init()
+ * pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+
+ assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0);
+
+ assert(mutex == NULL);
+
+ assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+ assert(mutex != NULL);
+
+ assert(pthread_mutex_lock(&mutex) == 0);
+
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ assert(pthread_mutex_destroy(&mutex) == 0);
+
+ assert(mutex == NULL);
+
+ return 0;
+}
diff --git a/tests/mutex1r.c b/tests/mutex1r.c
new file mode 100644
index 0000000..b5131bb
--- /dev/null
+++ b/tests/mutex1r.c
@@ -0,0 +1,42 @@
+/*
+ * mutex1r.c
+ *
+ * As for mutex1.c but with type set to PTHREAD_MUTEX_RECURSIVE.
+ *
+ * Create a simple mutex object, lock it, unlock it, then destroy it.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ * pthread_mutexattr_settype()
+ * pthread_mutex_init()
+ * pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+
+ assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
+
+ assert(mutex == NULL);
+
+ assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+ assert(mutex != NULL);
+
+ assert(pthread_mutex_lock(&mutex) == 0);
+
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ assert(pthread_mutex_destroy(&mutex) == 0);
+
+ assert(mutex == NULL);
+
+ return 0;
+}
diff --git a/tests/mutex5.c b/tests/mutex5.c
new file mode 100644
index 0000000..6a9a917
--- /dev/null
+++ b/tests/mutex5.c
@@ -0,0 +1,31 @@
+/*
+ * mutex5.c
+ *
+ * Confirm the equality/inequality of the various mutex types,
+ * and the default not-set value.
+ */
+
+#include "test.h"
+
+static pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+ int mxType = -1;
+
+ assert(PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL);
+ assert(PTHREAD_MUTEX_DEFAULT != PTHREAD_MUTEX_ERRORCHECK);
+ assert(PTHREAD_MUTEX_DEFAULT != PTHREAD_MUTEX_RECURSIVE);
+ assert(PTHREAD_MUTEX_RECURSIVE != PTHREAD_MUTEX_ERRORCHECK);
+
+ assert(PTHREAD_MUTEX_NORMAL == PTHREAD_MUTEX_FAST_NP);
+ assert(PTHREAD_MUTEX_RECURSIVE == PTHREAD_MUTEX_RECURSIVE_NP);
+ assert(PTHREAD_MUTEX_ERRORCHECK == PTHREAD_MUTEX_ERRORCHECK_NP);
+
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+ assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+ assert(mxType == PTHREAD_MUTEX_NORMAL);
+
+ return 0;
+}
diff --git a/tests/mutex6.c b/tests/mutex6.c
new file mode 100644
index 0000000..39b95e5
--- /dev/null
+++ b/tests/mutex6.c
@@ -0,0 +1,51 @@
+/*
+ * mutex6.c
+ *
+ * Test the default (type not set) mutex type.
+ * Should be the same as PTHREAD_MUTEX_NORMAL.
+ * Thread locks mutex twice (recursive lock).
+ * Locking thread should deadlock on second attempt.
+ *
+ * Depends on API functions:
+ * pthread_mutex_lock()
+ * pthread_mutex_trylock()
+ * pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+
+void * locker(void * arg)
+{
+ assert(pthread_mutex_lock(&mutex) == 0);
+ lockCount++;
+ assert(pthread_mutex_lock(&mutex) != 0);
+ lockCount++;
+ Sleep(1000);
+ assert(pthread_mutex_unlock(&mutex) == 0);
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ return 0;
+}
+
+int
+main()
+{
+ pthread_t t;
+
+ assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+ assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+ Sleep(2000);
+
+ assert(lockCount == 1);
+
+ exit(0);
+
+ /* Never reached */
+ return 0;
+}
diff --git a/tests/mutex6e.c b/tests/mutex6e.c
new file mode 100644
index 0000000..e22550f
--- /dev/null
+++ b/tests/mutex6e.c
@@ -0,0 +1,70 @@
+/*
+ * mutex6e.c
+ *
+ * Tests PTHREAD_MUTEX_ERRORCHECK mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * This should fail with an EDEADLK error.
+ * The second unlock attempt should fail with an EPERM error.
+ *
+ * Depends on API functions:
+ * pthread_create()
+ * pthread_join()
+ * pthread_mutexattr_init()
+ * pthread_mutexattr_destroy()
+ * pthread_mutexattr_settype()
+ * pthread_mutexattr_gettype()
+ * pthread_mutex_init()
+ * pthread_mutex_destroy()
+ * pthread_mutex_lock()
+ * pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+ assert(pthread_mutex_lock(&mutex) == 0);
+ lockCount++;
+ assert(pthread_mutex_lock(&mutex) == EDEADLK);
+ lockCount++;
+ assert(pthread_mutex_unlock(&mutex) == 0);
+ assert(pthread_mutex_unlock(&mutex) == EPERM);
+
+ return (void *) 555;
+}
+
+int
+main()
+{
+ pthread_t t;
+ int result = 0;
+ int mxType = -1;
+
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+ assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0);
+ assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+ assert(mxType == PTHREAD_MUTEX_ERRORCHECK);
+
+ assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+ assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+ assert(pthread_join(t, (void **) &result) == 0);
+ assert(result == 555);
+
+ assert(lockCount == 2);
+
+ assert(pthread_mutex_destroy(&mutex) == 0);
+ assert(pthread_mutexattr_destroy(&mxAttr) == 0);
+
+ exit(0);
+
+ /* Never reached */
+ return 0;
+}
+
diff --git a/tests/mutex6n.c b/tests/mutex6n.c
new file mode 100644
index 0000000..19e917c
--- /dev/null
+++ b/tests/mutex6n.c
@@ -0,0 +1,61 @@
+/*
+ * mutex6n.c
+ *
+ * Tests PTHREAD_MUTEX_NORMAL mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * The thread should deadlock.
+ *
+ * Depends on API functions:
+ * pthread_create()
+ * pthread_mutexattr_init()
+ * pthread_mutexattr_settype()
+ * pthread_mutexattr_gettype()
+ * pthread_mutex_init()
+ * pthread_mutex_lock()
+ * pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+ assert(pthread_mutex_lock(&mutex) == 0);
+ lockCount++;
+ assert(pthread_mutex_lock(&mutex) != 0);
+ lockCount++;
+ assert(pthread_mutex_unlock(&mutex) == 0);
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ return (void *) 555;
+}
+
+int
+main()
+{
+ pthread_t t;
+ int mxType = -1;
+
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+ assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0);
+ assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+ assert(mxType == PTHREAD_MUTEX_NORMAL);
+
+ assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+ assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+ Sleep(1000);
+
+ assert(lockCount == 1);
+
+ exit(0);
+
+ /* Never reached */
+ return 0;
+}
+
diff --git a/tests/mutex6r.c b/tests/mutex6r.c
new file mode 100644
index 0000000..586cc84
--- /dev/null
+++ b/tests/mutex6r.c
@@ -0,0 +1,68 @@
+/*
+ * mutex6r.c
+ *
+ * Tests PTHREAD_MUTEX_RECURSIVE mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * Both locks and unlocks should succeed.
+ *
+ * Depends on API functions:
+ * pthread_create()
+ * pthread_join()
+ * pthread_mutexattr_init()
+ * pthread_mutexattr_destroy()
+ * pthread_mutexattr_settype()
+ * pthread_mutexattr_gettype()
+ * pthread_mutex_init()
+ * pthread_mutex_destroy()
+ * pthread_mutex_lock()
+ * pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+ assert(pthread_mutex_lock(&mutex) == 0);
+ lockCount++;
+ assert(pthread_mutex_lock(&mutex) == 0);
+ lockCount++;
+ assert(pthread_mutex_unlock(&mutex) == 0);
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ return (void *) 555;
+}
+
+int
+main()
+{
+ pthread_t t;
+ int result = 0;
+ int mxType = -1;
+
+ assert(pthread_mutexattr_init(&mxAttr) == 0);
+ assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
+ assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+ assert(mxType == PTHREAD_MUTEX_RECURSIVE);
+
+ assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+ assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+ assert(pthread_join(t, (void **) &result) == 0);
+ assert(result == 555);
+
+ assert(lockCount == 2);
+
+ assert(pthread_mutex_destroy(&mutex) == 0);
+ assert(pthread_mutexattr_destroy(&mxAttr) == 0);
+
+ exit(0);
+
+ /* Never reached */
+ return 0;
+}
diff --git a/tests/rwlock7.c b/tests/rwlock7.c
new file mode 100644
index 0000000..9c6a5f1
--- /dev/null
+++ b/tests/rwlock7.c
@@ -0,0 +1,185 @@
+/*
+ * 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>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#define THREADS 5
+#define DATASIZE 15
+#define ITERATIONS 1000000
+
+/*
+ * 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 {
+ pthread_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++)
+ {
+ if (iteration % (ITERATIONS / 10) == 0)
+ {
+ putchar('.');
+ fflush(stdout);
+ }
+ /*
+ * 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 ("\nThread %d found unchanged elements %d times",
+ self->thread_num, repeats);
+ fflush(stdout);
+ }
+
+ return NULL;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int count;
+ int data_count;
+ int thread_updates = 0;
+ int data_updates = 0;
+ int seed = 1;
+
+ 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, NULL) == 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);
+ }
+
+ putchar('\n');
+ fflush(stdout);
+
+ /*
+ * 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: %ld/%d, stop: %ld/%d, duration:%ld\n",
+ currSysTime1.time,currSysTime1.millitm,
+ currSysTime2.time,currSysTime2.millitm,
+ (currSysTime2.time*1000+currSysTime2.millitm) -
+ (currSysTime1.time*1000+currSysTime1.millitm));
+
+ return 0;
+}