summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpj <rpj>1999-03-18 16:18:39 +0000
committerrpj <rpj>1999-03-18 16:18:39 +0000
commit907de7f11ebcac02b705b421c3a4480cac9deaaf (patch)
tree5db3a96522f91a7ab9e38b10c89c370c7cb9e4b1
parent6f37434d05b3598c132702d1a5c92a04927dfa58 (diff)
==> ChangeLog <==
Fri Mar 19 09:12:59 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * private.c (_pthread_threadStart): status returns PTHREAD_CANCELED. * pthread.h (PTHREAD_CANCELED): defined. ==> tests/ChangeLog <== Fri Mar 19 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * *.bat: redirect unwanted output to nul: * runall.bat: new. * cancel1.c: new. Not part of suite yet.
-rw-r--r--ANNOUNCE2
-rw-r--r--ChangeLog6
-rw-r--r--MAINTAINERS1
-rw-r--r--private.c24
-rw-r--r--pthread.h10
-rw-r--r--tests/ChangeLog8
-rw-r--r--tests/cancel1.c273
-rw-r--r--tests/ccl.bat2
-rw-r--r--tests/runall.bat21
-rw-r--r--tests/runtest.bat43
10 files changed, 361 insertions, 29 deletions
diff --git a/ANNOUNCE b/ANNOUNCE
index 275a8ce..00987c4 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -130,7 +130,7 @@ The following functions are implemented:
Static Initializers (macros)
---------------------------
PTHREAD_ONCE_INIT
- PTHREAD_MUTEXINITIALIZER
+ PTHREAD_MUTEX_INITIALIZER
PTHREAD_COND_INITIALIZER
---------------------------
diff --git a/ChangeLog b/ChangeLog
index 8df6928..9bf3ccc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Fri Mar 19 09:12:59 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * private.c (_pthread_threadStart): status returns PTHREAD_CANCELED.
+
+ * pthread.h (PTHREAD_CANCELED): defined.
+
Tue Mar 16 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* all: Add GNU LGPL and Copyright and Warranty.
diff --git a/MAINTAINERS b/MAINTAINERS
index 99e35cd..43d3142 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10,4 +10,5 @@ Contributors (in order of appearance)
Robert Colquhoun rjc@trump.net.au
John E. Bossom John.Bossom@cognos.com
Anders Norlander anorland@hem2.passagen.se
+Tor Lillqvist tml@iki.fi
Kevin Ruland Kevin.Ruland@anheuser-busch.com
diff --git a/private.c b/private.c
index a4cdcda..9ffd1b3 100644
--- a/private.c
+++ b/private.c
@@ -147,7 +147,7 @@ _pthread_threadStart (ThreadParms * threadParms)
void *(*start) (void *);
void *arg;
- int status;
+ void * status;
tid = threadParms->tid;
start = threadParms->start;
@@ -165,7 +165,7 @@ _pthread_threadStart (ThreadParms * threadParms)
* Run the caller's routine;
*/
(*start) (arg);
- status = 0;
+ status = (void *) 0;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
@@ -173,7 +173,7 @@ _pthread_threadStart (ThreadParms * threadParms)
* A system unexpected exception had occurred running the user's
* routine. We get control back within this block.
*/
- status = -1;
+ status = PTHREAD_CANCELED;
}
#else /* _MSC_VER */
@@ -186,14 +186,14 @@ _pthread_threadStart (ThreadParms * threadParms)
* Run the caller's routine;
*/
(*start) (arg);
- status = 0;
+ status = (void *) 0;
}
catch (Pthread_exception)
{
/*
* Thread was cancelled.
*/
- status = -1;
+ status = PTHREAD_CANCELED;
}
catch (...)
{
@@ -201,24 +201,28 @@ _pthread_threadStart (ThreadParms * threadParms)
* A system unexpected exception had occurred running the user's
* routine. We get control back within this block.
*/
- status = -1;
+ status = PTHREAD_CANCELED;
}
#else /* __cplusplus */
/*
- * Run the caller's routine;
+ * Run the caller's routine; no cancelation or other exceptions will
+ * be honoured.
*/
(*start) (arg);
- status = 0;
+ status = (void *) 0;
#endif /* __cplusplus */
#endif /* _WIN32 */
- pthread_exit ((void *) status);
+ pthread_exit (status);
- return ((void *) status);
+ /*
+ * Never reached.
+ */
+ return (status);
} /* threadStart */
diff --git a/pthread.h b/pthread.h
index 9deff4d..bc11d1b 100644
--- a/pthread.h
+++ b/pthread.h
@@ -477,6 +477,16 @@ extern "C"
/*
* ====================
* ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/*
+ * ====================
+ * ====================
* Once Key
* ====================
* ====================
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 16af11f..7354fba 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+Fri Mar 19 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * *.bat: redirect unwanted output to nul:
+
+ * runall.bat: new.
+
+ * cancel1.c: new. Not part of suite yet.
+
Mon Mar 15 00:17:55 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* mutex1.c: only test mutex init and destroy; add assertions.
diff --git a/tests/cancel1.c b/tests/cancel1.c
new file mode 100644
index 0000000..189fc64
--- /dev/null
+++ b/tests/cancel1.c
@@ -0,0 +1,273 @@
+/********************************************************
+ * An example source module to accompany...
+ *
+ * "Using POSIX Threads: Programming with Pthreads"
+ * by Brad nichols, Dick Buttlar, Jackie Farrell
+ * O'Reilly & Associates, Inc.
+ *
+ ********************************************************
+ * cancel.c --
+ *
+ * Demonstrates pthread cancellation.
+ *
+ */
+
+#include <stdio.h>
+#include "pthread.h"
+
+#define NUM_THREADS 3
+#define MESSAGE_MAX_LEN 80
+
+int count=NUM_THREADS; /* number of threads active */
+pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER; /* mutual exclusion
+ for count */
+pthread_cond_t init_done=PTHREAD_COND_INITIALIZER; /* signaled by
+ each thread after
+ completing initial-
+ ization */
+int id_arg[3] = {0,1,2};
+
+/*
+ * Cleanup routine: last_breath()
+ */
+void last_breath(char *messagep)
+{
+ printf("\n\n%s last_breath() cleanup routine: free'ing 0x%x\n\n",
+ messagep, messagep);
+
+ free(messagep);
+}
+
+/*
+ * print_count()
+ */
+void print_count(char *messagep, int id, int i)
+{
+ int last_type,tmp_type;
+
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type);
+ switch(id) {
+ case 0:
+ printf("%s %4d\n", messagep, i);
+ break;
+ case 1:
+ printf("%s \t%4d\n", messagep, i);
+ break;
+ case 2:
+ printf("%s \t\t%4d\n", messagep, i);
+ break;
+ }
+ pthread_setcanceltype(last_type, &tmp_type);
+}
+
+/*
+ * bullet_proof()
+ */
+void *bullet_proof(void *id_p)
+{
+ int i=0, last_state;
+ int *my_id = id_p;
+ char *messagep;
+
+
+ messagep = (char *)malloc(MESSAGE_MAX_LEN);
+ sprintf(messagep, "Bullet Proof, thread #%d: ", *my_id);
+
+ printf("%s\tI'm Alive, setting general cancellation OFF\n",
+ messagep);
+
+ /* push last_breath() routine onto stack */
+ pthread_cleanup_push( (void *)last_breath, (void *)messagep );
+
+ /* We turn off general cancelability here ... */
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &last_state);
+
+ pthread_mutex_lock(&lock);
+ {
+ printf("\n%s signaling main that my init is done\n", messagep);
+ count -= 1;
+ /* signal to program that entering loop */
+ pthread_cond_signal(&init_done);
+ pthread_mutex_unlock(&lock);
+ }
+
+ /* loop forever until picked off with a cancel */
+ for(;;i++) {
+ if (i%1000 == 0)
+ print_count(messagep, *my_id, i);
+ if (i%100000 == 0) {
+ printf("\n%s This is the thread that never ends... #%d\n",
+ messagep, i);
+ }
+ }
+
+ /* Never get this far */
+
+ /* This pop is required by the standard, every push must have a pop
+ in the same lexical block. */
+ pthread_cleanup_pop(0);
+
+ return(NULL);
+}
+
+/*
+ * ask_for_it()
+ */
+void *ask_for_it(void *id_p)
+{
+ int i=0, last_state, last_type;
+ int *my_id = id_p;
+ char *messagep;
+
+
+ messagep = (char *)malloc(MESSAGE_MAX_LEN);
+ sprintf(messagep, "Ask For It, thread #%d: ", *my_id);
+
+ /* push last_breath() routine onto stack */
+ pthread_cleanup_push( (void *)last_breath, (void *)messagep);
+
+ /* We can turn on general cancelability here. Disable async cancellation */
+ printf("%s\tI'm Alive, setting deferred cancellation ON\n",
+ messagep);
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
+
+ pthread_mutex_lock(&lock);
+ {
+ printf("\n%s signaling main that my init is done\n", messagep);
+ count -= 1;
+ /* signal to program that entering loop */
+ pthread_cond_signal(&init_done);
+ pthread_mutex_unlock(&lock);
+ }
+
+ /* loop forever until picked off with a cancel */
+ for(;;i++) {
+ if (i%1000 == 0)
+ print_count(messagep, *my_id, i);
+ if (i%10000 == 0) {
+ printf("\n%s\tLook, I'll tell you when you can cancel me.\n",messagep,i);
+ }
+ pthread_testcancel();
+ }
+
+ /* never get this far */
+
+ /* This pop is required by the standard, every push must have a pop
+ in the same lexical block. */
+ pthread_cleanup_pop(0);
+
+ return(NULL);
+}
+
+/*
+ * sitting_duck()
+ */
+void *sitting_duck(void *id_p)
+{
+ int i=0, last_state, last_type, last_tmp;
+ int *my_id = id_p;
+ char *messagep;
+
+
+ messagep = (char *)malloc(MESSAGE_MAX_LEN);
+ sprintf(messagep, "Sitting Duck, thread #%d: ", *my_id);
+
+ /* push last_breath() routine onto stack */
+ pthread_cleanup_push( (void *)last_breath, (void *)messagep);
+
+ pthread_mutex_lock(&lock);
+ {
+ printf("\n%s signaling main that my init is done\n", messagep);
+ count -= 1;
+ /* signal to program that entering loop */
+ pthread_cond_signal(&init_done);
+ pthread_mutex_unlock(&lock);
+ }
+
+ /* Now, we're safe to turn on async cancellability */
+ printf("%s\tI'm Alive, setting async cancellation ON\n",
+ messagep);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
+
+ /* loop forever until picked off with a cancel */
+ for(;;i++) {
+ if (i%1000 == 0)
+ print_count(messagep, *my_id, i++);
+ if (i%10000 == 0) {
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_tmp);
+ printf("\n%s\tHum, nobody here but us chickens. %d\n", messagep,i);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_tmp);
+ }
+ }
+
+ /* never get this far */
+
+ /* This pop is required by the standard, every push must have a pop
+ in the same lexical block. */
+ pthread_cleanup_pop(0);
+
+ return(NULL);
+}
+
+extern int
+main(void)
+{
+ int i;
+ void * statusp;
+ pthread_t threads[NUM_THREADS];
+
+
+ /* spawn the threads */
+ pthread_create(&(threads[0]),
+ NULL,
+ ask_for_it,
+ (void *) &(id_arg[0]));
+
+ pthread_create(&(threads[1]),
+ NULL,
+ sitting_duck,
+ (void *) &(id_arg[1]));
+
+ pthread_create(&(threads[2]),
+ NULL,
+ bullet_proof,
+ (void *) &(id_arg[2]));
+
+ printf("main(): %d threads created\n", NUM_THREADS);
+
+ pthread_mutex_lock(&lock);
+
+ /* wait until all threads have entered loops */
+ while (count != 0) {
+ pthread_cond_wait(&init_done, &lock);
+ }
+
+ pthread_mutex_unlock(&lock);
+
+ printf("main(): all threads have signaled that ready\n");
+
+ /* cancel each thread */
+ for (i=0; i<NUM_THREADS; i++) {
+ pthread_cancel(threads[i]);
+ }
+
+ /* wait until all threads have finished */
+ for (i=0; i<NUM_THREADS; i++) {
+ pthread_join(threads[i], &statusp);
+ if (statusp == PTHREAD_CANCELED) {
+ printf("main(): joined to thread %d, statusp=PTHREAD_CANCELED\n",i);
+ } else {
+ printf("main(): joined to thread %d\n",i);
+ }
+ }
+
+ printf("main()\t\tall %d threads have finished. \n", NUM_THREADS);
+
+ return 0;
+}
+
+
+
+
diff --git a/tests/ccl.bat b/tests/ccl.bat
index 1f45e33..9dc72d9 100644
--- a/tests/ccl.bat
+++ b/tests/ccl.bat
@@ -1,3 +1,3 @@
cl /W3 /MT /nologo /Yd /Zi -I. -D_WIN32_WINNT=0x400 -DSTDCALL=_stdcall -c ..\%1.c
cl /Feaout.exe /Zi %1.obj .\pthread.lib
-del %1.obj
+del %1.obj > nul:
diff --git a/tests/runall.bat b/tests/runall.bat
new file mode 100644
index 0000000..21bbbbe
--- /dev/null
+++ b/tests/runall.bat
@@ -0,0 +1,21 @@
+erase *.result
+
+call runtest cl mutex1
+call runtest cl mutex2
+call runtest cl exit1
+call runtest cl condvar1
+call runtest cl self1
+call runtest cl condvar2
+call runtest cl create1
+call runtest cl mutex3
+call runtest cl equal1
+call runtest cl exit2
+call runtest cl exit3
+call runtest cl join1
+call runtest cl count1
+call runtest cl once1
+call runtest cl tsd1
+call runtest cl self2
+call runtest cl eyal1
+call runtest cl condvar3
+call runtest cl condvar4
diff --git a/tests/runtest.bat b/tests/runtest.bat
index c9106a2..03a9413 100644
--- a/tests/runtest.bat
+++ b/tests/runtest.bat
@@ -1,30 +1,39 @@
@echo off
+
+REM Usage: runtest cl|gcc testname testarg ...
+
+echo y | erase /s tmp > nul:
+rmdir tmp
+mkdir tmp
cd tmp
REM Make sure we start with only those files we expect to need
-if exist pthread.dll erase pthread.dll
-if exist pthread.h erase pthread.h
-if exist pthread.lib erase pthread.lib
-if exist libpthread32.a erase libpthread32.a
-copy ..\..\pthread.dll .
-copy ..\..\pthread.h .
-copy ..\..\pthread.lib .
-copy ..\..\libpthread32.a .
+if exist pthread.dll erase pthread.dll > nul:
+if exist pthread.h erase pthread.h > nul:
+if exist test.h erase test.h > nul:
+if exist pthread.lib erase pthread.lib > nul:
+if exist libpthread32.a erase libpthread32.a > nul:
+copy ..\..\pthread.dll . > nul:
+copy ..\..\pthread.h . > nul:
+copy ..\test.h . > nul:
+copy ..\..\pthread.lib . > nul:
+copy ..\..\libpthread32.a . > nul:
REM Compile the test case
REM produces aout.exe using the compiler given as %1
-call ..\c%1.bat %2
+call ..\c%1.bat %2 > nul:
-echo TEST: %2 [%1] > results.txt
+echo TEST: %2 [%1] > ..\%2.result
REM Run the test case
-aout.exe %3 %4 %5 %6 %7 %8 %9 >> results.txt
+aout.exe %3 %4 %5 %6 %7 %8 %9 >> ..\%2.result
REM Clean up
-erase aout.exe
-if exist pthread.dll erase pthread.dll
-if exist pthread.h erase pthread.h
-if exist pthread.lib erase pthread.lib
-if exist libpthread32.a erase libpthread32.a
+erase aout.exe > nul:
+if exist pthread.dll erase pthread.dll > nul:
+if exist pthread.h erase pthread.h > nul:
+if exist pthread.lib erase pthread.lib > nul:
+if exist libpthread32.a erase libpthread32.a > nul:
cd ..
-more < tmp\results.txt
+more < %2.result
+