summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorrpj <rpj>2001-07-05 15:19:22 +0000
committerrpj <rpj>2001-07-05 15:19:22 +0000
commitec27b9c8303540de6b5a8ebefee114f3cdd436f0 (patch)
tree965ddfd011b9deb0091d2930fd55ce250c54ed58 /tests
parent99e8ecc5759668fd3af379eaddd70b4ae50ecd7f (diff)
* barrier.c: Remove static initialisation - irrelevent
for this object. * pthread.h (PTHREAD_BARRIER_INITIALIZER): Removed. * rwlock.c (pthread_rwlock_wrlock): This routine is not a cancelation point - disable deferred cancelation around call to pthread_cond_wait(). tests/ChangeLog: * spin1.c: New; testing spinlocks. * spin2.c: New; testing spinlocks. * spin3.c: New; testing spinlocks. * spin4.c: New; testing spinlocks. * barrier1.c: New; testing barriers. * barrier2.c: New; testing barriers. * barrier3.c: New; testing barriers. * barrier4.c: New; testing barriers. * GNUmakefile: Add new tests. * Makefile: Add new tests.
Diffstat (limited to 'tests')
-rw-r--r--tests/ChangeLog13
-rw-r--r--tests/GNUmakefile11
-rw-r--r--tests/Makefile10
-rw-r--r--tests/barrier1.c26
-rw-r--r--tests/barrier2.c23
-rw-r--r--tests/barrier3.c40
-rw-r--r--tests/barrier4.c64
-rw-r--r--tests/spin1.c31
-rw-r--r--tests/spin2.c43
-rw-r--r--tests/spin3.c40
-rw-r--r--tests/spin4.c65
11 files changed, 366 insertions, 0 deletions
diff --git a/tests/ChangeLog b/tests/ChangeLog
index f99d1be..565f0ad 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,16 @@
+2001-07-05 Ross Johnson <rpj@special.ise.canberra.edu.au>
+
+ * spin1.c: New; testing spinlocks.
+ * spin2.c: New; testing spinlocks.
+ * spin3.c: New; testing spinlocks.
+ * spin4.c: New; testing spinlocks.
+ * barrier1.c: New; testing barriers.
+ * barrier2.c: New; testing barriers.
+ * barrier3.c: New; testing barriers.
+ * barrier4.c: New; testing barriers.
+ * GNUmakefile: Add new tests.
+ * Makefile: Add new tests.
+
2001-07-01 Ross Johnson <rpj@special.ise.canberra.edu.au>
* benchtest3.c: New; timing mutexes.
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index b952eed..f005664 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -48,6 +48,8 @@ TESTS = loadfree \
context1 cancel3 cancel4 cancel5 \
cleanup0 cleanup1 cleanup2 cleanup3 \
priority1 priority2 inherit1 \
+ spin1 spin2 spin3 spin4 \
+ barrier1 barrier2 barrier3 barrier4 \
exception1 exception2 exception3
BENCHTESTS = \
@@ -89,6 +91,11 @@ benchtest1.bench:
benchtest2.bench:
benchtest3.bench:
benchtest4.bench:
+
+barrier1.pass:
+barrier2.pass: barrier1.pass
+barrier3.pass: barrier2.pass
+barrier4.pass: barrier3.pass
cancel1.pass: create1.pass
cancel2.pass: cancel1.pass
cancel2_1.pass: cancel2.pass
@@ -149,6 +156,10 @@ rwlock6.pass: rwlock5.pass
rwlock7.pass: rwlock6.pass
self1.pass:
self2.pass: create1.pass
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
tsd1.pass: join1.pass
#%.pass: %.exe $(HDR)
diff --git a/tests/Makefile b/tests/Makefile
index 6ac342d..f3a4f91 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -57,6 +57,8 @@ PASSES= loadfree.pass \
cancel3.pass cancel4.pass cancel5.pass \
cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \
priority1.pass priority2.pass inherit1.pass \
+ spin1.pass spin2.pass spin3.pass spin4.pass \
+ barrier1.pass barrier2.pass barrier3.pass barrier4.pass \
exception1.pass exception2.pass exception3.pass
BENCHRESULTS = \
@@ -145,6 +147,10 @@ benchtest1.bench:
benchtest2.bench:
benchtest3.bench:
benchtest4.bench:
+barrier1.pass:
+barrier2.pass: barrier1.pass
+barrier3.pass: barrier2.pass
+barrier4.pass: barrier3.pass
cancel1.pass: create1.pass
cancel2.pass: cancel1.pass
cancel3.pass: context1.pass
@@ -204,4 +210,8 @@ rwlock6.pass: rwlock5.pass
rwlock7.pass: rwlock6.pass
self1.pass:
self2.pass: create1.pass
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
tsd1.pass: join1.pass
diff --git a/tests/barrier1.c b/tests/barrier1.c
new file mode 100644
index 0000000..bc0eb52
--- /dev/null
+++ b/tests/barrier1.c
@@ -0,0 +1,26 @@
+/*
+ * barrier1.c
+ *
+ * Create a barrier object and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+pthread_barrier_t barrier = NULL;
+
+int
+main()
+{
+ assert(barrier == NULL);
+
+ assert(pthread_barrier_init(&barrier, NULL, 1) == 0);
+
+ assert(barrier != NULL);
+
+ assert(pthread_barrier_destroy(&barrier) == 0);
+
+ assert(barrier == NULL);
+
+ return 0;
+}
diff --git a/tests/barrier2.c b/tests/barrier2.c
new file mode 100644
index 0000000..c7b174c
--- /dev/null
+++ b/tests/barrier2.c
@@ -0,0 +1,23 @@
+/*
+ * barrier2.c
+ *
+ * Declare a single barrier object, wait on it,
+ * and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+pthread_barrier_t barrier = NULL;
+
+int
+main()
+{
+ assert(pthread_barrier_init(&barrier, NULL, 1) == 0);
+
+ assert(pthread_barrier_wait(&barrier) == PTHREAD_BARRIER_SERIAL_THREAD);
+
+ assert(pthread_barrier_destroy(&barrier) == 0);
+
+ return 0;
+}
diff --git a/tests/barrier3.c b/tests/barrier3.c
new file mode 100644
index 0000000..497b76a
--- /dev/null
+++ b/tests/barrier3.c
@@ -0,0 +1,40 @@
+/*
+ * barrier3.c
+ *
+ * Declare a single barrier object, multiple wait on it,
+ * and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+pthread_barrier_t barrier = NULL;
+static int result1 = -1;
+static int result2 = -1;
+
+void * func(void * arg)
+{
+ return (void *) pthread_barrier_wait(&barrier);
+}
+
+int
+main()
+{
+ pthread_t t;
+
+ assert(pthread_barrier_init(&barrier, NULL, 2) == 0);
+
+ assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+ result1 = pthread_barrier_wait(&barrier);
+
+ assert(pthread_join(t, &result2) == 0);
+
+ assert(result1 != result2);
+ assert(result1 == 0 || result1 == PTHREAD_BARRIER_SERIAL_THREAD);
+ assert(result2 == 0 || result2 == PTHREAD_BARRIER_SERIAL_THREAD);
+
+ assert(pthread_barrier_destroy(&barrier) == 0);
+
+ return 0;
+}
diff --git a/tests/barrier4.c b/tests/barrier4.c
new file mode 100644
index 0000000..1dd8291
--- /dev/null
+++ b/tests/barrier4.c
@@ -0,0 +1,64 @@
+/*
+ * barrier4.c
+ *
+ * Declare a single barrier object, multiple wait on it,
+ * and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+enum {
+ NUMTHREADS = 16
+};
+
+pthread_barrier_t barrier = NULL;
+pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;
+static int result1 = -1;
+static int result2 = -1;
+static int serialThreadCount = 0;
+static int otherThreadCount = 0;
+
+void * func(void * arg)
+{
+ int result = pthread_barrier_wait(&barrier);
+
+ assert(pthread_mutex_lock(&mx) == 0);
+ if (result == PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ serialThreadCount++;
+ }
+ else
+ {
+ otherThreadCount++;
+ }
+ assert(pthread_mutex_lock(&mx) == 0);
+
+ return NULL;
+}
+
+int
+main()
+{
+ pthread_t t[NUMTHREADS + 1];
+
+ assert(pthread_barrier_init(&barrier, NULL, NUMTHREADS) == 0);
+
+ for (i = 0; i < NUMTHREADS; i++)
+ {
+ assert(pthread_create(&t[i], NULL, func, NULL) == 0);
+ }
+
+ for (i = 0; i < NUMTHREADS; i++)
+ {
+ assert(pthread_join(t[i], NULL) == 0);
+ }
+
+ assert(serialThreadCount == 1);
+
+ assert(pthread_barrier_destroy(&barrier) == 0);
+
+ assert(pthread_mutex_destroy(&mx) == 0);
+
+ return 0;
+}
diff --git a/tests/spin1.c b/tests/spin1.c
new file mode 100644
index 0000000..e9e5731
--- /dev/null
+++ b/tests/spin1.c
@@ -0,0 +1,31 @@
+/*
+ * spin1.c
+ *
+ * Create a simple spinlock object, lock it, and then unlock it again.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ */
+
+#include "test.h"
+
+pthread_spinlock_t lock = NULL;
+
+int
+main()
+{
+ assert(lock == NULL);
+
+ assert(pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE) == 0);
+
+ assert(lock != NULL);
+
+ assert(pthread_spin_lock(&lock) == 0);
+
+ assert(pthread_spin_unlock(&lock) == 0);
+
+ assert(pthread_spin_destroy(&lock) == 0);
+
+ assert(lock == NULL);
+
+ return 0;
+}
diff --git a/tests/spin2.c b/tests/spin2.c
new file mode 100644
index 0000000..4a6a2bb
--- /dev/null
+++ b/tests/spin2.c
@@ -0,0 +1,43 @@
+/*
+ * spin2.c
+ *
+ * Declare a spinlock object, lock it, trylock it,
+ * and then unlock it again.
+ *
+ */
+
+#include "test.h"
+
+pthread_spinlock_t lock = NULL;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+ assert(pthread_spin_trylock(&lock) == EBUSY);
+
+ washere = 1;
+
+ return 0;
+}
+
+int
+main()
+{
+ pthread_t t;
+
+ assert(pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE) == 0);
+
+ assert(pthread_spin_lock(&lock) == 0);
+
+ assert(pthread_create(&t, NULL, func, NULL) == 0);
+ assert(pthread_join(t, NULL) == 0);
+
+ assert(pthread_spin_unlock(&lock) == 0);
+
+ assert(pthread_spin_destroy(&lock) == 0);
+
+ assert(washere == 1);
+
+ return 0;
+}
diff --git a/tests/spin3.c b/tests/spin3.c
new file mode 100644
index 0000000..8b383de
--- /dev/null
+++ b/tests/spin3.c
@@ -0,0 +1,40 @@
+/*
+ * spin3.c
+ *
+ * Thread A locks spin - thread B tries to unlock.
+ * This should succeed, but it's undefined behaviour.
+ *
+ */
+
+#include "test.h"
+
+static int wasHere = 0;
+
+static pthread_spinlock_t spin;
+
+void * unlocker(void * arg)
+{
+ int expectedResult = (int) arg;
+
+ wasHere++;
+ assert(pthread_spin_unlock(&spin) == expectedResult);
+ wasHere++;
+ return NULL;
+}
+
+int
+main()
+{
+ pthread_t t;
+ pthread_spinattr_t ma;
+
+ wasHere = 0;
+ assert(pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE) == 0);
+ assert(pthread_spin_lock(&spin) == 0);
+ assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0);
+ assert(pthread_join(t, NULL) == 0);
+ assert(pthread_spin_unlock(&spin) == EPERM);
+ assert(wasHere == 2);
+
+ return 0;
+}
diff --git a/tests/spin4.c b/tests/spin4.c
new file mode 100644
index 0000000..a435d04
--- /dev/null
+++ b/tests/spin4.c
@@ -0,0 +1,65 @@
+/*
+ * spin4.c
+ *
+ * Declare a spinlock object, lock it, spin on it,
+ * and then unlock it again.
+ *
+ * For this to work on a single processor machine we have
+ * to static initialise the spinlock. This bypasses the
+ * check of the number of processors done by pthread_spin_init.
+ * This is a non-portable side-effect of this implementation.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_spinlock_t lock = PTHREADS_SPINLOCK_INITIALIZER;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+ - (_TStart.time*1000+_TStart.millitm))
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+ _ftime(&currSysTimeStart);
+ assert(pthread_spin_lock(&lock) == 0);
+ assert(pthread_spin_unlock(&lock) == 0);
+ _ftime(&currSysTimeStop);
+ washere = 1;
+
+ return (void *) GetDurationMilliSecs(currSysTimeStart, currSysTimeStop);
+}
+
+int
+main()
+{
+ long result = 0;
+ pthread_t t;
+
+ assert(pthread_spin_lock(&lock) == 0);
+
+ assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+ /*
+ * This should relinqish the CPU to the func thread enough times
+ * to waste approximately 2000 millisecs only if the lock really
+ * is spinning in the func thread (assuming 10 millisec CPU quantum).
+ for (i = 0; i < 200; i++)
+ {
+ sched_yield();
+ }
+
+ assert(pthread_spin_unlock(&lock) == 0);
+
+ assert(pthread_join(t, (void *) &result) == 0);
+ assert(result > 1000);
+
+ assert(pthread_spin_destroy(&lock) == 0);
+
+ assert(washere == 1);
+
+ return 0;
+}