summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpj <rpj>1999-10-30 09:17:28 +0000
committerrpj <rpj>1999-10-30 09:17:28 +0000
commit588b7f6616834651ea4062cf440e57a8a0cba25f (patch)
tree52851833a18a06ffadcca2e1c9dac08e9ec30d9a
parent9d592dbd51949858e2e787d16476420f10d2c9a5 (diff)
./ChangeLog:
1999-10-30 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * create.c (pthread_create): Explicitly initialise thread state to default values. * cancel.c (pthread_setcancelstate): Check for NULL 'oldstate' for compatibility with Solaris pthreads; (pthread_setcanceltype): ditto: - Erik Hensema <erik.hensema@group2000.nl> 1999-10-23 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * pthread.h (ctime_r): Fix incorrect argument "_tm" - Erik Hensema <erik.hensema@group2000.nl> tests/ChangeLog: 1999-10-30 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * cancel1.c: New. Test pthread_setcancelstate and pthread_setcanceltype functions. * eyal1.c (waste_time): Change calculation to avoid FP exception on Aplhas - Rich Peters <rpeters@micro-magic.com>
-rw-r--r--ANNOUNCE15
-rw-r--r--ChangeLog15
-rw-r--r--cancel.c22
-rw-r--r--create.c8
-rw-r--r--tests/ChangeLog8
-rw-r--r--tests/Makefile2
-rw-r--r--tests/cancel1.c354
-rw-r--r--tests/eyal1.c2
-rw-r--r--tests/runall.bat1
-rw-r--r--tests/runtest.bat4
10 files changed, 183 insertions, 248 deletions
diff --git a/ANNOUNCE b/ANNOUNCE
index 18373a5..84f8926 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
- PTHREADS-WIN32 SNAPSHOT 1999-10-17
+ PTHREADS-WIN32 SNAPSHOT 1999-??-??
----------------------------------
Web Site: http://sourceware.cygnus.com/pthreads-win32/
FTP Site: ftp://sourceware.cygnus.com/pub/pthreads-win32
@@ -24,8 +24,17 @@ Change Summary (since the last snapshot)
(See the ChangeLog file for details.)
-Bug fix - Cancelation of threads waiting on condition variables
-now works properly (Lorin Hochstein and Peter Slacik)
+Bugs fixed:
+- ctime_r had incorrect argument (Erik Hensema),
+- threads were being created with incorrect type
+ PTHREAD_CANCEL_ASYNCHRONOUS (Ross Johnson).
+
+Some compatibility improvements added, eg.
+- pthread_setcancelstate accepts NULL pointer
+ for the previous value argument. Ditto for
+ pthread_setcanceltype. This is compatible
+ with Solaris but should not affect
+ standard applications (Erik Hensema)
Level of standards conformance
diff --git a/ChangeLog b/ChangeLog
index 9c4b413..5e20044 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+1999-10-30 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * create.c (pthread_create): Explicitly initialise thread state to
+ default values.
+
+ * cancel.c (pthread_setcancelstate): Check for NULL 'oldstate'
+ for compatibility with Solaris pthreads;
+ (pthread_setcanceltype): ditto:
+ - Erik Hensema <erik.hensema@group2000.nl>
+
+1999-10-23 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * pthread.h (ctime_r): Fix incorrect argument "_tm"
+ - Erik Hensema <erik.hensema@group2000.nl>
+
1999-10-21 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* pthread.h (_POSIX_THREADS): Only define it if it isn't
diff --git a/cancel.c b/cancel.c
index c3711e2..a5d923d 100644
--- a/cancel.c
+++ b/cancel.c
@@ -50,12 +50,16 @@ pthread_setcancelstate (int state, int *oldstate)
* This function atomically sets the calling thread's
* cancelability state to 'state' and returns the previous
* cancelability state at the location referenced by
- * 'oldstate'
+ * 'oldstate'.
*
* NOTES:
* 1) Use to disable cancellation around 'atomic' code that
* includes cancellation points
*
+ * COMPATIBILITY ADDITIONS
+ * If 'oldstate' is NULL then the previous state is not returned
+ * but the function still succeeds. (Solaris)
+ *
* RESULTS
* 0 successfully set cancelability type,
* EINVAL 'state' is invalid
@@ -71,7 +75,11 @@ pthread_setcancelstate (int state, int *oldstate)
state == PTHREAD_CANCEL_DISABLE))
{
- *oldstate = self->cancelState;
+ if (oldstate != NULL)
+ {
+ *oldstate = self->cancelState;
+ }
+
self->cancelState = state;
result = 0;
@@ -116,6 +124,10 @@ pthread_setcanceltype (int type, int *oldtype)
* 1) Use with caution; most code is not safe for use
* with asynchronous cancelability.
*
+ * COMPATIBILITY ADDITIONS
+ * If 'oldtype' is NULL then the previous type is not returned
+ * but the function still succeeds. (Solaris)
+ *
* RESULTS
* 0 successfully set cancelability type,
* EINVAL 'type' is invalid
@@ -131,7 +143,11 @@ pthread_setcanceltype (int type, int *oldtype)
type == PTHREAD_CANCEL_ASYNCHRONOUS))
{
- *oldtype = self->cancelType;
+ if (oldtype != NULL)
+ {
+ *oldtype = self->cancelType;
+ }
+
self->cancelType = type;
result = 0;
diff --git a/create.c b/create.c
index 426ad9a..0575643 100644
--- a/create.c
+++ b/create.c
@@ -78,6 +78,14 @@ pthread_create (pthread_t * tid,
{
goto FAIL0;
}
+
+ /*
+ * Setup standard default state.
+ */
+ thread->detachState = PTHREAD_CREATE_JOINABLE;
+ thread->cancelState = PTHREAD_CANCEL_ENABLE;
+ thread->cancelType = PTHREAD_CANCEL_DEFERRED;
+
thread->cancelEvent =
CreateEvent (
0,
diff --git a/tests/ChangeLog b/tests/ChangeLog
index ee69577..5e8fca9 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+1999-10-30 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * cancel1.c: New. Test pthread_setcancelstate and
+ pthread_setcanceltype functions.
+ * eyal1.c (waste_time): Change calculation to avoid FP exception
+ on Aplhas
+ - Rich Peters <rpeters@micro-magic.com>
+
Oct 14 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* condvar7.c: New. Test broadcast after waiting thread is canceled.
diff --git a/tests/Makefile b/tests/Makefile
index 0263769..7056d2b 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -39,7 +39,7 @@ COPYFILES = $(HDR) $(LIB) $(DLL)
TESTS = mutex1 condvar1 condvar2 exit1 create1 equal1 \
exit2 exit3 \
join1 join2 mutex2 mutex3 \
- count1 once1 tsd1 self1 self2 eyal1 \
+ count1 once1 tsd1 self1 self2 cancel1 eyal1 \
condvar3 condvar4 condvar5 condvar6 condvar7 condvar8 \
errno1 \
rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6
diff --git a/tests/cancel1.c b/tests/cancel1.c
index 189fc64..41f393e 100644
--- a/tests/cancel1.c
+++ b/tests/cancel1.c
@@ -1,273 +1,147 @@
-/********************************************************
- * An example source module to accompany...
+/*
+ * File: cancel1.c
+ *
+ * Test Synopsis: Test setting cancel state and cancel type.
+ * -
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * Requirements Tested:
+ * - pthread_setcancelstate function
+ * - pthread_setcanceltype function
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * -
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
*
- * "Using POSIX Threads: Programming with Pthreads"
- * by Brad nichols, Dick Buttlar, Jackie Farrell
- * O'Reilly & Associates, Inc.
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
*
- ********************************************************
- * cancel.c --
+ * Assumptions:
+ * - pthread_create, pthread_self work.
*
- * Demonstrates pthread cancellation.
+ * Pass Criteria:
+ * - Process returns zero exit status.
*
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
*/
-#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};
+#include "test.h"
/*
- * Cleanup routine: last_breath()
+ * Create NUMTHREADS threads in addition to the Main thread.
*/
-void last_breath(char *messagep)
-{
- printf("\n\n%s last_breath() cleanup routine: free'ing 0x%x\n\n",
- messagep, messagep);
+enum {
+ NUMTHREADS = 2
+};
- free(messagep);
-}
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+ int threadnum;
+ int started;
+ /* Add more per-thread state variables here */
+};
-/*
- * 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);
-}
+static bag_t threadbag[NUMTHREADS + 1];
-/*
- * bullet_proof()
- */
-void *bullet_proof(void *id_p)
+void *
+mythread(void * arg)
{
- int i=0, last_state;
- int *my_id = id_p;
- char *messagep;
-
+ bag_t * bag = (bag_t *) arg;
- messagep = (char *)malloc(MESSAGE_MAX_LEN);
- sprintf(messagep, "Bullet Proof, thread #%d: ", *my_id);
+ assert(bag == &threadbag[bag->threadnum]);
+ assert(bag->started == 0);
+ bag->started = 1;
- 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);
+ int oldstate;
+ int oldtype;
+
+ assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) == 0);
+ assert(oldstate == PTHREAD_CANCEL_ENABLE); /* Check default */
+ assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+ assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) == 0);
+ assert(pthread_setcancelstate(oldstate, &oldstate) == 0);
+ assert(oldstate == PTHREAD_CANCEL_DISABLE); /* Check setting */
+
+ assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype) == 0);
+ assert(oldtype == PTHREAD_CANCEL_DEFERRED); /* Check default */
+ assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0);
+ assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+ assert(pthread_setcanceltype(oldtype, &oldtype) == 0);
+ assert(oldtype == PTHREAD_CANCEL_ASYNCHRONOUS); /* Check setting */
}
- /* 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);
+ return 0;
}
-/*
- * ask_for_it()
- */
-void *ask_for_it(void *id_p)
+int
+main()
{
- int i=0, last_state, last_type;
- int *my_id = id_p;
- char *messagep;
-
+ int failed = 0;
+ int i;
+ pthread_t t[NUMTHREADS + 1];
- 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);
- }
+ assert((t[0] = pthread_self()) != NULL);
- /* 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);
+ for (i = 1; i <= NUMTHREADS; i++)
+ {
+ threadbag[i].started = 0;
+ threadbag[i].threadnum = i;
+ assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
}
- 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);
+ /*
+ * Code to control or munipulate child threads should probably go here.
+ */
+
+ /*
+ * Give threads time to run.
+ */
+ Sleep(NUMTHREADS * 1000);
+
+ /*
+ * Standard check that all threads started.
+ */
+ for (i = 1; i <= NUMTHREADS; i++)
+ {
+ failed = !threadbag[i].started;
+
+ if (failed)
+ {
+ fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+ }
}
- }
-
- /* 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);
+ assert(!failed);
- 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);
+ /*
+ * Check any results here. Set "failed" and only print ouput on failure.
+ */
+ for (i = 1; i <= NUMTHREADS; i++)
+ {
+ /* ... */
}
- }
- printf("main()\t\tall %d threads have finished. \n", NUM_THREADS);
+ assert(!failed);
+ /*
+ * Success.
+ */
return 0;
}
-
-
-
-
diff --git a/tests/eyal1.c b/tests/eyal1.c
index 533822d..7a2dc37 100644
--- a/tests/eyal1.c
+++ b/tests/eyal1.c
@@ -96,7 +96,7 @@ waste_time (int n)
for (i = n*100; i > 0; --i)
{
- f = sqrt (f) * f + 10000.0;
+ f = 2 * f * f / (f * f);
}
}
diff --git a/tests/runall.bat b/tests/runall.bat
index e3a927b..5c2d783 100644
--- a/tests/runall.bat
+++ b/tests/runall.bat
@@ -23,6 +23,7 @@ call runtest cl count1 join1
call runtest cl once1 create1
call runtest cl tsd1 join1
call runtest cl self2 create1
+call runtest cl cancel1 self2
call runtest cl eyal1 tsd1
call runtest cl condvar3 create1
call runtest cl condvar4 create1
diff --git a/tests/runtest.bat b/tests/runtest.bat
index 73fae97..dc36666 100644
--- a/tests/runtest.bat
+++ b/tests/runtest.bat
@@ -6,8 +6,12 @@ if %3==_ goto noprereq
if NOT EXIST %3.pass goto needprereq
:noprereq
+if EXIST %2.fail goto forcetest
if EXIST %2.pass goto bypass
+:forcetest
+if EXIST %2.fail erase %2.fail
+
REM Make sure we start with only those files we expect to need
if exist tmp\*.* echo y | erase tmp\*.* > nul:
rmdir tmp