From 2ef097640758653a0e9d63e90a4aac329cd86368 Mon Sep 17 00:00:00 2001 From: rpj Date: Mon, 22 Feb 1999 02:54:12 +0000 Subject: 1999-02-23 Ross Johnson * Makefile: Some refinement. * *.c: More exhaustive checking through assertions; clean up; add some more tests. --- tests/ChangeLog | 5 ++ tests/Makefile | 46 +++++++++----- tests/count1.c | 42 ++++++------- tests/create1.c | 26 +++++--- tests/exit2.c | 24 +++++++- tests/exit3.c | 12 ++-- tests/eyal1.c | 182 +++++++++++++++++++++----------------------------------- tests/join1.c | 41 +++++++++++++ tests/mutex1.c | 25 ++++---- tests/mutex2.c | 27 ++++----- tests/mutex3.c | 42 +++++++++++-- tests/once1.c | 32 +++++----- tests/self1.c | 23 ++++--- tests/self2.c | 41 ++++++++----- tests/self3.c | 32 ---------- tests/tsd1.c | 156 +++++++++++++++++++++++++----------------------- 16 files changed, 407 insertions(+), 349 deletions(-) create mode 100644 tests/join1.c delete mode 100644 tests/self3.c diff --git a/tests/ChangeLog b/tests/ChangeLog index 2d57206..ecbaa2a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,10 @@ 1999-02-23 Ross Johnson + * Makefile: Some refinement. + + * *.c: More exhaustive checking through assertions; clean up; + add some more tests. + * Makefile: Now actually runs the tests. * tests.h: Define our own assert macro. The Mingw32 diff --git a/tests/Makefile b/tests/Makefile index 56968e5..4fef3c3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,52 +4,66 @@ CP = copy RM = erase +MKDIR = mkdir TOUCH = echo Passed > +ECHO = @echo # # Mingw32 # CC = gcc CFLAGS = -g -O2 -UNDEBUG -Wall -o $@ $^ -BUILD_DIR = ../build -RELEASE_DIR = ../release -INCLUDES = -I$(BUILD_DIR)/include -LIBS = $(BUILD_DIR)/lib/libpthread32.a +BUILD_DIR = ..\build +INCLUDES = -I./include +LIBS = ./lib/libpthread32.a ## ## MSVC ## #CC = cl #CFLAGS = /W3 /MT /nologo /Yd /Zi /Fe$@ $^ -#BUILD_DIR = ..\build -#RELEASE_DIR = ..\release -#INCLUDES = -I$(BUILD_DIR)\include -#LIBS = $(BUILD_DIR)\lib\pthread.lib +#BUILD_DIR = .. +#INCLUDES = -I.\include +#LIBS = .\lib\pthread.lib +HDR = .\include\pthread.h +LIB = .\lib\libpthread32.a DLL = pthread.dll # If a test case returns a non-zero exit code to the shell, make will # stop. -TESTS = count1 create1 equal1 exit1 exit2 \ - exit3 eyal1 mutex1 mutex2 mutex3 \ - once1 self1 self2 self3 tsd1 +TESTS = count1 create1 equal1 exit1 exit2 exit3 \ + join1 eyal1 mutex1 mutex2 mutex3 \ + once1 self1 self2 tsd1 PASSES = $(TESTS:%=%.pass) all: $(PASSES) + @ $(ECHO) ALL TESTS PASSED! Congratulations! -%.pass: %.exe $(DLL) +%.pass: %.exe $(LIB) $(DLL) $(HDR) $* - $(TOUCH) $@ + @$(ECHO) Passed + @ $(TOUCH) $@ %.exe: %.c - $(CC) $(CFLAGS) $(INCLUDES) $(LIBS) + @ $(CC) $(CFLAGS) $(INCLUDES) $(LIBS) + +$(LIB): + @- $(MKDIR) .\lib + @ $(CP) $(BUILD_DIR)\$@ .\$@ + +$(HDR): + @- $(MKDIR) .\include + @ $(CP) $(BUILD_DIR)\$@ .\$@ $(DLL): - $(CP) ..\build\bin\$@ . + @ $(CP) $(BUILD_DIR)\$@ .\$@ clean: + - $(RM) *.dll + - $(RM) $(LIB) + - $(RM) $(HDR) - $(RM) *.exe - $(RM) *.pass - diff --git a/tests/count1.c b/tests/count1.c index c4e0c4e..61e82e0 100644 --- a/tests/count1.c +++ b/tests/count1.c @@ -7,8 +7,7 @@ * Test some basic assertions about the number of threads at runtime. */ -#include -#include +#include "test.h" static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t threads[10]; @@ -27,36 +26,37 @@ myfunc(void *arg) int main() { - int i, result; + int i; int maxThreads = sizeof(threads) / sizeof(pthread_t); - /* Spawn ten threads. Each thread should increment the numThreads - variable, sleep for one second, decrement the variable and then - exit. The final result of numThreads should be 1 again. */ + /* + * Spawn ten threads. Each thread should increment the numThreads + * variable, sleep for one second, decrement the variable and then + * exit. The final result of numThreads should be 1 again. + */ for (i = 0; i < maxThreads; i++) { - result = pthread_create(&threads[i], NULL, myfunc, 0); - if (result != 0) - { - return 1; - } + assert(pthread_create(&threads[i], NULL, myfunc, 0) == 0); } - /* Wait for all the threads to exit. */ + /* + * Wait for all the threads to exit. + */ for (i = 0; i < maxThreads; i++) { - pthread_join(threads[i], NULL); - pthread_mutex_lock(&lock); + assert(pthread_join(threads[i], NULL) == 0); + assert(pthread_mutex_lock(&lock) == 0); numThreads--; - pthread_mutex_unlock(&lock); + assert(pthread_mutex_unlock(&lock) == 0); } - /* Check the number of live threads. */ - if (numThreads != 1) - { - return 1; - } + /* + * Check the number of live threads. + */ + assert(numThreads == 1); - /* Success. */ + /* + * Success. + */ return 0; } diff --git a/tests/create1.c b/tests/create1.c index 2741401..192e52d 100644 --- a/tests/create1.c +++ b/tests/create1.c @@ -1,9 +1,19 @@ -#include -#include -#include +/* + * create1.c + * + * Description: + * Create a thread and check that it ran. + * + * Depends on API functions: None. + */ + +#include "test.h" + +static int washere = 0; void * func(void * arg) { + washere = 1; return 0; } @@ -11,14 +21,14 @@ int main() { pthread_t t; - if (pthread_create(&t, NULL, func, NULL) != 0) - { - return 1; - } + + assert(pthread_create(&t, NULL, func, NULL) == 0); /* A dirty hack, but we cannot rely on pthread_join in this primitive test. */ - Sleep(5000); + Sleep(2000); + + assert(washere == 1); return 0; } diff --git a/tests/exit2.c b/tests/exit2.c index 48ad5d0..786e4aa 100644 --- a/tests/exit2.c +++ b/tests/exit2.c @@ -1,12 +1,30 @@ /* * Test for pthread_exit(). + * + * Depends on API functions: + * pthread_create() + * pthread_exit() */ -#include +#include "test.h" + +void * +func(void * arg) +{ + pthread_exit(arg); + + /* Never reached. */ + exit(1); +} int main(int argc, char * argv[]) { - /* Should be the same as return 0; */ - pthread_exit(0); + pthread_t t; + + assert(pthread_create(&t, NULL, func, (void *) NULL) == 0); + + Sleep(2000); + + return 0; } diff --git a/tests/exit3.c b/tests/exit3.c index f15b39d..b666624 100644 --- a/tests/exit3.c +++ b/tests/exit3.c @@ -4,8 +4,7 @@ * Depends on API functions: pthread_create(). */ -#include -#include +#include "test.h" void * func(void * arg) @@ -13,7 +12,7 @@ func(void * arg) pthread_exit(arg); /* Never reached. */ - return 0; + exit(1); } int @@ -25,11 +24,8 @@ main(int argc, char * argv[]) /* Create a few threads and then exit. */ for (i = 0; i < 4; i++) { - if (pthread_create(&id[i], NULL, func, (void *) i) != 0) - { - return 1; - } - } + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } /* Success. */ return 0; diff --git a/tests/eyal1.c b/tests/eyal1.c index f51bc9c..4345452 100644 --- a/tests/eyal1.c +++ b/tests/eyal1.c @@ -43,13 +43,11 @@ * the threads knows its 'id' and also filles in the 'work' done). */ -#include +#include "test.h" + #include #include -#include - - struct thread_control { int id; pthread_t thread; /* thread id */ @@ -63,8 +61,8 @@ struct thread_control { typedef struct thread_control TC; static TC *tcs = NULL; -static int nthreads = 2; -static int nwork = 0; +static int nthreads = 7; +static int nwork = 50; static int quiet = 0; static int todo = -1; @@ -112,8 +110,7 @@ do_work_unit (int who, int n) else { /* get lock on stdout */ - if (pthread_mutex_lock (&mutex_stdout)) - return (-1); + assert(pthread_mutex_lock (&mutex_stdout) == 0); /* do our job */ @@ -125,8 +122,7 @@ do_work_unit (int who, int n) /* release lock on stdout */ - if (pthread_mutex_unlock (&mutex_stdout)) - return (-2); + assert(pthread_mutex_unlock (&mutex_stdout) == 0); } n = rand () % 10000; /* ignore incoming 'n' */ @@ -142,25 +138,19 @@ print_server (void *ptr) int n; TC *tc = (TC *)ptr; - if (pthread_mutex_lock (&tc->mutex_started)) - return (-1); + assert(pthread_mutex_lock (&tc->mutex_started) == 0); for (;;) { - if (pthread_mutex_lock (&tc->mutex_start)) - return (-2); - if (pthread_mutex_unlock (&tc->mutex_start)) - return (-3); - if (pthread_mutex_lock (&tc->mutex_ended)) - return (-4); - if (pthread_mutex_unlock (&tc->mutex_started)) - return (-5); + assert(pthread_mutex_lock (&tc->mutex_start) == 0); + assert(pthread_mutex_unlock (&tc->mutex_start) == 0); + assert(pthread_mutex_lock (&tc->mutex_ended) == 0); + assert(pthread_mutex_unlock (&tc->mutex_started) == 0); for (;;) { /* get lock on todo list */ - if (pthread_mutex_lock (&mutex_todo)) - return (-6); + assert(pthread_mutex_lock (&mutex_todo) == 0); mywork = todo; if (todo >= 0) { @@ -168,140 +158,102 @@ print_server (void *ptr) if (todo >= nwork) todo = -1; } - if (pthread_mutex_unlock (&mutex_todo)) - return (-7); + assert(pthread_mutex_unlock (&mutex_todo) == 0); if (mywork < 0) break; - if ((n = do_work_unit (tc->id, mywork)) < 0) - return (-8); + assert((n = do_work_unit (tc->id, mywork)) >= 0); tc->work += n; } - if (pthread_mutex_lock (&tc->mutex_end)) - return (-9); - if (pthread_mutex_unlock (&tc->mutex_end)) - return (-10); - if (pthread_mutex_lock (&tc->mutex_started)) - return (-11); - if (pthread_mutex_unlock (&tc->mutex_ended)) - return (-12); + assert(pthread_mutex_lock (&tc->mutex_end) == 0); + assert(pthread_mutex_unlock (&tc->mutex_end) == 0); + assert(pthread_mutex_lock (&tc->mutex_started) == 0); + assert(pthread_mutex_unlock (&tc->mutex_ended) == 0); if (-2 == mywork) break; } - if (pthread_mutex_unlock (&tc->mutex_started)) - return (-13); + assert(pthread_mutex_unlock (&tc->mutex_started) == 0); return (0); } -static int +static void dosync (void) { int i; for (i = 0; i < nthreads; ++i) { - if (pthread_mutex_lock (&tcs[i].mutex_end)) - return (-1); - if (pthread_mutex_unlock (&tcs[i].mutex_start)) - return (-2); - if (pthread_mutex_lock (&tcs[i].mutex_started)) - return (-3); - if (pthread_mutex_unlock (&tcs[i].mutex_started)) - return (-4); + assert(pthread_mutex_lock (&tcs[i].mutex_end) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_start) == 0); + assert(pthread_mutex_lock (&tcs[i].mutex_started) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0); } /* Now threads do their work */ for (i = 0; i < nthreads; ++i) { - if (pthread_mutex_lock (&tcs[i].mutex_start)) - return (-5); - if (pthread_mutex_unlock (&tcs[i].mutex_end)) - return (-6); - if (pthread_mutex_lock (&tcs[i].mutex_ended)) - return (-7); - if (pthread_mutex_unlock (&tcs[i].mutex_ended)) - return (-8); + assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_end) == 0); + assert(pthread_mutex_lock (&tcs[i].mutex_ended) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_ended) == 0); } - - return (0); } -static int +static void dowork (void) { todo = 0; - if (dosync () < 0) - return (-1); + dosync(); todo = 0; - if (dosync () < 0) - return (-2); - - return (0); + dosync(); } int main (int argc, char *argv[]) { int i; - int nargs; - - nthreads = 1; - nwork = 100; - nargs = 0; - for (i = 1; i < argc; ++i) { - if (!strcmp ("-q", argv[i])) { - quiet = 1; - continue; - } - if (!strcmp ("-h", argv[i])) { - printf ("usage: pthreads [nthreads] [nwork] [-q]\n"); - exit (0); - } - switch (++nargs) { - case 1: - nthreads = atoi (argv[i]); - if (nthreads > 36) { - printf ("max 36 threads allowed\n"); - die (1); - } - break; - case 2: - nwork = atoi (argv[i]); - break; - default: - printf ("bad argument '%s'\n", argv[i]); - die (1); - break; - } - } - if (NULL == (tcs = calloc (nthreads, sizeof (*tcs)))) - die (1); + assert(NULL != (tcs = calloc (nthreads, sizeof (*tcs)))); /* Launch threads */ for (i = 0; i < nthreads; ++i) { tcs[i].id = i; - pthread_mutex_init (&tcs[i].mutex_start, NULL); - pthread_mutex_init (&tcs[i].mutex_started, NULL); - pthread_mutex_init (&tcs[i].mutex_end, NULL); - pthread_mutex_init (&tcs[i].mutex_ended, NULL); + + assert(pthread_mutex_init (&tcs[i].mutex_start, NULL) == 0); + assert(pthread_mutex_init (&tcs[i].mutex_started, NULL) == 0); + assert(pthread_mutex_init (&tcs[i].mutex_end, NULL) == 0); + assert(pthread_mutex_init (&tcs[i].mutex_ended, NULL) == 0); + tcs[i].work = 0; - if (pthread_mutex_lock (&tcs[i].mutex_start)) - {} - tcs[i].stat = pthread_create (&tcs[i].thread, - NULL /*&pthread_attr_default*/, - (void*)&print_server, (void *)&tcs[i]); + + assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0); + assert((tcs[i].stat = + pthread_create (&tcs[i].thread, + NULL, + (void*)&print_server, (void *)&tcs[i]) + ) == 0); /* Wait for thread initialisation */ - while (!pthread_mutex_trylock (&tcs[i].mutex_started)) - pthread_mutex_unlock (&tcs[i].mutex_started); + while (1) + { + int trylock; + + trylock = pthread_mutex_trylock(&tcs[i].mutex_started); + assert(trylock == 0 || trylock == EBUSY); + + if (trylock == 0) + { + assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0); + break; + } + } } dowork (); @@ -309,18 +261,17 @@ main (int argc, char *argv[]) /* Terminate threads */ todo = -2; /* please terminate */ - if (dosync () < 0) - die (2); + dosync(); for (i = 0; i < nthreads; ++i) { if (0 == tcs[i].stat) - pthread_join (tcs[i].thread, NULL); + assert(pthread_join (tcs[i].thread, NULL) == 0); } /* destroy locks */ - pthread_mutex_destroy (&mutex_stdout); - pthread_mutex_destroy (&mutex_todo); + assert(pthread_mutex_destroy (&mutex_stdout) == 0); + assert(pthread_mutex_destroy (&mutex_todo) == 0); /* Cleanup */ @@ -334,10 +285,11 @@ main (int argc, char *argv[]) printf ("%10ld\n", tcs[i].work); else printf ("failed %d\n", tcs[i].stat); - pthread_mutex_destroy (&tcs[i].mutex_start); - pthread_mutex_destroy (&tcs[i].mutex_started); - pthread_mutex_destroy (&tcs[i].mutex_end); - pthread_mutex_destroy (&tcs[i].mutex_ended); + + assert(pthread_mutex_destroy (&tcs[i].mutex_start) == 0); + assert(pthread_mutex_destroy (&tcs[i].mutex_started) == 0); + assert(pthread_mutex_destroy (&tcs[i].mutex_end) == 0); + assert(pthread_mutex_destroy (&tcs[i].mutex_ended) == 0); } die (0); diff --git a/tests/join1.c b/tests/join1.c new file mode 100644 index 0000000..f6240de --- /dev/null +++ b/tests/join1.c @@ -0,0 +1,41 @@ +/* + * Test for pthread_join(). + * + * Depends on API functions: pthread_create(), pthread_exit(). + */ + +#include "test.h" + +void * +func(void * arg) +{ + Sleep(1000); + + pthread_exit(arg); + + /* Never reached. */ + exit(1); +} + +int +main(int argc, char * argv[]) +{ + pthread_t id[4]; + int i; + int result; + + /* Create a few threads and then exit. */ + for (i = 0; i < 4; i++) + { + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } + + for (i = 0; i < 4; i++) + { + assert(pthread_join(id[i], (void *) &result) == 0); + assert(result == i); + } + + /* Success. */ + return 0; +} diff --git a/tests/mutex1.c b/tests/mutex1.c index f1c9240..60bb4e7 100644 --- a/tests/mutex1.c +++ b/tests/mutex1.c @@ -3,29 +3,28 @@ * * Create a simple mutex object, lock it, and then unlock it again. * This is the simplest test of the pthread mutex family that we can do. + * + * Depends on API functions: + * pthread_mutex_init() + * pthread_mutex_lock() + * pthread_mutex_unlock() + * pthread_mutex_destroy() */ -#include +#include "test.h" pthread_mutex_t mutex1; int main() { - if (pthread_mutex_init(&mutex1, NULL) != 0) - { - return 1; - } + assert(pthread_mutex_init(&mutex1, NULL) == 0); + + assert(pthread_mutex_lock(&mutex1) == 0); - if (pthread_mutex_lock(&mutex1) != 0) - { - return 1; - } + assert(pthread_mutex_unlock(&mutex1) == 0); - if (pthread_mutex_unlock(&mutex1) != 0) - { - return 1; - } + assert(pthread_mutex_destroy(&mutex1) == 0); return 0; } diff --git a/tests/mutex2.c b/tests/mutex2.c index cfbebdc..7956f14 100644 --- a/tests/mutex2.c +++ b/tests/mutex2.c @@ -1,29 +1,24 @@ /* - * mutex1.c + * mutex2.c * - * Declare a static mutex object, lock it, and then unlock it again. + * Declare a static mutex object, lock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_unlock() */ -#include #include "test.h" -pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +int main() { - int result; - - result = pthread_mutex_trylock(&mutex1); - printf("pthread_mutex_trylock returned %s\n", error_string[result]); - if (result != 0) - { - return 1; - } + assert(pthread_mutex_lock(&mutex) == 0); - if (pthread_mutex_unlock(&mutex1) != 0) - { - return 1; - } + assert(pthread_mutex_unlock(&mutex) == 0); return 0; } diff --git a/tests/mutex3.c b/tests/mutex3.c index 2bb6106..26cb070 100644 --- a/tests/mutex3.c +++ b/tests/mutex3.c @@ -1,12 +1,44 @@ -#include +/* + * mutex3.c + * + * Declare a static mutex object, lock it, trylock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#include "test.h" + +pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_mutex_trylock(&mutex1) == EBUSY); + + washere = 1; + + return 0; +} + int main() { - pthread_mutex_lock(&mutex); - /* do stuff */ - pthread_mutex_unlock(&mutex); + pthread_t t; + + assert(pthread_mutex_lock(&mutex1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_mutex_unlock(&mutex1) == 0); + + assert(washere == 1); + return 0; } diff --git a/tests/once1.c b/tests/once1.c index 661d322..91dc038 100644 --- a/tests/once1.c +++ b/tests/once1.c @@ -1,25 +1,29 @@ /* - * Test for pthread_once(). + * once1.c * - * Depends on functions: pthread_create. + * Create a static pthread_once and test that it calls myfunc once. + * + * Depends on API functions: + * pthread_once() + * pthread_create() */ -#include -#include +#include "test.h" pthread_once_t once = PTHREAD_ONCE_INIT; +static int washere = 0; + void myfunc(void) { - printf("only see this once\n"); + washere++; } void * mythread(void * arg) { - int rc = pthread_once(&once, myfunc); - printf("returned %d\n", rc); + assert(pthread_once(&once, myfunc) == 0); return 0; } @@ -27,19 +31,15 @@ mythread(void * arg) int main() { - int rc; pthread_t t1, t2; - if (pthread_create(&t1, NULL, mythread, NULL) != 0) - { - return 1; - } + assert(pthread_create(&t1, NULL, mythread, NULL) == 0); - if (pthread_create(&t2, NULL, mythread, NULL) != 0) - { - return 1; - } + assert(pthread_create(&t2, NULL, mythread, NULL) == 0); Sleep(2000); + + assert(washere == 1); + return 0; } diff --git a/tests/self1.c b/tests/self1.c index 0addfc8..d460818 100644 --- a/tests/self1.c +++ b/tests/self1.c @@ -1,21 +1,26 @@ /* + * self1.c + * * Test for pthread_self(). * - * Depends on API functions: None. + * Depends on API functions: + * pthread_self() + * + * Implicitly depends on: + * pthread_getspecific() + * pthread_setspecific() */ -#include +#include "test.h" int main(int argc, char * argv[]) { - pthread_t id; - - /* We can't do anything with this, though, because it is not - safe to assume anything about the internal structure of - a `pthread_t'. */ - - id = pthread_self(); + /* + * This should always succeed unless the system has no + * resources (memory) left. + */ + assert(pthread_self() != NULL); return 0; } diff --git a/tests/self2.c b/tests/self2.c index 461e5f9..83339f1 100644 --- a/tests/self2.c +++ b/tests/self2.c @@ -1,33 +1,46 @@ -#include -#include -#include +/* + * self2.c + * + * Test for pthread_self(). + * + * Depends on API functions: + * pthread_create() + * pthread_self() + * + * Implicitly depends on: + * pthread_getspecific() + * pthread_setspecific() + */ + +#include "test.h" +#include + +static pthread_t me; void * entry(void * arg) { - /* Like systems such as HP-UX, we can't print the value of the thread ID - because it's not an integral type. Instead, we'll poke our noses into - the pthread_t structure and dump a useful internal value. This is - ordinarily bad, m'kay? */ + me = pthread_self(); - pthread_t t = pthread_self(); - printf("my thread is %lx\n", t->threadH); return arg; } int main() { - int rc; pthread_t t; - if (pthread_create(&t, NULL, entry, NULL) != 0) - { - return 1; - } + assert(pthread_create(&t, NULL, entry, NULL) == 0); Sleep(2000); + /* + * Not much more we can do here but bytewise compare t with + * what pthread_self returned. + */ + assert(t == me); + assert(memcmp((const void *) t, (const void *) me, sizeof t) == 0); + /* Success. */ return 0; } diff --git a/tests/self3.c b/tests/self3.c deleted file mode 100644 index dc220b7..0000000 --- a/tests/self3.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include - -void * -entry(void * arg) -{ - /* Like systems such as HP-UX, we can't print the value of the thread ID - because it's not an integral type. Instead, we'll poke our noses into - the pthread_t structure and dump a useful internal value. This is - ordinarily bad, m'kay? */ - - pthread_t t = pthread_self(); - printf("thread no. %d has id %lx\n", (int) arg, t->threadH); - return 0; -} - -int -main() -{ - int rc; - pthread_t t[2]; - - rc = pthread_create(&t[0], NULL, entry, (void *) 1); - assert(rc == 0); - - rc = pthread_create(&t[1], NULL, entry, (void *) 2); - assert(rc == 0); - - Sleep(2000); - return 0; -} diff --git a/tests/tsd1.c b/tests/tsd1.c index 8137a64..93403b1 100644 --- a/tests/tsd1.c +++ b/tests/tsd1.c @@ -1,8 +1,7 @@ /* - * File: tsd1.c + * tsd1.c * - * Test Synopsis: - * - Thread Specific Data (TSD) key creation and destruction. + * Test Thread Specific Data (TSD) key creation and destruction. * * Description: * - @@ -44,74 +43,53 @@ * - output identifies failed component */ -#include -#include +#include "test.h" -pthread_key_t key = NULL; -pthread_once_t key_once = PTHREAD_ONCE_INIT; +static pthread_key_t key = NULL; +static int accesscount[10]; +static int thread_set[10]; +static int thread_destroyed[10]; -void +static void destroy_key(void * arg) { - /* arg is not NULL if we get to here. */ - printf("SUCCESS: %s: destroying key.\n", (char *) arg); + int * j = (int *) arg; - free((char *) arg); -} + (*j)++; -void -make_key(void) -{ - if (pthread_key_create(&key, destroy_key) != 0) - { - printf("Key create failed\n"); - exit(1); - } + assert(*j == 2); + + thread_destroyed[j - accesscount] = 1; } -void +static void setkey(void * arg) { - void * ptr; + int * j = (int *) arg; - if ((ptr = pthread_getspecific(key)) != NULL) - { - printf("ERROR: Thread %d, Key not initialised to NULL\n", - (int) arg); - exit(1); - } - else - { - ptr = (void *) malloc(80); - sprintf((char *) ptr, "Thread %d Key", - (int) arg); - (void) pthread_setspecific(key, ptr); - } + thread_set[j - accesscount] = 1; - if ((ptr = pthread_getspecific(key)) == NULL) - { - printf("FAILED: Thread %d Key value set or get failed.\n", - (int) arg); - exit(1); - } - else - { - printf("SUCCESS: Thread %d Key value set and get succeeded.\n", - (int) arg); + assert(*j == 0); - printf("SUCCESS: %s: exiting thread.\n", (char *) ptr); - } + assert(pthread_getspecific(key) == NULL); + + assert(pthread_setspecific(key, arg) == 0); + + assert(pthread_getspecific(key) == arg); + + (*j)++; + + assert(*j == 1); } -void * +static void * mythread(void * arg) { while (key == NULL) { + Sleep(0); } - printf("Thread %d, Key created\n", (int) arg); - setkey(arg); return 0; @@ -122,38 +100,70 @@ mythread(void * arg) int main() { - int rc; - int t; + int i; + int fail = 0; pthread_t thread[10]; - for (t = 0; t < 5; t++) + for (i = 1; i < 5; i++) + { + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); + } + + Sleep(2000); + + /* + * Here we test that existing threads will get a key created + * for them. + */ + assert(pthread_key_create(&key, destroy_key) == 0); + + /* + * Test main thread key. + */ + accesscount[0] = 0; + setkey((void *) &accesscount[0]); + + /* + * Here we test that new threads will get a key created + * for them. + */ + for (i = 5; i < 10; i++) { - rc = pthread_create(&thread[t], NULL, mythread, (void *) (t + 1)); - printf("pthread_create returned %d\n", rc); - if (rc != 0) - { - return 1; - } + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); } - (void) pthread_once(&key_once, make_key); + /* + * Wait for all threads to complete. + */ + for (i = 1; i < 10; i++) + { + int result = 0; - /* Test main thread key. */ - setkey((void *) 0); + assert(pthread_join(thread[i], (void *) &result) == 0); + } - Sleep(500); + assert(pthread_key_delete(key) == 0); - for (t = 5; t < 10; t++) + for (i = 0; i < 10; i++) { - rc = pthread_create(&thread[t], NULL, mythread, (void *) (t + 1)); - printf("pthread_create returned %d\n", rc); - if (rc != 0) - { - return 1; - } + /* + * The counter is incremented once when the key is set to + * a value, and again when the key is destroyed. If the key + * doesn't get set for some reason then it will still be + * NULL and the destroy function will not be called, and + * hence accesscount will not equal 2. + */ + if (accesscount[i] != 2) + { + fail++; + fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n", + i, thread_set[i], thread_destroyed[i]); + } } - Sleep(2000); - return 0; -} + fflush(stderr); + return (fail) ? 1 : 0; +} -- cgit v1.2.3