From ec27b9c8303540de6b5a8ebefee114f3cdd436f0 Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 5 Jul 2001 15:19:22 +0000 Subject: * 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. --- tests/ChangeLog | 13 +++++++++++ tests/GNUmakefile | 11 ++++++++++ tests/Makefile | 10 +++++++++ tests/barrier1.c | 26 ++++++++++++++++++++++ tests/barrier2.c | 23 ++++++++++++++++++++ tests/barrier3.c | 40 ++++++++++++++++++++++++++++++++++ tests/barrier4.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/spin1.c | 31 ++++++++++++++++++++++++++ tests/spin2.c | 43 ++++++++++++++++++++++++++++++++++++ tests/spin3.c | 40 ++++++++++++++++++++++++++++++++++ tests/spin4.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 366 insertions(+) create mode 100644 tests/barrier1.c create mode 100644 tests/barrier2.c create mode 100644 tests/barrier3.c create mode 100644 tests/barrier4.c create mode 100644 tests/spin1.c create mode 100644 tests/spin2.c create mode 100644 tests/spin3.c create mode 100644 tests/spin4.c (limited to 'tests') 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 + + * 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 * 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 + +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; +} -- cgit v1.2.3