From ec8290acdaea21b16d98f1ef5d4ae8a28ab2109a Mon Sep 17 00:00:00 2001
From: rpj <rpj>
Date: Wed, 3 Nov 2004 01:08:41 +0000
Subject: Mutex, semaphore, thread ID, test suite changes - see ChangeLogs

---
 ANNOUNCE                           |    7 +-
 CONTRIBUTORS                       |  232 +-
 ChangeLog                          | 8812 ++++++++++++++++++------------------
 FAQ                                |  806 ++--
 GNUmakefile                        |    4 +-
 Makefile                           |    5 +-
 NEWS                               |   66 +
 PROGRESS                           |    8 +-
 README                             |  923 ++--
 README.NONPORTABLE                 |  570 +--
 TODO                               |   14 +-
 cleanup.c                          |    4 +-
 create.c                           |   52 +-
 dll.c                              |    5 +-
 global.c                           |    3 +-
 implement.h                        |   21 +-
 pthread.h                          |   34 +-
 pthread_cancel.c                   |   40 +-
 pthread_cond_destroy.c             |    1 -
 pthread_cond_wait.c                |   21 +-
 pthread_delay_np.c                 |   21 +-
 pthread_detach.c                   |    5 +-
 pthread_equal.c                    |    2 +-
 pthread_exit.c                     |    8 +-
 pthread_getschedparam.c            |    2 +-
 pthread_getw32threadhandle_np.c    |    2 +-
 pthread_join.c                     |   19 +-
 pthread_kill.c                     |   10 +-
 pthread_mutex_init.c               |    2 +-
 pthread_mutex_unlock.c             |    6 +-
 pthread_self.c                     |   40 +-
 pthread_setcancelstate.c           |   23 +-
 pthread_setcanceltype.c            |   23 +-
 pthread_setschedparam.c            |    9 +-
 pthread_setspecific.c              |   28 +-
 pthread_testcancel.c               |   35 +-
 pthread_win32_attach_detach_np.c   |   46 +-
 ptw32_InterlockedCompareExchange.c |    4 +-
 ptw32_callUserDestroyRoutines.c    |   14 +-
 ptw32_new.c                        |   49 +-
 ptw32_processTerminate.c           |   13 +-
 ptw32_reuse.c                      |   84 +-
 ptw32_semwait.c                    |    2 +-
 ptw32_threadDestroy.c              |   13 +-
 ptw32_threadStart.c                |   65 +-
 ptw32_throw.c                      |    8 +-
 ptw32_tkAssocCreate.c              |    6 +-
 ptw32_tkAssocDestroy.c             |    2 +-
 sem_timedwait.c                    |   21 +-
 sem_wait.c                         |   31 +-
 signal.c                           |    8 +-
 tests/ChangeLog                    | 1581 +++----
 tests/Debug.dsp                    |   93 +
 tests/Debug.dsw                    |   29 +
 tests/Debug.ncb                    |  Bin 0 -> 66535 bytes
 tests/Debug.opt                    |  Bin 0 -> 53741 bytes
 tests/Debug.plg                    |   35 +
 tests/Debug.txt                    |    6 +
 tests/GNUmakefile                  |   10 +-
 tests/Makefile                     |  698 +--
 tests/README                       |   14 +-
 tests/README.benchtests            |  194 +-
 tests/cancel1.c                    |    2 +-
 tests/cancel2.c                    |    2 +-
 tests/cancel3.c                    |    2 +-
 tests/cancel4.c                    |    2 +-
 tests/cancel6a.c                   |    2 +-
 tests/cancel6d.c                   |    7 +-
 tests/cancel7.c                    |    4 +-
 tests/cancel8.c                    |    4 +-
 tests/cleanup0.c                   |    2 +-
 tests/cleanup1.c                   |    3 +-
 tests/cleanup2.c                   |    2 +-
 tests/cleanup3.c                   |    2 +-
 tests/condvar1_2.c                 |    4 +-
 tests/condvar3.c                   |    2 +-
 tests/condvar4.c                   |    2 +-
 tests/condvar5.c                   |    2 +-
 tests/condvar6.c                   |    4 +-
 tests/condvar7.c                   |   21 +-
 tests/condvar8.c                   |    4 +-
 tests/condvar9.c                   |   56 +-
 tests/context1.c                   |    2 +-
 tests/errno1.c                     |    2 +-
 tests/exception1.c                 |    2 +-
 tests/exception2.c                 |    2 +-
 tests/exception3.c                 |    2 +-
 tests/exit5.c                      |    4 +-
 tests/reuse1.c                     |   13 +-
 tests/reuse2.c                     |   71 +-
 tests/self1.c                      |    6 +-
 tests/self2.c                      |    9 +-
 tests/semaphore3.c                 |   21 +-
 tests/semaphore4.c                 |  138 +
 tests/semaphore4t.c                |  132 +
 tests/sizes.c                      |    3 +-
 tests/test.h                       |   12 +
 tests/valid2.c                     |   10 +-
 w32_CancelableWait.c               |   25 +-
 99 files changed, 8095 insertions(+), 7377 deletions(-)
 create mode 100644 tests/Debug.dsp
 create mode 100644 tests/Debug.dsw
 create mode 100644 tests/Debug.ncb
 create mode 100644 tests/Debug.opt
 create mode 100644 tests/Debug.plg
 create mode 100644 tests/Debug.txt
 create mode 100644 tests/semaphore4.c
 create mode 100644 tests/semaphore4t.c

diff --git a/ANNOUNCE b/ANNOUNCE
index 9784535..8528af8 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,4 +1,4 @@
-		 PTHREADS-WIN32 SNAPSHOT 2004-06-22
+		 PTHREADS-WIN32 SNAPSHOT 2004-11-03
 		 ----------------------------------
 	 Web Site: http://sources.redhat.com/pthreads-win32/
 	FTP Site: ftp://sources.redhat.com/pub/pthreads-win32
@@ -22,13 +22,14 @@ General Public License (LGPL).
 
 Acknowledgements
 ----------------
-This library is based substantially on a Win32 pthreads
+This library is based originally on a Win32 pthreads
 implementation contributed by John Bossom <John.Bossom@cognos.com>.
 
 The implementation of Condition Variables uses algorithms developed
 by Alexander Terekhov and Louis Thomas.
 
-The implementation of POSIX mutexes has been improved by Thomas Pfaff.
+The implementation of POSIX mutexes has been improved by Thomas Pfaff
+and later by Alexander Terekhov.
 
 The implementation of Spinlocks and Barriers was contributed
 by Ross Johnson.
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index de417df..115ce04 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1,116 +1,116 @@
-Contributors (in approximate order of appearance)
-
-[See also the ChangeLog file where individuals are
-attributed in log entries. Likewise in the FAQ file.]
-
-Ben Elliston		bje at cygnus dot com
-					Initiated the project;
-					setup the project infrastructure (CVS, web page, etc.);
-					early prototype routines.
-Ross Johnson		rpj at callisto dot canberra dot edu dot au
-					early prototype routines;
-					ongoing project coordination/maintenance;
-					implementation of spin locks and barriers;
-					bug fixes;
-					documentation;
-					testsuite.
-Robert Colquhoun	rjc at trump dot net dot au
-					Early bug fixes.
-John E. Bossom		John dot Bossom at cognos dot com
-					Contributed substantial original working implementation;
-					bug fixes;
-					ongoing guidance and standards interpretation.
-Anders Norlander	anorland at hem2 dot passagen dot se
-					Early enhancements and runtime checking for supported
-					Win32 routines.
-Tor Lillqvist		tml at iki dot fi
-					General enhancements;
-					early bug fixes to condition variables.
-Scott Lightner		scott at curriculum dot com
-					Bug fix.
-Kevin Ruland		Kevin dot Ruland at anheuser-busch dot com
-					Various bug fixes.
-Mike Russo		miker at eai dot com
-					Bug fix.
-Mark E. Armstrong	avail at pacbell dot net
-					Bug fixes.
-Lorin Hochstein 	lmh at xiphos dot ca
-					general bug fixes; bug fixes to condition variables.
-Peter Slacik		Peter dot Slacik at tatramed dot sk
-					Bug fixes.
-Mumit Khan		khan at xraylith dot wisc dot edu
-					Fixes to work with Mingw32.
-Milan Gardian		mg at tatramed dot sk
-					Bug fixes and reports/analyses of obscure problems.
-Aurelio Medina		aureliom at crt dot com
-					First implementation of read-write locks.
-Graham Dumpleton	Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au
-					Bug fix in condition variables.
-Tristan Savatier	tristan at mpegtv dot com
-					WinCE port.
-Erik Hensema		erik at hensema dot xs4all dot nl
-					Bug fixes.
-Rich Peters		rpeters at micro-magic dot com
-Todd Owen		towen at lucidcalm dot dropbear dot id dot au
-					Bug fixes to dll loading.
-Jason Nye		jnye at nbnet dot nb dot ca
-					Implementation of async cancelation.
-Fred Forester		fforest at eticomm dot net
-Kevin D. Clark		kclark at cabletron dot com
-David Baggett		dmb at itasoftware dot com
-					Bug fixes.
-Paul Redondo		paul at matchvision dot com
-Scott McCaskill 	scott at 3dfx dot com
-					Bug fixes.
-Jef Gearhart		jgearhart at tpssys dot com
-					Bug fix.
-Arthur Kantor		akantor at bexusa dot com
-					Mutex enhancements.
-Steven Reddie		smr at essemer dot com dot au
-					Bug fix.
-Alexander Terekhov	TEREKHOV at de dot ibm dot com
-					Re-implemented and improved read-write locks;
-					(with Louis Thomas) re-implemented and improved
-					condition variables;
-					enhancements to semaphores;
-					system clock change handling re CV timeouts;
-					bug fixes.
-Thomas Pfaff		tpfaff at gmx dot net
-					Changes to make C version usable with C++ applications;
-					re-implemented mutex routines to avoid Win32 mutexes
-					and TryEnterCriticalSection;
-					procedure to fix Mingw32 thread-safety issues.
-Franco Bez		franco dot bez at gmx dot de
-					procedure to fix Mingw32 thread-safety issues.
-Louis Thomas		lthomas at arbitrade dot com
-					(with Alexander Terekhov) re-implemented and improved
-					condition variables.
-David Korn		dgk at research dot att dot com
-					Ported to UWIN.
-Phil Frisbie, Jr.	phil at hawksoft dot com
-					Bug fix.
-Ralf Brese		Ralf dot Brese at pdb4 dot siemens dot de
-					Bug fix.
-prionx at juno dot com 	prionx at juno dot com
-					Bug fixes.
-Max Woodbury		mtew at cds dot duke dot edu
-					POSIX versioning conditionals;
-					reduced namespace pollution;
-					idea to separate routines to reduce statically
-					linked image sizes.
-Rob Fanner		rfanner at stonethree dot com
-					Bug fix.
-Michael Johnson 	michaelj at maine dot rr dot com
-					Bug fix.
-Nicolas Barry		boozai at yahoo dot com
-					Bug fixes.
-Piet van Bruggen	pietvb at newbridges dot nl
-					Bug fix.
-Makoto Kato		raven at oldskool dot jp
-					AMD64 port.
-Panagiotis E. Hadjidoukas	peh at hpclab dot ceid dot upatras dot gr
-					Contributed the QueueUserAPCEx package which
-					makes preemptive async cancelation possible.
-
-Will Bryant			will dot bryant at ecosm dot com
-					Borland compiler patch and makefile.
+Contributors (in approximate order of appearance)
+
+[See also the ChangeLog file where individuals are
+attributed in log entries. Likewise in the FAQ file.]
+
+Ben Elliston		bje at cygnus dot com
+					Initiated the project;
+					setup the project infrastructure (CVS, web page, etc.);
+					early prototype routines.
+Ross Johnson		rpj at callisto dot canberra dot edu dot au
+					early prototype routines;
+					ongoing project coordination/maintenance;
+					implementation of spin locks and barriers;
+					bug fixes;
+					documentation;
+					testsuite.
+Robert Colquhoun	rjc at trump dot net dot au
+					Early bug fixes.
+John E. Bossom		John dot Bossom at cognos dot com
+					Contributed substantial original working implementation;
+					bug fixes;
+					ongoing guidance and standards interpretation.
+Anders Norlander	anorland at hem2 dot passagen dot se
+					Early enhancements and runtime checking for supported
+					Win32 routines.
+Tor Lillqvist		tml at iki dot fi
+					General enhancements;
+					early bug fixes to condition variables.
+Scott Lightner		scott at curriculum dot com
+					Bug fix.
+Kevin Ruland		Kevin dot Ruland at anheuser-busch dot com
+					Various bug fixes.
+Mike Russo		miker at eai dot com
+					Bug fix.
+Mark E. Armstrong	avail at pacbell dot net
+					Bug fixes.
+Lorin Hochstein 	lmh at xiphos dot ca
+					general bug fixes; bug fixes to condition variables.
+Peter Slacik		Peter dot Slacik at tatramed dot sk
+					Bug fixes.
+Mumit Khan		khan at xraylith dot wisc dot edu
+					Fixes to work with Mingw32.
+Milan Gardian		mg at tatramed dot sk
+					Bug fixes and reports/analyses of obscure problems.
+Aurelio Medina		aureliom at crt dot com
+					First implementation of read-write locks.
+Graham Dumpleton	Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au
+					Bug fix in condition variables.
+Tristan Savatier	tristan at mpegtv dot com
+					WinCE port.
+Erik Hensema		erik at hensema dot xs4all dot nl
+					Bug fixes.
+Rich Peters		rpeters at micro-magic dot com
+Todd Owen		towen at lucidcalm dot dropbear dot id dot au
+					Bug fixes to dll loading.
+Jason Nye		jnye at nbnet dot nb dot ca
+					Implementation of async cancelation.
+Fred Forester		fforest at eticomm dot net
+Kevin D. Clark		kclark at cabletron dot com
+David Baggett		dmb at itasoftware dot com
+					Bug fixes.
+Paul Redondo		paul at matchvision dot com
+Scott McCaskill 	scott at 3dfx dot com
+					Bug fixes.
+Jef Gearhart		jgearhart at tpssys dot com
+					Bug fix.
+Arthur Kantor		akantor at bexusa dot com
+					Mutex enhancements.
+Steven Reddie		smr at essemer dot com dot au
+					Bug fix.
+Alexander Terekhov	TEREKHOV at de dot ibm dot com
+					Re-implemented and improved read-write locks;
+					(with Louis Thomas) re-implemented and improved
+					condition variables;
+					enhancements to semaphores;
+					system clock change handling re CV timeouts;
+					bug fixes.
+Thomas Pfaff		tpfaff at gmx dot net
+					Changes to make C version usable with C++ applications;
+					re-implemented mutex routines to avoid Win32 mutexes
+					and TryEnterCriticalSection;
+					procedure to fix Mingw32 thread-safety issues.
+Franco Bez		franco dot bez at gmx dot de
+					procedure to fix Mingw32 thread-safety issues.
+Louis Thomas		lthomas at arbitrade dot com
+					(with Alexander Terekhov) re-implemented and improved
+					condition variables.
+David Korn		dgk at research dot att dot com
+					Ported to UWIN.
+Phil Frisbie, Jr.	phil at hawksoft dot com
+					Bug fix.
+Ralf Brese		Ralf dot Brese at pdb4 dot siemens dot de
+					Bug fix.
+prionx at juno dot com 	prionx at juno dot com
+					Bug fixes.
+Max Woodbury		mtew at cds dot duke dot edu
+					POSIX versioning conditionals;
+					reduced namespace pollution;
+					idea to separate routines to reduce statically
+					linked image sizes.
+Rob Fanner		rfanner at stonethree dot com
+					Bug fix.
+Michael Johnson 	michaelj at maine dot rr dot com
+					Bug fix.
+Nicolas Barry		boozai at yahoo dot com
+					Bug fixes.
+Piet van Bruggen	pietvb at newbridges dot nl
+					Bug fix.
+Makoto Kato		raven at oldskool dot jp
+					AMD64 port.
+Panagiotis E. Hadjidoukas	peh at hpclab dot ceid dot upatras dot gr
+					Contributed the QueueUserAPCEx package which
+					makes preemptive async cancelation possible.
+
+Will Bryant			will dot bryant at ecosm dot com
+					Borland compiler patch and makefile.
diff --git a/ChangeLog b/ChangeLog
index 303cb65..eed0f6b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,19 +1,59 @@
-2004-10-23  Ross Johnson  <ross@localhost.localdomain>
+2004-11-02  Ross Johnson  <rpj at callisto.canberra.edu.au>
 
-	* sem_timedwait.c (ptw32_sem_timedwait_cleanup): Release
-	Win32 semaphore.
-	sem_wait.c (ptw32_sem_wait_cleanup): Likewise.
+	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): Lock CV mutex at
+	start of cleanup handler rather than at the end.
+	* implement.h (PTW32_THREAD_REUSE_EMPTY): Renamed from *_BOTTOM.
+	(ptw32_threadReuseBottom): New global variable.
+	* global.c (ptw32_threadReuseBottom): Declare new variable.
+	* ptw32_reuse.c (ptw32_reuse): Change reuse LIFO stack to LILO queue
+	to more evenly distribute use of reusable thread IDs; use renamed
+	PTW32_THREAD_REUSE_EMPTY.
+	* ptw32_processTerminate.c (ptw2_processTerminate): Use renamed
+	PTW32_THREAD_REUSE_EMPTY.
 
-2004-10-22  Ross Johnson  <rpj at callisto.canberra.edu.au>
+2004-10-31  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* implement.h (PThreadState): Add new state value
+	'PThreadStateCancelPending'.
+	* pthread_testcancel.c (pthread_testcancel): Use new thread
+	'PThreadStateCancelPending' state as short cut to avoid entering
+	kernel space via WaitForSingleObject() call. This was obviated
+	by user space sema acquisition in sem_wait() and sem_timedwait(),
+	which are also cancelation points. A call to pthread_testcancel()
+	was required, which introduced a kernel call, effectively nullifying
+	any gains made by the user space sem acquisition checks.
+	* pthread_cancel.c (pthread_cancel): Set new thread
+	'PThreadStateCancelPending' state.
+
+2004-10-29  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* implement.h (pthread_t): Renamed to ptw32_thread_t; struct contains
+	all thread state.
+	* pthread.h (ptw32_handle_t): New general purpose struct to serve
+	as a handle for various reusable object IDs - currently only used
+	by pthread_t; contains a pointer to ptw32_thread_t (thread state)
+	and a general purpose uint for use as a reuse counter or flags etc.
+	(pthread_t): typedef'ed to ptw32_handle_t; the uint is the reuse
+	counter that allows the library to maintain unique POSIX thread IDs.
+	When the pthread struct reuse stack was introduced, threads would
+	often acquire an identical ID to a previously destroyed thread. The
+	same was true for the pre-reuse stack library, by virtue of pthread_t
+	being the address of the thread struct. The new pthread_t retains
+	the reuse stack but provides virtually unique thread IDs.
+	* sem_wait.c (ptw32_sem_wait_cleanup): New routine used for
+	cancelation cleanup.
+	* sem_timedwait.c (ptw32_sem_timedwait_cleanup): Likewise.
+
+2004-10-22  Ross Johnson  <rpj at callisto.canberra.edu.au>
 
 	* sem_init.c (sem_init): Introduce a 'lock' element in order to
 	replace the interlocked operations with conventional serialisation.
-	This is needed in order to be able to atomically modify the sema value
-	and perform Win32 sema release operations. Win32 semaphores are used
-	instead of events in order to support efficient multiple posting.
-	If the whole modify/release isn't atomic, a race between sem_timedwait()
-	and sem_post() could result in a release when there is no waiting
-	semaphore, which would cause too many threads to proceed.
+	This is needed in order to be able to atomically modify the sema
+	value and perform Win32 sema release operations. Win32 semaphores are
+	used instead of events in order to support efficient multiple posting.
+	If the whole modify/release isn't atomic, a race between
+	sem_timedwait() and sem_post() could result in a release when there is
+	no waiting semaphore, which would cause too many threads to proceed.
 	* sem_wait.c (sem_wait): Use new 'lock'element.
 	* sem_timedwait.c (sem_timedwait): Likewise.
 	* sem_trywait.c (sem_trywait): Likewise.
@@ -28,17 +68,27 @@
 	restore sema value when cancelled.
 	* sem_wait.c (sem_wait): Likewise.
 
-2004-10-21  Ross Johnson  <rpj at callisto.canberra.edu.au>
+2004-10-21  Ross Johnson  <rpj at callisto.canberra.edu.au>
 
 	* pthread_mutex_unlock.c (pthread_mutex_unlock): Must use PulseEvent()
 	rather than SetEvent() to reset the event if there are no waiters.
 
-2004-10-19  Ross Johnson  <rpj at callisto.canberra.edu.au>
+2004-10-19  Ross Johnson  <rpj at callisto.canberra.edu.au>
 
 	* sem_init.c (sem_init): New semaphore model based on the same idea
 	as mutexes, i.e. user space interlocked check to avoid 
 	unnecessarily entering kernel space. Wraps the Win32 semaphore and
-	keeps it's own counter.
+	keeps it's own counter. Although the motivation to do this has existed
+	for a long time, credit goes to Alexander Terekhov for providing
+	the logic. I have deviated slightly from AT's logic to add the waiters
+	count, which has made the code more complicated by adding cancelation
+	cleanup. This also appears to have broken the VCE (C++ EH) version of
+	the library (the same problem as previously reported - see BUGS #2),
+	only apparently not fixable using the usual workaround, nor by turning
+	all optimisation off. The GCE version works fine, so it is presumed to
+	be a bug in MSVC++ 6.0. The cancelation exception is thrown and caught
+	correctly, but the cleanup class destructor is never called. The failing
+	test is tests\semaphore4.c.
 	* sem_wait.c (sem_wait): Implemented user space check model.
 	* sem_post.c (sem_post): Likewise.
 	* sem_trywait.c (sem_trywait): Likewise.
@@ -48,4370 +98,4370 @@
 	* ptw32_semwait.c (ptw32_semwait): Likewise.
 	* implement.h (sem_t_): Add counter element.
 
-2004-10-15  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* implement.h (othread_mutex_t_): Use an event in place of
-	the POSIX semaphore.
-	* pthread_mutex_init.c: Create the event; remove semaphore init.
-	* pthread_mutex_destroy.c: Delete the event.
-	* pthread_mutex_lock.c: Replace the semaphore wait with the event wait.
-	* pthread_mutex_trylock.c: Likewise.
-	* pthread_mutex_timedlock.c: Likewise.
-	* pthread_mutex_unlock.c: Set the event.
-	
-2004-10-14  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_mutex_lock.c (pthread_mutex_lock): New algorithm using
-	Terekhov's xchg based variation of Drepper's cmpxchg model.
-	Theoretically, xchg uses fewer clock cycles than cmpxchg (using IA-32
-	as a reference), however, in my opinion bus locking dominates the
-	equation on smp systems, so the model with the least number of bus
-	lock operations in the execution path should win, which is Terekhov's
-	variant. On IA-32 uni-processor systems, it's faster to use the
-	CMPXCHG instruction without locking the bus than to use the XCHG
-	instruction, which always locks the bus. This makes the two variants
-	equal for the non-contended lock (fast lane) execution path on up
-	IA-32. Testing shows that the xchg variant is faster on up IA-32 as
-	well if the test forces higher lock contention frequency, even though
-	kernel calls should be dominating the times (on up IA-32, both
-	variants used CMPXCHG instructions and neither locked the bus).
-	* pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly.
-	* pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly.
-	* pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly.
-	* ptw32_InterlockedCompareExchange.c (ptw32_InterlockExchange): New
-	function.
-	(PTW32_INTERLOCKED_EXCHANGE): Sets up macro to use inlined
-	ptw32_InterlockedExchange.
-	* implement.h (PTW32_INTERLOCKED_EXCHANGE): Set default to
-	InterlockedExchange().
-	* Makefile: Building using /Ob2 so that asm sections within inline
-	functions are inlined.
-
-2004-10-08  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_mutex_destroy.c (pthread_mutex_destroy): Critical Section
-	element is no longer required.
-	* pthread_mutex_init.c (pthread_mutex_init): Likewise.
-	* pthread_mutex_lock.c (pthread_mutex_lock): New algorithm following
-	Drepper's paper at http://people.redhat.com/drepper/futex.pdf, but
-	using the existing semaphore in place of the futex described in the
-	paper. Idea suggested by Alexander Terekhov - see:
-	http://sources.redhat.com/ml/pthreads-win32/2003/msg00108.html
-	* pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly.
-	* pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly.
-	* pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly.
-	* pthread_barrier_wait.c (pthread_barrier_wait): Use inlined version
-	of InterlockedCompareExchange() if possible - determined at
-	build-time.
-	* pthread_spin_destroy.c pthread_spin_destroy(): Likewise.
-	* pthread_spin_lock.c pthread_spin_lock():Likewise.
-	* pthread_spin_trylock.c (pthread_spin_trylock):Likewise.
-	* pthread_spin_unlock.c (pthread_spin_unlock):Likewise.
-	* ptw32_InterlockedCompareExchange.c: Sets up macro for inlined use.
-	* implement.h (pthread_mutex_t_): Remove Critical Section element.
-	(PTW32_INTERLOCKED_COMPARE_EXCHANGE): Set to default non-inlined
-	version of InterlockedCompareExchange().
-	* private.c: Include ptw32_InterlockedCompareExchange.c first for
-	inlining.
-	* GNUmakefile: Add commandline option to use inlined
-	InterlockedCompareExchange().
-	* Makefile: Likewise.
-
-2004-09-27  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_mutex_lock.c (pthread_mutex_lock): Separate
-	PTHREAD_MUTEX_NORMAL logic since we do not need to keep or check some
-	state required by other mutex types; do not check mutex pointer arg
-	for validity - leave this to the system since we are only checking
-	for NULL pointers. This should improve speed of NORMAL mutexes and
-	marginally improve speed of other type.
-	* pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
-	* pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise; also avoid
-	entering the critical section for the no-waiters case, with approx.
-	30% reduction in lock/unlock overhead for this case.
-	* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise; also
-	no longer keeps mutex if post-timeout second attempt succeeds - this
-	will assist applications that wish to impose strict lock deadlines,
-	rather than simply to escape from frozen locks.
-
-2004-09-09  Tristan Savatier  <tristan at mpegtv.com>
-	* pthread.h (struct pthread_once_t_): Qualify the 'done' element
-	as 'volatile'.
-	* pthread_once.c: Concerned about possible race condition,
-	specifically on MPU systems re concurrent access to multibyte types.
-	[Maintainer's note: the race condition is harmless on SPU systems
-	and only a problem on MPU systems if concurrent access results in an
-	exception (presumably generated by a hardware interrupt). There are
-	other instances of similar harmless race conditions that have not
-	been identified as issues.]
-
-2004-09-09  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread.h: Declare additional types as volatile.
-
-2004-08-27  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_barrier_wait.c (pthread_barrier_wait): Remove excessive code
-	by substituting the internal non-cancelable version of sem_wait
-	(ptw32_semwait).
-
-2004-08-25  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_join.c (pthread_join): Rewrite and re-order the conditional
-	tests in an attempt to improve efficiency and remove a race
-	condition.
-
-2004-08-23  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* create.c (pthread_create): Don't create a thread if the thread
-	id pointer location (first arg) is inaccessible. A memory
-	protection fault will result if the thread id arg isn't an accessible
-	location. This is consistent with GNU/Linux but different to
-	Solaris or MKS (and possibly others), which accept NULL as meaning
-	'don't return the created thread's ID'. Applications that run
-	using pthreads-win32 will run on all other POSIX threads
-	implementations, at least w.r.t. this feature.
-
-	It was decided not to copy the Solaris et al behaviour because,
-	although it would have simplified some application porting (but only
-	from Solaris to Windows), the feature is not technically necessary,
-	and the alternative segfault behaviour helps avoid buggy application
-	code.
-
-2004-07-01  Anuj Goyal  <anuj.goyal at gmail.com>
-
-	* builddmc.bat: New; Windows bat file to build the library.
-	* config.h (__DMC__): Support for Digital Mars compiler.
-	* create.c (__DMC__): Likewise.
-	* pthread_exit.c (__DMC__): Likewise.
-	* pthread_join.c (__DMC__): Likewise.
-	* ptw32_threadDestroy.c (__DMC__): Likewise.
-	* ptw32_threadStart.c (__DMC__): Likewise.
-	* ptw32_throw.c (__DMC__): Likewise.
-
-2004-06-29  Anuj Goyal  <anuj.goyal at gmail.com>
-
-	* pthread.h (__DMC__): Initial support for Digital Mars compiler.
-
-2004-06-29  Will Bryant  <will.bryant at ecosm.com>
-
-	* README.Borland: New; description of Borland changes.
-	* Bmakefile: New makefile for the Borland make utility.
-	* ptw32_InterlockedCompareExchange.c:
-	Add Borland compatible asm code.
-
-2004-06-26  Jason Bard  <BardJA at Npt.NUWC.Navy.Mil>
-
-	* pthread.h (HAVE_STRUCT_TIMESPEC): If undefined, define it
-	to avoid timespec struct redefined errors elsewhere in an
-	application.
-
-2004-06-21  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Mutex
-	initialiser added for compatibility with Linux threads and
-	others; currently not included in SUSV3.
-	* pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER): Likewise.
-	* pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Likewise.
-	* pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise.
-
-	* ptw32_mutex_check_need_init.c (ptw32_mutex_check_need_init): 
-	Add new initialisers.
-
-	* pthread_mutex_lock.c (pthread_mutex_lock): Check for new
-	initialisers.
-	* pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
-	* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
-	* pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise.
-	* pthread_mutex_destroy.c (pthread_mutex_destroy): Likewise.
-
-2004-05-20  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* README.NONPORTABLE: Document pthread_win32_test_features_np().
-	* FAQ: Update various answers.
-
-2004-05-19  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* Makefile: Don't define _WIN32_WINNT on compiler command line.
-	* GNUmakefile: Likewise.
-
-2004-05-16  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_cancel.c (pthread_cancel): Adapted to use auto-detected
-	QueueUserAPCEx features at run-time.
-	(ptw32_RegisterCancelation): Drop in replacement for QueueUserAPCEx()
-	if it can't be used. Provides older style non-preemptive async
-	cancelation.
-	* pthread_win32_attach_detach_np.c (pthread_win32_attach_np):
-	Auto-detect quserex.dll and the availability of alertdrv.sys;
-	initialise and close on process attach/detach.
-	* global.c (ptw32_register_cancelation): Pointer to either
-	QueueUserAPCEx() or ptw32_RegisterCancelation() depending on
-	availability. QueueUserAPCEx makes pre-emptive async cancelation
-	possible.
-	* implement.h: Add definitions and prototypes related to QueueUserAPC.
-
-2004-05-16  Panagiotis E. Hadjidoukas <peh at hpclab.ceid.upatras.gr>
-
-	* QueueUserAPCEx (separate contributed package): Provides preemptive
-	APC feature.
-	* pthread_cancel.c (pthread_cancel): Initial integration of
-	QueueUserAPCEx into pthreads-win32 to provide true pre-emptive
-	async cancelation of threads, including blocked threads.
-
-2004-05-06  Makoto Kato  <raven at oldskool.jp>
-
-	* pthread.h (DWORD_PTR): Define typedef for older MSVC.
-	* pthread_cancel.c (AMD64): Add architecture specific Context register.
-	* ptw32_getprocessors.c: Use correct types (DWORD_PTR) for mask
-	variables.
-
-2004-04-06  P. van Bruggen  <pietvb at newbridges.nl>
-
-	* ptw32_threadDestroy.c: Destroy threadLock mutex to
-	close a memory leak.
-
-2004-02-13  Gustav Hallberg  <gustav at virtutech.com>
-
-	* pthread_equal.c: Remove redundant equality logic.
-
-2003-12-10  Philippe Di Cristo  <philipped at voicebox.com>
-
-	* sem_timedwait.c (sem_timedwait): Fix timeout calculations.
-
-2003-10-20  Alexander Terekhov  <TEREKHOV at de.ibm.com>
-
-	* pthread_mutex_timedlock.c (ptw32_semwait): Move to individual module.
-	* ptw32_semwait.c: New module.
-	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): Replace cancelable
-	sem_wait() call with non-cancelable ptw32_semwait() call.
-	* pthread.c (private.c): Re-order for inlining. GNU C warned that
-	function ptw32_semwait() was defined 'inline' after it was called.
-	* pthread_cond_signal.c (ptw32_cond_unblock): Likewise.
-	* pthread_delay_np.c: Disable Watcom warning with comment.
-	* *.c (process.h): Remove include from .c files. This is conditionally
-	included by the common project include files.
-
-2003-10-20  James Ewing  <james.ewing at sveasoft.com>
-
-	* ptw32_getprocessors.c: Some Win32 environments don't have
-	GetProcessAffinityMask(), so always return CPU count = 1 for them.
-	* config.h (NEED_PROCESSOR_AFFINITY_MASK): Define for WinCE.
-	
-2003-10-15  Ross Johnson  <ross at callisto.canberra.edu.au>
-
-	* Re-indented all .c files using default GNU style to remove assorted
-	editor ugliness (used GNU indent utility in default style).
-
-2003-10-15  Alex Blanco  <Alex.Blanco at motorola.com>
-
-	* sem_init.c (sem_init): Would call CreateSemaphore even if the sema
-	struct calloc failed; was not freeing calloced memory if either
-	CreateSemaphore or CreateEvent failed.
-
-2003-10-14  Ross Johnson  <ross at callisto.canberra.edu.au>
-
-	* pthread.h: Add Watcom compiler compatibility. Esssentially just add
-	the cdecl attribute to all exposed function prototypes so that Watcom
-	generates function call code compatible with non-Watcom built libraries.
-	By default, Watcom uses registers to pass function args if possible rather
-	than pushing to stack.
-	* semaphore.h: Likewise.
-	* sched.h: Likewise.
-	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): Define with cdecl attribute
-	for Watcom compatibility. This routine is called via pthread_cleanup_push so
-	it had to match function arg definition.
-	* Wmakefile: New makefile for Watcom builds.
-
-2003-09-14  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_setschedparam.c (pthread_setschedparam): Attempt to map
-	all priority levels between max and min (as returned by
-	sched_get_priority_min/max) to reasonable Win32 priority levels - i.e.
-	levels between THREAD_PRIORITY_LOWEST/IDLE to THREAD_PRIORITY_LOWEST and
-	between THREAD_PRIORITY_HIGHEST/TIME_CRITICAL to THREAD_PRIORITY_HIGHEST
-	while others remain unchanged; record specified thread priority level
-	for return by pthread_getschedparam.
-
-	Note that, previously, specified levels not matching Win32 priority levels
-	would silently leave the current thread priority unaltered.
-
-	* pthread_getschedparam.c (pthread_getschedparam): Return the priority
-	level specified by the latest pthread_setschedparam or pthread_create rather
-	than the actual running thread priority as returned by GetThreadPriority - as
-	required by POSIX. I.e. temporary or adjusted actual priority levels are not
-	returned by this routine.
-
-	* pthread_create.c (pthread_create): For priority levels specified via
-	pthread attributes, attempt to map all priority levels between max and
-	min (as returned by sched_get_priority_min/max) to reasonable Win32
-	priority levels; record priority level given via attributes, or
-	inherited from parent thread, for later return by pthread_getschedparam.
-
-	* ptw32_new.c (ptw32_new): Initialise pthread_t_ sched_priority element.
-
-	* pthread_self.c (pthread_self): Set newly created implicit POSIX thread
-	sched_priority to Win32 thread's current actual priority. Temporarily
-	altered priorities can't be avoided in this case.
-
-	* implement.h (struct pthread_t_): Add new sched_priority element.
-
-2003-09-12  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* sched_get_priority_min.c (sched_get_priority_min): On error should return -1
-	with errno set.
-	* sched_get_priority_max.c (sched_get_priority_max): Likewise.
-
-2003-09-03  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* w32_cancelableWait.c (ptw32_cancelable_wait): Allow cancelation
-	of implicit POSIX threads as well.
-
-2003-09-02  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np):
-	Add comment.
-
-	* pthread_exit.c (pthread_exit): Fix to recycle the POSIX thread handle in
-	addition to calling user TSD destructors. Move the implicit POSIX thread exit
-	handling to ptw32_throw to centralise the logic.
-
-	* ptw32_throw.c (ptw32_throw): Implicit POSIX threads have no point
-	to jump or throw to, so cleanup and exit the thread here in this case. For
-	processes using the C runtime, the exit code will be set to the POSIX
-	reason for the throw (i.e. PTHREAD_CANCEL or the value given to pthread_exit).
-	Note that pthread_exit() already had similar logic, which has been moved to
-	here.
-
-	* ptw32_threadDestroy.c (ptw32_threadDestroy): Don't close the Win32 handle
-	of implicit POSIX threads - expect this to be done by Win32?
-
-2003-09-01  Ross Johnson  <rpj at callisto.canberra.edu.au>
-
-	* pthread_self.c (pthread_self): The newly aquired pthread_t must be
-	assigned to the reuse stack, not freed, if the routine fails somehow.
-
-2003-08-13  Ross Johnson  <rpj at ise.canberra.edu.au>
-
-	* pthread_getschedparam.c (pthread_getschedparam): An invalid thread ID
-	parameter was returning an incorrect error value; now uses a more exhaustive
-	check for validity.
-
-	* pthread_setschedparam.c (pthread_setschedparam): Likewise.
-
-	* pthread_join.c (pthread_join): Now uses a more exhaustive
-	check for validity.
-
-	* pthread_detach.c (pthread_detach): Likewise.
-
-	* pthread_cancel.c (pthread_cancel): Likewise.
-
-	* ptw32_threadDestroy.c (ptw32_threadDestroy): pthread_t structs are
-	never freed - push them onto a stack for reuse.
-
-	* ptw32_new.c (ptw32_new): Check for reusable pthread_t before dynamically
-	allocating new memory for the struct.
-
-	* pthread_kill.c (pthread_kill): New file; new routine; takes only a zero
-	signal arg so that applications can check the thread arg for validity; checks
-	that the underlying Win32 thread HANDLE is valid.
-
-	* pthread.h (pthread_kill): Add prototype.
-
-	* ptw32_reuse.c (ptw32_threadReusePop): New file; new routine; pop a
-	pthread_t off the reuse stack. pthread_t_ structs that have been destroyed, i.e.
-	have exited detached or have been joined, are cleaned up and put onto a reuse
-	stack. Consequently, thread IDs are no longer freed once calloced. The library
-	will attempt to get a struct off this stack before asking the system to alloc
-	new memory when creating threads. The stack is guarded by a global mutex.
-	(ptw32_threadReusePush): New routine; push a pthread_t onto the reuse stack.
-
-	* implement.h (ptw32_threadReusePush): Add new prototype.
-	(ptw32_threadReusePop): Likewise.
-	(pthread_t): Add new element.
-
-	* ptw32_processTerminate.c (ptw32_processTerminate): Delete the thread
-	reuse lock; free all thread ID structs on the thread reuse stack.
-
-	* ptw32_processInitialize.c (ptw32_processInitialize): Initialise the
-	thread reuse lock.
-
-2003-07-19  Ross Johnson  <rpj at ise.canberra.edu.au>
-
-	* GNUmakefile: modified to work under MsysDTK environment.
-	* pthread_spin_lock.c (pthread_spin_lock): Check for NULL arg.
-	* pthread_spin_unlock.c (pthread_spin_unlock): Likewise.
-	* pthread_spin_trylock.c (pthread_spin_trylock): Likewise;
-	fix incorrect pointer value if lock is dynamically initialised by
-	this function.
-	* sem_init.c (sem_init): Initialise sem_t value to quell compiler warning.
-	* sem_destroy.c (sem_destroy): Likewise.
-	* ptw32_threadStart.c (non-MSVC code sections): Include <exception> rather
-	than old-style <new.h>; fix all std:: namespace entities such as
-	std::terminate_handler instances and associated methods.
-	* ptw32_callUserDestroyRoutines.c (non-MSVC code sections): Likewise.
-
-2003-06-24  Piet van Bruggen  <pietvb at newbridges.nl>
-
-	* pthread_spin_destroy.c (pthread_spin_destroy): Was not freeing the
-	spinlock struct.
-
-2003-06-22  Nicolas Barry  <boozai at yahoo.com>
-
-	* pthread_mutex_destroy.c (pthread_mutex_destroy): When called
-	with a recursive mutex that was locked by the current thread, the
-	function was failing with a success return code.
-
-2003-05-15  Steven Reddie  <Steven.Reddie at ca.com>
-
-	* pthread_win32_attach_detach_np.c (pthread_win32_process_detach_np):
-	NULLify ptw32_selfThreadKey after the thread is destroyed, otherwise
-	destructors calling pthreads routines might resurrect it again, creating
-	memory leaks. Call the underlying Win32 Tls routine directly rather than
-	pthread_setspecific().
-	(pthread_win32_thread_detach_np): Likewise.
-
-2003-05-14  Viv  <vcotirlea at hotmail.com>
-
-	* pthread.dsp: Change /MT compile flag to /MD.
-
-2003-03-04  Alexander Terekhov  <TEREKHOV at de.ibm.com>
-
-	* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Fix failure to
-	set ownership of mutex on second grab after abstime timeout.
-	- bug reported by Robert Strycek <strycek at posam.sk>
-
-2002-12-17  Thomas Pfaff  <tpfaff at gmx.net>
-
-	* pthread_mutex_lock.c (ptw32_semwait): New static routine to provide
-	a non-cancelable sem_wait() function. This is consistent with the
-	way that pthread_mutex_timedlock.c does it.
-	(pthread_mutex_lock): Use ptw32_semwait() instead of sem_wait().
-
-2002-12-11  Thomas Pfaff  <tpfaff at gmx.net>
-
-	* pthread_mutex_trylock.c: Should return EBUSY rather than EDEADLK.
-	* pthread_mutex_destroy.c: Remove redundant ownership test (the
-	trylock call does this for us); do not destroy a recursively locked
-	mutex.
-
-2002-09-20  Michael Johnson  <michaelj at maine.rr.com>
-
-	* pthread_cond_destroy.c (pthread_cond_destroy): 
-	When two different threads exist, and one is attempting to
-	destroy a condition variable while the other is attempting to
-	initialize a condition variable that was created with
-	PTHREAD_COND_INITIALIZER, a deadlock can occur. Shrink
-	the ptw32_cond_list_lock critical section to fix it.
-
-2002-07-31  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* ptw32_threadStart.c (ptw32_threadStart): Thread cancelLock
-	destruction moved to ptw32_threadDestroy().
-
-	* ptw32_threadDestroy.c (ptw32_threadDestroy):  Destroy
-	the thread's cancelLock. Moved here from ptw32_threadStart.c
-	to cleanup implicit threads as well.
-
-2002-07-30  Alexander Terekhov  <TEREKHOV at de.ibm.com>
-
-	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): 
-	Remove code designed to avoid/prevent spurious wakeup
-	problems. It is believed that the sem_timedwait() call
-	is consuming a CV signal that it shouldn't and this is
-	breaking the avoidance logic.
-
-2002-07-30  Ross Johnson  <rpj at ise.canberra.edu.au>
-
-	* sem_timedwait.c (sem_timedwait): Tighten checks for
-	unreasonable abstime values - that would result in
-	unexpected timeout values.
-
-	* w32_CancelableWait.c (ptw32_cancelable_wait):
-	Tighten up return value checking and add comments.
-
-
-2002-06-08  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* sem_getvalue.c (sem_getvalue): Now returns a value for the
-	NEED_SEM version (i.e. earlier versions of WinCE).
-
-
-2002-06-04  Rob Fanner  <rfanner at stonethree.com>
-
-	* sem_getvalue.c (sem_getvalue): The Johnson M. Hart
-	approach didn't work - we are forced to take an
-	intrusive approach. We try to decrement the sema
-	and then immediately release it again to get the
-	value. There is a small probability that this may
-	block other threads, but only momentarily.
-
-2002-06-03  Ross Johnson  <rpj at ise.canberra.edu.au>
-
-	* sem_init.c (sem_init): Initialise Win32 semaphores
-	to _POSIX_SEM_VALUE_MAX (which this implementation
-	defines in pthread.h) so that sem_getvalue() can use
-	the trick described in the comments in sem_getvalue().
-	* pthread.h (_POSIX_SEM_VALUE_MAX): Defined.
-	(_POSIX_SEM_NSEMS_MAX): Defined - not used but may be
-	useful for source code portability.
-
-2002-06-03  Rob Fanner  <rfanner at stonethree.com>
-
-	* sem_getvalue.c (sem_getvalue): Did not work on NT.
-	Use approach suggested by Johnson M. Hart in his book
-	"Win32 System Programming".
-
-2002-02-28  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* errno.c: Compiler directive was incorrectly including code.
-	* pthread.h: Conditionally added some #defines from config.h
-	needed when not building the library. e.g. NEED_ERRNO, NEED_SEM.
-	(PTW32_DLLPORT): Now only defined if _DLL defined.
-	(_errno): Compiler directive was incorrectly including prototype.
-	* sched.h: Conditionally added some #defines from config.h
-	needed when not building the library.
-	* semaphore.h: Replace an instance of NEED_SEM that should
-	have been NEED_ERRNO. This change currently has nil effect.
-
-	* GNUmakefile: Correct some recent changes.
-
-	* Makefile: Add rule to generate pre-processor output.
-
-2002-02-23  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* pthread_rwlock_timedrdlock.c: New - untested.
-	* pthread_rwlock_timedwrlock.c: New - untested.
-	
-	* Testsuite passed (except known MSVC++ problems)
-
-	* pthread_cond_destroy.c: Expand the time change
-	critical section to solve deadlock problem.
-
-	* pthread.c: Add all remaining C modules.
-	* pthread.h: Use dllexport/dllimport attributes on functions
-	to avoid using pthread.def.
-	* sched.h: Likewise.
-	* semaphore.h: Likewise.
-	* GNUmakefile: Add new targets for single translation
-	unit build to maximise inlining potential; generate
-	pthread.def automatically.
-	* Makefile: Likewise, but no longer uses pthread.def.
-
-2002-02-20  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* pthread_cond_destroy.c (pthread_cond_destroy):
-	Enter the time change critical section earlier.
-
-2002-02-17  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
-
-	* Testsuite passed.
-
-	* pthread_timechange_handler_np.c: New; following
-	a suggestion from Alexander Terekhov that CVs should
-	be broadcast so that they all re-evaluate their
-	condition variables and reset a new timeout if
-	required, whenever an application receives a
-	WM_TIMECHANGE message. This message indicates that
-	the system time has been changed. Therefore, CVs
-	waiting for a timeout set as an abs_time will possibly
-	not wake up at the expected time. Some applications
-	may not be tolerant of this.
-	* pthread_cond_init.c: Add CV to linked list.
-	* pthread_cond_destroy.c: Remove CV from linked list.
-	* global.c (ptw32_cond_list_head): New variable.
-	(ptw32_cond_list_tail): New variable.
-	(ptw32_cond_list_cs): New critical section.
-	* ptw32_processInitialize (ptw32_cond_list_cs): Initialize.
-	* ptw32_processTerminate (ptw32_cond_list_cs): Delete.
-
-
-	* Reduce executable size.
-	  -----------------------
-	When linking with the static library, only those
-	routines actually called, either directly or indirectly
-	should be included.
-
-	[Gcc has the -ffunction-segments option to do this but MSVC
-	doesn't have this feature as far as I can determine. Other
-	compilers are undetermined as well. - rpj]
-
-	* spin.c: Split file into function segments.
-	* ptw32_spinlock_check_need_init.c: Separated routine from spin.c.
-	* pthread_spin_init.c: Likewise.
-	* pthread_spin_destroy.c: Likewise.
-	* pthread_spin_lock.c: Likewise.
-	* pthread_spin_unlock.c: Likewise.
-	* pthread_spin_trylock.c: Likewise.
-
-	* sync.c: Split file into function segments.
-	* pthread_detach.c: Separated routine from sync.c.
-	* pthread_join.c: Likewise.
-
-	* tsd.c: Split file into function segments.
-	* pthread_key_create.c: Separated routine from tsd.c.
-	* pthread_key_delete.c: Likewise.
-	* pthread_setspecific.c: Likewise.
-	* pthread_getspecific.c: Likewise.
-
-	* sched.c: Split file into function segments.
-	* pthread_attr_setschedpolicy.c: Separated routine from sched.c.
-	* pthread_attr_getschedpolicy.c: Likewise.
-	* pthread_attr_setschedparam.c: Likewise.
-	* pthread_attr_getschedparam.c: Likewise.
-	* pthread_attr_setinheritsched.c: Likewise.
-	* pthread_attr_getinheritsched.c: Likewise.
-	* pthread_setschedparam.c: Likewise.
-	* pthread_getschedparam.c: Likewise.
-	* sched_get_priority_max.c: Likewise.
-	* sched_get_priority_min.c: Likewise.
-	* sched_setscheduler.c: Likewise.
-	* sched_getscheduler.c: Likewise.
-	* sched_yield.c: Likewise.
-
-
-2002-02-16  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
-
-	Reduce executable size.
-	-----------------------
-	When linking with the static library, only those
-	routines actually called, either directly or indirectly
-	should be included.
-
-	[Gcc has the -ffunction-segments option to do this but MSVC
-	doesn't have this feature as far as I can determine. Other
-	compilers are undetermined as well. - rpj]
-
-	* mutex.c: Split file into function segments.
-	* pthread_mutexattr_destroy.c: Separated routine from mutex.c
-	* pthread_mutexattr_getpshared.c: Likewise.
-	* pthread_mutexattr_gettype.c: Likewise.
-	* pthread_mutexattr_init.c: Likewise.
-	* pthread_mutexattr_setpshared.c: Likewise.
-	* pthread_mutexattr_settype.c: Likewise.
-	* ptw32_mutex_check_need_init.c: Likewise.
-	* pthread_mutex_destroy.c: Likewise.
-	* pthread_mutex_init.c: Likewise.
-	* pthread_mutex_lock.c: Likewise.
-	* pthread_mutex_timedlock.c: Likewise.
-	* pthread_mutex_trylock.c: Likewise.
-	* pthread_mutex_unlock.c: Likewise.
-	
-	* private.c: Split file into function segments.
-	* ptw32_InterlockedCompareExchange.c: Separated routine from private.c
-	* ptw32_callUserDestroyRoutines.c: Likewise.
-	* ptw32_getprocessors.c: Likewise.
-	* ptw32_processInitialize.c: Likewise.
-	* ptw32_processTerminate.c: Likewise.
-	* ptw32_threadDestroy.c: Likewise.
-	* ptw32_threadStart.c: Likewise.
-	* ptw32_throw.c: Likewise.
-	* ptw32_timespec.c: Likewise.
-	* ptw32_tkAssocCreate.c: Likewise.
-	* ptw32_tkAssocDestroy.c: Likewise.
-
-	* rwlock.c: Split file into function segments.
-	* pthread_rwlockattr_destroy.c: Separated routine from rwlock.c
-	* pthread_rwlockattr_getpshared.c: Likewise.
-	* pthread_rwlockattr_init.c: Likewise.
-	* pthread_rwlockattr_setpshared.c: Likewise.
-	* ptw32_rwlock_check_need_init.c: Likewise.
-	* pthread_rwlock_destroy.c: Likewise.
-	* pthread_rwlock_init.c: Likewise.
-	* pthread_rwlock_rdlock.c: Likewise.
-	* pthread_rwlock_tryrdlock.c: Likewise.
-	* pthread_rwlock_trywrlock.c: Likewise.
-	* pthread_rwlock_unlock.c: Likewise.
-	* pthread_rwlock_wrlock.c: Likewise.
-
-2002-02-10  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
-
-	Reduce executable size.
-	-----------------------
-	When linking with the static library, only those
-	routines actually called, either directly or indirectly
-	should be included.
-
-	[Gcc has the -ffunction-segments option to do this but MSVC
-	doesn't have this feature as far as I can determine. Other
-	compilers are undetermined as well. - rpj]
-
-	* nonportable.c: Split file into function segments.
-	* np_delay.c: Separated routine from nonportable.c
-	* np_getw32threadhandle.c: Likewise.
-	* np_mutexattr_setkind.c: Likewise.
-	* np_mutexattr_getkind.c: Likewise.
-	* np_num_processors.c: Likewise.
-	* np_win32_attach_detach.c: Likewise.
-
-	* misc.c: Split file into function segments.
-	* pthread_equal.c: Separated routine from nonportable.c.
-	* pthread_getconcurrency.c: Likewise.
-	* pthread_once.c: Likewise.
-	* pthread_self.c: Likewise.
-	* pthread_setconcurrency.c: Likewise.
-	* ptw32_calloc.c: Likewise.
-	* ptw32_new.c: Likewise.
-	* w32_CancelableWait.c: Likewise.
-	
-2002-02-09  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
-
-	Reduce executable size.
-	-----------------------
-	When linking with the static library, only those
-	routines actually called, either directly or indirectly
-	should be included.
-
-	[Gcc has the -ffunction-segments option to do this but MSVC
-	doesn't have this feature as far as I can determine. Other
-	compilers are undetermined as well. - rpj]
-
-	* condvar.c: Split file into function segments.
-	* pthread_condattr_destroy.c: Separated routine from condvar.c.
-	* pthread_condattr_getpshared.c: Likewise.
-	* pthread_condattr_init.c: Likewise.
-	* pthread_condattr_setpshared.c: Likewise.
-	* ptw32_cond_check_need_init.c: Likewise.
-	* pthread_cond_destroy.c: Likewise.
-	* pthread_cond_init.c: Likewise.
-	* pthread_cond_signal.c: Likewise.
-	* pthread_cond_wait.c: Likewise.
-	
-2002-02-07  Alexander Terekhov<TEREKHOV at de.ibm.com>
-
-	* nonportable.c (pthread_delay_np): Make a true
-	cancelation point. Deferred cancels will interrupt the
-	wait.
-
-2002-02-07  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
-
-	* misc.c (ptw32_new): Add creation of cancelEvent so that
-	implicit POSIX threads (Win32 threads with a POSIX face)
-	are cancelable; mainly so that pthread_delay_np doesn't fail
-	if called from the main thread.
-	* create.c (pthread_create): Remove creation of cancelEvent
-	from here; now in ptw32_new().
-
-	Reduce executable size.
-	-----------------------
-	When linking with the static library, only those
-	routines actually called, either directly or indirectly
-	should be included.
-
-	[Gcc has the -ffunction-segments option to do this but MSVC
-	doesn't have this feature as far as I can determine. Other
-	compilers are undetermined as well. - rpj]
-
-	* barrier.c: All routines are now in separate compilation units;
-	This file is used to congregate the separate modules for
-	potential inline optimisation and backward build compatibility.
-	* cancel.c: Likewise.
-	* pthread_barrierattr_destroy.c: Separated routine from cancel.c.
-	* pthread_barrierattr_getpshared.c: Likewise.
-	* pthread_barrierattr_init.c: Likewise.
-	* pthread_barrierattr_setpshared.c: Likewise.
-	* pthread_barrier_destroy.c: Likewise.
-	* pthread_barrier_init.c: Likewise.
-	* pthread_barrier_wait.c: Likewise.
-	* pthread_cancel.c: Likewise.
-	* pthread_setcancelstate.c: Likewise.
-	* pthread_setcanceltype.c: Likewise.
-	* pthread_testcancel.c: Likewise.
-
-2002-02-04  Max Woodbury <mtew at cds.duke.edu>
-
-	Reduced name space pollution.
-	-----------------------------
-	When the appropriate symbols are defined, the headers
-	will restrict the definitions of new names. In particular,
-	it must be possible to NOT include the <windows.h>
-	header and related definitions with some combination
-	of symbol definitions. Secondly, it should be possible
-	that additional definitions should be limited to POSIX 
-	compliant symbols by the definition of appropriate symbols.
-
-	* pthread.h: POSIX conditionals.
-	* sched.h: POSIX conditionals.
-	* semaphore.h: POSIX conditionals.
-
-	* semaphore.c: Included <limits.h>.
-	(sem_init): Changed magic 0x7FFFFFFFL to INT_MAX.
-	(sem_getvalue): Trial version.
-
-	Reduce executable size.
-	-----------------------
-	When linking with the static library, only those
-	routines actually called, either directly or indirectly
-	should be included.
-
-	[Gcc has the -ffunction-segments option to do this but MSVC
-	doesn't have this feature as far as I can determine. Other
-	compilers are undetermined as well. - rpj]
-
-	* semaphore.c: All routines are now in separate compilation units;
-	This file is used to congregate the separate modules for
-	potential inline optimisation and backward build compatibility.
-	* sem_close.c: Separated routine from semaphore.c.
-	* ptw32_decrease_semaphore.c: Likewise.
-	* sem_destroy.c: Likewise.
-	* sem_getvalue.c: Likewise.
-	* ptw32_increase_semaphore.c: Likewise.
-	* sem_init.c: Likewise.
-	* sem_open.c: Likewise.
-	* sem_post.c: Likewise.
-	* sem_post_multiple.c: Likewise.
-	* sem_timedwait.c: Likewise.
-	* sem_trywait.c: Likewise.
-	* sem_unlink.c: Likewise.
-	* sem_wait.c: Likewise.
-
-2002-02-04  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	The following extends the idea above to the rest of pthreads-win32 - rpj
-	
-	* attr.c: All routines are now in separate compilation units;
-	This file is used to congregate the separate modules for
-	potential inline optimisation and backward build compatibility.
-	* pthread_attr_destroy.c: Separated routine from attr.c.
-	* pthread_attr_getdetachstate.c: Likewise.
-	* pthread_attr_getscope.c: Likewise.
-	* pthread_attr_getstackaddr.c: Likewise.
-	* pthread_attr_getstacksize.c: Likewise.
-	* pthread_attr_init.c: Likewise.
-	* pthread_attr_is_attr.c: Likewise.
-	* pthread_attr_setdetachstate.c: Likewise.
-	* pthread_attr_setscope.c: Likewise.
-	* pthread_attr_setstackaddr.c: Likewise.
-	* pthread_attr_setstacksize.c: Likewise.
-
-	* pthread.c: Agregation of agregate modules for super-inlineability.
-
-2002-02-02  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* cancel.c: Rearranged some code and introduced checks
-	to disable cancelation at the start of a thread's cancelation
-	run to prevent double cancelation. The main problem
-	arises if a thread is canceling and then receives a subsequent
-	async cancel request.
-	* private.c: Likewise.
-	* condvar.c: Place pragmas around cleanup_push/pop to turn
-	off inline optimisation (/Obn where n>0 - MSVC only). Various
-	optimisation switches in MSVC turn this on, which interferes with
-	the way that cleanup handlers are run in C++ EH and SEH
-	code. Application code compiled with inline optimisation must
-	also wrap cleanup_push/pop blocks with the pragmas, e.g.
-	  #pragma inline_depth(0)
-	  pthread_cleanup_push(...)
-	    ...
-	  pthread_cleanup_pop(...)
-	  #pragma inline_depth(8)
-	* rwlock.c: Likewise.
-	* mutex.c: Remove attempts to inline some functions.
-	* signal.c: Modify misleading comment.
-
-2002-02-01  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* semaphore.c (sem_trywait): Fix missing errno return
-	for systems that define NEED_SEM (e.g. early WinCE).
-	* mutex.c (pthread_mutex_timedlock): Return ENOTSUP
-	for systems that define NEED_SEM since they don't
-	have sem_trywait().
-
-2002-01-27  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* mutex.c (pthread_mutex_timedlock): New function suggested by
-	Alexander Terekhov. The logic required to implement this
-	properly came from Alexander, with some collaboration
-	with Thomas Pfaff.
-	(pthread_mutex_unlock): Wrap the waiters check and sema
-	post in a critical section to prevent a race with
-	pthread_mutex_timedlock.
-	(ptw32_timed_semwait): New function;
-	returns a special result if the absolute timeout parameter
-	represents a time already passed when called; used by
-	pthread_mutex_timedwait(). Have deliberately not reused
-	the name "ptw32_sem_timedwait" because they are not the same
-	routine.
-	* condvar.c (ptw32_cond_timedwait): Use the new sem_timedwait()
-	instead of ptw32_sem_timedwait(), which now has a different
-	function. See previous.
-	* implement.h: Remove prototype for ptw32_sem_timedwait.
-	See next.
-	(pthread_mutex_t_): Add critical section element for access
-	to lock_idx during mutex post-timeout processing.
-	* semaphore.h (sem_timedwait): See next.
-	* semaphore.c (sem_timedwait): See next.
-	* private.c (ptw32_sem_timedwait): Move to semaphore.c
-	and rename as sem_timedwait().
-
-2002-01-18  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* sync.c (pthread_join): Was getting the exit code from the
-	calling thread rather than the joined thread if
-	defined(__MINGW32__) && !defined(__MSVCRT__).
-
-2002-01-15  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.h: Unless the build explicitly defines __CLEANUP_SEH,
-	__CLEANUP_CXX, or __CLEANUP_C, then the build defaults to
-	__CLEANUP_C style cleanup. This style uses setjmp/longjmp
-	in the cancelation and thread exit implementations and therefore
-	won't do stack unwinding if linked to applications that have it
-	(e.g. C++ apps). This is currently consistent with most/all
-	commercial Unix POSIX threads implementations.
-
-	* spin.c (pthread_spin_init): Edit renamed function call.
-	* nonportable.c (pthread_num_processors_np): New.
-	(pthread_getprocessors_np): Renamed to ptw32_getprocessors
-	and moved to private.c.
-	* private.c (pthread_getprocessors): Moved here from
-	nonportable.c.
-	* pthread.def (pthread_getprocessors_np): Removed
-	from export list.
-
-	* rwlock.c (pthread_rwlockattr_init): New.
-	(pthread_rwlockattr_destroy): New.
-	(pthread_rwlockattr_getpshared): New.
-	(pthread_rwlockattr_setpshared): New.
-
-2002-01-14  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* attr.c (pthread_attr_setscope): Fix struct pointer
-	indirection error introduced 2002-01-04.
-	(pthread_attr_getscope): Likewise.
-
-2002-01-12  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.dsp (SOURCE): Add missing source files.
-
-2002-01-08  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* mutex.c (pthread_mutex_trylock): use
-	ptw32_interlocked_compare_exchange function pointer
-	rather than ptw32_InterlockedCompareExchange() directly
-	to retain portability to non-iX86 processors,
-	e.g. WinCE etc. The pointer will point to the native
-	OS version of InterlockedCompareExchange() if the
-	OS supports it (see ChangeLog entry of 2001-10-17).
-
-2002-01-07  Thomas Pfaff <tpfaff at gmx.net>, Alexander Terekhov <TEREKHOV at de.ibm.com>
-
-	* mutex.c (pthread_mutex_init): Remove critical
-	section calls.
-	(pthread_mutex_destroy): Likewise.
-	(pthread_mutex_unlock): Likewise.
-	(pthread_mutex_trylock): Likewise; uses
-	ptw32_InterlockedCompareExchange() to avoid need for
-	critical section; library is no longer i386 compatible;
-	recursive mutexes now increment the lock count rather
-	than return EBUSY; errorcheck mutexes return EDEADLCK
-	rather than EBUSY. This behaviour is consistent with the
-	Solaris pthreads implementation.
-	* implement.h (pthread_mutex_t_): Remove critical
-	section element - no longer needed.
-	
-
-2002-01-04  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* attr.c (pthread_attr_setscope): Add more error
-	checking and actually store the scope value even
-	though it's not really necessary.
-	(pthread_attr_getscope): Return stored value.
-	* implement.h (pthread_attr_t_): Add new scope element.
-	* ANNOUNCE: Fix out of date comment next to
-	pthread_attr_setscope in conformance section.
-
-2001-12-21  Alexander Terekhov <TEREKHOV at de.ibm.com>
-
-	* mutex.c (pthread_mutex_lock): Decrementing lock_idx was
-	not thread-safe.
-	(pthread_mutex_trylock): Likewise.
-
-2001-10-26  prionx@juno.com
-
-	* semaphore.c (sem_init): Fix typo and missing bracket
-	in conditionally compiled code. Only older versions of
-	WinCE require this code, hence it doesn't normally get
-	tested; somehow when sem_t reverted to an opaque struct
-	the calloc NULL check was left in the conditionally included
-	section.
-	(sem_destroy): Likewise, the calloced sem_t wasn't being freed.
-
-2001-10-25  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* GNUmakefile (libwsock32): Add to linker flags for
-	WSAGetLastError() and WSASetLastError().
-	* Makefile (wsock32.lib): Likewise.
-	* create.c: Minor mostly inert changes.
-	* implement.h (PTW32_MAX): Move into here and renamed
-	from sched.h.
-	(PTW32_MIN): Likewise.
-	* GNUmakefile (TEST_ICE): Define if testing internal
-	implementation of InterlockedCompareExchange.
-	* Makefile (TEST_ICE): Likewise.
-	* private.c (TEST_ICE): Likewise.
-	
-2001-10-24  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* attr.c (pthread_attr_setstacksize): Quell warning
-	from LCC by conditionally compiling the stacksize
-	validity check. LCC correctly warns that the condition
-	(stacksize < PTHREAD_STACK_MIN) is suspicious
-	because STACK_MIN is 0 and stacksize is of type
-	size_t (or unsigned int).
-
-2001-10-17  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* barrier.c: Move _LONG and _LPLONG defines into
-	implement.h; rename to PTW32_INTERLOCKED_LONG and
-	PTW32_INTERLOCKED_LPLONG respectively.
-	* spin.c: Likewise; ptw32_interlocked_compare_exchange used
-	in place of InterlockedCompareExchange directly.
-	* global.c (ptw32_interlocked_compare_exchange): Add
-	prototype for this new routine pointer to be used when
-	InterlockedCompareExchange isn't supported by Windows.
-	* nonportable.c (pthread_win32_process_attach_np): Check for
-	support of InterlockedCompareExchange in kernel32 and assign its
-	address to ptw32_interlocked_compare_exchange if it exists, or
-	our own ix86 specific implementation ptw32_InterlockedCompareExchange.
-	*private.c (ptw32_InterlockedCompareExchange): An
-	implementation of InterlockedCompareExchange() which is
-	specific to ix86; written directly in assembler for either
-	MSVC or GNU C; needed because Windows 95 doesn't support
-	InterlockedCompareExchange().
-
-	* sched.c (sched_get_priority_min): Extend to return
-	THREAD_PRIORITY_IDLE.
-	(sched_get_priority_max): Extend to return
-	THREAD_PRIORITY_CRITICAL.
-
-2001-10-15  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* spin.c (pthread_spin_lock): PTHREAD_SPINLOCK_INITIALIZER
-	was causing a program fault.
-	(pthread_spin_init): Could have alloced memory
-	without freeing under some error conditions.
-
-	* mutex.c (pthread_mutex_init): Move memory
-	allocation of mutex struct after checking for
-	PROCESS_SHARED.
-
-2001-10-12  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* spin.c (pthread_spin_unlock): Was not returning
-	EPERM if the spinlock was not locked, for multi CPU
-	machines.
-
-2001-10-08  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* spin.c (pthread_spin_trylock): Was not returning
-	EBUSY for multi CPU machines.
-
-2001-08-24  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* condvar.c (pthread_cond_destroy): Remove cv element
-	that is no longer used.
-	* implement.h: Likewise.
-
-2001-08-23  Alexander Terekhov <TEREKHOV at de.ibm.com>
-
-	* condvar.c (pthread_cond_destroy): fix bug with
-	respect to deadlock in the case of concurrent
-	_destroy/_unblock; a condition variable can be destroyed
-	immediately after all the threads that are blocked on
-	it are awakened.
-
-2001-08-23  Phil Frisbie, Jr. <phil at hawksoft.com>
-
-	* tsd.c (pthread_getspecific): Preserve the last
-	winsock error [from WSAGetLastError()].
-
-2001-07-18  Scott McCaskill <scott at magruder.org>
-
-	* mutex.c (pthread_mutexattr_init): Return ENOMEM
-	immediately and don't dereference the NULL pointer
-	if calloc fails.
-	(pthread_mutexattr_getpshared): Don't dereference
-	a pointer that is possibly NULL.
-	* barrier.c (pthread_barrierattr_init): Likewise
-	(pthread_barrierattr_getpshared): Don't dereference
-	a pointer that is possibly NULL.
-	* condvar.c (pthread_condattr_getpshared): Don't dereference
-	a pointer that is possibly NULL.
-
-2001-07-15  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* rwlock.c (pthread_rwlock_wrlock): Is allowed to be
-	a cancelation point; re-enable deferred cancelability
-	around the CV call.
-
-2001-07-10  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* barrier.c: Still more revamping. The exclusive access
-	mutex isn't really needed so it has been removed and replaced
-	by an InterlockedDecrement(). nSerial has been removed.
-	iStep is now dual-purpose. The process shared attribute
-	is now stored in the barrier struct.
-	* implement.h (pthread_barrier_t_): Lost some/gained one
-	elements.
-	* private.c (ptw32_threadStart): Removed some comments.
-
-2001-07-10  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* barrier.c: Revamped to fix the race condition. Two alternating
-	semaphores are used instead of the PulseEvent. Also improved
-	overall throughput by returning PTHREAD_BARRIER_SERIAL_THREAD
-	to the first waking thread.
-	* implement.h (pthread_barrier_t_): Revamped.
-
-2001-07-09  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* barrier.c: Fix several bugs in all routines. Now passes
-	tests/barrier5.c which is fairly rigorous. There is still
-	a non-optimal work-around for a race condition between
-	the barrier breeched event signal and event wait. Basically
-	the last (signalling) thread to hit the barrier yields
-	to allow any other threads, which may have lost the race,
-	to complete.
-
-2001-07-07  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* barrier.c: Changed synchronisation mechanism to a
-	Win32 manual reset Event and use PulseEvent to signal
-	waiting threads. If the implementation continued to use
-	a semaphore it would require a second semaphore and
-	some management to use them alternately as barriers. A
-	single semaphore allows threads to cascade from one barrier
-	through the next, leaving some threads blocked at the first.
-	* implement.h (pthread_barrier_t_): As per above.
-	* general: Made a number of other routines inlinable.
-
-2001-07-07  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* spin.c: Revamped and working; included static initialiser.
-	Now beta level.
-	* barrier.c: Likewise.
-	* condvar.c: Macro constant change; inline auto init routine.
-	* mutex.c: Likewise.
-	* rwlock.c: Likewise.
-	* private.c: Add support for spinlock initialiser.
-	* global.c: Likewise.
-	* implement.h: Likewise.
-	* pthread.h (PTHREAD_SPINLOCK_INITIALIZER): Fix typo.
-
-2001-07-05  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* 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().
-
-2001-07-05  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* spin.c: New module implementing spin locks.
-	* barrier.c: New module implementing barriers.
-	* pthread.h (_POSIX_SPIN_LOCKS): defined.
-	(_POSIX_BARRIERS): Defined.
-	(pthread_spin_*): Defined.
-	(pthread_barrier*): Defined.
-	(PTHREAD_BARRIER_SERIAL_THREAD): Defined.
-	* implement.h (pthread_spinlock_t_): Defined.
-	(pthread_barrier_t_): Defined.
-	(pthread_barrierattr_t_): Defined.
-
-	* mutex.c (pthread_mutex_lock): Return with the error
-	if an auto-initialiser initialisation fails.
-
-	* nonportable.c (pthread_getprocessors_np): New; gets the
-	number of available processors for the current process.
-
-2001-07-03  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* pthread.h (_POSIX_READER_WRITER_LOCKS): Define it
-	if not already defined.
-
-2001-07-01  Alexander Terekhov <TEREKHOV at de.ibm.com>
-
-	* condvar.c: Fixed lost signal bug reported by Timur Aydin
-	(taydin@snet.net).
-	[RPJ (me) didn't translate the original algorithm
-	correctly.]
-	* semaphore.c: Added sem_post_multiple; this is a useful
-	routine, but it doesn't appear to be standard. For now it's
-	not an exported function.
-	
-2001-06-25  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* create.c (pthread_create): Add priority inheritance
-	attributes.
-	* mutex.c (pthread_mutex_lock): Remove some overhead for
-	PTHREAD_MUTEX_NORMAL mutex types. Specifically, avoid
-	calling pthread_self() and pthread_equal() to check/set
-	the mutex owner. Introduce a new pseudo owner for this
-	type. Test results suggest increases in speed of up to
-	90% for non-blocking locks.
-	This is the default type of mutex used internally by other
-	synchronising objects, ie. condition variables and
-	read-write locks. The test rwlock7.c shows about a
-	30-35% speed increase over snapshot 2001-06-06. The
-	price of this is that the application developer
-	must ensure correct behaviour, or explicitly set the
-	mutex to a safer type such as PTHREAD_MUTEX_ERRORCHECK.
-	For example, PTHREAD_MUTEX_NORMAL (or PTHREAD_MUTEX_DEFAULT)
-	type mutexes will not return an error if a thread which is not
-	the owner calls pthread_mutex_unlock. The call will succeed
-	in unlocking the mutex if it is currently locked, but a
-	subsequent unlock by the true owner will then fail with EPERM.
-	This is however consistent with some other implementations.
-	(pthread_mutex_unlock): Likewise.
-	(pthread_mutex_trylock): Likewise.
-	(pthread_mutex_destroy): Likewise.
-	* attr.c (pthread_attr_init): PTHREAD_EXPLICIT_SCHED is the
-	default inheritance attribute; THREAD_PRIORITY_NORMAL is
-	the default priority for new threads.
-	* sched.c (pthread_attr_setschedpolicy): Added routine.
-	(pthread_attr_getschedpolicy): Added routine.
-	(pthread_attr_setinheritsched): Added routine.
-	(pthread_attr_getinheritsched): Added routine.
-	* pthread.h (sched_rr_set_interval): Added as a macro;
-	returns -1 with errno set to ENOSYS.
-
-2001-06-23  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	*sched.c (pthread_attr_setschedparam): Add priority range
-	check.
-	(sched_setscheduler): New function; checks for a valid
-	pid and policy; checks for permission to set information
-	in the target process; expects pid to be a Win32 process ID,
-	not a process handle; the only scheduler policy allowed is
-	SCHED_OTHER.
-	(sched_getscheduler): Likewise, but checks for permission
-	to query.
-	* pthread.h (SCHED_*): Moved to sched.h as defined in the
-	POSIX standard.
-	* sched.h (SCHED_*): Moved from pthread.h.
-	(pid_t): Defined if necessary.
-	(sched_setscheduler): Defined.
-	(sched_getscheduler): Defined.
-	* pthread.def (sched_setscheduler): Exported.
-	(sched_getscheduler): Likewise.
-
-2001-06-23  Ralf Brese <Ralf.Brese at pdb4.siemens.de>
-
-	* create.c (pthread_create): Set thread priority from
-	thread attributes.
-
-2001-06-18  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* Made organisational-only changes to UWIN additions.
-	* dll.c (dllMain): Moved UWIN process attach code
-	to pthread_win32_process_attach_np(); moved
-	instance of pthread_count to global.c.
-	* global.c (pthread_count): Moved from dll.c.
-	* nonportable.c (pthread_win32_process_attach_np):
-	Moved _UWIN code to here from dll.c.
-	* implement.h (pthread_count): Define extern int.
-	* create.c (pthread_count): Remove extern int.
-	* private.c (pthread_count): Likewise.
-	* exit.c (pthread_count): Likewise.
-
-2001-06-18  David Korn <dgk at research.att.com>
-
-	* dll.c: Added changes necessary to work with UWIN.
-	* create.c: Likewise.
-	* pthread.h: Likewise.
-	* misc.c: Likewise.
-	* exit.c: Likewise.
-	* private.c: Likewise.
-	* implement.h: Likewise.
-	There is some room at the start of struct pthread_t_
-	to implement the signal semantics in UWIN's posix.dll
-	although this is not yet complete.
-	* Nmakefile: Compatible with UWIN's Nmake utility.
-	* Nmakefile.tests: Likewise - for running the tests.
-
-2001-06-08  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* semaphore.h (sem_t): Fixed for compile and test.
-	* implement.h (sem_t_): Likewise.
-	* semaphore.c: Likewise.
-	* private.c (ptw32_sem_timedwait): Updated to use new
-	opaque sem_t.
-
-2001-06-06  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* semaphore.h (sem_t): Is now an opaque pointer;
-	moved actual definition to implement.h.
-	* implement.h (sem_t_): Move here from semaphore.h;
-	was the definition of sem_t.
-	* semaphore.c: Wherever necessary, changed use of sem
-	from that of a pointer to a pointer-pointer; added
-	extra checks for a valid sem_t; NULL sem_t when
-	it is destroyed; added extra checks when creating
-	and destroying sem_t elements in the NEED_SEM
-	code branches; changed from using a pthread_mutex_t
-	((*sem)->mutex) to CRITICAL_SECTION ((*sem)->sem_lock_cs)
-	in NEED_SEM branches for access serialisation.
-
-2001-06-06  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* mutex.c (pthread_mutexattr_init): Remove 
-	ptw32_mutex_default_kind.
-	
-2001-06-05  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* nonportable.c (pthread_mutex_setdefaultkind_np):
-	Remove - should not have been included in the first place.
-	(pthread_mutex_getdefaultkind_np): Likewise.
-	* global.c (ptw32_mutex_default_kind): Likewise.
-	* mutex.c (pthread_mutex_init): Remove use of
-	ptw32_mutex_default_kind.
-	* pthread.h (pthread_mutex_setdefaultkind_np): Likewise.
-	(pthread_mutex_getdefaultkind_np): Likewise.
-	* pthread.def (pthread_mutexattr_setkind_np): Added.
-	(pthread_mutexattr_getkind_np): Likewise.
-
-	* README: Many changes that should have gone in before
-	the last snapshot.
-	* README.NONPORTABLE: New - referred to by ANNOUNCE
-	but never created; documents the non-portable routines
-	included in the library - moved from README with new
-	routines added.
-	* ANNOUNCE (pthread_mutexattr_setkind_np): Added to
-	compliance list.
-	(pthread_mutexattr_getkind_np): Likewise.
-
-2001-06-04  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* condvar.c: Add original description of the algorithm as
-	developed by Terekhov and Thomas, plus reference to
-	README.CV.
-
-2001-06-03  Alexander Terekhov <TEREKHOV at de.ibm.com>, Louis Thomas <lthomas at arbitrade.com>
-
-	* condvar.c (pthread_cond_init): Completely revamped.
-	(pthread_cond_destroy): Likewise.
-	(ptw32_cond_wait_cleanup): Likewise.
-	(ptw32_cond_timedwait): Likewise.
-	(ptw32_cond_unblock): New general signaling routine.
-	(pthread_cond_signal): Now calls ptw32_cond_unblock.
-	(pthread_cond_broadcast): Likewise.
-	* implement.h (pthread_cond_t_): Revamped.
-	* README.CV: New; explanation of the above changes.
-
-2001-05-30  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* pthread.h (rand_r): Fake using _seed argument to quell
-	compiler warning (compiler should optimise this away later).
-
-	* GNUmakefile (OPT): Leave symbolic information out of the library
-	and increase optimisation level - for smaller faster prebuilt
-	dlls.
-	
-2001-05-29  Milan Gardian <Milan.Gardian at LEIBINGER.com>
-
-	* Makefile: fix typo.
-	* pthreads.h: Fix problems with stdcall/cdecl conventions, in particular
-	remove the need for PT_STDCALL everywhere; remove warning supression.
-	* (errno): Fix the longstanding "inconsistent dll linkage" problem
-	with errno; now also works with /MD debugging libs - 
-	warnings emerged when compiling pthreads library with /MD (or /MDd)
-	compiler switch, instead of /MT (or /MTd) (i.e. when compiling pthreads
-	using Multithreaded DLL CRT instead of Multithreaded statically linked
-	CRT).
-	* create.c (pthread_create): Likewise; fix typo.
-	* private.c (ptw32_threadStart): Eliminate use of terminate() which doesn't
-	throw exceptions.
-	* Remove unnecessary #includes from a number of modules -
-	[I had to #include malloc.h in implement.h for gcc - rpj].
-
-2001-05-29  Thomas Pfaff <tpfaff at gmx.net>
-
-	* pthread.h (PTHREAD_MUTEX_DEFAULT): New; equivalent to
-	PTHREAD_MUTEX_DEFAULT_NP.
-	* (PTHREAD_MUTEX_NORMAL): Similarly.
-	* (PTHREAD_MUTEX_ERRORCHECK): Similarly.
-	* (PTHREAD_MUTEX_RECURSIVE): Similarly.
-	* (pthread_mutex_setdefaultkind_np): New; Linux compatibility stub
-	for pthread_mutexattr_settype.
-	* (pthread_mutexattr_getkind_np): New; Linux compatibility stub
-	for pthread_mutexattr_gettype.
-	* mutex.c (pthread_mutexattr_settype): New; allow
-	the following types of mutex:
-	  PTHREAD_MUTEX_DEFAULT_NP
-	  PTHREAD_MUTEX_NORMAL_NP
-	  PTHREAD_MUTEX_ERRORCHECK_NP
-	  PTHREAD_MUTEX_RECURSIVE_NP
-	* Note that PTHREAD_MUTEX_DEFAULT is equivalent to
-	PTHREAD_MUTEX_NORMAL - ie. mutexes should no longer
-	be recursive by default, and a thread will deadlock if it
-	tries to relock a mutex it already owns. This is inline with
-	other pthreads implementations.
-	* (pthread_mutex_lock): Process the lock request
-	according to the mutex type.
-	* (pthread_mutex_init): Eliminate use of Win32 mutexes as the
-	basis of POSIX mutexes - instead, a combination of one critical section
-	and one semaphore are used in conjunction with Win32 Interlocked* routines.
-	* (pthread_mutex_destroy): Likewise.
-	* (pthread_mutex_lock): Likewise.
-	* (pthread_mutex_trylock): Likewise.
-	* (pthread_mutex_unlock): Likewise.
-	* Use longjmp/setjmp to implement cancelation when building the library
-	using a C compiler which doesn't support exceptions, e.g. gcc -x c (note
-	that gcc -x c++ uses exceptions).
-	* Also fixed some of the same typos and eliminated PT_STDCALL as
-	Milan Gardian's patches above.
-
-2001-02-07  Alexander Terekhov <TEREKHOV at de.ibm.com>
-
-	* rwlock.c: Revamped.
-	* implement.h (pthread_rwlock_t_): Redefined.
-	This implementation does not have reader/writer starvation problem.
-	Rwlock attempts to behave more like a normal mutex with
-	races and scheduling policy determining who is more important;
-	It also supports recursive locking,
-	has less synchronization overhead (no broadcasts at all,
-	readers are not blocked on any condition variable) and seem to
-	be faster than the current implementation [W98 appears to be
-	approximately 15 percent faster at least - on top of speed increase
-	from Thomas Pfaff's changes to mutex.c - rpj].
-
-2000-12-29  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* Makefile: Back-out "for" loops which don't work.
-
-	* GNUmakefile: Remove the fake.a target; add the "realclean"
-	target; don't remove built libs under the "clean" target.
-
-	* config.h: Add a guard against multiple inclusion.
-
-	* semaphore.h: Add some defines from config.h to make
-	semaphore.h independent of config.h when building apps.
-
-	* pthread.h (_errno): Back-out previous fix until we know how to
-	fix it properly.
-
-	* implement.h (lockCount): Add missing element to pthread_mutex_t_.
-
-	* sync.c (pthread_join): Spelling fix in comment.
-
-	* private.c (ptw32_threadStart): Reset original termination
-	function (C++).
-	(ptw32_threadStart): Cleanup detached threads early in case
-	the library is statically linked.
-	(ptw32_callUserDestroyRoutines): Remove [SEH] __try block from
-	destructor call so that unhandled exceptions will be passed through
-	to the 	system; call terminate() from [C++] try block for the same
-	reason.
-
-	* tsd.c (pthread_getspecific): Add comment.
-
-	* mutex.c (pthread_mutex_init): Initialise new elements in
-	pthread_mutex_t.
-	(pthread_mutex_unlock): Invert "pthread_equal()" test.
-
-2000-12-28  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* semaphore.c (mode_t): Use ifndef HAVE_MODE_T to include definition.
-
-	* config.h.in (HAVE_MODE_T): Added.
-	(_UWIN): Start adding defines for the UWIN package.
-
-	* private.c (ptw32_threadStart): Unhandled exceptions are
-	now passed through to the system to deal with. This is consistent
-	with normal Windows behaviour. C++ applications may use
-	set_terminate() to override the default behaviour which is
-	to call ptw32_terminate(). Ptw32_terminate() cleans up some
-	POSIX thread stuff before calling the system default function
-	which calls abort(). The users termination function should conform
-	to standard C++ semantics which is to not return. It should
-	exit the thread (call pthread_exit()) or exit the application.
-	* private.c (ptw32_terminate): Added as the default set_terminate()
-	function. It calls the system default function after cleaning up
-	some POSIX thread stuff.
-
-	* implement.h (ptw32_try_enter_critical_section): Move
-	declaration.
-	* global.c (ptw32_try_enter_critical_section): Moved
-	from dll.c.
-	* dll.c: Move process and thread attach/detach code into
-	functions in nonportable.c.
-	* nonportable.c (pthread_win32_process_attach_np): Process
-	attach code from dll.c is now available to static linked
-	applications.
-	* nonportable.c (pthread_win32_process_detach_np): Likewise.
-	* nonportable.c (pthread_win32_thread_attach_np): Likewise.
-	* nonportable.c (pthread_win32_thread_detach_np): Likewise.
-
-	* pthread.h: Add new non-portable prototypes for static
-	linked applications.
-
-	* GNUmakefile (OPT): Increase optimisation flag and remove
-	debug info flag.
-
-	* pthread.def: Add new non-portable exports for static
-	linked applications.
-
-2000-12-11  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* FAQ: Update Answer 6 re getting a fully working
-	Mingw32 built library.
-
-2000-10-10  Steven Reddie <smr at essemer.com.au>
- 
-        * misc.c (pthread_self): Restore Win32 "last error"
-        cleared by TlsGetValue() call in
-        pthread_getspecific()
- 
-2000-09-20  Arthur Kantor <akantor at bexusa.com>
- 
-        * mutex.c (pthread_mutex_lock): Record the owner
-        of the mutex. This requires also keeping count of
-        recursive locks ourselves rather than leaving it
-        to Win32 since we need to know when to NULL the
-        thread owner when the mutex is unlocked.
-        (pthread_mutex_trylock): Likewise.
-        (pthread_mutex_unlock): Check that the calling
-        thread owns the mutex, decrement the recursive
-        lock count, and NULL the owner if zero. Return
-        EPERM if the mutex is owned by another thread.
-        * implement.h (pthread_mutex_t_): Add ownerThread
-        and lockCount members.
-
-2000-09-13  Jef Gearhart <jgearhart at tpssys.com>
-
-	* mutex.c (pthread_mutex_init): Call
-	TryEnterCriticalSection through the pointer
-	rather than directly so that the dll can load
-	on Windows versions that can't resolve the
-	function, eg. Windows 95
-
-2000-09-09  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.h (ctime_r): Fix arg.
-
-2000-09-08  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* GNUmakefile(_WIN32_WINNT=0x400): Define in CFLAGS;
-	doesn't seem to be needed though.
-
-	* cancel.c (pthread_cancel): Must get "self" through
-	calling pthread_self() which will ensure a POSIX thread
-	struct is built for non-POSIX threads; return an error
-	if this fails
-	- Ollie Leahy <ollie at mpt.ie>
-	(pthread_setcancelstate): Likewise.
-	(pthread_setcanceltype): Likewise.
-	* misc.c (ptw32_cancelable_wait): Likewise.
-
-	* private.c (ptw32_tkAssocCreate): Remove unused #if 0
-	wrapped code.
-
-	* pthread.h (ptw32_get_exception_services_code):
-	Needed to be forward declared unconditionally.
-
-2000-09-06  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* cancel.c (pthread_cancel): If called from the main
-	thread "self" would be NULL; get "self" via pthread_self()
-	instead of directly from TLS so that an implicit
-	pthread object is created.
-
-	* misc.c (pthread_equal): Strengthen test for NULLs.
-
-2000-09-02  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* condvar.c (ptw32_cond_wait_cleanup): Ensure that all
-	waking threads check if they are the last, and notify
-	the broadcaster if so - even if an error occurs in the
-	waiter.
-
-	* semaphore.c (_decrease_semaphore): Should be
-	a call to ptw32_decrease_semaphore.
-	(_increase_semaphore): Should be a call to
-	ptw32_increase_semaphore.
-
-	* misc.c (ptw32_cancelable_wait): Renamed from
-	CancelableWait.
-	* rwlock.c (_rwlock_check*): Renamed to
-	ptw32_rwlock_check*.
-	* mutex.c (_mutex_check*): Renamed to ptw32_mutex_check*.
-	* condvar.c (cond_timed*): Renamed to ptw32_cond_timed*.
-	(_cond_check*): Renamed to ptw32_cond_check*.
-	(cond_wait_cleanup*): Rename to ptw32_cond_wait_cleanup*.
-	(ptw32_cond_timedwait): Add comments.
-
-2000-08-22  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* private.c (ptw32_throw): Fix exception test;
-	move exceptionInformation declaration.
-
-	* tsd.c (pthread_key_create): newkey wrongly declared.
-
-	* pthread.h: Fix comment block.
-
-2000-08-18  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* mutex.c (pthread_mutex_destroy): Check that the mutex isn't
-	held; invalidate the mutex as early as possible to avoid
-	contention; not perfect - FIXME!
-
-	* rwlock.c (pthread_rwlock_init): Remove redundant assignment
-	to "rw".
-	(pthread_rwlock_destroy): Invalidate the rwlock before
-	freeing up any of it's resources - to avoid contention.
-
-	* private.c (ptw32_tkAssocCreate): Change assoc->lock
-	to use a dynamically initialised mutex - only consumes
-	a W32 mutex or critical section when first used,
-	not before.
-
-	* mutex.c (pthread_mutex_init): Remove redundant assignment
-	to "mx".
-	(pthread_mutexattr_destroy): Set attribute to NULL
-	before freeing it's memory - to avoid contention.
-
-	* implement.h (PTW32_EPS_CANCEL/PTW32_EPS_EXIT):
-	Must be defined for all compilers - used as generic
-	exception selectors by ptw32_throw().
-
-	* Several: Fix typos from scripted edit session
-	yesterday.
-
-	* nonportable.c (pthread_mutexattr_setforcecs_np):
-	Moved this function from mutex.c.
-	(pthread_getw32threadhandle_np): New function to
-	return the win32 thread handle that the POSIX
-	thread is using.
-	* mutex.c (pthread_mutexattr_setforcecs_np):
-	Moved to new file "nonportable.c".
-
-	* pthread.h (PTW32_BUILD): Only	redefine __except
-	and catch compiler keywords if we aren't building
-	the library (ie. PTW32_BUILD is not defined) - 
-	this is safer than defining and then undefining
-	if not building the library.
-	* implement.h: Remove __except and catch undefines.
-	* Makefile (CFLAGS): Define PTW32_BUILD.
-	* GNUmakefile (CFLAGS): Define PTW32_BUILD.
-
-	* All appropriate: Change Pthread_exception* to
-	ptw32_exception* to be consistent with internal
-	identifier naming.
-
-	* private.c (ptw32_throw): New function to provide
-	a generic exception throw for all internal
-	exceptions and EH schemes.
-	(ptw32_threadStart): pthread_exit() value is now
-	returned via the thread structure exitStatus
-	element.
-	* exit.c (pthread_exit): pthread_exit() value is now
-	returned via the thread structure exitStatus
-	element.
-	* cancel.c (ptw32_cancel_self): Now uses ptw32_throw.
-	(pthread_setcancelstate): Ditto.
-	(pthread_setcanceltype): Ditto.
-	(pthread_testcancel): Ditto.
-	(pthread_cancel): Ditto.
-	* misc.c (CancelableWait): Ditto.
-	* exit.c (pthread_exit): Ditto.
-	* All applicable: Change PTW32_ prefix to
-	PTW32_ prefix to remove leading underscores
-	from private library identifiers.
-
-2000-08-17  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* All applicable: Change _pthread_ prefix to
-	ptw32_ prefix to remove leading underscores
-	from private library identifiers (single
-	and double leading underscores are reserved in the
-	ANSI C standard for compiler implementations).
-
-	* tsd.c (pthread_create_key): Initialise temporary
-	key before returning it's address to avoid race
-	conditions.
-
-2000-08-13  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* errno.c: Add _MD precompile condition; thus far
-	had no effect when using /MD compile option but I
-	thnk it should be there.
-
-	* exit.c: Add __cplusplus to various #if lines;
-	was compiling SEH code even when VC++ had
-	C++ compile options.
-
-	* private.c: ditto.
-
-	* create.c (pthread_create): Add PT_STDCALL macro to
-	function pointer arg in _beginthread().
-
-	* pthread.h: PT_STDCALL really does need to be defined
-	in both this and impliment.h; don't set it to __cdecl
-	- this macro is only used to extend function pointer
-	casting for functions that will be passed as parameters.
-	(~PThreadCleanup): add cast and group expression.
-	(_errno): Add _MD compile conditional.
-	(PtW32NoCatchWarn): Change pragma message.
-
-	* implement.h: Move and change PT_STDCALL define.
-
-	* need_errno.h: Add _MD to compilation conditional.
-
-	* GNUmakefile: Substantial rewrite for new naming
-	convention; set for nil optimisation (turn it up
-	when we have a working library build; add target
-	"fake.a" to build a libpthreadw32.a from the VC++
-	built DLL pthreadVCE.dll.
-
-	* pthread.def (LIBRARY): Don't specify in the .def
-	file - it is specified on the linker command line
-	since we now use the same .def file for variously
-	named .dlls.
-
-	* Makefile: Substantial rewrite for new naming
-	convention; default nmake target only issues a
-	help message; run nmake with specific target
-	corresponding to the EH scheme being used.
-
-	* README: Update information; add naming convention
-	explanation.
-
-	* ANNOUNCE: Update information.
-
-2000-08-12  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.h: Add compile-time message when using
-	MSC_VER compiler and C++ EH to warn application
-	programmers to use PtW32Catch instead of catch(...)
-	if they want cancelation and pthread_exit to work.
-
-	* implement.h: Remove #include <semaphore.h>; we
-	use our own local semaphore.h.
-
-2000-08-10  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* cleanup.c (pthread_pop_cleanup): Remove _pthread
-	prefix from __except and catch keywords; implement.h
-	now simply undefines ptw32__except and
-	ptw32_catch if defined; VC++ was not textually
-	substituting ptw32_catch etc back to catch as
-	it was redefined; the reason for using the prefixed
-	version was to make it clear that it was not using
-	the pthread.h redefined catch keyword.
-
-	* private.c (ptw32_threadStart): Ditto.
-	(ptw32_callUserDestroyRoutines): Ditto.
-
-	* implement.h (ptw32__except): Remove #define.
-	(ptw32_catch): Remove #define.
-
-	* GNUmakefile (pthread.a): New target to build
-	libpthread32.a from pthread.dll using dlltool.
-
-	* buildlib.bat: Duplicate cl commands with args to
-	build C++ EH version of pthread.dll; use of .bat
-	files is redundant now that nmake compatible
-	Makefile is included; used as a kludge only now.
-
-	* Makefile: Localise some macros and fix up the clean:
-	target to extend it and work properly.
-
-	* CONTRIBUTORS: Add contributors.
-
-	* ANNOUNCE: Updated.
-
-	* README: Updated.
-
-2000-08-06  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.h: Remove #warning - VC++ doesn't accept it.
-
-2000-08-05  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.h (PtW32CatchAll): Add macro. When compiling
-	applications using VC++ with C++ EH rather than SEH
-	'PtW32CatchAll' must be used in place of any 'catch( ... )'
-	if the application wants pthread cancelation or
-	pthread_exit() to work.
-
-2000-08-03  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* pthread.h: Add a base class ptw32_exception for
-	library internal exceptions and change the "catch"
-	re-define macro to use it.
-
-2000-08-02  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* GNUmakefile (CFLAGS): Add -mthreads.
-	Add new targets to generate cpp and asm output.
-
-	* sync.c (pthread_join): Remove dead code.
-
-2000-07-25  Tristan Savatier <tristan at mpegtv.com>
-
-	* sched.c (sched_get_priority_max): Handle different WinCE and
-	Win32 priority values together.
-	(sched_get_priority_min): Ditto.
-
-2000-07-25  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* create.c (pthread_create): Force new threads to wait until
-	pthread_create has the new thread's handle; we also retain
-	a local copy of the handle for internal use until
-	pthread_create returns.
-
-	* private.c (ptw32_threadStart): Initialise ei[].
-	(ptw32_threadStart): When beginthread is used to start the
-	thread, force waiting until the creator thread had the 
-	thread handle.
-
-	* cancel.c (ptw32_cancel_thread): Include context switch
-	code for defined(_X86_) environments in addition to _M_IX86.
-
-	* rwlock.c (pthread_rwlock_destroy): Assignment changed
-	to avoid compiler warning.
-
-	* private.c (ptw32_get_exception_services_code): Cast
-	NULL return value to avoid compiler warning.
-
-	* cleanup.c (pthread_pop_cleanup): Initialise "cleanup" variable
-	to avoid compiler warnings.
-
-	* misc.c (ptw32_new): Change "new" variable to "t" to avoid
-	confusion with the C++ keyword of the same name.
-
-	* condvar.c (cond_wait_cleanup): Initialise lastWaiter variable.
-	(cond_timedwait): Remove unused local variables. to avoid
-	compiler warnings.
-
-	* dll.c (dllMain): Remove 2000-07-21 change - problem
-	appears to be in pthread_create().
-
-2000-07-22  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* tsd.c (pthread_key_create): If a destructor was given
-	and the pthread_mutex_init failed, then would try to
-	reference a NULL pointer (*key); eliminate this section of
-	code by using a dynamically initialised mutex
-	(PTHREAD_MUTEX_INITIALIZER).
-
-	* tsd.c (pthread_setspecific): Return an error if
-	unable to set the value; simplify cryptic conditional.
-
-	* tsd.c (pthread_key_delete): Locking threadsLock relied
-	on mutex_lock returning an error if the key has no destructor.
-	ThreadsLock is only initialised if the key has a destructor.
-	Making this mutex a static could reduce the number of mutexes
-	used by an application since it is actually created only at
-	first use and it's often destroyed soon after.
-	
-2000-07-22  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* FAQ: Added Q5 and Q6.
-
-2000-07-21  David Baggett <dmb at itasoftware.com>
-
-	* dll.c: Include resource leakage work-around. This is a
-	partial FIXME which doesn't stop all leakage. The real
-	problem needs to be found and fixed.
-
-2000-07-21  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
-
-	* create.c (pthread_create): Set threadH to 0 (zero)
-	everywhere. Some assignments were using NULL. Maybe
-	it should be NULL everywhere - need to check. (I know
-	they are nearly always the same thing - but not by
-	definition.)
-
-	* misc.c (pthread_self): Try to catch NULL thread handles
-	at the point where they might be generated, even though
-	they should always be valid at this point.
-
-	* tsd.c (pthread_setspecific): return an error value if
-	pthread_self() returns NULL.
-
-	* sync.c (pthread_join): return an error value if
-	pthread_self() returns NULL.
-
-	* signal.c (pthread_sigmask): return an error value if
-	pthread_self() returns NULL.
-
-2000-03-02  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* attr.c (pthread_attr_init): Set default stacksize to zero (0)
-	rather than PTHREAD_STACK_MIN even though these are now the same.
-
-	* pthread.h (PTHREAD_STACK_MIN): Lowered to 0.
-
-2000-01-28  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* mutex.c (pthread_mutex_init): Free mutex if it has been alloced;
-	if critical sections can be used instead of Win32 mutexes, test
-	that the critical section works and return an error if not.
-
-2000-01-07  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* cleanup.c (pthread_pop_cleanup): Include SEH code only if MSC is not
-	compiling as C++.
-	(pthread_push_cleanup): Include SEH code only if MSC is not
-	compiling as C++.
-
-	* pthread.h: Include SEH code only if MSC is not
-	compiling as C++.
-
-	* implement.h: Include SEH code only if MSC is not
-	compiling as C++.
-
-	* cancel.c (ptw32_cancel_thread): Add _M_IX86 check.
-	(pthread_testcancel): Include SEH code only if MSC is not
-	compiling as C++.
-	(ptw32_cancel_self): Include SEH code only if MSC is not
-	compiling as C++.
-
-2000-01-06  Erik Hensema <erik.hensema at group2000.nl>
-
-	* Makefile: Remove inconsistencies in 'cl' args
-
-2000-01-04  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* private.c (ptw32_get_exception_services_code): New; returns
-	value of EXCEPTION_PTW32_SERVICES.
-	(ptw32_processInitialize): Remove initialisation of
-	ptw32_exception_services which is no longer needed.
-
-	* pthread.h (ptw32_exception_services): Remove extern.
-	(ptw32_get_exception_services_code): Add function prototype;
-	use this to return EXCEPTION_PTW32_SERVICES value instead of
-	using the ptw32_exception_services variable which I had
-	trouble exporting through pthread.def.
-
-	* global.c (ptw32_exception_services): Remove declaration.
-
-1999-11-22  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* implement.h: Forward declare ptw32_new();
-
-	* misc.c (ptw32_new): New; alloc and initialise a new pthread_t.
-	(pthread_self): New thread struct is generated 	by new routine
-	ptw32_new().
-
-	* create.c (pthread_create): New thread struct is generated
-	by new routine ptw32_new().
-
-1999-11-21  Ross Johnson  <rpj at special.ise.canberra.edu.au>
-
-	* global.c (ptw32_exception_services): Declare new variable. 
-
-	* private.c (ptw32_threadStart): Destroy thread's
-	cancelLock mutex; make 'catch' and '__except' usageimmune to
-	redfinitions in pthread.h.
-	(ptw32_processInitialize): Init new constant ptw32_exception_services.
-
-	* create.c (pthread_create): Initialise thread's cancelLock
-	mutex.
-
-	* cleanup.c (pthread_pop_cleanup): Make 'catch' and '__except'
-	usage immune to redfinition s in pthread.h.
-
-	* private.c: Ditto.
-
-	* pthread.h (catch): Redefine 'catch' so that C++ applications
-	won't catch our internal exceptions.
-	(__except): ditto for __except.
-
-	* implement.h (ptw32_catch): Define internal version
-	of 'catch' because 'catch' is redefined by pthread.h.
-	(__except): ditto for __except.
-	(struct pthread_t_): Add cancelLock mutex for async cancel
-	safety.
-
-1999-11-21  Jason Nye <jnye at nbnet.nb.ca>, Erik Hensema <erik.hensema at group2000.nl>
-
-	* cancel.c (ptw32_cancel_self): New; part of the async
-	cancellation implementation.
-	(ptw32_cancel_thread): Ditto; this function is X86
-	processor specific.
-	(pthread_setcancelstate): Add check for pending async
-	cancel request and cancel the calling thread if
-	required; add async-cancel safety lock.
-	(pthread_setcanceltype): Ditto.
-
-1999-11-13  Erik Hensema <erik.hensema at group2000.nl>
-
-	* configure.in (AC_OUTPUT): Put generated output into GNUmakefile
-	rather than Makefile. Makefile will become the MSC nmake compatible
-	version
-
-1999-11-13  John Bossom (John.Bossom@cognos.com>
-
-	* misc.c (pthread_self): Add a note about GetCurrentThread
-	returning a pseudo-handle
-
-1999-11-10  Todd Owen <towen at lucidcalm.dropbear.id.au>
-
-	* dll.c (dllMain): Free kernel32 ASAP.
-	If TryEnterCriticalSection is not being used, then free
-	the kernel32.dll handle now, rather than leaving it until
-	DLL_PROCESS_DETACH.
-
-	Note: this is not a pedantic exercise in freeing unused
-	resources!  It is a work-around for a bug in Windows 95
-	(see microsoft knowledge base article, Q187684) which
-	does Bad Things when FreeLibrary is called within
-	the DLL_PROCESS_DETACH code, in certain situations.
-	Since w95 just happens to be a platform which does not
-	provide TryEnterCriticalSection, the bug will be
-	effortlessly avoided.
-
-1999-11-10  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sync.c (pthread_join): Make it a deferred cancelation point.
-
-	* misc.c (pthread_self): Explicitly initialise implicitly
-	created thread state to default values.
-
-1999-11-05  Tristan Savatier <tristan at mpegtv.com>
-
-	* pthread.h (winsock.h): Include unconditionally.
-	(ETIMEDOUT): Change fallback value to that defined by winsock.h.
-	
-	* general: Patched for portability to WinCE. The details are
-	described in the file WinCE-PORT. Follow the instructions
-	in README.WinCE to make the appropriate changes in config.h.
-
-1999-10-30  Erik Hensema <erik.hensema at group2000.nl>
-
-	* 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:
-
-1999-10-23  Erik Hensema <erik.hensema at group2000.nl>
-
-	* pthread.h (ctime_r): Fix incorrect argument "_tm"
-
-1999-10-21  Aurelio Medina <aureliom at crt.com>
-
-	* pthread.h (_POSIX_THREADS): Only define it if it isn't
-	already defined. Projects may need to define this on
-	the CC command line under Win32 as it doesn't have unistd.h
-
-1999-10-17  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* rwlock.c (pthread_rwlock_destroy): Add cast to remove compile
-	warning.
-
-	* condvar.c (pthread_cond_broadcast): Only release semaphores
-	if there are waiting threads.
-
-1999-10-15  Lorin Hochstein <lmh at xiphos.ca>, Peter Slacik <Peter.Slacik at tatramed.sk>
-
-	* condvar.c (cond_wait_cleanup): New static cleanup handler for
-	cond_timedwait;
-	(cond_timedwait): pthread_cleanup_push args changed;
-	canceling a thread while it's in pthread_cond_wait
-	will now decrement the waiters count and cleanup if it's the
-	last waiter.
-
-1999-10-15  Graham Dumpleton <Graham.Dumpleton at ra.pad.otc.telstra.com.au>
-
-	* condvar.c (cond_wait_cleanup): the last waiter will now reset the CV's
-	wasBroadcast flag
-
-Thu Sep 16 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* rwlock.c (pthread_rwlock_destroy): Add serialisation.
-	(_rwlock_check_need_init): Check for detroyed rwlock.
-	* rwlock.c: Check return codes from _rwlock_check_need_init();
-	modify comments; serialise access to rwlock objects during
-	operations; rename rw_mutex to rw_lock.
-	* implement.h: Rename rw_mutex to rw_lock.
-	* mutex.c (pthread_mutex_destroy): Add serialisation.
-	(_mutex_check_need_init): Check for detroyed mutex.
-	* condvar.c (pthread_cond_destroy): Add serialisation.
-	(_cond_check_need_init): Check for detroyed condvar.
-	* mutex.c: Modify comments.
-	* condvar.c: Modify comments.
-
-1999-08-10  Aurelio Medina  <aureliom at crt.com>
-
-	* implement.h (pthread_rwlock_t_): Add.
-	* pthread.h (pthread_rwlock_t): Add.
-	(PTHREAD_RWLOCK_INITIALIZER): Add.
-	Add rwlock function prototypes.
-	* rwlock.c: New module.
-	* pthread.def: Add new rwlock functions.
-	* private.c (ptw32_processInitialize): initialise
-	ptw32_rwlock_test_init_lock critical section.
-	* global.c (ptw32_rwlock_test_init_lock): Add.
-
-	* mutex.c (pthread_mutex_destroy): Don't free mutex memory
-	if mutex is PTHREAD_MUTEX_INITIALIZER and has not been
-	initialised yet.
-
-1999-08-08 Milan Gardian <mg at tatramed.sk>
-
-	* mutex.c (pthread_mutex_destroy): Free mutex memory.
-
-1999-08-22  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* exit.c (pthread_exit): Fix reference to potentially
-	uninitialised pointer.
-
-1999-08-21  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_threadStart): Apply fix of 1999-08-19
-	this time to C++ and non-trapped C versions. Ommitted to
-	do this the first time through.
-
-1999-08-19  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_threadStart): Return exit status from
-	the application thread startup routine.
-	- Milan Gardian <mg at tatramed.sk>
-
-1999-08-18  John Bossom <john.Bossom at cognos.com>
-
-	* exit.c (pthread_exit): Put status into pthread_t->exitStatus
-	* private.c (ptw32_threadStart): Set pthread->exitStatus
-	on exit of try{} block.
-	* sync.c (pthread_join): use pthread_exitStatus value if the
-	thread exit doesn't return a value (for Mingw32 CRTDLL
-	which uses endthread instead of _endthreadex).
-
-Tue Aug 17 20:17:58 CDT 1999  Mumit Khan  <khan at xraylith.wisc.edu>
-
-        * create.c (pthread_create): Add CRTDLL suppport.
-        * exit.c (pthread_exit): Likewise.
-        * private.c (ptw32_threadStart): Likewise.
-        (ptw32_threadDestroy): Likewise.
-        * sync.c (pthread_join): Likewise.
-        * tests/join1.c (main): Warn about partial support for CRTDLL.
-
-Tue Aug 17 20:00:08 1999  Mumit Khan  <khan at xraylith.wisc.edu>
-
-        * Makefile.in (LD): Delete entry point.
-        * acconfig.h (STDCALL): Delete unused macro.
-        * configure.in: Remove test for STDCALL.
-        * config.h.in: Regenerate.
-        * errno.c (_errno): Fix self type.
-        * pthread.h (PT_STDCALL): Move from here to
-        * implement.h (PT_STDCALL): here.
-        (ptw32_threadStart): Fix prototype.
-        * private.c (ptw32_threadStart): Likewise.
-
-1999-08-14  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* exit.c (pthread_exit): Don't call pthread_self() but
-	get thread handle directly from TSD for efficiency.
-	
-1999-08-12  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_threadStart): ei[] only declared if _MSC_VER.
-
-	* exit.c (pthread_exit): Check for implicitly created threads
-	to avoid raising an unhandled exception.
-	
-1999-07-12  Peter Slacik <Peter.Slacik at tatramed.sk>
-
-	* condvar.c (pthread_cond_destroy): Add critical section.
-	(cond_timedwait): Add critical section; check for timeout
-	waiting on semaphore.
-	(pthread_cond_broadcast): Add critical section.
-
-1999-07-09  Lorin Hochstein <lmh at xiphos.ca>, John Bossom <John.Bossom at Cognos.COM>
-
-	The problem was that cleanup handlers were not executed when
-	pthread_exit() was called.
-
-	* implement.h (pthread_t_): Add exceptionInformation element for
-	C++ per-thread exception information.
-	(general): Define and rename exceptions.
-
-1999-07-09  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* misc.c (CancelableWait):  PTW32_EPS_CANCEL (SEH) and
-	ptw32_exception_cancel (C++) used to identify the exception.
-
-	* cancel.c (pthread_testcancel): PTW32_EPS_CANCEL (SEH) and
-	ptw32_exception_cancel (C++) used to identify the exception.
-
-	* exit.c (pthread_exit): throw/raise an exception to return to
-	ptw32_threadStart() to exit the thread. PTW32_EPS_EXIT (SEH)
-	and ptw32_exception_exit (C++) used to identify the exception.
-
-	* private.c (ptw32_threadStart): Add pthread_exit exception trap;
-	clean up and exit the thread directly rather than via pthread_exit().
-
-Sun May 30 00:25:02 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* semaphore.h (mode_t): Conditionally typedef it.
-
-Fri May 28 13:33:05 1999  Mark E. Armstrong <avail at pacbell.net>
-
-	* condvar.c (pthread_cond_broadcast): Fix possible memory fault
-	
-Thu May 27 13:08:46 1999  Peter Slacik <Peter.Slacik at tatramed.sk>
-
-	* condvar.c (pthread_cond_broadcast): Fix logic bug
-
-Thu May 27 13:08:46 1999  Bossom, John <John.Bossom at Cognos.COM>
-
-	* condvar.c (pthread_cond_broadcast): optimise sem_post loop
-
-Fri May 14 12:13:18 1999  Mike Russo <miker at eai.com>
-
-	* attr.c (pthread_attr_setdetachstate): Fix logic bug
-
-Sat May  8 09:42:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.def (sem_open): Add.
-	(sem_close): Add.
-	(sem_unlink): Add.
-	(sem_getvalue): Add.
-
-	* FAQ (Question 3): Add.
-
-Thu Apr  8 01:16:23 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* semaphore.c (sem_open): New function; returns an error (ENOSYS).
-	(sem_close): ditto.
-	(sem_unlink): ditto.
-	(sem_getvalue): ditto.
-
-	* semaphore.h (_POSIX_SEMAPHORES): define.
-	
-Wed Apr  7 14:09:52 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* errno.c (_REENTRANT || _MT): Invert condition.
-
-	* pthread.h (_errno): Conditionally include prototype.
-
-Wed Apr  7 09:37:00 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* *.c (comments): Remove individual attributions - these are
-	documented sufficiently elsewhere.
-
-	* implement.h (pthread.h): Remove extraneous include.
-
-Sun Apr  4 11:05:57 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sched.c (sched.h): Include.
-
-	* sched.h: New file for POSIX 1b scheduling.
-
-	* pthread.h: Move opaque structures to implement.h; move sched_*
-	prototypes out and into sched.h.
-
-	* implement.h: Add opaque structures from pthread.h.
-
-	* sched.c (sched_yield): New function.
-
-	* condvar.c (ptw32_sem_*): Rename to sem_*; except for
-	ptw32_sem_timedwait which is an private function.
-
-Sat Apr  3 23:28:00 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* Makefile.in (OBJS): Add errno.o.
-
-Fri Apr  2 11:08:50 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h (ptw32_sem_*): Remove prototypes now defined in
-	semaphore.h.
-
-	* pthread.h (sempahore.h): Include.
-
-	* semaphore.h: New file for POSIX 1b semaphores.
-
-	* semaphore.c (ptw32_sem_timedwait): Moved to private.c.
-
-	* pthread.h (ptw32_sem_t): Change to sem_t. 
-
-	* private.c (ptw32_sem_timedwait): Moved from semaphore.c;
-	set errno on error.
-
-	* pthread.h (pthread_t_): Add per-thread errno element.
-
-Fri Apr  2 11:08:50 1999  John Bossom <jebossom at cognos.com>
-
-	* semaphore.c (ptw32_sem_*): Change to sem_*; these functions
-	will be exported from the library; set errno on error.
-
-	* errno.c (_errno): New file. New function.
-
-Fri Mar 26 14:11:45 1999  Tor Lillqvist <tml at iki.fi>
-
-	* semaphore.c (ptw32_sem_timedwait): Check for negative
-	milliseconds.
-
-Wed Mar 24 11:32:07 1999  John Bossom <jebossom at cognos.com>
-
-	* misc.c (CancelableWait): Initialise exceptionInformation[2].
-	(pthread_self): Get a real Win32 thread handle for implicit threads.
-
-	* cancel.c (pthread_testcancel): Initialise exceptionInformation[2].
-
-	* implement.h (SE_INFORMATION): Fix values.
-
-	* private.c (ptw32_threadDestroy): Close the thread handle.
-
-Fri Mar 19 12:57:27 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cancel.c (comments): Update and cleanup.
-
-Fri Mar 19 09:12:59 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_threadStart): status returns PTHREAD_CANCELED.
-
-	* pthread.h (PTHREAD_CANCELED): defined.
-
-Tue Mar 16  1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* all: Add GNU LGPL and Copyright and Warranty.
-	
-Mon Mar 15 00:20:13 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* condvar.c (pthread_cond_init): fix possible uninitialised use
-	of cv.
-
-Sun Mar 14 21:01:59 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* condvar.c (pthread_cond_destroy): don't do full cleanup if
-	static initialised cv has never been used.
-	(cond_timedwait): check result of auto-initialisation.
-
-Thu Mar 11 09:01:48 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (pthread_mutex_t): revert to (pthread_mutex_t *);
-	define a value to serve as PTHREAD_MUTEX_INITIALIZER.
-	(pthread_mutex_t_): remove staticinit and valid elements.
-	(pthread_cond_t): revert to (pthread_cond_t_ *);
-	define a value to serve as PTHREAD_COND_INITIALIZER.
-	(pthread_cond_t_): remove staticinit and valid elements.
-
-	* mutex.c (pthread_mutex_t args): adjust indirection of references.
-	(all functions): check for PTHREAD_MUTEX_INITIALIZER value;
-	check for NULL (invalid).
-
-	* condvar.c (pthread_cond_t args): adjust indirection of references.
-	(all functions): check for PTHREAD_COND_INITIALIZER value;
-	check for NULL (invalid).
-
-Wed Mar 10 17:18:12 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* misc.c (CancelableWait): Undo changes from Mar 8 and 7.
-
-Mon Mar  8 11:18:59 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* misc.c (CancelableWait): Ensure cancelEvent handle is the lowest
-	indexed element in the handles array. Enhance test for abandoned
-	objects.
-
-	* pthread.h (PTHREAD_MUTEX_INITIALIZER): Trailing elements not
-	initialised are set to zero by the compiler. This avoids the
-	problem of initialising the opaque critical section element in it.
-	(PTHREAD_COND_INITIALIZER): Ditto.
-
-	* semaphore.c (ptw32_sem_timedwait): Check sem == NULL earlier.
-
-Sun Mar  7 12:31:14 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* condvar.c (pthread_cond_init): set semaphore initial value
-	to 0, not 1. cond_timedwait was returning signaled immediately.
-
-	* misc.c (CancelableWait): Place the cancel event handle first
-	in the handle table for WaitForMultipleObjects. This ensures that
-	the cancel event is recognised and acted apon if both objects
-	happen to be signaled together.
-
-	* private.c (ptw32_cond_test_init_lock): Initialise and destroy.
-
-	* implement.h (ptw32_cond_test_init_lock): Add extern.
-
-	* global.c (ptw32_cond_test_init_lock): Add declaration. 
-
-	* condvar.c (pthread_cond_destroy): check for valid initialised CV;
-	flag destroyed CVs as invalid.
-	(pthread_cond_init): pthread_cond_t is no longer just a pointer.
-	This is because PTHREAD_COND_INITIALIZER needs state info to reside
-	in pthread_cond_t so that it can initialise on first use. Will work on
-	making pthread_cond_t (and other objects like it) opaque again, if
-	possible, later.
-	(cond_timedwait): add check for statically initialisation of
-	CV; initialise on first use.
-	(pthread_cond_signal): check for valid CV.
-	(pthread_cond_broadcast): check for valid CV.
-	(_cond_check_need_init): Add.
-
-	* pthread.h (PTHREAD_COND_INITIALIZER): Fix.
-	(pthread_cond_t): no longer a pointer to pthread_cond_t_.
-	(pthread_cond_t_): add 'staticinit' and 'valid' elements.
-
-Sat Mar 6 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Undate comments.
-
-Sun Feb 21 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (PTHREAD_MUTEX_INITIALIZER): missing braces around
-	cs element initialiser.
-
-1999-02-21  Ben Elliston  <bje at cygnus.com>
-
-	* pthread.h (pthread_exit): The return type of this function is
-	void, not int.
-
-	* exit.c (pthread_exit): Do not return 0.
-
-Sat Feb 20 16:03:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* dll.c (DLLMain): Expand TryEnterCriticalSection support test.
-
-	* mutex.c (pthread_mutex_trylock): The check for
-	ptw32_try_enter_critical_section == NULL should have been
-	removed long ago.
-
-Fri Feb 19 16:03:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sync.c (pthread_join): Fix pthread_equal() test.
-
-	* mutex.c (pthread_mutex_trylock): Check mutex != NULL before
-	using it.
-
-Thu Feb 18 16:17:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* misc.c (pthread_equal): Fix inverted result.
-
-	* Makefile.in: Use libpthread32.a as the name of the DLL export
-	library instead of pthread.lib.
-
-	* condvar.c (pthread_cond_init): cv could have been used unitialised;
-	initialise.
-
-	* create.c (pthread_create): parms could have been used unitialised;
-	initialise.
-
-	* pthread.h (struct pthread_once_t_): Remove redefinition.
-
-Sat Feb 13 03:03:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (struct pthread_once_t_): Replaced.
-
-	* misc.c (pthread_once): Replace with John Bossom's version;
-	has lighter weight serialisation; fixes problem of not holding
-	competing threads until after the init_routine completes.
-
-Thu Feb 11 13:34:14 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* misc.c (CancelableWait): Change C++ exception throw.
-
-	* sync.c (pthread_join): Change FIXME comment - issue resolved.
-
-Wed Feb 10 12:49:11 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* configure: Various temporary changes.
-	- Kevin Ruland <Kevin.Ruland at anheuser-busch.com>
-
-	* README: Update.
-
-	* pthread.def (pthread_attr_getstackaddr): uncomment
-	(pthread_attr_setstackaddr): uncomment
-
-Fri Feb  5 13:42:30 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* semaphore.c: Comment format changes.
-
-Thu Feb  4 10:07:28 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* global.c: Remove ptw32_exception instantiation.
-
-	* cancel.c (pthread_testcancel): Change C++ exception throw.
-
-	* implement.h: Remove extern declaration.
-
-Wed Feb  3 13:04:44 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cleanup.c: Rename ptw32_*_cleanup() to pthread_*_cleanup().
-
-	* pthread.def: Ditto.
-	
-	* pthread.h: Ditto.
-
-	* pthread.def (pthread_cleanup_push): Remove from export list;
-	the function is defined as a macro under all compilers.
-	(pthread_cleanup_pop): Ditto.
-
-	* pthread.h: Remove #if defined().
-
-Wed Feb  3 10:13:48 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sync.c (pthread_join): Check for NULL value_ptr arg;
-	check for detached threads.
-
-Tue Feb  2 18:07:43 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* implement.h: Add #include <pthread.h>.
-	Change sem_t to ptw32_sem_t.
-
-Tue Feb  2 18:07:43 1999  Kevin Ruland <Kevin.Ruland at anheuser-busch.com>
-
-	* signal.c (pthread_sigmask): Add and modify casts.
-	Reverse LHS/RHS bitwise assignments.
-
-	* pthread.h: Remove #include <semaphore.h>.
-	(PTW32_ATTR_VALID): Add cast.
-	(struct pthread_t_): Add sigmask element.
-
-	* dll.c: Add "extern C" for DLLMain.
-	(DllMain): Add cast.
-
-	* create.c (pthread_create): Set sigmask in thread.
-
-	* condvar.c: Remove #include. Change sem_* to ptw32_sem_*.
-
-	* attr.c: Changed #include.
-
-	* Makefile.in: Additional targets and changes to build the library
-	as a DLL.
-
-Fri Jan 29 11:56:28 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* Makefile.in (OBJS): Add semaphore.o to list.
-
-	* semaphore.c (ptw32_sem_timedwait): Move from private.c.
-	Rename sem_* to ptw32_sem_*.
-
-	* pthread.h (pthread_cond_t): Change type of sem_t.
-	_POSIX_SEMAPHORES no longer defined.
-
-	* semaphore.h: Contents moved to implement.h.
-	Removed from source tree.
-
-	* implement.h: Add semaphore function prototypes and rename all
-	functions to prepend 'ptw32_'. They are
-	now private to the pthreads-win32 implementation.
-
-	* private.c: Change #warning.
-	Move ptw32_sem_timedwait() to semaphore.c.
-
-	* cleanup.c: Change #warning.
-
-	* misc.c: Remove #include <errno.h>
-
-	* pthread.def: Cleanup CVS merge conflicts.
-
-	* global.c: Ditto.
-
-	* ChangeLog: Ditto.
-
-	* cleanup.c: Ditto.
-
-Sun Jan 24 01:34:52 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* semaphore.c (sem_wait): Remove second arg to 
-	pthreadCancelableWait() call.
-
-Sat Jan 23 17:36:40 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.def: Add new functions to export list.
-
-	* pthread.h (PTHREAD_MUTEX_AUTO_CS_NP): New.
-	(PTHREAD_MUTEX_FORCE_CS_NP): New.
-
-	* README: Updated.
-
-Fri Jan 22 14:31:59 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* Makefile.in (CFLAGS): Remove -fhandle-exceptions. Not needed
-	with egcs. Add -g for debugging.
-
-	* create.c (pthread_create): Replace __stdcall with PT_STDCALL
-	macro. This is a hack and must be fixed.
-
-	* misc.c (CancelableWait): Remove redundant statement.
-
-	* mutex.c (pthread_mutexattr_init): Cast calloc return value.
-
-	* misc.c (CancelableWait): Add cast.
-	(pthread_self): Add cast.
-
-	* exit.c (pthread_exit): Add cast.
-
-	* condvar.c (pthread_condattr_init): Cast calloc return value.
-
-	* cleanup.c: Reorganise conditional compilation.
-
-	* attr.c (pthread_attr_init): Remove unused 'result'.
-	Cast malloc return value.
-
-	* private.c (ptw32_callUserDestroyRoutines): Redo conditional
-	compilation.
-
-	* misc.c (CancelableWait): C++ version uses 'throw'.
-
-	* cancel.c (pthread_testcancel): Ditto.
-
-	* implement.h (class ptw32_exception): Define for C++.
-
-	* pthread.h: Fix C, C++, and Win32 SEH condition compilation
-	mayhem around pthread_cleanup_* defines. C++ version now uses John
-	Bossom's cleanup handlers.
-	(pthread_attr_t): Make 'valid' unsigned.
-	Define '_timeb' as 'timeb' for Ming32.
-	Define PT_STDCALL as nothing for Mingw32. May be temporary.
-
-	* cancel.c (pthread_testcancel): Cast return value.
-
-Wed Jan 20 09:31:28 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (pthread_mutexattr_t): Changed to a pointer.
-
-	* mutex.c (pthread_mutex_init): Conditionally create Win32 mutex
-	- from John Bossom's implementation.
-	(pthread_mutex_destroy): Conditionally close Win32 mutex
-	- from John Bossom's implementation.
-	(pthread_mutexattr_init): Replaced by John Bossom's version.
-	(pthread_mutexattr_destroy): Ditto.
-	(pthread_mutexattr_getpshared): New function from John Bossom's
-	implementation.
-	(pthread_mutexattr_setpshared): New function from John Bossom's
-	implementation.
-
-Tue Jan 19 18:27:42 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* pthread.h (pthreadCancelableTimedWait): New prototype.
-	(pthreadCancelableWait): Remove second argument.
-
-	* misc.c (CancelableWait): New static function is 
-	pthreadCancelableWait() renamed.
-	(pthreadCancelableWait): Now just calls CancelableWait() with
-	INFINITE timeout.
-	(pthreadCancelableTimedWait): Just calls CancelableWait()
-	with passed in timeout.
-
-Tue Jan 19 18:27:42 1999  Scott Lightner <scott at curriculum.com>
-
-	* private.c (ptw32_sem_timedwait): 'abstime' arg really is
-	absolute time. Calculate relative time to wait from current
-	time before passing timeout to new routine 
-	pthreadCancelableTimedWait().
-
-Tue Jan 19 10:27:39 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (pthread_mutexattr_setforcecs_np): New prototype.
-	
-	* mutex.c (pthread_mutexattr_init): Init 'pshared' and 'forcecs'
-	attributes to 0.
-	(pthread_mutexattr_setforcecs_np): New function (not portable).
-
-	* pthread.h (pthread_mutex_t): 
-	Add 'mutex' element. Set to NULL in PTHREAD_MUTEX_INITIALIZER.
-	The pthread_mutex_*() routines will try to optimise performance
-	by choosing either mutexes or critical sections as the basis
-	for pthread mutexes for each indevidual mutex.
-	(pthread_mutexattr_t_): Add 'forcecs' element.
-	Some applications may choose to force use of critical sections
-	if they know that:-
-	     the mutex is PROCESS_PRIVATE and, 
-	         either the OS supports TryEnterCriticalSection() or
-	         pthread_mutex_trylock() will never be called on the mutex.
-	This attribute will be setable via a non-portable routine.
-
-	Note: We don't yet support PROCESS_SHARED mutexes, so the
-	implementation as it stands will default to Win32 mutexes only if
-	the OS doesn't support TryEnterCriticalSection. On Win9x, and early
-	versions of NT 'forcecs' will need to be set in order to get
-	critical section based mutexes.
-
-Sun Jan 17 12:01:26 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (PTHREAD_MUTEX_INITIALIZER): Init new 'staticinit'
-	value to '1' and existing 'valid' value to '1'.
-
-	* global.c (ptw32_mutex_test_init_lock): Add.
-
-	* implement.h (ptw32_mutex_test_init_lock.): Add extern.
-
-	* private.c (ptw32_processInitialize): Init critical section for
-	global lock used by _mutex_check_need_init().
-	(ptw32_processTerminate): Ditto (:s/Init/Destroy/).
-
-	* dll.c (dllMain): Move call to FreeLibrary() so that it is only
-	called once when the process detaches.
-
-	* mutex.c (_mutex_check_need_init): New static function to test
-	and init PTHREAD_MUTEX_INITIALIZER mutexes. Provides serialised
-	access to the internal state of the uninitialised static mutex. 
-	Called from pthread_mutex_trylock() and pthread_mutex_lock() which
-	do a quick unguarded test to check if _mutex_check_need_init()
-	needs to be called. This is safe as the test is conservative
- 	and is repeated inside the guarded section of 
-	_mutex_check_need_init(). Thus in all calls except the first
-	calls to lock static mutexes, the additional overhead to lock any
-	mutex is a single memory fetch and test for zero.
-
-	* pthread.h (pthread_mutex_t_): Add 'staticinit' member. Mutexes
-	initialised by PTHREAD_MUTEX_INITIALIZER aren't really initialised
-	until the first attempt to lock it. Using the 'valid'
-	flag (which flags the mutex as destroyed or not) to record this
-	information would be messy. It is possible for a statically
-	initialised mutex such as this to be destroyed before ever being
-	used.
-
-	* mutex.c (pthread_mutex_trylock): Call _mutex_check_need_init()
-	to test/init PTHREAD_MUTEX_INITIALIZER mutexes.
-	(pthread_mutex_lock): Ditto.
-	(pthread_mutex_unlock): Add check to ensure we don't try to unlock
-	an unitialised static mutex.
-	(pthread_mutex_destroy): Add check to ensure we don't try to delete
-	a critical section that we never created. Allows us to destroy
-	a static mutex that has never been locked (and hence initialised).
-	(pthread_mutex_init): Set 'staticinit' flag to 0 for the new mutex.
-
-Sun Jan 17 12:01:26 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_sem_timedwait): Move from semaphore.c.
-
-	* semaphore.c : Remove redundant #includes.
-	(ptw32_sem_timedwait): Move to private.c.
-	(sem_wait): Add missing abstime arg to pthreadCancelableWait() call.
-
-Fri Jan 15 23:38:05 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* condvar.c (cond_timedwait): Remove comment.
-
-Fri Jan 15 15:41:28 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* pthread.h: Add new 'abstime' arg to pthreadCancelableWait()
-	prototype.
-
-	* condvar.c (cond_timedwait): New generalised function called by
-	both pthread_cond_wait() and pthread_cond_timedwait(). This is
-	essentially pthread_cond_wait() renamed and modified to add the
-	'abstime' arg and call the new ptw32_sem_timedwait() instead of
-	sem_wait().
-	(pthread_cond_wait): Now just calls the internal static
-	function cond_timedwait() with an INFINITE wait.
-	(pthread_cond_timedwait): Now implemented. Calls the internal
-	static function cond_timedwait().
-
-	* implement.h (ptw32_sem_timedwait): New internal function
-	prototype.
-
-	* misc.c (pthreadCancelableWait): Added new 'abstime' argument
-	to allow shorter than INFINITE wait.
-
-	* semaphore.c (ptw32_sem_timedwait): New function for internal
-	use.  This is essentially sem_wait() modified to add the
-        'abstime' arg and call the modified (see above)
-        pthreadCancelableWait().
-
-Thu Jan 14 14:27:13 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cleanup.c: Correct _cplusplus to __cplusplus wherever used.
-
-	* Makefile.in: Add CC=g++ and add -fhandle-exceptions to CFLAGS.
-	The derived Makefile will compile all units of the package as C++
-	so that those which include try/catch exception handling should work
-	properly. The package should compile ok if CC=gcc, however, exception
-	handling will not be included and thus thread cancellation, for
- 	example, will not work.
-
-	* cleanup.c (ptw32_pop_cleanup): Add #warning to compile this
- 	file as C++ if using a cygwin32 environment. Perhaps the whole package
-	should be compiled using g++ under cygwin.
-
-	* private.c (ptw32_threadStart): Change #error directive
-	into #warning and bracket for __CYGWIN__ and derivative compilers.
-
-Wed Jan 13 09:34:52 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* build.bat: Delete old binaries before compiling/linking.
-
-Tue Jan 12 09:58:38 1999  Tor Lillqvist <tml at iki.fi>
-
-	* dll.c: The Microsoft compiler pragmas probably are more
-	appropriately protected by _MSC_VER than by _WIN32.
-
-	* pthread.h: Define ETIMEDOUT. This should be returned by
-	pthread_cond_timedwait which is not implemented yet as of
-	snapshot-1999-01-04-1305. It was implemented in the older version.
-	The Microsoft compiler pragmas probably are more appropriately
-	protected by _MSC_VER than by _WIN32.
-
-	* pthread.def: pthread_mutex_destroy was missing from the def file
-
-	* condvar.c (pthread_cond_broadcast): Ensure we only wait on threads
-	if there were any waiting on the condition.
-	I think pthread_cond_broadcast should do the WaitForSingleObject
-	only if cv->waiters > 0? Otherwise it seems to hang, at least in the
-	testg thread program from glib.
-
-Tue Jan 12 09:58:38 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* condvar.c (pthread_cond_timedwait): Fix function description
-	comments.
-
-	* semaphore.c (sem_post): Correct typo in comment.
-
-Mon Jan 11 20:33:19 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h: Re-arrange conditional compile of pthread_cleanup-*
-	macros.
-
-	* cleanup.c (ptw32_push_cleanup): Provide conditional 
-	compile of cleanup->prev.
-
-1999-01-11  Tor Lillqvist <tml at iki.fi>
-
-	* condvar.c (pthread_cond_init): Invert logic when testing the
-	return value from calloc().
-
-Sat Jan  9 14:32:08 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Compile-time switch for CYGWIN derived environments
-	to use CreateThread instead of _beginthreadex. Ditto for ExitThread.
-	Patch provided by Anders Norlander  <anorland at hem2.passagen.se>.
-
-Tue Jan  5 16:33:04 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cleanup.c (ptw32_pop_cleanup): Add C++ version of __try/__except
-	block. Move trailing "}" out of #ifdef _WIN32 block left there by
-	(rpj's) mistake.
-
-	* private.c: Remove #include <errno.h> which is included by pthread.h.
-
-1998-12-11  Ben Elliston  <bje at toilet.to.cygnus.com>
-
-	* README: Update info about subscribing to the mailing list.
-
-Mon Jan  4 11:23:40 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* all: No code changes, just cleanup.
-	- remove #if 0 /* Pre Bossom */ enclosed code.
-	- Remove some redundant #includes.
-	* pthread.h: Update implemented/unimplemented routines list.
-	* Tag the bossom merge branch getting ready to merge back to main
-	trunk.
-
-Tue Dec 29 13:11:16 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Move the following struct definitions to pthread.h:
-	pthread_t_, pthread_attr_t_, pthread_mutex_t_, pthread_mutex_t_,
-	pthread_mutexattr_t_, pthread_key_t_, pthread_cond_t_,
-	pthread_condattr_t_, pthread_once_t_.
-
-	* pthread.h: Add "_" prefix to pthread_push_cleanup and 
-	pthread_pop_cleanup internal routines, and associated struct and
-	typedefs.
-
-	* buildlib.bat: Add compile command for semaphore.c
-
-	* pthread.def: Comment out pthread_atfork routine name. 
-	Now unimplemented.
-
-	* tsd.c (pthread_setspecific): Rename tkAssocCreate to
-	ptw32_tkAssocCreate.
-	(pthread_key_delete): Rename tkAssocDestroy to
-	ptw32_tkAssocDestroy.
-
-	* sync.c (pthread_join): Rename threadDestroy to ptw32_threadDestroy
-
-	* sched.c (is_attr): attr is now **attr (was *attr), so add extra
-	NULL pointer test.
-	(pthread_attr_setschedparam): Increase redirection for attr which is
-	now a **.
-	(pthread_attr_getschedparam): Ditto.
-	(pthread_setschedparam): Change thread validation and rename "thread"
- 	Win32 thread Handle element name to match John Bossom's version.
-	(pthread_getschedparam): Ditto.
-
-	* private.c (ptw32_threadDestroy): Rename call to
-	callUserDestroyRoutines() as ptw32_callUserDestroyRoutines()
-
-	* misc.c: Add #include "implement.h".
-
-	* dll.c: Remove defined(KLUDGE) wrapped code.
-
-	* fork.c: Remove redefinition of ENOMEM.
-	Remove pthread_atfork() and fork() with #if 0/#endif.
-
-	* create.c (pthread_create): Rename threadStart and threadDestroy calls
-	to ptw32_threadStart and ptw32_threadDestroy.
-
-	* implement.h: Rename "detachedstate" to "detachstate".
-
-	* attr.c: Rename "detachedstate" to "detachstate".
-
-Mon Dec 28 09:54:39 1998  John Bossom
-
-	* semaphore.c: Initial version.
-	* semaphore.h: Initial version.
-
-Mon Dec 28 09:54:39 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.h (pthread_attr_t_): Change to *pthread_attr_t.
-
-Mon Dec 28 09:54:39 1998  John Bossom, Ben Elliston
-
-	* attr.c (pthread_attr_setstacksize): Merge with John's version.
-	(pthread_attr_getstacksize): Merge with John's version.
-	(pthread_attr_setstackaddr): Merge with John's version.
-	(pthread_attr_getstackaddr): Merge with John's version.
-	(pthread_attr_init): Merge with John's version.
-	(pthread_attr_destroy): Merge with John's version.
-	(pthread_attr_getdetachstate): Merge with John's version.
-	(pthread_attr_setdetachstate): Merge with John's version.
-	(is_attr): attr is now **attr (was *attr), so add extra NULL pointer
-	test.
-
-Mon Dec 28 09:54:39 1998  Ross Johnson
-
-	* implement.h (pthread_attr_t_): Add and rename elements in JEB's
-	version to correspond to original, so that it can be used with
-	original attr routines.
-
-	* pthread.h: Add #endif at end which was truncated in merging.
-
-Sun Dec 20 14:51:58 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* misc.c (pthreadCancelableWait): New function by John Bossom. Non-standard
-	but provides a hook that can be used to implement cancellation points in
-	applications that use this library.
-
-	* pthread.h (pthread_cleanup_pop): C++ (non-WIN32) version uses
-	try/catch to emulate John Bossom's WIN32 __try/__finally behaviour.
-	In the WIN32 version __finally block, add a test for AbnormalTermination otherwise
-	cleanup is only run if the cleanup_pop execute arg is non-zero. Cancellation
-	should cause the cleanup to run irrespective of the execute arg.
-
-	* condvar.c (pthread_condattr_init): Replaced by John Bossom's version.
-	(pthread_condattr_destroy): Replaced by John Bossom's version.
-	(pthread_condattr_getpshared): Replaced by John Bossom's version.
-	(pthread_condattr_setpshared): Replaced by John Bossom's version.
-	(pthread_cond_init): Replaced by John Bossom's version.
-	Fix comment (refered to mutex rather than condition variable).
-	(pthread_cond_destroy): Replaced by John Bossom's version.
-	(pthread_cond_wait): Replaced by John Bossom's version.
-	(pthread_cond_timedwait): Replaced by John Bossom's version.
-	(pthread_cond_signal): Replaced by John Bossom's version.
-	(pthread_cond_broadcast): Replaced by John Bossom's version.
-
-Thu Dec 17 19:10:46 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* tsd.c (pthread_key_create): Replaced by John Bossom's version.
-	(pthread_key_delete): Replaced by John Bossom's version.
-	(pthread_setspecific): Replaced by John Bossom's version.
-	(pthread_getspecific): Replaced by John Bossom's version.
-
-Mon Dec  7 09:44:40 1998  John Bossom
-
-	* cancel.c (pthread_setcancelstate): Replaced.
-	(pthread_setcanceltype): Replaced.
-	(pthread_testcancel): Replaced.
-	(pthread_cancel): Replaced.
-	
-	* exit.c (pthread_exit): Replaced.
-
-	* misc.c (pthread_self): Replaced.
-	(pthread_equal): Replaced.
-
-	* sync.c (pthread_detach): Replaced.
-	(pthread_join): Replaced.
-
-	* create.c (pthread_create): Replaced.
-
-	* private.c (ptw32_processInitialize): New.
-	(ptw32_processTerminate): New.
-	(ptw32_threadStart): New.
- 	(ptw32_threadDestroy): New.
-	(ptw32_cleanupStack): New.
-	(ptw32_tkAssocCreate): New.
-	(ptw32_tkAssocDestroy): New.
-	(ptw32_callUserDestroyRoutines): New.
-
-	* implement.h: Added non-API structures and declarations.
-
-	* dll.c (PthreadsEntryPoint): Cast return value of GetProcAddress
-	to resolve compile warning from MSVC.
-
-	* dll.c (DLLmain): Replaced.
-	* dll.c (PthreadsEntryPoint):
-	Re-applied Anders Norlander's patch:-
-	Initialize ptw32_try_enter_critical_section at startup
-	and release kernel32 handle when DLL is being unloaded.
-
-Sun Dec  6 21:54:35 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* buildlib.bat: Fix args to CL when building the .DLL
-
-	* cleanup.c (ptw32_destructor_run_all): Fix TSD key management.
-	This is a tidy-up before TSD and Thread management is completely
-	replaced by John Bossom's code.
-
-	* tsd.c (pthread_key_create): Fix TSD key management.
-
-	* global.c (ptw32_key_virgin_next): Initialise.
-
-	* build.bat: New DOS script to compile and link a pthreads app
-	using Microsoft's CL compiler linker.
-	* buildlib.bat: New DOS script to compile all the object files
-	and create pthread.lib and pthread.dll using Microsoft's CL
-	compiler linker.
-
-1998-12-05  Anders Norlander  <anorland at hem2.passagen.se>
-
-	* implement.h (ptw32_try_enter_critical_section): New extern
-	* dll.c (ptw32_try_enter_critical_section): New pointer to
-	TryEnterCriticalSection if it exists; otherwise NULL.
-	* dll.c (PthreadsEntryPoint):
-	Initialize ptw32_try_enter_critical_section at startup
-	and release kernel32 handle when DLL is being unloaded.
-	* mutex.c (pthread_mutex_trylock): Replaced check for NT with
-	a check if ptw32_try_enter_critical_section is valid
-	pointer to a function. Call ptw32_try_enter_critical_section
-	instead of TryEnterCriticalSection to avoid errors on Win95.
-
-Thu Dec 3 13:32:00 1998  Ross Johnson  <rpj at ise.canberra.edu.au>
-
-	* README: Correct cygwin32 compatibility statement.
-
-Sun Nov 15 21:24:06 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* cleanup.c (ptw32_destructor_run_all): Declare missing void * arg.
-	Fixup CVS merge conflicts.
-
-1998-10-30  Ben Elliston  <bje at cygnus.com>
-
-	* condvar.c (cond_wait): Fix semantic error. Test for equality
-	instead of making an assignment.
-
-Fri Oct 30 15:15:50 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cleanup.c (ptw32_handler_push): Fixed bug appending new
-	handler to list reported by Peter Slacik
-	<Peter.Slacik at leibinger.freinet.de>.
-	(new_thread): Rename poorly named local variable to
-	"new_handler".
-
-Sat Oct 24 18:34:59 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* global.c: Add TSD key management array and index declarations.
-
-	* implement.h: Ditto for externs.
-
-Fri Oct 23 00:08:09 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h (PTW32_TSD_KEY_REUSE): Add enum.
-
-	* private.c (ptw32_delete_thread): Add call to
-	ptw32_destructor_run_all() to clean up the threads keys.
-
-	* cleanup.c (ptw32_destructor_run_all): Check for no more dirty
-	keys to run destructors on. Assume that the destructor call always
-	succeeds and set the key value to NULL.
-
-Thu Oct 22 21:44:44 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* tsd.c (pthread_setspecific): Add key management code.
-	(pthread_key_create): Ditto.
-	(pthread_key_delete): Ditto.
-
-	* implement.h (struct ptw32_tsd_key): Add status member.
-
-	* tsd.c: Add description of pthread_key_delete() from the
-	standard as a comment.
-
-Fri Oct 16 17:38:47 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cleanup.c (ptw32_destructor_run_all): Fix and improve
-	stepping through the key table.
-
-Thu Oct 15 14:05:01 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* private.c (ptw32_new_thread): Remove init of destructorstack.
-	No longer an element of pthread_t.
-
-	* tsd.c (pthread_setspecific): Fix type declaration and cast.
-	(pthread_getspecific): Ditto.
-	(pthread_getspecific): Change error return value to NULL if key
-	is not in use.
-
-Thu Oct 15 11:53:21 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* global.c (ptw32_tsd_key_table): Fix declaration.
-
-	* implement.h(ptw32_TSD_keys_TlsIndex): Add missing extern.
-	(ptw32_tsd_mutex): Ditto.
-
-	* create.c (ptw32_start_call): Fix "keys" array declaration.
-	Add comment.
-
-	* tsd.c (pthread_setspecific): Fix type declaration and cast.
-	(pthread_getspecific): Ditto.
-
-	* cleanup.c (ptw32_destructor_run_all): Declare missing loop
-	counter.
-
-Wed Oct 14 21:09:24 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_new_thread): Increment ptw32_threads_count.
-	(ptw32_delete_thread): Decrement ptw32_threads_count.
-	Remove some comments.
-
-	* exit.c (ptw32_exit): : Fix two pthread_mutex_lock() calls that
- 	should have been pthread_mutex_unlock() calls.
-	(ptw32_vacuum): Remove call to ptw32_destructor_pop_all().
-
-	* create.c (pthread_create): Fix two pthread_mutex_lock() calls that
- 	should have been pthread_mutex_unlock() calls.
-
-	* global.c (ptw32_tsd_mutex): Add mutex for TSD operations.
-
-	* tsd.c (pthread_key_create): Add critical section.
-	(pthread_setspecific): Ditto.
-	(pthread_getspecific): Ditto.
-	(pthread_key_delete): Ditto.
-
-	* sync.c (pthread_join): Fix two pthread_mutex_lock() calls that
- 	should have been pthread_mutex_unlock() calls.
-
-Mon Oct 12 00:00:44 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h (ptw32_tsd_key_table): New.
-
-	* create.c (ptw32_start_call): Initialise per-thread TSD keys
-	to NULL.
-
-	* misc.c (pthread_once): Correct typo in comment.
-
-	* implement.h (ptw32_destructor_push): Remove.
-	(ptw32_destructor_pop): Remove.
-	(ptw32_destructor_run_all): Rename from ptw32_destructor_pop_all.
-	(PTW32_TSD_KEY_DELETED): Add enum.
-	(PTW32_TSD_KEY_INUSE): Add enum.
-
-	* cleanup.c (ptw32_destructor_push): Remove.
-	(ptw32_destructor_pop): Remove.
-	(ptw32_destructor_run_all): Totally revamped TSD.
-
-	* dll.c (ptw32_TSD_keys_TlsIndex): Initialise.
-
-	* tsd.c (pthread_setspecific): Totally revamped TSD.
-	(pthread_getspecific): Ditto.
-	(pthread_create): Ditto.
-	(pthread_delete): Ditto.
-
-Sun Oct 11 22:44:55 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* global.c (ptw32_tsd_key_table): Add new global.
-
-	* implement.h (ptw32_tsd_key_t and struct ptw32_tsd_key):
-	Add.
-	(struct _pthread): Remove destructorstack.
-
-	* cleanup.c (ptw32_destructor_run_all): Rename from
- 	ptw32_destructor_pop_all. The key destructor stack was made
- 	global rather than per-thread. No longer removes destructor nodes
-	from the stack. Comments updated.
-
-1998-10-06  Ben Elliston  <bje at cygnus.com>
-
-	* condvar.c (cond_wait): Use POSIX, not Win32 mutex calls.
-	(pthread_cond_broadcast): Likewise.
-	(pthread_cond_signal): Likewise.
-
-1998-10-05  Ben Elliston  <bje at cygnus.com>
-
-	* pthread.def: Update. Some functions aren't available yet, others
-	are macros in <pthread.h>.
-
-	* tests/join.c: Remove; useless.
-
-Mon Oct  5 14:25:08 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* pthread.def: New file for building the DLL.
-
-1998-10-05  Ben Elliston  <bje at cygnus.com>
-
-	* misc.c (pthread_equal): Correct inverted logic bug.
-	(pthread_once): Use the POSIX mutex primitives, not Win32. Remove
-	irrelevant FIXME comment.
-
-	* global.c (PTHREAD_MUTEX_INITIALIZER): Move to pthread.h.
-
-	* pthread.h (PTHREAD_MUTEX_INITIALIZER): Define.
-	(pthread_mutex_t): Reimplement as a struct containing a valid
-	flag. If the flag is ever down upon entry to a mutex operation,
-	we call pthread_mutex_create() to initialise the object. This
-	fixes the problem of how to handle statically initialised objects
-	that can't call InitializeCriticalSection() due to their context.
-	(PTHREAD_ONCE_INIT): Define.
-
-	* mutex.c (pthread_mutex_init): Set valid flag.
-	(pthread_mutex_destroy): Clear valid flag.
-	(pthread_mutex_lock): Check and handle the valid flag.
-	(pthread_mutex_unlock): Likewise.
-	(pthread_mutex_trylock): Likewise.
-
-	* tests/mutex3.c: New file; test for the static initialisation
-	macro. Passes.
-
-	* tests/create1.c: New file; test pthread_create(). Passes.
-	
-	* tests/equal.c: Poor test; remove.
-	
-	* tests/equal1.c New file; test pthread_equal(). Passes.
-
-	* tests/once1.c: New file; test for pthread_once(). Passes.
-
-	* tests/self.c: Remove; rename to self1.c.
-
-	* tests/self1.c: This is the old self.c.
-
-	* tests/self2.c: New file. Test pthread_self() with a single
-	thread. Passes.
-
-	* tests/self3.c: New file. Test pthread_self() with a couple of
-	threads to ensure their thread IDs differ. Passes.
-	
-1998-10-04  Ben Elliston  <bje at cygnus.com>
-
-	* tests/mutex2.c: Test pthread_mutex_trylock(). Passes.
-
-	* tests/mutex1.c: New basic test for mutex functions (it passes).
-	(main): Eliminate warning.
-
-	* configure.in: Test for __stdcall, not _stdcall. Typo.
-
-	* configure: Regenerate.
-
-	* attr.c (pthread_attr_setstackaddr): Remove FIXME comment. Win32
-	does know about ENOSYS after all.
-	(pthread_attr_setstackaddr): Likewise.
-
-1998-10-03  Ben Elliston  <bje at cygnus.com>
-
-	* configure.in: Test for the `_stdcall' keyword.  Define `STDCALL'
-	to `_stdcall' if we have it, null otherwise.
-
-	* configure: Regenerate.
-
-	* acconfig.h (STDCALL): New define.
-
-	* config.h.in: Regenerate.
-
-	* create.c (ptw32_start_call): Add STDCALL prefix.
-	
-	* mutex.c (pthread_mutex_init): Correct function signature.
-
-	* attr.c (pthread_attr_init): Only zero out the `sigmask' member
-	if we have the sigset_t type.
-
-	* pthread.h: No need to include <unistd.h>.  It doesn't even exist
-	on Win32! Again, an artifact of cross-compilation.	
-	(pthread_sigmask): Only provide if we have the sigset_t type.
-
-	* process.h: Remove. This was a stand-in before we started doing
-	native compilation under Win32.
-
-	* pthread.h (pthread_mutex_init): Make `attr' argument const.
-
-1998-10-02  Ben Elliston  <bje at cygnus.com>
-
-	* COPYING: Remove.
-
-	* COPYING.LIB: Add. This library is under the LGPL.
-
-1998-09-13  Ben Elliston  <bje at cygnus.com>
-
-	* configure.in: Test for required system features.
-
-	* configure: Generate. 
-
-	* acconfig.h: New file.
-
-	* config.h.in: Generate.
-
-	* Makefile.in: Renamed from Makefile.
-
-	* COPYING: Import from a recent GNU package.
-
-	* config.guess: Likewise.
-
-	* config.sub: Likewise.
-
-	* install-sh: Likewise.
-
-	* config.h: Remove.  
-
-	* Makefile: Likewise.
-
-1998-09-12  Ben Elliston  <bje at cygnus.com>
-
-	* windows.h: No longer needed; remove.
-
-	* windows.c: Likewise.
-
-Sat Sep 12 20:09:24 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* windows.h: Remove error number definitions. These are in <errno.h>
-	
-	* tsd.c: Add comment explaining rationale for not building
-	POSIX TSD on top of Win32 TLS.
-
-1998-09-12  Ben Elliston  <bje at cygnus.com>
-
-	* {most}.c: Include <errno.h> to get POSIX error values.
-
-	* signal.c (pthread_sigmask): Only provide if HAVE_SIGSET_T is
-	defined.
- 
-	* config.h: #undef features, don't #define them.  This will be
-	generated by autoconf very soon.
-	
-1998-08-11  Ben Elliston  <bje at cygnus.com>
-
-	* Makefile (LIB): Define.
-	(clean): Define target.
-	(all): Build a library not just the object files.
-
-	* pthread.h: Provide a definition for struct timespec if we don't
-	already have one.
-
-	* windows.c (TlsGetValue): Bug fix.
-	
-Thu Aug  6 15:19:22 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* misc.c (pthread_once): Fix arg 1 of EnterCriticalSection()
- 	and LeaveCriticalSection() calls to pass address-of lock.
-
-	* fork.c (pthread_atfork): Typecast (void (*)(void *)) funcptr
-	in each ptw32_handler_push() call.
-
-	* exit.c (ptw32_exit): Fix attr arg in 
-	pthread_attr_getdetachstate() call.
-
-	* private.c (ptw32_new_thread): Typecast (HANDLE) NULL.
-	(ptw32_delete_thread): Ditto.
-
-	* implement.h: (PTW32_MAX_THREADS): Add define. This keeps
-	changing in an attempt to make thread administration data types
-	opaque and cleanup DLL startup.
-
-	* dll.c (PthreadsEntryPoint): 
-	(ptw32_virgins): Remove malloc() and free() calls.
-	(ptw32_reuse): Ditto.
-	(ptw32_win32handle_map): Ditto.
-	(ptw32_threads_mutex_table): Ditto.
-
-	* global.c (_POSIX_THREAD_THREADS_MAX): Initialise with 
-	PTW32_MAX_THREADS.
-	(ptw32_virgins): Ditto.
-	(ptw32_reuse): Ditto.
-	(ptw32_win32handle_map): Ditto.
-	(ptw32_threads_mutex_table): Ditto.
-
-	* create.c (pthread_create): Typecast (HANDLE) NULL.
-	Typecast (unsigned (*)(void *)) start_routine.
-
-	* condvar.c (pthread_cond_init): Add address-of operator & to
-	arg 1 of pthread_mutex_init() call.
-	(pthread_cond_destroy): Add address-of operator & to
-	arg 1 of pthread_mutex_destroy() call. 
-
-	* cleanup.c (ptw32_destructor_pop_all): Add (int) cast to 
-	pthread_getspecific() arg.
-	(ptw32_destructor_pop): Add (void *) cast to "if" conditional.
-	(ptw32_destructor_push): Add (void *) cast to
-	ptw32_handler_push() "key" arg.
-	(malloc.h): Add include.
-
-	* implement.h (ptw32_destructor_pop): Add prototype.
-
-	* tsd.c (implement.h): Add include.
-
-	* sync.c (pthread_join): Remove target_thread_mutex and it's
-	initialisation. Rename getdetachedstate to getdetachstate.
-	Remove unused variable "exitcode".
-	(pthread_detach): Remove target_thread_mutex and it's
-	initialisation. Rename getdetachedstate to getdetachstate.
-	Rename setdetachedstate to setdetachstate.
-
-	* signal.c (pthread_sigmask): Rename SIG_SET to SIG_SETMASK.
-	Cast "set" to (long *) in assignment to passify compiler warning.
-	Add address-of operator & to thread->attr.sigmask in memcpy() call
-	and assignment.
-	(pthread_sigmask): Add address-of operator & to thread->attr.sigmask
-	in memcpy() call and assignment.
-
-	* windows.h (THREAD_PRIORITY_ERROR_RETURN): Add.
-	(THREAD_PRIORITY_LOWEST): Add.
-	(THREAD_PRIORITY_HIGHEST): Add.
-
-	* sched.c (is_attr): Add function.
-	(implement.h): Add include.
-	(pthread_setschedparam): Rename all instances of "sched_policy"
-	to "sched_priority".
-	(pthread_getschedparam): Ditto.
-
-Tue Aug  4 16:57:58 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* private.c (ptw32_delete_thread): Fix typo. Add missing ';'.
-
-	* global.c (ptw32_virgins): Change types from pointer to 
-	array pointer.
-	(ptw32_reuse): Ditto.
-	(ptw32_win32handle_map): Ditto.
-	(ptw32_threads_mutex_table): Ditto.
-
-	* implement.h(ptw32_virgins): Change types from pointer to 
-	array pointer.
-	(ptw32_reuse): Ditto.
-	(ptw32_win32handle_map): Ditto.
-	(ptw32_threads_mutex_table): Ditto.
-
-	* private.c (ptw32_delete_thread): Fix "entry" should be "thread".
-
-	* misc.c (pthread_self): Add extern for ptw32_threadID_TlsIndex.
-
-	* global.c: Add comment.
-
-	* misc.c (pthread_once): Fix member -> dereferences.
-	Change ptw32_once_flag to once_control->flag in "if" test.
-
-Tue Aug  4 00:09:30 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h(ptw32_virgins): Add extern.
-	(ptw32_virgin_next): Ditto.
-	(ptw32_reuse): Ditto.
-	(ptw32_reuse_top): Ditto.
-	(ptw32_win32handle_map): Ditto.
-	(ptw32_threads_mutex_table): Ditto.
-
-	* global.c (ptw32_virgins): Changed from array to pointer.
-	Storage allocation for the array moved into dll.c.
-	(ptw32_reuse): Ditto.
-	(ptw32_win32handle_map): Ditto.
-	(ptw32_threads_mutex_table): Ditto.
-
-	* dll.c (PthreadsEntryPoint): Set up thread admin storage when
-	DLL is loaded.
-
-	* fork.c (pthread_atfork): Fix function pointer arg to all
-	ptw32_handler_push() calls. Change "arg" arg to NULL in child push.
-
-	* exit.c: Add windows.h and process.h includes.
-	(ptw32_exit): Add local detachstate declaration.
-	(ptw32_exit): Fix incorrect name for pthread_attr_getdetachstate().
-
-	* pthread.h (_POSIX_THREAD_ATTR_STACKSIZE): Move from global.c
-	(_POSIX_THREAD_ATTR_STACKADDR): Ditto.
-
-	* create.c (pthread_create): Fix #if should be #ifdef.
-	(ptw32_start_call): Remove usused variables.
-
-	* process.h: Create.
-
-	* windows.h: Move _beginthreadex and _endthreadex into
-	process.h
-
-Mon Aug  3 21:19:57 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* condvar.c (pthread_cond_init): Add NULL attr to
-	pthread_mutex_init() call - default attributes will be used.
-	(cond_wait): Fix typo.
-	(cond_wait): Fix typo - cv was ev.
-	(pthread_cond_broadcast): Fix two identical typos.
-
-	* cleanup.c (ptw32_destructor_pop_all): Remove _ prefix from
-	PTHREAD_DESTRUCTOR_ITERATIONS.
-
-	* pthread.h: Move _POSIX_* values into posix.h
-
-	* pthread.h: Fix typo in pthread_mutex_init() prototype.
-
-	* attr.c (pthread_attr_init): Fix error in priority member init.
-
-	* windows.h (THREAD_PRIORITY_NORMAL): Add.
-
-	* pthread.h (sched_param): Add missing ';' to struct definition. 
-
-	* attr.c (pthread_attr_init): Remove obsolete pthread_attr_t
-	member initialisation - cancelstate, canceltype, cancel_pending.
-	(is_attr): Make arg "attr" a const.
-
-	* implement.h (PTW32_HANDLER_POP_LIFO): Remove definition.
-	(PTW32_HANDLER_POP_FIFO): Ditto.
-	(PTW32_VALID): Add missing newline escape (\).
-	(ptw32_handler_node): Make element "next" a pointer.
-
-1998-08-02  Ben Elliston  <bje at cygnus.com>
-
-	* windows.h: Remove duplicate TlsSetValue() prototype.  Add 
-	TlsGetValue() prototype.
-	(FALSE): Define.
-	(TRUE): Likewise.
-	Add forgotten errno values.  Guard against multiple #includes.
-
-	* windows.c: New file.  Implement stubs for Win32 functions.
-
-	* Makefile (SRCS): Remove.  Not explicitly needed.
-	(CFLAGS): Add -Wall for all warnings with GCC.
-
-Sun Aug  2 19:03:42 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* config.h: Create. This is a temporary stand-in for autoconf yet
-	to be done.
- 	(HAVE_SIGNAL_H): Add.
-
-	* pthread.h: Minor rearrangement for temporary config.h.
-
-Fri Jul 31 14:00:29 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* cleanup.c (ptw32_destructor_pop): Implement. Removes
-	destructors associated with a key without executing them.
-	(ptw32_destructor_pop_all): Add FIXME comment.
-
-	* tsd.c (pthread_key_delete): Add call to ptw32_destructor_pop().
-
-Fri Jul 31 00:05:45 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* tsd.c (pthread_key_create): Update to properly associate
-	the destructor routine with the key.
-	(pthread_key_delete): Add FIXME comment.
-
-	* exit.c (ptw32_vacuum): Add call to
-	ptw32_destructor_pop_all().
-
-	* implement.h (ptw32_handler_pop_all): Add prototype.
-	(ptw32_destructor_pop_all): Ditto.
-
-	* cleanup.c (ptw32_destructor_push): Implement. This is just a
-	call to ptw32_handler_push().
-	(ptw32_destructor_pop_all): Implement. This is significantly
-	different to ptw32_handler_pop_all().
-
-	* Makefile (SRCS): Create. Preliminary.
-
-	* windows.h: Create. Contains Win32 definitions for compile
-	testing. This is just a standin for the real one.
-
-	* pthread.h (SIG_UNBLOCK): Fix typo. Was SIG_BLOCK.
-	(windows.h): Add include. Required for CRITICAL_SECTION.
-	(pthread_cond_t): Move enum declaration outside of struct
-	definition.
-	(unistd.h): Add include - may be temporary.
-
-	* condvar.c (windows.h): Add include.
-
-	* implement.h (PTW32_THIS): Remove - no longer required.
-	(PTW32_STACK): Use pthread_self() instead of PTW32_THIS.
-
-Thu Jul 30 23:12:45 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Remove ptw32_find_entry() prototype.
-
-	* private.c: Extend comments.
-	Remove ptw32_find_entry() - no longer needed.
-
-	* create.c (ptw32_start_call): Add call to TlsSetValue() to
-	store the thread ID.
-
-	* dll.c (PthreadsEntryPoint): Implement. This is called
-	whenever a process loads the DLL. Used to initialise thread
-	local storage.
-
-	* implement.h: Add ptw32_threadID_TlsIndex.
-	Add ()s around PTW32_VALID expression.
-
-	* misc.c (pthread_self): Re-implement using Win32 TLS to store
-	the threads own ID.
-
-Wed Jul 29 11:39:03 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c: Corrections in comments.
-	(ptw32_new_thread): Alter "if" flow to be more natural.
-
-	* cleanup.c (ptw32_handler_push): Same as below.
-
-	* create.c (pthread_create): Same as below.
-
-	* private.c (ptw32_new_thread): Rename "new" to "new_thread".
-	Since when has a C programmer been required to know C++?
-
-Tue Jul 28 14:04:29 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* implement.h: Add PTW32_VALID macro.
-
-	* sync.c (pthread_join): Modify to use the new thread
-	type and ptw32_delete_thread(). Rename "target" to "thread".
-	Remove extra local variable "target".
-	(pthread_detach): Ditto.
-
-	* signal.c (pthread_sigmask): Move init of "us" out of inner block.
-	Fix instance of "this" should have been "us". Rename "us" to "thread".
-
-	* sched.c (pthread_setschedparam): Modify to use the new thread
-	type.
-	(pthread_getschedparam): Ditto.
-
-	* private.c (ptw32_find_thread): Fix return type and arg.
-
-	* implement.h: Remove PTW32_YES and PTW32_NO.
-	(ptw32_new_thread): Add prototype.
-	(ptw32_find_thread): Ditto.
-	(ptw32_delete_thread): Ditto.
-	(ptw32_new_thread_entry): Remove prototype.
-	(ptw32_find_thread_entry): Ditto.
-	(ptw32_delete_thread_entry): Ditto.
-	(  PTW32_NEW, PTW32_INUSE, PTW32_EXITED, PTW32_REUSE):
-	Add.
-
-
-	* create.c (pthread_create): Minor rename "us" to "new" (I need
-	these cues but it doesn't stop me coming out with some major bugs
-	at times).
-	Load start_routine and arg into the thread so the wrapper can
-	call it.
-
-	* exit.c (pthread_exit): Fix pthread_this should be pthread_self.
-
-	* cancel.c (pthread_setcancelstate): Change
- 	ptw32_threads_thread_t * to pthread_t and init with
- 	pthread_this().
-	(pthread_setcanceltype): Ditto.
-
-	* exit.c (ptw32_exit): Add new pthread_t arg.
-	Rename ptw32_delete_thread_entry to ptw32_delete_thread.
-	Rename "us" to "thread".
-	(pthread_exit): Call ptw32_exit with added thread arg.
-
-	* create.c (ptw32_start_call): Insert missing ")".
-	Add "us" arg to ptw32_exit() call.
-	(pthread_create): Modify to use new thread allocation scheme.
-
-	* private.c: Added detailed explanation of the new thread
-	allocation scheme.
-	(ptw32_new_thread): Totally rewritten to use
-	new thread allocation scheme.
-	(ptw32_delete_thread): Ditto.
-	(ptw32_find_thread): Obsolete.
-
-Mon Jul 27 17:46:37 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* create.c (pthread_create): Start of rewrite. Not completed yet.
-
-	* private.c (ptw32_new_thread_entry): Start of rewrite. Not
-	complete.
-
-	* implement.h (ptw32_threads_thread): Rename, remove thread
-	member, add win32handle and ptstatus members.
-	(ptw32_t): Add.
-
-	* pthread.h: pthread_t is no longer mapped directly to a Win32
-	HANDLE type. This is so we can let the Win32 thread terminate and
-	reuse the HANDLE while pthreads holds it's own thread ID until
-	the last waiting join exits.
-
-Mon Jul 27 00:20:37 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_delete_thread_entry): Destroy the thread
- 	entry attribute object before deleting the thread entry itself.
-
-	* attr.c (pthread_attr_init): Initialise cancel_pending = FALSE.
-	(pthread_attr_setdetachstate): Rename "detached" to "detachedstate".
-	(pthread_attr_getdetachstate): Ditto.
-
-	* exit.c (ptw32_exit): Fix incorrect check for detachedstate.
-
-	* implement.h (ptw32_call_t): Remove env member. 
-
-Sun Jul 26 13:06:12 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h (ptw32_new_thread_entry): Fix prototype.
-	(ptw32_find_thread_entry): Ditto.
-	(ptw32_delete_thread_entry): Ditto.
-	(ptw32_exit): Add prototype.
-
-	* exit.c (ptw32_exit): New function. Called from pthread_exit()
-	and ptw32_start_call() to exit the thread. It allows an extra
-	argument which is the return code passed to _endthreadex().
-	(ptw32_exit): Move thread entry delete call from ptw32_vacuum()
-	into here. Add more explanation of thread entry deletion.
-	(ptw32_exit): Clarify comment.
-
-	* create.c (ptw32_start_call): Change pthread_exit() call to
-	ptw32_exit() call.
-
-	* exit.c (ptw32_vacuum): Add thread entry deletion code
-	moved from ptw32_start_call(). See next item.
-	(pthread_exit): Remove longjmp(). Add mutex lock around thread table
-	manipulation code. This routine now calls _enthreadex().
-
-	* create.c (ptw32_start_call): Remove setjmp() call and move
-	cleanup code out. Call pthread_exit(NULL) to terminate the thread.
-
-1998-07-26  Ben Elliston  <bje at cygnus.com>
-
-	* tsd.c (pthread_getspecific): Update comments.
-
-	* mutex.c (pthread_mutexattr_setpshared): Not supported; remove.
-	(pthread_mutexattr_getpshared): Likewise.
-
-	* pthread.h (pthread_mutexattr_setpshared): Remove prototype.
-	(pthread_mutexattr_getpshared): Likewise.
-
-Sun Jul 26 00:09:59 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sync.c: Rename all instances of ptw32_count_mutex to
-	ptw32_table_mutex.
-
-	* implement.h: Rename ptw32_count_mutex to
-	ptw32_table_mutex.
-
-	* global.c: Rename ptw32_count_mutex to
-	ptw32_table_mutex.
-
-	* create.c (pthread_create): Add critical sections.
-	(ptw32_start_call): Rename ptw32_count_mutex to
-	ptw32_table_mutex.
-
-	* cancel.c (pthread_setcancelstate): Fix indirection bug and rename
-	"this" to "us".
-
-	* signal.c (pthread_sigmask): Rename "this" to "us" and fix some
-	minor syntax errors. Declare "us" and initialise it.
-
-	* sync.c (pthread_detach): Rename "this" to "target".
-
-	* pthread.h: Converting PTHREAD_* defines to alias the (const int)
-	values in global.c.
-
-	* global.c: Started converting PTHREAD_* defines to (const int) as
- 	a part of making the eventual pthreads DLL binary compatible
- 	through version changes.
-
-	* condvar.c (cond_wait): Add cancelation point. This applies the
-	point to both pthread_cond_wait() and pthread_cond_timedwait().
-
-	* exit.c (pthread_exit): Rename "this" to "us".
-
-	* implement.h: Add comment.
-
-	* sync.c (pthread_join): I've satisfied myself that pthread_detach()
-	does set the detached attribute in the thread entry attributes
-	to PTHREAD_CREATE_DETACHED. "if" conditions were changed to test
-	that attribute instead of a separate flag.
-
-	* create.c (pthread_create): Rename "this" to "us".
-	(pthread_create): cancelstate and canceltype are not attributes
-	so the copy to thread entry attribute storage was removed.
-	Only the thread itself can change it's cancelstate or canceltype,
-	ie. the thread must exist already.
-
-	* private.c (ptw32_delete_thread_entry): Mutex locks removed.
-	Mutexes must be applied at the caller level.
-	(ptw32_new_thread_entry): Ditto.
-	(ptw32_new_thread_entry): Init cancelstate, canceltype, and
-	cancel_pending to default values.
-	(ptw32_new_thread_entry): Rename "this" to "new".
-	(ptw32_find_thread_entry): Rename "this" to "entry".
-	(ptw32_delete_thread_entry): Rename "thread_entry" to "entry".
-
-	* create.c (ptw32_start_call): Mutexes changed to
-	ptw32_count_mutex. All access to the threads table entries is
-	under the one mutex. Otherwise chaos reigns.
-
-Sat Jul 25 23:16:51 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h (ptw32_threads_thread): Move cancelstate and
- 	canceltype members out of pthread_attr_t into here.
-
-	* fork.c (fork): Add comment.
-
-1998-07-25  Ben Elliston  <bje at cygnus.com>
-
-	* fork.c (fork): Autoconfiscate.
-
-Sat Jul 25 00:00:13 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* create.c (ptw32_start_call): Set thread priority.  Ensure our
- 	thread entry is removed from the thread table but only if
- 	pthread_detach() was called and there are no waiting joins.
-	(pthread_create): Set detach flag in thread entry if the 
-	thread is created PTHREAD_CREATE_DETACHED.
-
-	* pthread.h (pthread_attr_t): Rename member "detachedstate".
-
-	* attr.c (pthread_attr_init): Rename attr members.
-
-	* exit.c (pthread_exit): Fix indirection mistake.
-
-	* implement.h (PTW32_THREADS_TABLE_INDEX): Add.
-
-	* exit.c (ptw32_vacuum): Fix incorrect args to
-	ptw32_handler_pop_all() calls.
-	Make thread entry removal conditional.
-
-	* sync.c (pthread_join): Add multiple join and async detach handling.
-
-	* implement.h (PTW32_THREADS_TABLE_INDEX): Add.
-
-	* global.c (ptw32_threads_mutex_table): Add.
-
-	* implement.h (ptw32_once_flag): Remove.
-	(ptw32_once_lock): Ditto.
-	(ptw32_threads_mutex_table): Add.
-
-	* global.c (ptw32_once_flag): Remove.
-	(ptw32_once_lock): Ditto.
-
-	* sync.c (pthread_join): Fix tests involving new return value
-	from ptw32_find_thread_entry().
-	(pthread_detach): Ditto.
-
-	* private.c (ptw32_find_thread_entry): Failure return code
-	changed from -1 to NULL.
-
-Fri Jul 24 23:09:33 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* create.c (pthread_create): Change . to -> in sigmask memcpy() args.
-
-	* pthread.h: (pthread_cancel): Add function prototype.
-	(pthread_testcancel): Ditto.
-
-1998-07-24  Ben Elliston  <bje at cygnus.com>
-
-	* pthread.h (pthread_condattr_t): Rename dummy structure member.
-	(pthread_mutexattr_t): Likewise.
-
-Fri Jul 24 21:13:55 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* cancel.c (pthread_cancel): Implement.
-	(pthread_testcancel): Implement.
-
-	* exit.c (pthread_exit): Add comment explaining the longjmp().
-
-	* implement.h (ptw32_threads_thread_t): New member cancelthread.
-	(PTW32_YES): Define.
-	(PTW32_NO): Define.
-	(RND_SIZEOF): Remove.
-
-	* create.c (pthread_create): Rename cancelability to cancelstate.
-
-	* pthread.h (pthread_attr_t): Rename cancelability to cancelstate.
-	(PTHREAD_CANCELED): Define.
-
-1998-07-24  Ben Elliston  <bje at cygnus.com>
-
-	* pthread.h (SIG_BLOCK): Define if not already defined.
-	(SIG_UNBLOCK): Likewise.
-	(SIG_SETMASK): Likewise.
-	(pthread_attr_t): Add signal mask member.
-	(pthread_sigmask): Add function prototype.
-
-	* signal.c (pthread_sigmask): Implement.
-
-	* create.c: #include <string.h> to get a prototype for memcpy().
-	(pthread_create): New threads inherit their creator's signal
-	mask.  Copy the signal mask to the new thread structure if we know
-	about signals.
-	
-Fri Jul 24 16:33:17 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
-
-	* fork.c (pthread_atfork): Add all the necessary push calls.
-	Local implementation semantics:
-	If we get an ENOMEM at any time then ALL handlers
-	(including those from previous pthread_atfork() calls) will be
-	popped off each of the three atfork stacks before we return.
-	(fork): Add all the necessary pop calls. Add the thread cancellation
-	and join calls to the child fork.
-	Add #includes.
-
-	* implement.h: (ptw32_handler_push): Fix return type and stack arg
-	type in prototype.
-	(ptw32_handler_pop): Fix stack arg type in prototype.
-	(ptw32_handler_pop_all): Fix stack arg type in prototype.
-
-	* cleanup.c (ptw32_handler_push): Change return type to int and
-	return ENOMEM if malloc() fails.
-
-	* sync.c (pthread_detach): Use equality test, not assignment.
-
-	* create.c (ptw32_start_call): Add call to Win32 CloseHandle()
-	if thread is detached.
-
-1998-07-24  Ben Elliston  <bje at cygnus.com>
-
-	* sync.c (pthread_detach): Close the Win32 thread handle to
-	emulate detached (or daemon) threads.
-
-Fri Jul 24 03:00:25 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sync.c (pthread_join): Save valueptr arg in joinvalueptr for
-	pthread_exit() to use.
-
-	* private.c (ptw32_new_thread_entry): Initialise joinvalueptr to
-	NULL.
-
-	* create.c (ptw32_start_call): Rewrite to facilitate joins.
-	pthread_exit() will do a longjmp() back to here. Does appropriate
-	cleanup and exit/return from the thread.
-	(pthread_create): _beginthreadex() now passes a pointer to our
-	thread table entry instead of just the call member of that entry.
-
-	* implement.h (ptw32_threads_thread): New member 
-	void ** joinvalueptr.
-	(ptw32_call_t): New member jmpbuf env.
-
-	* exit.c (pthread_exit): Major rewrite to handle joins and handing
-	value pointer to joining thread. Uses longjmp() back to 
-	ptw32_start_call().
-
-	* create.c (pthread_create): Ensure values of new attribute members
-	are copied to the thread attribute object.
-
-	* attr.c (pthread_attr_destroy):  Fix merge conflicts.
-	(pthread_attr_getdetachstate):  Fix merge conflicts.
-	(pthread_attr_setdetachstate):  Fix merge conflicts.
-
-	* pthread.h:  Fix merge conflicts.
-
-	* sync.c (pthread_join): Fix merge conflicts.
-
-Fri Jul 24 00:21:21 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* sync.c (pthread_join): Add check for valid and joinable
-	thread.
-	(pthread_detach): Implement. After checking for a valid and joinable
-	thread, it's still a no-op.
-
-	* private.c (ptw32_find_thread_entry): Bug prevented returning
-	an error value in some cases.
-
-	* attr.c (pthread_attr_setdetachedstate): Implement.
-	(pthread_attr_getdetachedstate): Implement.
-
-	* implement.h: Move more hidden definitions into here from
-	pthread.h.
-
-1998-07-24  Ben Elliston  <bje at cygnus.com>
-
-	* pthread.h (PTHREAD_CREATE_JOINABLE): Define.
-	(PTHREAD_CREATE_DETACHED): Likewise.
-	(pthread_attr_t): Add new structure member `detached'.
-	(pthread_attr_getdetachstate): Add function prototype.
-	(pthread_attr_setdetachstate): Likewise.
-
-	* sync.c (pthread_join): Return if the target thread is detached.
-
-	* attr.c (pthread_attr_init): Initialise cancelability and
-	canceltype structure members.
-	(pthread_attr_getdetachstate): Implement.
-	(pthread_attr_setdetachstate): Likewise.
-
-	* implement.h (PTW32_CANCEL_DEFAULTS): Remove.  Bit fields
-	proved to be too cumbersome.  Set the defaults in attr.c using the
-	public PTHREAD_CANCEL_* constants.
-
-	* cancel.c: New file.
-
-	* pthread.h (sched_param): Define this type.
-	(pthread_attr_getschedparam): Add function prototype.
-	(pthread_attr_setschedparam): Likewise.
-	(pthread_setcancelstate): Likewise.
-	(pthread_setcanceltype): Likewise.
-	(sched_get_priority_min): Likewise.
-	(sched_get_priority_max): Likewise.
-	(pthread_mutexattr_setprotocol): Remove; not supported.
-	(pthread_mutexattr_getprotocol): Likewise.
-	(pthread_mutexattr_setprioceiling): Likewise.
-	(pthread_mutexattr_getprioceiling): Likewise.
-	(pthread_attr_t): Add canceltype member.  Update comments.
-	(SCHED_OTHER): Define this scheduling policy constant.
-	(SCHED_FIFO): Likewise.
-	(SCHED_RR): Likewise.
-	(SCHED_MIN): Define the lowest possible value for this constant.
-	(SCHED_MAX): Likewise, the maximum possible value.
-	(PTHREAD_CANCEL_ASYNCHRONOUS): Redefine.
-	(PTHREAD_CANCEL_DEFERRED): Likewise.
-	
-	* sched.c: New file.
-	(pthread_setschedparam): Implement.
-	(pthread_getschedparam): Implement.
-	(sched_get_priority_max): Validate policy argument.
-	(sched_get_priority_min): Likewise.
-
-	* mutex.c (pthread_mutexattr_setprotocol): Remove; not supported.
-	(pthread_mutexattr_getprotocol): Likewise.
-	(pthread_mutexattr_setprioceiling): Likewise.
-	(pthread_mutexattr_getprioceiling): Likewise.
-
-Fri Jul 24 00:21:21 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* create.c (pthread_create): Arg to ptw32_new_thread_entry()
-	changed. See next entry. Move mutex locks out. Changes made yesterday
-	and today allow us to start the new thread running rather than
-	temporarily suspended.
-
-	* private.c (ptw32_new_thread_entry): ptw32_thread_table
-	was changed back to a table of thread structures rather than pointers.
-	As such we're trading storage for increaded speed. This routine
-	was modified to work with the new table. Mutex lock put in around
-	global data accesses.
-	(ptw32_find_thread_entry): Ditto
-	(ptw32_delete_thread_entry): Ditto
-
-Thu Jul 23 23:25:30 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* global.c: New. Global data objects declared here. These moved from
-	pthread.h.
-
-	* pthread.h: Move implementation hidden definitions into
-	implement.h.
-
-	* implement.h: Move implementation hidden definitions from
-	pthread.h. Add constants to index into the different handler stacks.
-
-	* cleanup.c (ptw32_handler_push): Simplify args. Restructure.
-	(ptw32_handler_pop): Simplify args. Restructure.
-	(ptw32_handler_pop_all): Simplify args. Restructure.
-
-Wed Jul 22 00:16:22 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* attr.c, implement.h, pthread.h, ChangeLog: Resolve CVS merge
-	conflicts.
-
-	* private.c (ptw32_find_thread_entry): Changes to return type
-	to support leaner ptw32_threads_table[] which now only stores
-	ptw32_thread_thread_t *.
-	(ptw32_new_thread_entry): Internal changes.
-	(ptw32_delete_thread_entry): Internal changes to avoid contention.
- 	Calling routines changed accordingly.
-
-	* pthread.h: Modified cleanup macros to use new generic push and pop.
-	Added destructor and atfork stacks to ptw32_threads_thread_t.
-
-	* cleanup.c (ptw32_handler_push, ptw32_handler_pop,
-	ptw32_handler_pop_all): Renamed cleanup push and pop routines
-	and made generic to handle destructors and atfork handlers as
-	well.
-
-	* create.c (ptw32_start_call): New function is a wrapper for
-	all new threads. It allows us to do some cleanup when the thread
-	returns, ie. that is otherwise only done if the thread is cancelled.
-
-	* exit.c (ptw32_vacuum): New function contains code from 
-	pthread_exit() that we need in the new ptw32_start_call()
-	as well.
-
-	* implement.h: Various additions and minor changes.
-
-	* pthread.h: Various additions and minor changes.
-	Change cleanup handler macros to use generic handler push and pop
-	functions.
-
-	* attr.c: Minor mods to all functions.
-	(is_attr): Implemented missing function.
-
-	* create.c (pthread_create): More clean up.
-
-	* private.c (ptw32_find_thread_entry): Implement.
-	(ptw32_delete_thread_entry): Implement.
-	(ptw32_new_thread_entry): Implement.
-	These functions manipulate the implementations internal thread
-	table and are part of general code cleanup and modularisation.
-	They replace ptw32_getthreadindex() which was removed.
-
-	* exit.c (pthread_exit): Changed to use the new code above.
-
-	* pthread.h: Add cancelability constants. Update comments.
-
-1998-07-22  Ben Elliston  <bje at cygnus.com>
-
-	* attr.c (pthread_setstacksize): Update test of attr argument.
-	(pthread_getstacksize): Likewise.
-	(pthread_setstackaddr): Likewise.
-	(pthread_getstackaddr): Likewise.
-	(pthread_attr_init): No need to allocate any storage.
-	(pthread_attr_destroy): No need to free any storage.
-
-	* mutex.c (is_attr): Not likely to be needed; remove.
-	(remove_attr): Likewise.
-	(insert_attr): Likewise.
-
-	* implement.h (ptw32_mutexattr_t): Moved to a public definition
-	in pthread.h.  There was little gain in hiding these details.
-	(ptw32_condattr_t): Likewise.
-	(ptw32_attr_t): Likewise.
-
-	* pthread.h (pthread_atfork): Add function prototype.
-	(pthread_attr_t): Moved here from implement.h.
-
-	* fork.c (pthread_atfork): Preliminary implementation.
-	(ptw32_fork): Likewise.
-
-Wed Jul 22 00:16:22 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* cleanup.c (ptw32_cleanup_push): Implement.
-	(ptw32_cleanup_pop): Implement.
-	(ptw32_do_cancellation): Implement.
-	These are private to the implementation. The real cleanup functions
-	are macros. See below.
-
-	* pthread.h (pthread_cleanup_push): Implement as a macro.
-	(pthread_cleanup_pop): Implement as a macro.
-	Because these are macros which start and end a block, the POSIX scoping
-	requirement is observed. See the comment in the file.
-
-	* exit.c (pthread_exit): Refine the code.
-
-	* create.c (pthread_create): Code cleanup.
-
-	* implement.h (RND_SIZEOF): Add RND_SIZEOF(T) to round sizeof(T)
-	up to multiple of DWORD.
-	Add function prototypes.
-
-	* private.c (ptw32_getthreadindex): "*thread" should have been 
-	"thread". Detect empty slot fail condition.
-
-1998-07-20  Ben Elliston  <bje at cygnus.com>
-
-	* misc.c (pthread_once): Implement.  Don't use a per-application
-	flag and mutex--make `pthread_once_t' contain these elements in
-	their structure.  The earlier version had incorrect semantics.
-	
-	* pthread.h (ptw32_once_flag): Add new variable.  Remove.
-	(ptw32_once_lock): Add new mutex lock to ensure integrity of
-	access to ptw32_once_flag.  Remove.
-	(pthread_once): Add function prototype.
-	(pthread_once_t): Define this type.
-	
-Mon Jul 20 02:31:05 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* private.c (ptw32_getthreadindex): Implement.
-
-	* pthread.h: Add application static data dependent on
-	_PTHREADS_BUILD_DLL define. This is needed to avoid allocating
-	non-sharable static data within the pthread DLL.
-
-	* implement.h: Add ptw32_cleanup_stack_t, ptw32_cleanup_node_t
-	and PTW32_HASH_INDEX.
-
-	* exit.c (pthread_exit): Begin work on cleanup and de-allocate
-	thread-private storage.
-
-	* create.c (pthread_create): Add thread to thread table.
-	Keep a thread-private copy of the attributes with default values
-	filled in when necessary. Same for the cleanup stack. Make 
-	pthread_create C run-time library friendly by using _beginthreadex()
-	instead of CreateThread(). Fix error returns.
-
-Sun Jul 19 16:26:23 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Rename pthreads_thread_count to ptw32_threads_count.
-	Create ptw32_threads_thread_t struct to keep thread specific data.
-
-	* create.c: Rename pthreads_thread_count to ptw32_threads_count.
-	(pthread_create): Handle errors from CreateThread().
-
-1998-07-19  Ben Elliston  <bje at cygnus.com>
-
-	* condvar.c (pthread_cond_wait): Generalise.  Moved from here ..
-	(cond_wait): To here.
-	(pthread_cond_timedwait): Implement; use generalised cond_wait().
-
-	* pthread.h (pthread_key_t): Define this type.
-	(pthread_key_create): Add function prototype.
-	(pthread_setspecific): Likewise.
-	(pthread_getspecific): Likwise.
-	(pthread_key_delete): Likewise.
-
-	* tsd.c (pthread_key_create): Implement.
-	(pthread_setspecific): Likewise.
-	(pthread_getspecific): Likewise.
-	(pthread_key_delete): Likewise.
-
-	* mutex.c (pthread_mutex_trylock): Return ENOSYS if this function
-	is called on a Win32 platform which is not Windows NT.
-
-1998-07-18  Ben Elliston  <bje at cygnus.com>
-
-	* condvar.c (pthread_condattr_init): Do not attempt to malloc any
-	storage; none is needed now that condattr_t is an empty struct.
-	(pthread_condattr_destory): Likewise; do not free storage.
-	(pthread_condattr_setpshared): No longer supported; return ENOSYS.
-	(pthread_condattr_getpshared): Likewise.
-	(pthread_cond_init): Implement with help from Douglas Schmidt.
-	Remember to initialise the cv's internal mutex.
-	(pthread_cond_wait): Likewise.
-	(pthread_cond_signal): Likewise.
-	(pthread_cond_broadcast): Likewise.
-	(pthread_cond_timedwait): Preliminary implementation, but I need
-	to see some API documentation for `WaitForMultipleObject'.
-	(pthread_destory): Implement.
-
-	* pthread.h (pthread_cond_init): Add function protoype.
-	(pthread_cond_broadcast): Likewise.
-	(pthread_cond_signal): Likewise.
-	(pthread_cond_timedwait): Likewise.
-	(pthread_cond_wait): Likewise.
-	(pthread_cond_destroy): Likewise.
-	(pthread_cond_t): Define this type.  Fix for u_int.  Do not assume
-	that the mutex contained withing the pthread_cond_t structure will
-	be a critical section.  Use our new POSIX type!
-
-	* implement.h (ptw32_condattr_t): Remove shared attribute.
-
-1998-07-17  Ben Elliston  <bje at cygnus.com>
-
-	* pthread.h (PTHREADS_PROCESS_PRIVATE): Remove.
-	(PTHREAD_PROCESS_SHARED): Likewise.  No support for mutexes shared
-	across processes for now.
-	(pthread_mutex_t): Use a Win32 CRITICAL_SECTION type for better
-	performance.
-	
-	* implement.h (ptw32_mutexattr_t): Remove shared attribute.
-	
-	* mutex.c (pthread_mutexattr_setpshared): This optional function
-	is no longer supported, since we want to implement POSIX mutex
-	variables using the much more efficient Win32 critical section
-	primitives.  Critical section objects in Win32 cannot be shared
-	between processes.
-	(pthread_mutexattr_getpshared): Likewise.
-	(pthread_mutexattr_init): No need to malloc any storage; the
-	attributes structure is now empty.
-	(pthread_mutexattr_destroy): This is now a nop.
-	(pthread_mutex_init): Use InitializeCriticalSection().
-	(pthread_mutex_destroy): Use DeleteCriticalSection().
-	(pthread_mutex_lock): Use EnterCriticalSection().
-	(pthread_mutex_trylock): Use TryEnterCriticalSection().  This is
-	not supported by Windows 9x, but trylock is a hack anyway, IMHO.
-	(pthread_mutex_unlock): Use LeaveCriticalSection().
-
-1998-07-14  Ben Elliston  <bje at cygnus.com>
-
-	* attr.c (pthread_attr_setstacksize): Implement.
-	(pthread_attr_getstacksize): Likewise.
-	(pthread_attr_setstackaddr): Likewise.
-	(pthread_attr_getstackaddr): Likewise.
-	(pthread_attr_init): Likewise.
-	(pthread_attr_destroy): Likewise.
-	
-	* condvar.c (pthread_condattr_init): Add `_cond' to function name.
-
-	* mutex.c (pthread_mutex_lock): Add `_mutex' to function name.
-	(pthread_mutex_trylock): Likewise.
-	(pthread_mutex_unlock): Likewise.
-
-	* pthread.h (pthread_condattr_setpshared): Fix typo.
-	(pthread_attr_init): Add function prototype.
-	(pthread_attr_destroy): Likewise.
-	(pthread_attr_setstacksize): Likewise.
-	(pthread_attr_getstacksize): Likewise.
-	(pthread_attr_setstackaddr): Likewise.
-	(pthread_attr_getstackaddr): Likewise.
-	
-Mon Jul 13 01:09:55 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Wrap in #ifndef _IMPLEMENT_H
-
-	* create.c (pthread_create): Map stacksize attr to Win32.
-
-	* mutex.c: Include implement.h
-
-1998-07-13  Ben Elliston  <bje at cygnus.com>
-
-	* condvar.c (pthread_condattr_init): Implement.
-	(pthread_condattr_destroy): Likewise.
-	(pthread_condattr_setpshared): Likewise.
-	(pthread_condattr_getpshared): Likewise.
-	
-	* implement.h (PTHREAD_THREADS_MAX): Remove trailing semicolon.
-	(PTHREAD_STACK_MIN): Specify; needs confirming.
-	(ptw32_attr_t): Define this type.
-	(ptw32_condattr_t): Likewise.
-
-	* pthread.h (pthread_mutex_t): Define this type.
-	(pthread_condattr_t): Likewise.
-	(pthread_mutex_destroy): Add function prototype.
-	(pthread_lock): Likewise.
-	(pthread_trylock): Likewise.
-	(pthread_unlock): Likewise.
-	(pthread_condattr_init): Likewise.
-	(pthread_condattr_destroy): Likewise.
-	(pthread_condattr_setpshared): Likewise.
-	(pthread_condattr_getpshared): Likewise.
-
-	* mutex.c (pthread_mutex_init): Implement.
-	(pthread_mutex_destroy): Likewise.
-	(pthread_lock): Likewise.
-	(pthread_trylock): Likewise.
-	(pthread_unlock): Likewise.
-
-1998-07-12  Ben Elliston  <bje at cygnus.com>
-
-	* implement.h (ptw32_mutexattr_t): Define this implementation
-	internal type.  Application programmers only see a mutex attribute
-	object as a void pointer.
-
-	* pthread.h (pthread_mutexattr_t): Define this type.
-	(pthread_mutexattr_init): Add function prototype.
-	(pthread_mutexattr_destroy): Likewise.
-	(pthread_mutexattr_setpshared): Likewise.
-	(pthread_mutexattr_getpshared): Likewise.
-	(pthread_mutexattr_setprotocol): Likewise.
-	(pthread_mutexattr_getprotocol): Likewise.
-	(pthread_mutexattr_setprioceiling): Likewise.
-	(pthread_mutexattr_getprioceiling): Likewise.
-	(PTHREAD_PROCESS_PRIVATE): Define.
-	(PTHREAD_PROCESS_SHARED): Define.
-
-	* mutex.c (pthread_mutexattr_init): Implement.
-	(pthread_mutexattr_destroy): Implement.
-	(pthread_mutexattr_setprotocol): Implement.
-	(pthread_mutexattr_getprotocol): Likewise.
-	(pthread_mutexattr_setprioceiling): Likewise.
-	(pthread_mutexattr_getprioceiling): Likewise.
-	(pthread_mutexattr_setpshared): Likewise.
-	(pthread_mutexattr_getpshared): Likewise.
-	(insert_attr): New function; very preliminary implementation!
-	(is_attr): Likewise.
-	(remove_attr): Likewise.
-	
-Sat Jul 11 14:48:54 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
-
-	* implement.h: Preliminary implementation specific defines.
-
-	* create.c (pthread_create): Preliminary implementation.
-
-1998-07-11  Ben Elliston  <bje at cygnus.com>
-
-	* sync.c (pthread_join): Implement.
-
-	* misc.c (pthread_equal): Likewise.
-	
-	* pthread.h (pthread_join): Add function prototype.
-	(pthread_equal): Likewise.
-	
-1998-07-10  Ben Elliston  <bje at cygnus.com>
-
-	* misc.c (pthread_self): Implement.
-
-	* exit.c (pthread_exit): Implement.
-
-	* pthread.h (pthread_exit): Add function prototype.
-	(pthread_self): Likewise.
-	(pthread_t): Define this type.
-
-1998-07-09  Ben Elliston  <bje at cygnus.com>
-
-	* create.c (pthread_create): A dummy stub right now.
-
-	* pthread.h (pthread_create): Add function prototype.
+2004-10-15  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* implement.h (pthread_mutex_t_): Use an event in place of
+	the POSIX semaphore.
+	* pthread_mutex_init.c: Create the event; remove semaphore init.
+	* pthread_mutex_destroy.c: Delete the event.
+	* pthread_mutex_lock.c: Replace the semaphore wait with the event wait.
+	* pthread_mutex_trylock.c: Likewise.
+	* pthread_mutex_timedlock.c: Likewise.
+	* pthread_mutex_unlock.c: Set the event.
+	
+2004-10-14  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_mutex_lock.c (pthread_mutex_lock): New algorithm using
+	Terekhov's xchg based variation of Drepper's cmpxchg model.
+	Theoretically, xchg uses fewer clock cycles than cmpxchg (using IA-32
+	as a reference), however, in my opinion bus locking dominates the
+	equation on smp systems, so the model with the least number of bus
+	lock operations in the execution path should win, which is Terekhov's
+	variant. On IA-32 uni-processor systems, it's faster to use the
+	CMPXCHG instruction without locking the bus than to use the XCHG
+	instruction, which always locks the bus. This makes the two variants
+	equal for the non-contended lock (fast lane) execution path on up
+	IA-32. Testing shows that the xchg variant is faster on up IA-32 as
+	well if the test forces higher lock contention frequency, even though
+	kernel calls should be dominating the times (on up IA-32, both
+	variants used CMPXCHG instructions and neither locked the bus).
+	* pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly.
+	* pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly.
+	* pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly.
+	* ptw32_InterlockedCompareExchange.c (ptw32_InterlockExchange): New
+	function.
+	(PTW32_INTERLOCKED_EXCHANGE): Sets up macro to use inlined
+	ptw32_InterlockedExchange.
+	* implement.h (PTW32_INTERLOCKED_EXCHANGE): Set default to
+	InterlockedExchange().
+	* Makefile: Building using /Ob2 so that asm sections within inline
+	functions are inlined.
+
+2004-10-08  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_mutex_destroy.c (pthread_mutex_destroy): Critical Section
+	element is no longer required.
+	* pthread_mutex_init.c (pthread_mutex_init): Likewise.
+	* pthread_mutex_lock.c (pthread_mutex_lock): New algorithm following
+	Drepper's paper at http://people.redhat.com/drepper/futex.pdf, but
+	using the existing semaphore in place of the futex described in the
+	paper. Idea suggested by Alexander Terekhov - see:
+	http://sources.redhat.com/ml/pthreads-win32/2003/msg00108.html
+	* pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly.
+	* pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly.
+	* pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly.
+	* pthread_barrier_wait.c (pthread_barrier_wait): Use inlined version
+	of InterlockedCompareExchange() if possible - determined at
+	build-time.
+	* pthread_spin_destroy.c pthread_spin_destroy(): Likewise.
+	* pthread_spin_lock.c pthread_spin_lock():Likewise.
+	* pthread_spin_trylock.c (pthread_spin_trylock):Likewise.
+	* pthread_spin_unlock.c (pthread_spin_unlock):Likewise.
+	* ptw32_InterlockedCompareExchange.c: Sets up macro for inlined use.
+	* implement.h (pthread_mutex_t_): Remove Critical Section element.
+	(PTW32_INTERLOCKED_COMPARE_EXCHANGE): Set to default non-inlined
+	version of InterlockedCompareExchange().
+	* private.c: Include ptw32_InterlockedCompareExchange.c first for
+	inlining.
+	* GNUmakefile: Add commandline option to use inlined
+	InterlockedCompareExchange().
+	* Makefile: Likewise.
+
+2004-09-27  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_mutex_lock.c (pthread_mutex_lock): Separate
+	PTHREAD_MUTEX_NORMAL logic since we do not need to keep or check some
+	state required by other mutex types; do not check mutex pointer arg
+	for validity - leave this to the system since we are only checking
+	for NULL pointers. This should improve speed of NORMAL mutexes and
+	marginally improve speed of other type.
+	* pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
+	* pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise; also avoid
+	entering the critical section for the no-waiters case, with approx.
+	30% reduction in lock/unlock overhead for this case.
+	* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise; also
+	no longer keeps mutex if post-timeout second attempt succeeds - this
+	will assist applications that wish to impose strict lock deadlines,
+	rather than simply to escape from frozen locks.
+
+2004-09-09  Tristan Savatier  <tristan at mpegtv.com>
+	* pthread.h (struct pthread_once_t_): Qualify the 'done' element
+	as 'volatile'.
+	* pthread_once.c: Concerned about possible race condition,
+	specifically on MPU systems re concurrent access to multibyte types.
+	[Maintainer's note: the race condition is harmless on SPU systems
+	and only a problem on MPU systems if concurrent access results in an
+	exception (presumably generated by a hardware interrupt). There are
+	other instances of similar harmless race conditions that have not
+	been identified as issues.]
+
+2004-09-09  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread.h: Declare additional types as volatile.
+
+2004-08-27  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_barrier_wait.c (pthread_barrier_wait): Remove excessive code
+	by substituting the internal non-cancelable version of sem_wait
+	(ptw32_semwait).
+
+2004-08-25  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_join.c (pthread_join): Rewrite and re-order the conditional
+	tests in an attempt to improve efficiency and remove a race
+	condition.
+
+2004-08-23  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* create.c (pthread_create): Don't create a thread if the thread
+	id pointer location (first arg) is inaccessible. A memory
+	protection fault will result if the thread id arg isn't an accessible
+	location. This is consistent with GNU/Linux but different to
+	Solaris or MKS (and possibly others), which accept NULL as meaning
+	'don't return the created thread's ID'. Applications that run
+	using pthreads-win32 will run on all other POSIX threads
+	implementations, at least w.r.t. this feature.
+
+	It was decided not to copy the Solaris et al behaviour because,
+	although it would have simplified some application porting (but only
+	from Solaris to Windows), the feature is not technically necessary,
+	and the alternative segfault behaviour helps avoid buggy application
+	code.
+
+2004-07-01  Anuj Goyal  <anuj.goyal at gmail.com>
+
+	* builddmc.bat: New; Windows bat file to build the library.
+	* config.h (__DMC__): Support for Digital Mars compiler.
+	* create.c (__DMC__): Likewise.
+	* pthread_exit.c (__DMC__): Likewise.
+	* pthread_join.c (__DMC__): Likewise.
+	* ptw32_threadDestroy.c (__DMC__): Likewise.
+	* ptw32_threadStart.c (__DMC__): Likewise.
+	* ptw32_throw.c (__DMC__): Likewise.
+
+2004-06-29  Anuj Goyal  <anuj.goyal at gmail.com>
+
+	* pthread.h (__DMC__): Initial support for Digital Mars compiler.
+
+2004-06-29  Will Bryant  <will.bryant at ecosm.com>
+
+	* README.Borland: New; description of Borland changes.
+	* Bmakefile: New makefile for the Borland make utility.
+	* ptw32_InterlockedCompareExchange.c:
+	Add Borland compatible asm code.
+
+2004-06-26  Jason Bard  <BardJA at Npt.NUWC.Navy.Mil>
+
+	* pthread.h (HAVE_STRUCT_TIMESPEC): If undefined, define it
+	to avoid timespec struct redefined errors elsewhere in an
+	application.
+
+2004-06-21  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Mutex
+	initialiser added for compatibility with Linux threads and
+	others; currently not included in SUSV3.
+	* pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER): Likewise.
+	* pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Likewise.
+	* pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise.
+
+	* ptw32_mutex_check_need_init.c (ptw32_mutex_check_need_init): 
+	Add new initialisers.
+
+	* pthread_mutex_lock.c (pthread_mutex_lock): Check for new
+	initialisers.
+	* pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
+	* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
+	* pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise.
+	* pthread_mutex_destroy.c (pthread_mutex_destroy): Likewise.
+
+2004-05-20  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* README.NONPORTABLE: Document pthread_win32_test_features_np().
+	* FAQ: Update various answers.
+
+2004-05-19  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* Makefile: Don't define _WIN32_WINNT on compiler command line.
+	* GNUmakefile: Likewise.
+
+2004-05-16  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_cancel.c (pthread_cancel): Adapted to use auto-detected
+	QueueUserAPCEx features at run-time.
+	(ptw32_RegisterCancelation): Drop in replacement for QueueUserAPCEx()
+	if it can't be used. Provides older style non-preemptive async
+	cancelation.
+	* pthread_win32_attach_detach_np.c (pthread_win32_attach_np):
+	Auto-detect quserex.dll and the availability of alertdrv.sys;
+	initialise and close on process attach/detach.
+	* global.c (ptw32_register_cancelation): Pointer to either
+	QueueUserAPCEx() or ptw32_RegisterCancelation() depending on
+	availability. QueueUserAPCEx makes pre-emptive async cancelation
+	possible.
+	* implement.h: Add definitions and prototypes related to QueueUserAPC.
+
+2004-05-16  Panagiotis E. Hadjidoukas <peh at hpclab.ceid.upatras.gr>
+
+	* QueueUserAPCEx (separate contributed package): Provides preemptive
+	APC feature.
+	* pthread_cancel.c (pthread_cancel): Initial integration of
+	QueueUserAPCEx into pthreads-win32 to provide true pre-emptive
+	async cancelation of threads, including blocked threads.
+
+2004-05-06  Makoto Kato  <raven at oldskool.jp>
+
+	* pthread.h (DWORD_PTR): Define typedef for older MSVC.
+	* pthread_cancel.c (AMD64): Add architecture specific Context register.
+	* ptw32_getprocessors.c: Use correct types (DWORD_PTR) for mask
+	variables.
+
+2004-04-06  P. van Bruggen  <pietvb at newbridges.nl>
+
+	* ptw32_threadDestroy.c: Destroy threadLock mutex to
+	close a memory leak.
+
+2004-02-13  Gustav Hallberg  <gustav at virtutech.com>
+
+	* pthread_equal.c: Remove redundant equality logic.
+
+2003-12-10  Philippe Di Cristo  <philipped at voicebox.com>
+
+	* sem_timedwait.c (sem_timedwait): Fix timeout calculations.
+
+2003-10-20  Alexander Terekhov  <TEREKHOV at de.ibm.com>
+
+	* pthread_mutex_timedlock.c (ptw32_semwait): Move to individual module.
+	* ptw32_semwait.c: New module.
+	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): Replace cancelable
+	sem_wait() call with non-cancelable ptw32_semwait() call.
+	* pthread.c (private.c): Re-order for inlining. GNU C warned that
+	function ptw32_semwait() was defined 'inline' after it was called.
+	* pthread_cond_signal.c (ptw32_cond_unblock): Likewise.
+	* pthread_delay_np.c: Disable Watcom warning with comment.
+	* *.c (process.h): Remove include from .c files. This is conditionally
+	included by the common project include files.
+
+2003-10-20  James Ewing  <james.ewing at sveasoft.com>
+
+	* ptw32_getprocessors.c: Some Win32 environments don't have
+	GetProcessAffinityMask(), so always return CPU count = 1 for them.
+	* config.h (NEED_PROCESSOR_AFFINITY_MASK): Define for WinCE.
+	
+2003-10-15  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* Re-indented all .c files using default GNU style to remove assorted
+	editor ugliness (used GNU indent utility in default style).
+
+2003-10-15  Alex Blanco  <Alex.Blanco at motorola.com>
+
+	* sem_init.c (sem_init): Would call CreateSemaphore even if the sema
+	struct calloc failed; was not freeing calloced memory if either
+	CreateSemaphore or CreateEvent failed.
+
+2003-10-14  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* pthread.h: Add Watcom compiler compatibility. Esssentially just add
+	the cdecl attribute to all exposed function prototypes so that Watcom
+	generates function call code compatible with non-Watcom built libraries.
+	By default, Watcom uses registers to pass function args if possible rather
+	than pushing to stack.
+	* semaphore.h: Likewise.
+	* sched.h: Likewise.
+	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): Define with cdecl attribute
+	for Watcom compatibility. This routine is called via pthread_cleanup_push so
+	it had to match function arg definition.
+	* Wmakefile: New makefile for Watcom builds.
+
+2003-09-14  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_setschedparam.c (pthread_setschedparam): Attempt to map
+	all priority levels between max and min (as returned by
+	sched_get_priority_min/max) to reasonable Win32 priority levels - i.e.
+	levels between THREAD_PRIORITY_LOWEST/IDLE to THREAD_PRIORITY_LOWEST and
+	between THREAD_PRIORITY_HIGHEST/TIME_CRITICAL to THREAD_PRIORITY_HIGHEST
+	while others remain unchanged; record specified thread priority level
+	for return by pthread_getschedparam.
+
+	Note that, previously, specified levels not matching Win32 priority levels
+	would silently leave the current thread priority unaltered.
+
+	* pthread_getschedparam.c (pthread_getschedparam): Return the priority
+	level specified by the latest pthread_setschedparam or pthread_create rather
+	than the actual running thread priority as returned by GetThreadPriority - as
+	required by POSIX. I.e. temporary or adjusted actual priority levels are not
+	returned by this routine.
+
+	* pthread_create.c (pthread_create): For priority levels specified via
+	pthread attributes, attempt to map all priority levels between max and
+	min (as returned by sched_get_priority_min/max) to reasonable Win32
+	priority levels; record priority level given via attributes, or
+	inherited from parent thread, for later return by pthread_getschedparam.
+
+	* ptw32_new.c (ptw32_new): Initialise pthread_t_ sched_priority element.
+
+	* pthread_self.c (pthread_self): Set newly created implicit POSIX thread
+	sched_priority to Win32 thread's current actual priority. Temporarily
+	altered priorities can't be avoided in this case.
+
+	* implement.h (struct pthread_t_): Add new sched_priority element.
+
+2003-09-12  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* sched_get_priority_min.c (sched_get_priority_min): On error should return -1
+	with errno set.
+	* sched_get_priority_max.c (sched_get_priority_max): Likewise.
+
+2003-09-03  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* w32_cancelableWait.c (ptw32_cancelable_wait): Allow cancelation
+	of implicit POSIX threads as well.
+
+2003-09-02  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np):
+	Add comment.
+
+	* pthread_exit.c (pthread_exit): Fix to recycle the POSIX thread handle in
+	addition to calling user TSD destructors. Move the implicit POSIX thread exit
+	handling to ptw32_throw to centralise the logic.
+
+	* ptw32_throw.c (ptw32_throw): Implicit POSIX threads have no point
+	to jump or throw to, so cleanup and exit the thread here in this case. For
+	processes using the C runtime, the exit code will be set to the POSIX
+	reason for the throw (i.e. PTHREAD_CANCEL or the value given to pthread_exit).
+	Note that pthread_exit() already had similar logic, which has been moved to
+	here.
+
+	* ptw32_threadDestroy.c (ptw32_threadDestroy): Don't close the Win32 handle
+	of implicit POSIX threads - expect this to be done by Win32?
+
+2003-09-01  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_self.c (pthread_self): The newly aquired pthread_t must be
+	assigned to the reuse stack, not freed, if the routine fails somehow.
+
+2003-08-13  Ross Johnson  <rpj at ise.canberra.edu.au>
+
+	* pthread_getschedparam.c (pthread_getschedparam): An invalid thread ID
+	parameter was returning an incorrect error value; now uses a more exhaustive
+	check for validity.
+
+	* pthread_setschedparam.c (pthread_setschedparam): Likewise.
+
+	* pthread_join.c (pthread_join): Now uses a more exhaustive
+	check for validity.
+
+	* pthread_detach.c (pthread_detach): Likewise.
+
+	* pthread_cancel.c (pthread_cancel): Likewise.
+
+	* ptw32_threadDestroy.c (ptw32_threadDestroy): pthread_t structs are
+	never freed - push them onto a stack for reuse.
+
+	* ptw32_new.c (ptw32_new): Check for reusable pthread_t before dynamically
+	allocating new memory for the struct.
+
+	* pthread_kill.c (pthread_kill): New file; new routine; takes only a zero
+	signal arg so that applications can check the thread arg for validity; checks
+	that the underlying Win32 thread HANDLE is valid.
+
+	* pthread.h (pthread_kill): Add prototype.
+
+	* ptw32_reuse.c (ptw32_threadReusePop): New file; new routine; pop a
+	pthread_t off the reuse stack. pthread_t_ structs that have been destroyed, i.e.
+	have exited detached or have been joined, are cleaned up and put onto a reuse
+	stack. Consequently, thread IDs are no longer freed once calloced. The library
+	will attempt to get a struct off this stack before asking the system to alloc
+	new memory when creating threads. The stack is guarded by a global mutex.
+	(ptw32_threadReusePush): New routine; push a pthread_t onto the reuse stack.
+
+	* implement.h (ptw32_threadReusePush): Add new prototype.
+	(ptw32_threadReusePop): Likewise.
+	(pthread_t): Add new element.
+
+	* ptw32_processTerminate.c (ptw32_processTerminate): Delete the thread
+	reuse lock; free all thread ID structs on the thread reuse stack.
+
+	* ptw32_processInitialize.c (ptw32_processInitialize): Initialise the
+	thread reuse lock.
+
+2003-07-19  Ross Johnson  <rpj at ise.canberra.edu.au>
+
+	* GNUmakefile: modified to work under MsysDTK environment.
+	* pthread_spin_lock.c (pthread_spin_lock): Check for NULL arg.
+	* pthread_spin_unlock.c (pthread_spin_unlock): Likewise.
+	* pthread_spin_trylock.c (pthread_spin_trylock): Likewise;
+	fix incorrect pointer value if lock is dynamically initialised by
+	this function.
+	* sem_init.c (sem_init): Initialise sem_t value to quell compiler warning.
+	* sem_destroy.c (sem_destroy): Likewise.
+	* ptw32_threadStart.c (non-MSVC code sections): Include <exception> rather
+	than old-style <new.h>; fix all std:: namespace entities such as
+	std::terminate_handler instances and associated methods.
+	* ptw32_callUserDestroyRoutines.c (non-MSVC code sections): Likewise.
+
+2003-06-24  Piet van Bruggen  <pietvb at newbridges.nl>
+
+	* pthread_spin_destroy.c (pthread_spin_destroy): Was not freeing the
+	spinlock struct.
+
+2003-06-22  Nicolas Barry  <boozai at yahoo.com>
+
+	* pthread_mutex_destroy.c (pthread_mutex_destroy): When called
+	with a recursive mutex that was locked by the current thread, the
+	function was failing with a success return code.
+
+2003-05-15  Steven Reddie  <Steven.Reddie at ca.com>
+
+	* pthread_win32_attach_detach_np.c (pthread_win32_process_detach_np):
+	NULLify ptw32_selfThreadKey after the thread is destroyed, otherwise
+	destructors calling pthreads routines might resurrect it again, creating
+	memory leaks. Call the underlying Win32 Tls routine directly rather than
+	pthread_setspecific().
+	(pthread_win32_thread_detach_np): Likewise.
+
+2003-05-14  Viv  <vcotirlea at hotmail.com>
+
+	* pthread.dsp: Change /MT compile flag to /MD.
+
+2003-03-04  Alexander Terekhov  <TEREKHOV at de.ibm.com>
+
+	* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Fix failure to
+	set ownership of mutex on second grab after abstime timeout.
+	- bug reported by Robert Strycek <strycek at posam.sk>
+
+2002-12-17  Thomas Pfaff  <tpfaff at gmx.net>
+
+	* pthread_mutex_lock.c (ptw32_semwait): New static routine to provide
+	a non-cancelable sem_wait() function. This is consistent with the
+	way that pthread_mutex_timedlock.c does it.
+	(pthread_mutex_lock): Use ptw32_semwait() instead of sem_wait().
+
+2002-12-11  Thomas Pfaff  <tpfaff at gmx.net>
+
+	* pthread_mutex_trylock.c: Should return EBUSY rather than EDEADLK.
+	* pthread_mutex_destroy.c: Remove redundant ownership test (the
+	trylock call does this for us); do not destroy a recursively locked
+	mutex.
+
+2002-09-20  Michael Johnson  <michaelj at maine.rr.com>
+
+	* pthread_cond_destroy.c (pthread_cond_destroy): 
+	When two different threads exist, and one is attempting to
+	destroy a condition variable while the other is attempting to
+	initialize a condition variable that was created with
+	PTHREAD_COND_INITIALIZER, a deadlock can occur. Shrink
+	the ptw32_cond_list_lock critical section to fix it.
+
+2002-07-31  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* ptw32_threadStart.c (ptw32_threadStart): Thread cancelLock
+	destruction moved to ptw32_threadDestroy().
+
+	* ptw32_threadDestroy.c (ptw32_threadDestroy):  Destroy
+	the thread's cancelLock. Moved here from ptw32_threadStart.c
+	to cleanup implicit threads as well.
+
+2002-07-30  Alexander Terekhov  <TEREKHOV at de.ibm.com>
+
+	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): 
+	Remove code designed to avoid/prevent spurious wakeup
+	problems. It is believed that the sem_timedwait() call
+	is consuming a CV signal that it shouldn't and this is
+	breaking the avoidance logic.
+
+2002-07-30  Ross Johnson  <rpj at ise.canberra.edu.au>
+
+	* sem_timedwait.c (sem_timedwait): Tighten checks for
+	unreasonable abstime values - that would result in
+	unexpected timeout values.
+
+	* w32_CancelableWait.c (ptw32_cancelable_wait):
+	Tighten up return value checking and add comments.
+
+
+2002-06-08  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* sem_getvalue.c (sem_getvalue): Now returns a value for the
+	NEED_SEM version (i.e. earlier versions of WinCE).
+
+
+2002-06-04  Rob Fanner  <rfanner at stonethree.com>
+
+	* sem_getvalue.c (sem_getvalue): The Johnson M. Hart
+	approach didn't work - we are forced to take an
+	intrusive approach. We try to decrement the sema
+	and then immediately release it again to get the
+	value. There is a small probability that this may
+	block other threads, but only momentarily.
+
+2002-06-03  Ross Johnson  <rpj at ise.canberra.edu.au>
+
+	* sem_init.c (sem_init): Initialise Win32 semaphores
+	to _POSIX_SEM_VALUE_MAX (which this implementation
+	defines in pthread.h) so that sem_getvalue() can use
+	the trick described in the comments in sem_getvalue().
+	* pthread.h (_POSIX_SEM_VALUE_MAX): Defined.
+	(_POSIX_SEM_NSEMS_MAX): Defined - not used but may be
+	useful for source code portability.
+
+2002-06-03  Rob Fanner  <rfanner at stonethree.com>
+
+	* sem_getvalue.c (sem_getvalue): Did not work on NT.
+	Use approach suggested by Johnson M. Hart in his book
+	"Win32 System Programming".
+
+2002-02-28  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* errno.c: Compiler directive was incorrectly including code.
+	* pthread.h: Conditionally added some #defines from config.h
+	needed when not building the library. e.g. NEED_ERRNO, NEED_SEM.
+	(PTW32_DLLPORT): Now only defined if _DLL defined.
+	(_errno): Compiler directive was incorrectly including prototype.
+	* sched.h: Conditionally added some #defines from config.h
+	needed when not building the library.
+	* semaphore.h: Replace an instance of NEED_SEM that should
+	have been NEED_ERRNO. This change currently has nil effect.
+
+	* GNUmakefile: Correct some recent changes.
+
+	* Makefile: Add rule to generate pre-processor output.
+
+2002-02-23  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* pthread_rwlock_timedrdlock.c: New - untested.
+	* pthread_rwlock_timedwrlock.c: New - untested.
+	
+	* Testsuite passed (except known MSVC++ problems)
+
+	* pthread_cond_destroy.c: Expand the time change
+	critical section to solve deadlock problem.
+
+	* pthread.c: Add all remaining C modules.
+	* pthread.h: Use dllexport/dllimport attributes on functions
+	to avoid using pthread.def.
+	* sched.h: Likewise.
+	* semaphore.h: Likewise.
+	* GNUmakefile: Add new targets for single translation
+	unit build to maximise inlining potential; generate
+	pthread.def automatically.
+	* Makefile: Likewise, but no longer uses pthread.def.
+
+2002-02-20  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* pthread_cond_destroy.c (pthread_cond_destroy):
+	Enter the time change critical section earlier.
+
+2002-02-17  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
+
+	* Testsuite passed.
+
+	* pthread_timechange_handler_np.c: New; following
+	a suggestion from Alexander Terekhov that CVs should
+	be broadcast so that they all re-evaluate their
+	condition variables and reset a new timeout if
+	required, whenever an application receives a
+	WM_TIMECHANGE message. This message indicates that
+	the system time has been changed. Therefore, CVs
+	waiting for a timeout set as an abs_time will possibly
+	not wake up at the expected time. Some applications
+	may not be tolerant of this.
+	* pthread_cond_init.c: Add CV to linked list.
+	* pthread_cond_destroy.c: Remove CV from linked list.
+	* global.c (ptw32_cond_list_head): New variable.
+	(ptw32_cond_list_tail): New variable.
+	(ptw32_cond_list_cs): New critical section.
+	* ptw32_processInitialize (ptw32_cond_list_cs): Initialize.
+	* ptw32_processTerminate (ptw32_cond_list_cs): Delete.
+
+
+	* Reduce executable size.
+	  -----------------------
+	When linking with the static library, only those
+	routines actually called, either directly or indirectly
+	should be included.
+
+	[Gcc has the -ffunction-segments option to do this but MSVC
+	doesn't have this feature as far as I can determine. Other
+	compilers are undetermined as well. - rpj]
+
+	* spin.c: Split file into function segments.
+	* ptw32_spinlock_check_need_init.c: Separated routine from spin.c.
+	* pthread_spin_init.c: Likewise.
+	* pthread_spin_destroy.c: Likewise.
+	* pthread_spin_lock.c: Likewise.
+	* pthread_spin_unlock.c: Likewise.
+	* pthread_spin_trylock.c: Likewise.
+
+	* sync.c: Split file into function segments.
+	* pthread_detach.c: Separated routine from sync.c.
+	* pthread_join.c: Likewise.
+
+	* tsd.c: Split file into function segments.
+	* pthread_key_create.c: Separated routine from tsd.c.
+	* pthread_key_delete.c: Likewise.
+	* pthread_setspecific.c: Likewise.
+	* pthread_getspecific.c: Likewise.
+
+	* sched.c: Split file into function segments.
+	* pthread_attr_setschedpolicy.c: Separated routine from sched.c.
+	* pthread_attr_getschedpolicy.c: Likewise.
+	* pthread_attr_setschedparam.c: Likewise.
+	* pthread_attr_getschedparam.c: Likewise.
+	* pthread_attr_setinheritsched.c: Likewise.
+	* pthread_attr_getinheritsched.c: Likewise.
+	* pthread_setschedparam.c: Likewise.
+	* pthread_getschedparam.c: Likewise.
+	* sched_get_priority_max.c: Likewise.
+	* sched_get_priority_min.c: Likewise.
+	* sched_setscheduler.c: Likewise.
+	* sched_getscheduler.c: Likewise.
+	* sched_yield.c: Likewise.
+
+
+2002-02-16  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
+
+	Reduce executable size.
+	-----------------------
+	When linking with the static library, only those
+	routines actually called, either directly or indirectly
+	should be included.
+
+	[Gcc has the -ffunction-segments option to do this but MSVC
+	doesn't have this feature as far as I can determine. Other
+	compilers are undetermined as well. - rpj]
+
+	* mutex.c: Split file into function segments.
+	* pthread_mutexattr_destroy.c: Separated routine from mutex.c
+	* pthread_mutexattr_getpshared.c: Likewise.
+	* pthread_mutexattr_gettype.c: Likewise.
+	* pthread_mutexattr_init.c: Likewise.
+	* pthread_mutexattr_setpshared.c: Likewise.
+	* pthread_mutexattr_settype.c: Likewise.
+	* ptw32_mutex_check_need_init.c: Likewise.
+	* pthread_mutex_destroy.c: Likewise.
+	* pthread_mutex_init.c: Likewise.
+	* pthread_mutex_lock.c: Likewise.
+	* pthread_mutex_timedlock.c: Likewise.
+	* pthread_mutex_trylock.c: Likewise.
+	* pthread_mutex_unlock.c: Likewise.
+	
+	* private.c: Split file into function segments.
+	* ptw32_InterlockedCompareExchange.c: Separated routine from private.c
+	* ptw32_callUserDestroyRoutines.c: Likewise.
+	* ptw32_getprocessors.c: Likewise.
+	* ptw32_processInitialize.c: Likewise.
+	* ptw32_processTerminate.c: Likewise.
+	* ptw32_threadDestroy.c: Likewise.
+	* ptw32_threadStart.c: Likewise.
+	* ptw32_throw.c: Likewise.
+	* ptw32_timespec.c: Likewise.
+	* ptw32_tkAssocCreate.c: Likewise.
+	* ptw32_tkAssocDestroy.c: Likewise.
+
+	* rwlock.c: Split file into function segments.
+	* pthread_rwlockattr_destroy.c: Separated routine from rwlock.c
+	* pthread_rwlockattr_getpshared.c: Likewise.
+	* pthread_rwlockattr_init.c: Likewise.
+	* pthread_rwlockattr_setpshared.c: Likewise.
+	* ptw32_rwlock_check_need_init.c: Likewise.
+	* pthread_rwlock_destroy.c: Likewise.
+	* pthread_rwlock_init.c: Likewise.
+	* pthread_rwlock_rdlock.c: Likewise.
+	* pthread_rwlock_tryrdlock.c: Likewise.
+	* pthread_rwlock_trywrlock.c: Likewise.
+	* pthread_rwlock_unlock.c: Likewise.
+	* pthread_rwlock_wrlock.c: Likewise.
+
+2002-02-10  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
+
+	Reduce executable size.
+	-----------------------
+	When linking with the static library, only those
+	routines actually called, either directly or indirectly
+	should be included.
+
+	[Gcc has the -ffunction-segments option to do this but MSVC
+	doesn't have this feature as far as I can determine. Other
+	compilers are undetermined as well. - rpj]
+
+	* nonportable.c: Split file into function segments.
+	* np_delay.c: Separated routine from nonportable.c
+	* np_getw32threadhandle.c: Likewise.
+	* np_mutexattr_setkind.c: Likewise.
+	* np_mutexattr_getkind.c: Likewise.
+	* np_num_processors.c: Likewise.
+	* np_win32_attach_detach.c: Likewise.
+
+	* misc.c: Split file into function segments.
+	* pthread_equal.c: Separated routine from nonportable.c.
+	* pthread_getconcurrency.c: Likewise.
+	* pthread_once.c: Likewise.
+	* pthread_self.c: Likewise.
+	* pthread_setconcurrency.c: Likewise.
+	* ptw32_calloc.c: Likewise.
+	* ptw32_new.c: Likewise.
+	* w32_CancelableWait.c: Likewise.
+	
+2002-02-09  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
+
+	Reduce executable size.
+	-----------------------
+	When linking with the static library, only those
+	routines actually called, either directly or indirectly
+	should be included.
+
+	[Gcc has the -ffunction-segments option to do this but MSVC
+	doesn't have this feature as far as I can determine. Other
+	compilers are undetermined as well. - rpj]
+
+	* condvar.c: Split file into function segments.
+	* pthread_condattr_destroy.c: Separated routine from condvar.c.
+	* pthread_condattr_getpshared.c: Likewise.
+	* pthread_condattr_init.c: Likewise.
+	* pthread_condattr_setpshared.c: Likewise.
+	* ptw32_cond_check_need_init.c: Likewise.
+	* pthread_cond_destroy.c: Likewise.
+	* pthread_cond_init.c: Likewise.
+	* pthread_cond_signal.c: Likewise.
+	* pthread_cond_wait.c: Likewise.
+	
+2002-02-07  Alexander Terekhov<TEREKHOV at de.ibm.com>
+
+	* nonportable.c (pthread_delay_np): Make a true
+	cancelation point. Deferred cancels will interrupt the
+	wait.
+
+2002-02-07  Ross Johnson  <rpj at setup1.ise.canberra.edu.au
+
+	* misc.c (ptw32_new): Add creation of cancelEvent so that
+	implicit POSIX threads (Win32 threads with a POSIX face)
+	are cancelable; mainly so that pthread_delay_np doesn't fail
+	if called from the main thread.
+	* create.c (pthread_create): Remove creation of cancelEvent
+	from here; now in ptw32_new().
+
+	Reduce executable size.
+	-----------------------
+	When linking with the static library, only those
+	routines actually called, either directly or indirectly
+	should be included.
+
+	[Gcc has the -ffunction-segments option to do this but MSVC
+	doesn't have this feature as far as I can determine. Other
+	compilers are undetermined as well. - rpj]
+
+	* barrier.c: All routines are now in separate compilation units;
+	This file is used to congregate the separate modules for
+	potential inline optimisation and backward build compatibility.
+	* cancel.c: Likewise.
+	* pthread_barrierattr_destroy.c: Separated routine from cancel.c.
+	* pthread_barrierattr_getpshared.c: Likewise.
+	* pthread_barrierattr_init.c: Likewise.
+	* pthread_barrierattr_setpshared.c: Likewise.
+	* pthread_barrier_destroy.c: Likewise.
+	* pthread_barrier_init.c: Likewise.
+	* pthread_barrier_wait.c: Likewise.
+	* pthread_cancel.c: Likewise.
+	* pthread_setcancelstate.c: Likewise.
+	* pthread_setcanceltype.c: Likewise.
+	* pthread_testcancel.c: Likewise.
+
+2002-02-04  Max Woodbury <mtew at cds.duke.edu>
+
+	Reduced name space pollution.
+	-----------------------------
+	When the appropriate symbols are defined, the headers
+	will restrict the definitions of new names. In particular,
+	it must be possible to NOT include the <windows.h>
+	header and related definitions with some combination
+	of symbol definitions. Secondly, it should be possible
+	that additional definitions should be limited to POSIX 
+	compliant symbols by the definition of appropriate symbols.
+
+	* pthread.h: POSIX conditionals.
+	* sched.h: POSIX conditionals.
+	* semaphore.h: POSIX conditionals.
+
+	* semaphore.c: Included <limits.h>.
+	(sem_init): Changed magic 0x7FFFFFFFL to INT_MAX.
+	(sem_getvalue): Trial version.
+
+	Reduce executable size.
+	-----------------------
+	When linking with the static library, only those
+	routines actually called, either directly or indirectly
+	should be included.
+
+	[Gcc has the -ffunction-segments option to do this but MSVC
+	doesn't have this feature as far as I can determine. Other
+	compilers are undetermined as well. - rpj]
+
+	* semaphore.c: All routines are now in separate compilation units;
+	This file is used to congregate the separate modules for
+	potential inline optimisation and backward build compatibility.
+	* sem_close.c: Separated routine from semaphore.c.
+	* ptw32_decrease_semaphore.c: Likewise.
+	* sem_destroy.c: Likewise.
+	* sem_getvalue.c: Likewise.
+	* ptw32_increase_semaphore.c: Likewise.
+	* sem_init.c: Likewise.
+	* sem_open.c: Likewise.
+	* sem_post.c: Likewise.
+	* sem_post_multiple.c: Likewise.
+	* sem_timedwait.c: Likewise.
+	* sem_trywait.c: Likewise.
+	* sem_unlink.c: Likewise.
+	* sem_wait.c: Likewise.
+
+2002-02-04  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	The following extends the idea above to the rest of pthreads-win32 - rpj
+	
+	* attr.c: All routines are now in separate compilation units;
+	This file is used to congregate the separate modules for
+	potential inline optimisation and backward build compatibility.
+	* pthread_attr_destroy.c: Separated routine from attr.c.
+	* pthread_attr_getdetachstate.c: Likewise.
+	* pthread_attr_getscope.c: Likewise.
+	* pthread_attr_getstackaddr.c: Likewise.
+	* pthread_attr_getstacksize.c: Likewise.
+	* pthread_attr_init.c: Likewise.
+	* pthread_attr_is_attr.c: Likewise.
+	* pthread_attr_setdetachstate.c: Likewise.
+	* pthread_attr_setscope.c: Likewise.
+	* pthread_attr_setstackaddr.c: Likewise.
+	* pthread_attr_setstacksize.c: Likewise.
+
+	* pthread.c: Agregation of agregate modules for super-inlineability.
+
+2002-02-02  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* cancel.c: Rearranged some code and introduced checks
+	to disable cancelation at the start of a thread's cancelation
+	run to prevent double cancelation. The main problem
+	arises if a thread is canceling and then receives a subsequent
+	async cancel request.
+	* private.c: Likewise.
+	* condvar.c: Place pragmas around cleanup_push/pop to turn
+	off inline optimisation (/Obn where n>0 - MSVC only). Various
+	optimisation switches in MSVC turn this on, which interferes with
+	the way that cleanup handlers are run in C++ EH and SEH
+	code. Application code compiled with inline optimisation must
+	also wrap cleanup_push/pop blocks with the pragmas, e.g.
+	  #pragma inline_depth(0)
+	  pthread_cleanup_push(...)
+	    ...
+	  pthread_cleanup_pop(...)
+	  #pragma inline_depth(8)
+	* rwlock.c: Likewise.
+	* mutex.c: Remove attempts to inline some functions.
+	* signal.c: Modify misleading comment.
+
+2002-02-01  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* semaphore.c (sem_trywait): Fix missing errno return
+	for systems that define NEED_SEM (e.g. early WinCE).
+	* mutex.c (pthread_mutex_timedlock): Return ENOTSUP
+	for systems that define NEED_SEM since they don't
+	have sem_trywait().
+
+2002-01-27  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* mutex.c (pthread_mutex_timedlock): New function suggested by
+	Alexander Terekhov. The logic required to implement this
+	properly came from Alexander, with some collaboration
+	with Thomas Pfaff.
+	(pthread_mutex_unlock): Wrap the waiters check and sema
+	post in a critical section to prevent a race with
+	pthread_mutex_timedlock.
+	(ptw32_timed_semwait): New function;
+	returns a special result if the absolute timeout parameter
+	represents a time already passed when called; used by
+	pthread_mutex_timedwait(). Have deliberately not reused
+	the name "ptw32_sem_timedwait" because they are not the same
+	routine.
+	* condvar.c (ptw32_cond_timedwait): Use the new sem_timedwait()
+	instead of ptw32_sem_timedwait(), which now has a different
+	function. See previous.
+	* implement.h: Remove prototype for ptw32_sem_timedwait.
+	See next.
+	(pthread_mutex_t_): Add critical section element for access
+	to lock_idx during mutex post-timeout processing.
+	* semaphore.h (sem_timedwait): See next.
+	* semaphore.c (sem_timedwait): See next.
+	* private.c (ptw32_sem_timedwait): Move to semaphore.c
+	and rename as sem_timedwait().
+
+2002-01-18  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* sync.c (pthread_join): Was getting the exit code from the
+	calling thread rather than the joined thread if
+	defined(__MINGW32__) && !defined(__MSVCRT__).
+
+2002-01-15  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.h: Unless the build explicitly defines __CLEANUP_SEH,
+	__CLEANUP_CXX, or __CLEANUP_C, then the build defaults to
+	__CLEANUP_C style cleanup. This style uses setjmp/longjmp
+	in the cancelation and thread exit implementations and therefore
+	won't do stack unwinding if linked to applications that have it
+	(e.g. C++ apps). This is currently consistent with most/all
+	commercial Unix POSIX threads implementations.
+
+	* spin.c (pthread_spin_init): Edit renamed function call.
+	* nonportable.c (pthread_num_processors_np): New.
+	(pthread_getprocessors_np): Renamed to ptw32_getprocessors
+	and moved to private.c.
+	* private.c (pthread_getprocessors): Moved here from
+	nonportable.c.
+	* pthread.def (pthread_getprocessors_np): Removed
+	from export list.
+
+	* rwlock.c (pthread_rwlockattr_init): New.
+	(pthread_rwlockattr_destroy): New.
+	(pthread_rwlockattr_getpshared): New.
+	(pthread_rwlockattr_setpshared): New.
+
+2002-01-14  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* attr.c (pthread_attr_setscope): Fix struct pointer
+	indirection error introduced 2002-01-04.
+	(pthread_attr_getscope): Likewise.
+
+2002-01-12  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.dsp (SOURCE): Add missing source files.
+
+2002-01-08  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* mutex.c (pthread_mutex_trylock): use
+	ptw32_interlocked_compare_exchange function pointer
+	rather than ptw32_InterlockedCompareExchange() directly
+	to retain portability to non-iX86 processors,
+	e.g. WinCE etc. The pointer will point to the native
+	OS version of InterlockedCompareExchange() if the
+	OS supports it (see ChangeLog entry of 2001-10-17).
+
+2002-01-07  Thomas Pfaff <tpfaff at gmx.net>, Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+	* mutex.c (pthread_mutex_init): Remove critical
+	section calls.
+	(pthread_mutex_destroy): Likewise.
+	(pthread_mutex_unlock): Likewise.
+	(pthread_mutex_trylock): Likewise; uses
+	ptw32_InterlockedCompareExchange() to avoid need for
+	critical section; library is no longer i386 compatible;
+	recursive mutexes now increment the lock count rather
+	than return EBUSY; errorcheck mutexes return EDEADLCK
+	rather than EBUSY. This behaviour is consistent with the
+	Solaris pthreads implementation.
+	* implement.h (pthread_mutex_t_): Remove critical
+	section element - no longer needed.
+	
+
+2002-01-04  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* attr.c (pthread_attr_setscope): Add more error
+	checking and actually store the scope value even
+	though it's not really necessary.
+	(pthread_attr_getscope): Return stored value.
+	* implement.h (pthread_attr_t_): Add new scope element.
+	* ANNOUNCE: Fix out of date comment next to
+	pthread_attr_setscope in conformance section.
+
+2001-12-21  Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+	* mutex.c (pthread_mutex_lock): Decrementing lock_idx was
+	not thread-safe.
+	(pthread_mutex_trylock): Likewise.
+
+2001-10-26  prionx@juno.com
+
+	* semaphore.c (sem_init): Fix typo and missing bracket
+	in conditionally compiled code. Only older versions of
+	WinCE require this code, hence it doesn't normally get
+	tested; somehow when sem_t reverted to an opaque struct
+	the calloc NULL check was left in the conditionally included
+	section.
+	(sem_destroy): Likewise, the calloced sem_t wasn't being freed.
+
+2001-10-25  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* GNUmakefile (libwsock32): Add to linker flags for
+	WSAGetLastError() and WSASetLastError().
+	* Makefile (wsock32.lib): Likewise.
+	* create.c: Minor mostly inert changes.
+	* implement.h (PTW32_MAX): Move into here and renamed
+	from sched.h.
+	(PTW32_MIN): Likewise.
+	* GNUmakefile (TEST_ICE): Define if testing internal
+	implementation of InterlockedCompareExchange.
+	* Makefile (TEST_ICE): Likewise.
+	* private.c (TEST_ICE): Likewise.
+	
+2001-10-24  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* attr.c (pthread_attr_setstacksize): Quell warning
+	from LCC by conditionally compiling the stacksize
+	validity check. LCC correctly warns that the condition
+	(stacksize < PTHREAD_STACK_MIN) is suspicious
+	because STACK_MIN is 0 and stacksize is of type
+	size_t (or unsigned int).
+
+2001-10-17  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* barrier.c: Move _LONG and _LPLONG defines into
+	implement.h; rename to PTW32_INTERLOCKED_LONG and
+	PTW32_INTERLOCKED_LPLONG respectively.
+	* spin.c: Likewise; ptw32_interlocked_compare_exchange used
+	in place of InterlockedCompareExchange directly.
+	* global.c (ptw32_interlocked_compare_exchange): Add
+	prototype for this new routine pointer to be used when
+	InterlockedCompareExchange isn't supported by Windows.
+	* nonportable.c (pthread_win32_process_attach_np): Check for
+	support of InterlockedCompareExchange in kernel32 and assign its
+	address to ptw32_interlocked_compare_exchange if it exists, or
+	our own ix86 specific implementation ptw32_InterlockedCompareExchange.
+	*private.c (ptw32_InterlockedCompareExchange): An
+	implementation of InterlockedCompareExchange() which is
+	specific to ix86; written directly in assembler for either
+	MSVC or GNU C; needed because Windows 95 doesn't support
+	InterlockedCompareExchange().
+
+	* sched.c (sched_get_priority_min): Extend to return
+	THREAD_PRIORITY_IDLE.
+	(sched_get_priority_max): Extend to return
+	THREAD_PRIORITY_CRITICAL.
+
+2001-10-15  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* spin.c (pthread_spin_lock): PTHREAD_SPINLOCK_INITIALIZER
+	was causing a program fault.
+	(pthread_spin_init): Could have alloced memory
+	without freeing under some error conditions.
+
+	* mutex.c (pthread_mutex_init): Move memory
+	allocation of mutex struct after checking for
+	PROCESS_SHARED.
+
+2001-10-12  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* spin.c (pthread_spin_unlock): Was not returning
+	EPERM if the spinlock was not locked, for multi CPU
+	machines.
+
+2001-10-08  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* spin.c (pthread_spin_trylock): Was not returning
+	EBUSY for multi CPU machines.
+
+2001-08-24  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* condvar.c (pthread_cond_destroy): Remove cv element
+	that is no longer used.
+	* implement.h: Likewise.
+
+2001-08-23  Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+	* condvar.c (pthread_cond_destroy): fix bug with
+	respect to deadlock in the case of concurrent
+	_destroy/_unblock; a condition variable can be destroyed
+	immediately after all the threads that are blocked on
+	it are awakened.
+
+2001-08-23  Phil Frisbie, Jr. <phil at hawksoft.com>
+
+	* tsd.c (pthread_getspecific): Preserve the last
+	winsock error [from WSAGetLastError()].
+
+2001-07-18  Scott McCaskill <scott at magruder.org>
+
+	* mutex.c (pthread_mutexattr_init): Return ENOMEM
+	immediately and don't dereference the NULL pointer
+	if calloc fails.
+	(pthread_mutexattr_getpshared): Don't dereference
+	a pointer that is possibly NULL.
+	* barrier.c (pthread_barrierattr_init): Likewise
+	(pthread_barrierattr_getpshared): Don't dereference
+	a pointer that is possibly NULL.
+	* condvar.c (pthread_condattr_getpshared): Don't dereference
+	a pointer that is possibly NULL.
+
+2001-07-15  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* rwlock.c (pthread_rwlock_wrlock): Is allowed to be
+	a cancelation point; re-enable deferred cancelability
+	around the CV call.
+
+2001-07-10  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* barrier.c: Still more revamping. The exclusive access
+	mutex isn't really needed so it has been removed and replaced
+	by an InterlockedDecrement(). nSerial has been removed.
+	iStep is now dual-purpose. The process shared attribute
+	is now stored in the barrier struct.
+	* implement.h (pthread_barrier_t_): Lost some/gained one
+	elements.
+	* private.c (ptw32_threadStart): Removed some comments.
+
+2001-07-10  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* barrier.c: Revamped to fix the race condition. Two alternating
+	semaphores are used instead of the PulseEvent. Also improved
+	overall throughput by returning PTHREAD_BARRIER_SERIAL_THREAD
+	to the first waking thread.
+	* implement.h (pthread_barrier_t_): Revamped.
+
+2001-07-09  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* barrier.c: Fix several bugs in all routines. Now passes
+	tests/barrier5.c which is fairly rigorous. There is still
+	a non-optimal work-around for a race condition between
+	the barrier breeched event signal and event wait. Basically
+	the last (signalling) thread to hit the barrier yields
+	to allow any other threads, which may have lost the race,
+	to complete.
+
+2001-07-07  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* barrier.c: Changed synchronisation mechanism to a
+	Win32 manual reset Event and use PulseEvent to signal
+	waiting threads. If the implementation continued to use
+	a semaphore it would require a second semaphore and
+	some management to use them alternately as barriers. A
+	single semaphore allows threads to cascade from one barrier
+	through the next, leaving some threads blocked at the first.
+	* implement.h (pthread_barrier_t_): As per above.
+	* general: Made a number of other routines inlinable.
+
+2001-07-07  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* spin.c: Revamped and working; included static initialiser.
+	Now beta level.
+	* barrier.c: Likewise.
+	* condvar.c: Macro constant change; inline auto init routine.
+	* mutex.c: Likewise.
+	* rwlock.c: Likewise.
+	* private.c: Add support for spinlock initialiser.
+	* global.c: Likewise.
+	* implement.h: Likewise.
+	* pthread.h (PTHREAD_SPINLOCK_INITIALIZER): Fix typo.
+
+2001-07-05  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* 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().
+
+2001-07-05  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* spin.c: New module implementing spin locks.
+	* barrier.c: New module implementing barriers.
+	* pthread.h (_POSIX_SPIN_LOCKS): defined.
+	(_POSIX_BARRIERS): Defined.
+	(pthread_spin_*): Defined.
+	(pthread_barrier*): Defined.
+	(PTHREAD_BARRIER_SERIAL_THREAD): Defined.
+	* implement.h (pthread_spinlock_t_): Defined.
+	(pthread_barrier_t_): Defined.
+	(pthread_barrierattr_t_): Defined.
+
+	* mutex.c (pthread_mutex_lock): Return with the error
+	if an auto-initialiser initialisation fails.
+
+	* nonportable.c (pthread_getprocessors_np): New; gets the
+	number of available processors for the current process.
+
+2001-07-03  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* pthread.h (_POSIX_READER_WRITER_LOCKS): Define it
+	if not already defined.
+
+2001-07-01  Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+	* condvar.c: Fixed lost signal bug reported by Timur Aydin
+	(taydin@snet.net).
+	[RPJ (me) didn't translate the original algorithm
+	correctly.]
+	* semaphore.c: Added sem_post_multiple; this is a useful
+	routine, but it doesn't appear to be standard. For now it's
+	not an exported function.
+	
+2001-06-25  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* create.c (pthread_create): Add priority inheritance
+	attributes.
+	* mutex.c (pthread_mutex_lock): Remove some overhead for
+	PTHREAD_MUTEX_NORMAL mutex types. Specifically, avoid
+	calling pthread_self() and pthread_equal() to check/set
+	the mutex owner. Introduce a new pseudo owner for this
+	type. Test results suggest increases in speed of up to
+	90% for non-blocking locks.
+	This is the default type of mutex used internally by other
+	synchronising objects, ie. condition variables and
+	read-write locks. The test rwlock7.c shows about a
+	30-35% speed increase over snapshot 2001-06-06. The
+	price of this is that the application developer
+	must ensure correct behaviour, or explicitly set the
+	mutex to a safer type such as PTHREAD_MUTEX_ERRORCHECK.
+	For example, PTHREAD_MUTEX_NORMAL (or PTHREAD_MUTEX_DEFAULT)
+	type mutexes will not return an error if a thread which is not
+	the owner calls pthread_mutex_unlock. The call will succeed
+	in unlocking the mutex if it is currently locked, but a
+	subsequent unlock by the true owner will then fail with EPERM.
+	This is however consistent with some other implementations.
+	(pthread_mutex_unlock): Likewise.
+	(pthread_mutex_trylock): Likewise.
+	(pthread_mutex_destroy): Likewise.
+	* attr.c (pthread_attr_init): PTHREAD_EXPLICIT_SCHED is the
+	default inheritance attribute; THREAD_PRIORITY_NORMAL is
+	the default priority for new threads.
+	* sched.c (pthread_attr_setschedpolicy): Added routine.
+	(pthread_attr_getschedpolicy): Added routine.
+	(pthread_attr_setinheritsched): Added routine.
+	(pthread_attr_getinheritsched): Added routine.
+	* pthread.h (sched_rr_set_interval): Added as a macro;
+	returns -1 with errno set to ENOSYS.
+
+2001-06-23  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	*sched.c (pthread_attr_setschedparam): Add priority range
+	check.
+	(sched_setscheduler): New function; checks for a valid
+	pid and policy; checks for permission to set information
+	in the target process; expects pid to be a Win32 process ID,
+	not a process handle; the only scheduler policy allowed is
+	SCHED_OTHER.
+	(sched_getscheduler): Likewise, but checks for permission
+	to query.
+	* pthread.h (SCHED_*): Moved to sched.h as defined in the
+	POSIX standard.
+	* sched.h (SCHED_*): Moved from pthread.h.
+	(pid_t): Defined if necessary.
+	(sched_setscheduler): Defined.
+	(sched_getscheduler): Defined.
+	* pthread.def (sched_setscheduler): Exported.
+	(sched_getscheduler): Likewise.
+
+2001-06-23  Ralf Brese <Ralf.Brese at pdb4.siemens.de>
+
+	* create.c (pthread_create): Set thread priority from
+	thread attributes.
+
+2001-06-18  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* Made organisational-only changes to UWIN additions.
+	* dll.c (dllMain): Moved UWIN process attach code
+	to pthread_win32_process_attach_np(); moved
+	instance of pthread_count to global.c.
+	* global.c (pthread_count): Moved from dll.c.
+	* nonportable.c (pthread_win32_process_attach_np):
+	Moved _UWIN code to here from dll.c.
+	* implement.h (pthread_count): Define extern int.
+	* create.c (pthread_count): Remove extern int.
+	* private.c (pthread_count): Likewise.
+	* exit.c (pthread_count): Likewise.
+
+2001-06-18  David Korn <dgk at research.att.com>
+
+	* dll.c: Added changes necessary to work with UWIN.
+	* create.c: Likewise.
+	* pthread.h: Likewise.
+	* misc.c: Likewise.
+	* exit.c: Likewise.
+	* private.c: Likewise.
+	* implement.h: Likewise.
+	There is some room at the start of struct pthread_t_
+	to implement the signal semantics in UWIN's posix.dll
+	although this is not yet complete.
+	* Nmakefile: Compatible with UWIN's Nmake utility.
+	* Nmakefile.tests: Likewise - for running the tests.
+
+2001-06-08  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* semaphore.h (sem_t): Fixed for compile and test.
+	* implement.h (sem_t_): Likewise.
+	* semaphore.c: Likewise.
+	* private.c (ptw32_sem_timedwait): Updated to use new
+	opaque sem_t.
+
+2001-06-06  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* semaphore.h (sem_t): Is now an opaque pointer;
+	moved actual definition to implement.h.
+	* implement.h (sem_t_): Move here from semaphore.h;
+	was the definition of sem_t.
+	* semaphore.c: Wherever necessary, changed use of sem
+	from that of a pointer to a pointer-pointer; added
+	extra checks for a valid sem_t; NULL sem_t when
+	it is destroyed; added extra checks when creating
+	and destroying sem_t elements in the NEED_SEM
+	code branches; changed from using a pthread_mutex_t
+	((*sem)->mutex) to CRITICAL_SECTION ((*sem)->sem_lock_cs)
+	in NEED_SEM branches for access serialisation.
+
+2001-06-06  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* mutex.c (pthread_mutexattr_init): Remove 
+	ptw32_mutex_default_kind.
+	
+2001-06-05  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* nonportable.c (pthread_mutex_setdefaultkind_np):
+	Remove - should not have been included in the first place.
+	(pthread_mutex_getdefaultkind_np): Likewise.
+	* global.c (ptw32_mutex_default_kind): Likewise.
+	* mutex.c (pthread_mutex_init): Remove use of
+	ptw32_mutex_default_kind.
+	* pthread.h (pthread_mutex_setdefaultkind_np): Likewise.
+	(pthread_mutex_getdefaultkind_np): Likewise.
+	* pthread.def (pthread_mutexattr_setkind_np): Added.
+	(pthread_mutexattr_getkind_np): Likewise.
+
+	* README: Many changes that should have gone in before
+	the last snapshot.
+	* README.NONPORTABLE: New - referred to by ANNOUNCE
+	but never created; documents the non-portable routines
+	included in the library - moved from README with new
+	routines added.
+	* ANNOUNCE (pthread_mutexattr_setkind_np): Added to
+	compliance list.
+	(pthread_mutexattr_getkind_np): Likewise.
+
+2001-06-04  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* condvar.c: Add original description of the algorithm as
+	developed by Terekhov and Thomas, plus reference to
+	README.CV.
+
+2001-06-03  Alexander Terekhov <TEREKHOV at de.ibm.com>, Louis Thomas <lthomas at arbitrade.com>
+
+	* condvar.c (pthread_cond_init): Completely revamped.
+	(pthread_cond_destroy): Likewise.
+	(ptw32_cond_wait_cleanup): Likewise.
+	(ptw32_cond_timedwait): Likewise.
+	(ptw32_cond_unblock): New general signaling routine.
+	(pthread_cond_signal): Now calls ptw32_cond_unblock.
+	(pthread_cond_broadcast): Likewise.
+	* implement.h (pthread_cond_t_): Revamped.
+	* README.CV: New; explanation of the above changes.
+
+2001-05-30  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* pthread.h (rand_r): Fake using _seed argument to quell
+	compiler warning (compiler should optimise this away later).
+
+	* GNUmakefile (OPT): Leave symbolic information out of the library
+	and increase optimisation level - for smaller faster prebuilt
+	dlls.
+	
+2001-05-29  Milan Gardian <Milan.Gardian at LEIBINGER.com>
+
+	* Makefile: fix typo.
+	* pthreads.h: Fix problems with stdcall/cdecl conventions, in particular
+	remove the need for PT_STDCALL everywhere; remove warning supression.
+	* (errno): Fix the longstanding "inconsistent dll linkage" problem
+	with errno; now also works with /MD debugging libs - 
+	warnings emerged when compiling pthreads library with /MD (or /MDd)
+	compiler switch, instead of /MT (or /MTd) (i.e. when compiling pthreads
+	using Multithreaded DLL CRT instead of Multithreaded statically linked
+	CRT).
+	* create.c (pthread_create): Likewise; fix typo.
+	* private.c (ptw32_threadStart): Eliminate use of terminate() which doesn't
+	throw exceptions.
+	* Remove unnecessary #includes from a number of modules -
+	[I had to #include malloc.h in implement.h for gcc - rpj].
+
+2001-05-29  Thomas Pfaff <tpfaff at gmx.net>
+
+	* pthread.h (PTHREAD_MUTEX_DEFAULT): New; equivalent to
+	PTHREAD_MUTEX_DEFAULT_NP.
+	* (PTHREAD_MUTEX_NORMAL): Similarly.
+	* (PTHREAD_MUTEX_ERRORCHECK): Similarly.
+	* (PTHREAD_MUTEX_RECURSIVE): Similarly.
+	* (pthread_mutex_setdefaultkind_np): New; Linux compatibility stub
+	for pthread_mutexattr_settype.
+	* (pthread_mutexattr_getkind_np): New; Linux compatibility stub
+	for pthread_mutexattr_gettype.
+	* mutex.c (pthread_mutexattr_settype): New; allow
+	the following types of mutex:
+	  PTHREAD_MUTEX_DEFAULT_NP
+	  PTHREAD_MUTEX_NORMAL_NP
+	  PTHREAD_MUTEX_ERRORCHECK_NP
+	  PTHREAD_MUTEX_RECURSIVE_NP
+	* Note that PTHREAD_MUTEX_DEFAULT is equivalent to
+	PTHREAD_MUTEX_NORMAL - ie. mutexes should no longer
+	be recursive by default, and a thread will deadlock if it
+	tries to relock a mutex it already owns. This is inline with
+	other pthreads implementations.
+	* (pthread_mutex_lock): Process the lock request
+	according to the mutex type.
+	* (pthread_mutex_init): Eliminate use of Win32 mutexes as the
+	basis of POSIX mutexes - instead, a combination of one critical section
+	and one semaphore are used in conjunction with Win32 Interlocked* routines.
+	* (pthread_mutex_destroy): Likewise.
+	* (pthread_mutex_lock): Likewise.
+	* (pthread_mutex_trylock): Likewise.
+	* (pthread_mutex_unlock): Likewise.
+	* Use longjmp/setjmp to implement cancelation when building the library
+	using a C compiler which doesn't support exceptions, e.g. gcc -x c (note
+	that gcc -x c++ uses exceptions).
+	* Also fixed some of the same typos and eliminated PT_STDCALL as
+	Milan Gardian's patches above.
+
+2001-02-07  Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+	* rwlock.c: Revamped.
+	* implement.h (pthread_rwlock_t_): Redefined.
+	This implementation does not have reader/writer starvation problem.
+	Rwlock attempts to behave more like a normal mutex with
+	races and scheduling policy determining who is more important;
+	It also supports recursive locking,
+	has less synchronization overhead (no broadcasts at all,
+	readers are not blocked on any condition variable) and seem to
+	be faster than the current implementation [W98 appears to be
+	approximately 15 percent faster at least - on top of speed increase
+	from Thomas Pfaff's changes to mutex.c - rpj].
+
+2000-12-29  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* Makefile: Back-out "for" loops which don't work.
+
+	* GNUmakefile: Remove the fake.a target; add the "realclean"
+	target; don't remove built libs under the "clean" target.
+
+	* config.h: Add a guard against multiple inclusion.
+
+	* semaphore.h: Add some defines from config.h to make
+	semaphore.h independent of config.h when building apps.
+
+	* pthread.h (_errno): Back-out previous fix until we know how to
+	fix it properly.
+
+	* implement.h (lockCount): Add missing element to pthread_mutex_t_.
+
+	* sync.c (pthread_join): Spelling fix in comment.
+
+	* private.c (ptw32_threadStart): Reset original termination
+	function (C++).
+	(ptw32_threadStart): Cleanup detached threads early in case
+	the library is statically linked.
+	(ptw32_callUserDestroyRoutines): Remove [SEH] __try block from
+	destructor call so that unhandled exceptions will be passed through
+	to the 	system; call terminate() from [C++] try block for the same
+	reason.
+
+	* tsd.c (pthread_getspecific): Add comment.
+
+	* mutex.c (pthread_mutex_init): Initialise new elements in
+	pthread_mutex_t.
+	(pthread_mutex_unlock): Invert "pthread_equal()" test.
+
+2000-12-28  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* semaphore.c (mode_t): Use ifndef HAVE_MODE_T to include definition.
+
+	* config.h.in (HAVE_MODE_T): Added.
+	(_UWIN): Start adding defines for the UWIN package.
+
+	* private.c (ptw32_threadStart): Unhandled exceptions are
+	now passed through to the system to deal with. This is consistent
+	with normal Windows behaviour. C++ applications may use
+	set_terminate() to override the default behaviour which is
+	to call ptw32_terminate(). Ptw32_terminate() cleans up some
+	POSIX thread stuff before calling the system default function
+	which calls abort(). The users termination function should conform
+	to standard C++ semantics which is to not return. It should
+	exit the thread (call pthread_exit()) or exit the application.
+	* private.c (ptw32_terminate): Added as the default set_terminate()
+	function. It calls the system default function after cleaning up
+	some POSIX thread stuff.
+
+	* implement.h (ptw32_try_enter_critical_section): Move
+	declaration.
+	* global.c (ptw32_try_enter_critical_section): Moved
+	from dll.c.
+	* dll.c: Move process and thread attach/detach code into
+	functions in nonportable.c.
+	* nonportable.c (pthread_win32_process_attach_np): Process
+	attach code from dll.c is now available to static linked
+	applications.
+	* nonportable.c (pthread_win32_process_detach_np): Likewise.
+	* nonportable.c (pthread_win32_thread_attach_np): Likewise.
+	* nonportable.c (pthread_win32_thread_detach_np): Likewise.
+
+	* pthread.h: Add new non-portable prototypes for static
+	linked applications.
+
+	* GNUmakefile (OPT): Increase optimisation flag and remove
+	debug info flag.
+
+	* pthread.def: Add new non-portable exports for static
+	linked applications.
+
+2000-12-11  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* FAQ: Update Answer 6 re getting a fully working
+	Mingw32 built library.
+
+2000-10-10  Steven Reddie <smr at essemer.com.au>
+ 
+        * misc.c (pthread_self): Restore Win32 "last error"
+        cleared by TlsGetValue() call in
+        pthread_getspecific()
+ 
+2000-09-20  Arthur Kantor <akantor at bexusa.com>
+ 
+        * mutex.c (pthread_mutex_lock): Record the owner
+        of the mutex. This requires also keeping count of
+        recursive locks ourselves rather than leaving it
+        to Win32 since we need to know when to NULL the
+        thread owner when the mutex is unlocked.
+        (pthread_mutex_trylock): Likewise.
+        (pthread_mutex_unlock): Check that the calling
+        thread owns the mutex, decrement the recursive
+        lock count, and NULL the owner if zero. Return
+        EPERM if the mutex is owned by another thread.
+        * implement.h (pthread_mutex_t_): Add ownerThread
+        and lockCount members.
+
+2000-09-13  Jef Gearhart <jgearhart at tpssys.com>
+
+	* mutex.c (pthread_mutex_init): Call
+	TryEnterCriticalSection through the pointer
+	rather than directly so that the dll can load
+	on Windows versions that can't resolve the
+	function, eg. Windows 95
+
+2000-09-09  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.h (ctime_r): Fix arg.
+
+2000-09-08  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* GNUmakefile(_WIN32_WINNT=0x400): Define in CFLAGS;
+	doesn't seem to be needed though.
+
+	* cancel.c (pthread_cancel): Must get "self" through
+	calling pthread_self() which will ensure a POSIX thread
+	struct is built for non-POSIX threads; return an error
+	if this fails
+	- Ollie Leahy <ollie at mpt.ie>
+	(pthread_setcancelstate): Likewise.
+	(pthread_setcanceltype): Likewise.
+	* misc.c (ptw32_cancelable_wait): Likewise.
+
+	* private.c (ptw32_tkAssocCreate): Remove unused #if 0
+	wrapped code.
+
+	* pthread.h (ptw32_get_exception_services_code):
+	Needed to be forward declared unconditionally.
+
+2000-09-06  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* cancel.c (pthread_cancel): If called from the main
+	thread "self" would be NULL; get "self" via pthread_self()
+	instead of directly from TLS so that an implicit
+	pthread object is created.
+
+	* misc.c (pthread_equal): Strengthen test for NULLs.
+
+2000-09-02  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* condvar.c (ptw32_cond_wait_cleanup): Ensure that all
+	waking threads check if they are the last, and notify
+	the broadcaster if so - even if an error occurs in the
+	waiter.
+
+	* semaphore.c (_decrease_semaphore): Should be
+	a call to ptw32_decrease_semaphore.
+	(_increase_semaphore): Should be a call to
+	ptw32_increase_semaphore.
+
+	* misc.c (ptw32_cancelable_wait): Renamed from
+	CancelableWait.
+	* rwlock.c (_rwlock_check*): Renamed to
+	ptw32_rwlock_check*.
+	* mutex.c (_mutex_check*): Renamed to ptw32_mutex_check*.
+	* condvar.c (cond_timed*): Renamed to ptw32_cond_timed*.
+	(_cond_check*): Renamed to ptw32_cond_check*.
+	(cond_wait_cleanup*): Rename to ptw32_cond_wait_cleanup*.
+	(ptw32_cond_timedwait): Add comments.
+
+2000-08-22  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* private.c (ptw32_throw): Fix exception test;
+	move exceptionInformation declaration.
+
+	* tsd.c (pthread_key_create): newkey wrongly declared.
+
+	* pthread.h: Fix comment block.
+
+2000-08-18  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* mutex.c (pthread_mutex_destroy): Check that the mutex isn't
+	held; invalidate the mutex as early as possible to avoid
+	contention; not perfect - FIXME!
+
+	* rwlock.c (pthread_rwlock_init): Remove redundant assignment
+	to "rw".
+	(pthread_rwlock_destroy): Invalidate the rwlock before
+	freeing up any of it's resources - to avoid contention.
+
+	* private.c (ptw32_tkAssocCreate): Change assoc->lock
+	to use a dynamically initialised mutex - only consumes
+	a W32 mutex or critical section when first used,
+	not before.
+
+	* mutex.c (pthread_mutex_init): Remove redundant assignment
+	to "mx".
+	(pthread_mutexattr_destroy): Set attribute to NULL
+	before freeing it's memory - to avoid contention.
+
+	* implement.h (PTW32_EPS_CANCEL/PTW32_EPS_EXIT):
+	Must be defined for all compilers - used as generic
+	exception selectors by ptw32_throw().
+
+	* Several: Fix typos from scripted edit session
+	yesterday.
+
+	* nonportable.c (pthread_mutexattr_setforcecs_np):
+	Moved this function from mutex.c.
+	(pthread_getw32threadhandle_np): New function to
+	return the win32 thread handle that the POSIX
+	thread is using.
+	* mutex.c (pthread_mutexattr_setforcecs_np):
+	Moved to new file "nonportable.c".
+
+	* pthread.h (PTW32_BUILD): Only	redefine __except
+	and catch compiler keywords if we aren't building
+	the library (ie. PTW32_BUILD is not defined) - 
+	this is safer than defining and then undefining
+	if not building the library.
+	* implement.h: Remove __except and catch undefines.
+	* Makefile (CFLAGS): Define PTW32_BUILD.
+	* GNUmakefile (CFLAGS): Define PTW32_BUILD.
+
+	* All appropriate: Change Pthread_exception* to
+	ptw32_exception* to be consistent with internal
+	identifier naming.
+
+	* private.c (ptw32_throw): New function to provide
+	a generic exception throw for all internal
+	exceptions and EH schemes.
+	(ptw32_threadStart): pthread_exit() value is now
+	returned via the thread structure exitStatus
+	element.
+	* exit.c (pthread_exit): pthread_exit() value is now
+	returned via the thread structure exitStatus
+	element.
+	* cancel.c (ptw32_cancel_self): Now uses ptw32_throw.
+	(pthread_setcancelstate): Ditto.
+	(pthread_setcanceltype): Ditto.
+	(pthread_testcancel): Ditto.
+	(pthread_cancel): Ditto.
+	* misc.c (CancelableWait): Ditto.
+	* exit.c (pthread_exit): Ditto.
+	* All applicable: Change PTW32_ prefix to
+	PTW32_ prefix to remove leading underscores
+	from private library identifiers.
+
+2000-08-17  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* All applicable: Change _pthread_ prefix to
+	ptw32_ prefix to remove leading underscores
+	from private library identifiers (single
+	and double leading underscores are reserved in the
+	ANSI C standard for compiler implementations).
+
+	* tsd.c (pthread_create_key): Initialise temporary
+	key before returning it's address to avoid race
+	conditions.
+
+2000-08-13  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* errno.c: Add _MD precompile condition; thus far
+	had no effect when using /MD compile option but I
+	thnk it should be there.
+
+	* exit.c: Add __cplusplus to various #if lines;
+	was compiling SEH code even when VC++ had
+	C++ compile options.
+
+	* private.c: ditto.
+
+	* create.c (pthread_create): Add PT_STDCALL macro to
+	function pointer arg in _beginthread().
+
+	* pthread.h: PT_STDCALL really does need to be defined
+	in both this and impliment.h; don't set it to __cdecl
+	- this macro is only used to extend function pointer
+	casting for functions that will be passed as parameters.
+	(~PThreadCleanup): add cast and group expression.
+	(_errno): Add _MD compile conditional.
+	(PtW32NoCatchWarn): Change pragma message.
+
+	* implement.h: Move and change PT_STDCALL define.
+
+	* need_errno.h: Add _MD to compilation conditional.
+
+	* GNUmakefile: Substantial rewrite for new naming
+	convention; set for nil optimisation (turn it up
+	when we have a working library build; add target
+	"fake.a" to build a libpthreadw32.a from the VC++
+	built DLL pthreadVCE.dll.
+
+	* pthread.def (LIBRARY): Don't specify in the .def
+	file - it is specified on the linker command line
+	since we now use the same .def file for variously
+	named .dlls.
+
+	* Makefile: Substantial rewrite for new naming
+	convention; default nmake target only issues a
+	help message; run nmake with specific target
+	corresponding to the EH scheme being used.
+
+	* README: Update information; add naming convention
+	explanation.
+
+	* ANNOUNCE: Update information.
+
+2000-08-12  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.h: Add compile-time message when using
+	MSC_VER compiler and C++ EH to warn application
+	programmers to use PtW32Catch instead of catch(...)
+	if they want cancelation and pthread_exit to work.
+
+	* implement.h: Remove #include <semaphore.h>; we
+	use our own local semaphore.h.
+
+2000-08-10  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* cleanup.c (pthread_pop_cleanup): Remove _pthread
+	prefix from __except and catch keywords; implement.h
+	now simply undefines ptw32__except and
+	ptw32_catch if defined; VC++ was not textually
+	substituting ptw32_catch etc back to catch as
+	it was redefined; the reason for using the prefixed
+	version was to make it clear that it was not using
+	the pthread.h redefined catch keyword.
+
+	* private.c (ptw32_threadStart): Ditto.
+	(ptw32_callUserDestroyRoutines): Ditto.
+
+	* implement.h (ptw32__except): Remove #define.
+	(ptw32_catch): Remove #define.
+
+	* GNUmakefile (pthread.a): New target to build
+	libpthread32.a from pthread.dll using dlltool.
+
+	* buildlib.bat: Duplicate cl commands with args to
+	build C++ EH version of pthread.dll; use of .bat
+	files is redundant now that nmake compatible
+	Makefile is included; used as a kludge only now.
+
+	* Makefile: Localise some macros and fix up the clean:
+	target to extend it and work properly.
+
+	* CONTRIBUTORS: Add contributors.
+
+	* ANNOUNCE: Updated.
+
+	* README: Updated.
+
+2000-08-06  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.h: Remove #warning - VC++ doesn't accept it.
+
+2000-08-05  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.h (PtW32CatchAll): Add macro. When compiling
+	applications using VC++ with C++ EH rather than SEH
+	'PtW32CatchAll' must be used in place of any 'catch( ... )'
+	if the application wants pthread cancelation or
+	pthread_exit() to work.
+
+2000-08-03  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* pthread.h: Add a base class ptw32_exception for
+	library internal exceptions and change the "catch"
+	re-define macro to use it.
+
+2000-08-02  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* GNUmakefile (CFLAGS): Add -mthreads.
+	Add new targets to generate cpp and asm output.
+
+	* sync.c (pthread_join): Remove dead code.
+
+2000-07-25  Tristan Savatier <tristan at mpegtv.com>
+
+	* sched.c (sched_get_priority_max): Handle different WinCE and
+	Win32 priority values together.
+	(sched_get_priority_min): Ditto.
+
+2000-07-25  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* create.c (pthread_create): Force new threads to wait until
+	pthread_create has the new thread's handle; we also retain
+	a local copy of the handle for internal use until
+	pthread_create returns.
+
+	* private.c (ptw32_threadStart): Initialise ei[].
+	(ptw32_threadStart): When beginthread is used to start the
+	thread, force waiting until the creator thread had the 
+	thread handle.
+
+	* cancel.c (ptw32_cancel_thread): Include context switch
+	code for defined(_X86_) environments in addition to _M_IX86.
+
+	* rwlock.c (pthread_rwlock_destroy): Assignment changed
+	to avoid compiler warning.
+
+	* private.c (ptw32_get_exception_services_code): Cast
+	NULL return value to avoid compiler warning.
+
+	* cleanup.c (pthread_pop_cleanup): Initialise "cleanup" variable
+	to avoid compiler warnings.
+
+	* misc.c (ptw32_new): Change "new" variable to "t" to avoid
+	confusion with the C++ keyword of the same name.
+
+	* condvar.c (cond_wait_cleanup): Initialise lastWaiter variable.
+	(cond_timedwait): Remove unused local variables. to avoid
+	compiler warnings.
+
+	* dll.c (dllMain): Remove 2000-07-21 change - problem
+	appears to be in pthread_create().
+
+2000-07-22  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* tsd.c (pthread_key_create): If a destructor was given
+	and the pthread_mutex_init failed, then would try to
+	reference a NULL pointer (*key); eliminate this section of
+	code by using a dynamically initialised mutex
+	(PTHREAD_MUTEX_INITIALIZER).
+
+	* tsd.c (pthread_setspecific): Return an error if
+	unable to set the value; simplify cryptic conditional.
+
+	* tsd.c (pthread_key_delete): Locking threadsLock relied
+	on mutex_lock returning an error if the key has no destructor.
+	ThreadsLock is only initialised if the key has a destructor.
+	Making this mutex a static could reduce the number of mutexes
+	used by an application since it is actually created only at
+	first use and it's often destroyed soon after.
+	
+2000-07-22  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* FAQ: Added Q5 and Q6.
+
+2000-07-21  David Baggett <dmb at itasoftware.com>
+
+	* dll.c: Include resource leakage work-around. This is a
+	partial FIXME which doesn't stop all leakage. The real
+	problem needs to be found and fixed.
+
+2000-07-21  Ross Johnson  <rpj at setup1.ise.canberra.edu.au>
+
+	* create.c (pthread_create): Set threadH to 0 (zero)
+	everywhere. Some assignments were using NULL. Maybe
+	it should be NULL everywhere - need to check. (I know
+	they are nearly always the same thing - but not by
+	definition.)
+
+	* misc.c (pthread_self): Try to catch NULL thread handles
+	at the point where they might be generated, even though
+	they should always be valid at this point.
+
+	* tsd.c (pthread_setspecific): return an error value if
+	pthread_self() returns NULL.
+
+	* sync.c (pthread_join): return an error value if
+	pthread_self() returns NULL.
+
+	* signal.c (pthread_sigmask): return an error value if
+	pthread_self() returns NULL.
+
+2000-03-02  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* attr.c (pthread_attr_init): Set default stacksize to zero (0)
+	rather than PTHREAD_STACK_MIN even though these are now the same.
+
+	* pthread.h (PTHREAD_STACK_MIN): Lowered to 0.
+
+2000-01-28  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* mutex.c (pthread_mutex_init): Free mutex if it has been alloced;
+	if critical sections can be used instead of Win32 mutexes, test
+	that the critical section works and return an error if not.
+
+2000-01-07  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* cleanup.c (pthread_pop_cleanup): Include SEH code only if MSC is not
+	compiling as C++.
+	(pthread_push_cleanup): Include SEH code only if MSC is not
+	compiling as C++.
+
+	* pthread.h: Include SEH code only if MSC is not
+	compiling as C++.
+
+	* implement.h: Include SEH code only if MSC is not
+	compiling as C++.
+
+	* cancel.c (ptw32_cancel_thread): Add _M_IX86 check.
+	(pthread_testcancel): Include SEH code only if MSC is not
+	compiling as C++.
+	(ptw32_cancel_self): Include SEH code only if MSC is not
+	compiling as C++.
+
+2000-01-06  Erik Hensema <erik.hensema at group2000.nl>
+
+	* Makefile: Remove inconsistencies in 'cl' args
+
+2000-01-04  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* private.c (ptw32_get_exception_services_code): New; returns
+	value of EXCEPTION_PTW32_SERVICES.
+	(ptw32_processInitialize): Remove initialisation of
+	ptw32_exception_services which is no longer needed.
+
+	* pthread.h (ptw32_exception_services): Remove extern.
+	(ptw32_get_exception_services_code): Add function prototype;
+	use this to return EXCEPTION_PTW32_SERVICES value instead of
+	using the ptw32_exception_services variable which I had
+	trouble exporting through pthread.def.
+
+	* global.c (ptw32_exception_services): Remove declaration.
+
+1999-11-22  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* implement.h: Forward declare ptw32_new();
+
+	* misc.c (ptw32_new): New; alloc and initialise a new pthread_t.
+	(pthread_self): New thread struct is generated 	by new routine
+	ptw32_new().
+
+	* create.c (pthread_create): New thread struct is generated
+	by new routine ptw32_new().
+
+1999-11-21  Ross Johnson  <rpj at special.ise.canberra.edu.au>
+
+	* global.c (ptw32_exception_services): Declare new variable. 
+
+	* private.c (ptw32_threadStart): Destroy thread's
+	cancelLock mutex; make 'catch' and '__except' usageimmune to
+	redfinitions in pthread.h.
+	(ptw32_processInitialize): Init new constant ptw32_exception_services.
+
+	* create.c (pthread_create): Initialise thread's cancelLock
+	mutex.
+
+	* cleanup.c (pthread_pop_cleanup): Make 'catch' and '__except'
+	usage immune to redfinition s in pthread.h.
+
+	* private.c: Ditto.
+
+	* pthread.h (catch): Redefine 'catch' so that C++ applications
+	won't catch our internal exceptions.
+	(__except): ditto for __except.
+
+	* implement.h (ptw32_catch): Define internal version
+	of 'catch' because 'catch' is redefined by pthread.h.
+	(__except): ditto for __except.
+	(struct pthread_t_): Add cancelLock mutex for async cancel
+	safety.
+
+1999-11-21  Jason Nye <jnye at nbnet.nb.ca>, Erik Hensema <erik.hensema at group2000.nl>
+
+	* cancel.c (ptw32_cancel_self): New; part of the async
+	cancellation implementation.
+	(ptw32_cancel_thread): Ditto; this function is X86
+	processor specific.
+	(pthread_setcancelstate): Add check for pending async
+	cancel request and cancel the calling thread if
+	required; add async-cancel safety lock.
+	(pthread_setcanceltype): Ditto.
+
+1999-11-13  Erik Hensema <erik.hensema at group2000.nl>
+
+	* configure.in (AC_OUTPUT): Put generated output into GNUmakefile
+	rather than Makefile. Makefile will become the MSC nmake compatible
+	version
+
+1999-11-13  John Bossom (John.Bossom@cognos.com>
+
+	* misc.c (pthread_self): Add a note about GetCurrentThread
+	returning a pseudo-handle
+
+1999-11-10  Todd Owen <towen at lucidcalm.dropbear.id.au>
+
+	* dll.c (dllMain): Free kernel32 ASAP.
+	If TryEnterCriticalSection is not being used, then free
+	the kernel32.dll handle now, rather than leaving it until
+	DLL_PROCESS_DETACH.
+
+	Note: this is not a pedantic exercise in freeing unused
+	resources!  It is a work-around for a bug in Windows 95
+	(see microsoft knowledge base article, Q187684) which
+	does Bad Things when FreeLibrary is called within
+	the DLL_PROCESS_DETACH code, in certain situations.
+	Since w95 just happens to be a platform which does not
+	provide TryEnterCriticalSection, the bug will be
+	effortlessly avoided.
+
+1999-11-10  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sync.c (pthread_join): Make it a deferred cancelation point.
+
+	* misc.c (pthread_self): Explicitly initialise implicitly
+	created thread state to default values.
+
+1999-11-05  Tristan Savatier <tristan at mpegtv.com>
+
+	* pthread.h (winsock.h): Include unconditionally.
+	(ETIMEDOUT): Change fallback value to that defined by winsock.h.
+	
+	* general: Patched for portability to WinCE. The details are
+	described in the file WinCE-PORT. Follow the instructions
+	in README.WinCE to make the appropriate changes in config.h.
+
+1999-10-30  Erik Hensema <erik.hensema at group2000.nl>
+
+	* 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:
+
+1999-10-23  Erik Hensema <erik.hensema at group2000.nl>
+
+	* pthread.h (ctime_r): Fix incorrect argument "_tm"
+
+1999-10-21  Aurelio Medina <aureliom at crt.com>
+
+	* pthread.h (_POSIX_THREADS): Only define it if it isn't
+	already defined. Projects may need to define this on
+	the CC command line under Win32 as it doesn't have unistd.h
+
+1999-10-17  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* rwlock.c (pthread_rwlock_destroy): Add cast to remove compile
+	warning.
+
+	* condvar.c (pthread_cond_broadcast): Only release semaphores
+	if there are waiting threads.
+
+1999-10-15  Lorin Hochstein <lmh at xiphos.ca>, Peter Slacik <Peter.Slacik at tatramed.sk>
+
+	* condvar.c (cond_wait_cleanup): New static cleanup handler for
+	cond_timedwait;
+	(cond_timedwait): pthread_cleanup_push args changed;
+	canceling a thread while it's in pthread_cond_wait
+	will now decrement the waiters count and cleanup if it's the
+	last waiter.
+
+1999-10-15  Graham Dumpleton <Graham.Dumpleton at ra.pad.otc.telstra.com.au>
+
+	* condvar.c (cond_wait_cleanup): the last waiter will now reset the CV's
+	wasBroadcast flag
+
+Thu Sep 16 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* rwlock.c (pthread_rwlock_destroy): Add serialisation.
+	(_rwlock_check_need_init): Check for detroyed rwlock.
+	* rwlock.c: Check return codes from _rwlock_check_need_init();
+	modify comments; serialise access to rwlock objects during
+	operations; rename rw_mutex to rw_lock.
+	* implement.h: Rename rw_mutex to rw_lock.
+	* mutex.c (pthread_mutex_destroy): Add serialisation.
+	(_mutex_check_need_init): Check for detroyed mutex.
+	* condvar.c (pthread_cond_destroy): Add serialisation.
+	(_cond_check_need_init): Check for detroyed condvar.
+	* mutex.c: Modify comments.
+	* condvar.c: Modify comments.
+
+1999-08-10  Aurelio Medina  <aureliom at crt.com>
+
+	* implement.h (pthread_rwlock_t_): Add.
+	* pthread.h (pthread_rwlock_t): Add.
+	(PTHREAD_RWLOCK_INITIALIZER): Add.
+	Add rwlock function prototypes.
+	* rwlock.c: New module.
+	* pthread.def: Add new rwlock functions.
+	* private.c (ptw32_processInitialize): initialise
+	ptw32_rwlock_test_init_lock critical section.
+	* global.c (ptw32_rwlock_test_init_lock): Add.
+
+	* mutex.c (pthread_mutex_destroy): Don't free mutex memory
+	if mutex is PTHREAD_MUTEX_INITIALIZER and has not been
+	initialised yet.
+
+1999-08-08 Milan Gardian <mg at tatramed.sk>
+
+	* mutex.c (pthread_mutex_destroy): Free mutex memory.
+
+1999-08-22  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* exit.c (pthread_exit): Fix reference to potentially
+	uninitialised pointer.
+
+1999-08-21  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_threadStart): Apply fix of 1999-08-19
+	this time to C++ and non-trapped C versions. Ommitted to
+	do this the first time through.
+
+1999-08-19  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_threadStart): Return exit status from
+	the application thread startup routine.
+	- Milan Gardian <mg at tatramed.sk>
+
+1999-08-18  John Bossom <john.Bossom at cognos.com>
+
+	* exit.c (pthread_exit): Put status into pthread_t->exitStatus
+	* private.c (ptw32_threadStart): Set pthread->exitStatus
+	on exit of try{} block.
+	* sync.c (pthread_join): use pthread_exitStatus value if the
+	thread exit doesn't return a value (for Mingw32 CRTDLL
+	which uses endthread instead of _endthreadex).
+
+Tue Aug 17 20:17:58 CDT 1999  Mumit Khan  <khan at xraylith.wisc.edu>
+
+        * create.c (pthread_create): Add CRTDLL suppport.
+        * exit.c (pthread_exit): Likewise.
+        * private.c (ptw32_threadStart): Likewise.
+        (ptw32_threadDestroy): Likewise.
+        * sync.c (pthread_join): Likewise.
+        * tests/join1.c (main): Warn about partial support for CRTDLL.
+
+Tue Aug 17 20:00:08 1999  Mumit Khan  <khan at xraylith.wisc.edu>
+
+        * Makefile.in (LD): Delete entry point.
+        * acconfig.h (STDCALL): Delete unused macro.
+        * configure.in: Remove test for STDCALL.
+        * config.h.in: Regenerate.
+        * errno.c (_errno): Fix self type.
+        * pthread.h (PT_STDCALL): Move from here to
+        * implement.h (PT_STDCALL): here.
+        (ptw32_threadStart): Fix prototype.
+        * private.c (ptw32_threadStart): Likewise.
+
+1999-08-14  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* exit.c (pthread_exit): Don't call pthread_self() but
+	get thread handle directly from TSD for efficiency.
+	
+1999-08-12  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_threadStart): ei[] only declared if _MSC_VER.
+
+	* exit.c (pthread_exit): Check for implicitly created threads
+	to avoid raising an unhandled exception.
+	
+1999-07-12  Peter Slacik <Peter.Slacik at tatramed.sk>
+
+	* condvar.c (pthread_cond_destroy): Add critical section.
+	(cond_timedwait): Add critical section; check for timeout
+	waiting on semaphore.
+	(pthread_cond_broadcast): Add critical section.
+
+1999-07-09  Lorin Hochstein <lmh at xiphos.ca>, John Bossom <John.Bossom at Cognos.COM>
+
+	The problem was that cleanup handlers were not executed when
+	pthread_exit() was called.
+
+	* implement.h (pthread_t_): Add exceptionInformation element for
+	C++ per-thread exception information.
+	(general): Define and rename exceptions.
+
+1999-07-09  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* misc.c (CancelableWait):  PTW32_EPS_CANCEL (SEH) and
+	ptw32_exception_cancel (C++) used to identify the exception.
+
+	* cancel.c (pthread_testcancel): PTW32_EPS_CANCEL (SEH) and
+	ptw32_exception_cancel (C++) used to identify the exception.
+
+	* exit.c (pthread_exit): throw/raise an exception to return to
+	ptw32_threadStart() to exit the thread. PTW32_EPS_EXIT (SEH)
+	and ptw32_exception_exit (C++) used to identify the exception.
+
+	* private.c (ptw32_threadStart): Add pthread_exit exception trap;
+	clean up and exit the thread directly rather than via pthread_exit().
+
+Sun May 30 00:25:02 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* semaphore.h (mode_t): Conditionally typedef it.
+
+Fri May 28 13:33:05 1999  Mark E. Armstrong <avail at pacbell.net>
+
+	* condvar.c (pthread_cond_broadcast): Fix possible memory fault
+	
+Thu May 27 13:08:46 1999  Peter Slacik <Peter.Slacik at tatramed.sk>
+
+	* condvar.c (pthread_cond_broadcast): Fix logic bug
+
+Thu May 27 13:08:46 1999  Bossom, John <John.Bossom at Cognos.COM>
+
+	* condvar.c (pthread_cond_broadcast): optimise sem_post loop
+
+Fri May 14 12:13:18 1999  Mike Russo <miker at eai.com>
+
+	* attr.c (pthread_attr_setdetachstate): Fix logic bug
+
+Sat May  8 09:42:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.def (sem_open): Add.
+	(sem_close): Add.
+	(sem_unlink): Add.
+	(sem_getvalue): Add.
+
+	* FAQ (Question 3): Add.
+
+Thu Apr  8 01:16:23 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* semaphore.c (sem_open): New function; returns an error (ENOSYS).
+	(sem_close): ditto.
+	(sem_unlink): ditto.
+	(sem_getvalue): ditto.
+
+	* semaphore.h (_POSIX_SEMAPHORES): define.
+	
+Wed Apr  7 14:09:52 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* errno.c (_REENTRANT || _MT): Invert condition.
+
+	* pthread.h (_errno): Conditionally include prototype.
+
+Wed Apr  7 09:37:00 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* *.c (comments): Remove individual attributions - these are
+	documented sufficiently elsewhere.
+
+	* implement.h (pthread.h): Remove extraneous include.
+
+Sun Apr  4 11:05:57 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sched.c (sched.h): Include.
+
+	* sched.h: New file for POSIX 1b scheduling.
+
+	* pthread.h: Move opaque structures to implement.h; move sched_*
+	prototypes out and into sched.h.
+
+	* implement.h: Add opaque structures from pthread.h.
+
+	* sched.c (sched_yield): New function.
+
+	* condvar.c (ptw32_sem_*): Rename to sem_*; except for
+	ptw32_sem_timedwait which is an private function.
+
+Sat Apr  3 23:28:00 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* Makefile.in (OBJS): Add errno.o.
+
+Fri Apr  2 11:08:50 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h (ptw32_sem_*): Remove prototypes now defined in
+	semaphore.h.
+
+	* pthread.h (sempahore.h): Include.
+
+	* semaphore.h: New file for POSIX 1b semaphores.
+
+	* semaphore.c (ptw32_sem_timedwait): Moved to private.c.
+
+	* pthread.h (ptw32_sem_t): Change to sem_t. 
+
+	* private.c (ptw32_sem_timedwait): Moved from semaphore.c;
+	set errno on error.
+
+	* pthread.h (pthread_t_): Add per-thread errno element.
+
+Fri Apr  2 11:08:50 1999  John Bossom <jebossom at cognos.com>
+
+	* semaphore.c (ptw32_sem_*): Change to sem_*; these functions
+	will be exported from the library; set errno on error.
+
+	* errno.c (_errno): New file. New function.
+
+Fri Mar 26 14:11:45 1999  Tor Lillqvist <tml at iki.fi>
+
+	* semaphore.c (ptw32_sem_timedwait): Check for negative
+	milliseconds.
+
+Wed Mar 24 11:32:07 1999  John Bossom <jebossom at cognos.com>
+
+	* misc.c (CancelableWait): Initialise exceptionInformation[2].
+	(pthread_self): Get a real Win32 thread handle for implicit threads.
+
+	* cancel.c (pthread_testcancel): Initialise exceptionInformation[2].
+
+	* implement.h (SE_INFORMATION): Fix values.
+
+	* private.c (ptw32_threadDestroy): Close the thread handle.
+
+Fri Mar 19 12:57:27 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cancel.c (comments): Update and cleanup.
+
+Fri Mar 19 09:12:59 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_threadStart): status returns PTHREAD_CANCELED.
+
+	* pthread.h (PTHREAD_CANCELED): defined.
+
+Tue Mar 16  1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* all: Add GNU LGPL and Copyright and Warranty.
+	
+Mon Mar 15 00:20:13 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* condvar.c (pthread_cond_init): fix possible uninitialised use
+	of cv.
+
+Sun Mar 14 21:01:59 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* condvar.c (pthread_cond_destroy): don't do full cleanup if
+	static initialised cv has never been used.
+	(cond_timedwait): check result of auto-initialisation.
+
+Thu Mar 11 09:01:48 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (pthread_mutex_t): revert to (pthread_mutex_t *);
+	define a value to serve as PTHREAD_MUTEX_INITIALIZER.
+	(pthread_mutex_t_): remove staticinit and valid elements.
+	(pthread_cond_t): revert to (pthread_cond_t_ *);
+	define a value to serve as PTHREAD_COND_INITIALIZER.
+	(pthread_cond_t_): remove staticinit and valid elements.
+
+	* mutex.c (pthread_mutex_t args): adjust indirection of references.
+	(all functions): check for PTHREAD_MUTEX_INITIALIZER value;
+	check for NULL (invalid).
+
+	* condvar.c (pthread_cond_t args): adjust indirection of references.
+	(all functions): check for PTHREAD_COND_INITIALIZER value;
+	check for NULL (invalid).
+
+Wed Mar 10 17:18:12 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* misc.c (CancelableWait): Undo changes from Mar 8 and 7.
+
+Mon Mar  8 11:18:59 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* misc.c (CancelableWait): Ensure cancelEvent handle is the lowest
+	indexed element in the handles array. Enhance test for abandoned
+	objects.
+
+	* pthread.h (PTHREAD_MUTEX_INITIALIZER): Trailing elements not
+	initialised are set to zero by the compiler. This avoids the
+	problem of initialising the opaque critical section element in it.
+	(PTHREAD_COND_INITIALIZER): Ditto.
+
+	* semaphore.c (ptw32_sem_timedwait): Check sem == NULL earlier.
+
+Sun Mar  7 12:31:14 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* condvar.c (pthread_cond_init): set semaphore initial value
+	to 0, not 1. cond_timedwait was returning signaled immediately.
+
+	* misc.c (CancelableWait): Place the cancel event handle first
+	in the handle table for WaitForMultipleObjects. This ensures that
+	the cancel event is recognised and acted apon if both objects
+	happen to be signaled together.
+
+	* private.c (ptw32_cond_test_init_lock): Initialise and destroy.
+
+	* implement.h (ptw32_cond_test_init_lock): Add extern.
+
+	* global.c (ptw32_cond_test_init_lock): Add declaration. 
+
+	* condvar.c (pthread_cond_destroy): check for valid initialised CV;
+	flag destroyed CVs as invalid.
+	(pthread_cond_init): pthread_cond_t is no longer just a pointer.
+	This is because PTHREAD_COND_INITIALIZER needs state info to reside
+	in pthread_cond_t so that it can initialise on first use. Will work on
+	making pthread_cond_t (and other objects like it) opaque again, if
+	possible, later.
+	(cond_timedwait): add check for statically initialisation of
+	CV; initialise on first use.
+	(pthread_cond_signal): check for valid CV.
+	(pthread_cond_broadcast): check for valid CV.
+	(_cond_check_need_init): Add.
+
+	* pthread.h (PTHREAD_COND_INITIALIZER): Fix.
+	(pthread_cond_t): no longer a pointer to pthread_cond_t_.
+	(pthread_cond_t_): add 'staticinit' and 'valid' elements.
+
+Sat Mar 6 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Undate comments.
+
+Sun Feb 21 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (PTHREAD_MUTEX_INITIALIZER): missing braces around
+	cs element initialiser.
+
+1999-02-21  Ben Elliston  <bje at cygnus.com>
+
+	* pthread.h (pthread_exit): The return type of this function is
+	void, not int.
+
+	* exit.c (pthread_exit): Do not return 0.
+
+Sat Feb 20 16:03:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* dll.c (DLLMain): Expand TryEnterCriticalSection support test.
+
+	* mutex.c (pthread_mutex_trylock): The check for
+	ptw32_try_enter_critical_section == NULL should have been
+	removed long ago.
+
+Fri Feb 19 16:03:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sync.c (pthread_join): Fix pthread_equal() test.
+
+	* mutex.c (pthread_mutex_trylock): Check mutex != NULL before
+	using it.
+
+Thu Feb 18 16:17:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* misc.c (pthread_equal): Fix inverted result.
+
+	* Makefile.in: Use libpthread32.a as the name of the DLL export
+	library instead of pthread.lib.
+
+	* condvar.c (pthread_cond_init): cv could have been used unitialised;
+	initialise.
+
+	* create.c (pthread_create): parms could have been used unitialised;
+	initialise.
+
+	* pthread.h (struct pthread_once_t_): Remove redefinition.
+
+Sat Feb 13 03:03:30 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (struct pthread_once_t_): Replaced.
+
+	* misc.c (pthread_once): Replace with John Bossom's version;
+	has lighter weight serialisation; fixes problem of not holding
+	competing threads until after the init_routine completes.
+
+Thu Feb 11 13:34:14 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* misc.c (CancelableWait): Change C++ exception throw.
+
+	* sync.c (pthread_join): Change FIXME comment - issue resolved.
+
+Wed Feb 10 12:49:11 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* configure: Various temporary changes.
+	- Kevin Ruland <Kevin.Ruland at anheuser-busch.com>
+
+	* README: Update.
+
+	* pthread.def (pthread_attr_getstackaddr): uncomment
+	(pthread_attr_setstackaddr): uncomment
+
+Fri Feb  5 13:42:30 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* semaphore.c: Comment format changes.
+
+Thu Feb  4 10:07:28 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* global.c: Remove ptw32_exception instantiation.
+
+	* cancel.c (pthread_testcancel): Change C++ exception throw.
+
+	* implement.h: Remove extern declaration.
+
+Wed Feb  3 13:04:44 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cleanup.c: Rename ptw32_*_cleanup() to pthread_*_cleanup().
+
+	* pthread.def: Ditto.
+	
+	* pthread.h: Ditto.
+
+	* pthread.def (pthread_cleanup_push): Remove from export list;
+	the function is defined as a macro under all compilers.
+	(pthread_cleanup_pop): Ditto.
+
+	* pthread.h: Remove #if defined().
+
+Wed Feb  3 10:13:48 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sync.c (pthread_join): Check for NULL value_ptr arg;
+	check for detached threads.
+
+Tue Feb  2 18:07:43 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* implement.h: Add #include <pthread.h>.
+	Change sem_t to ptw32_sem_t.
+
+Tue Feb  2 18:07:43 1999  Kevin Ruland <Kevin.Ruland at anheuser-busch.com>
+
+	* signal.c (pthread_sigmask): Add and modify casts.
+	Reverse LHS/RHS bitwise assignments.
+
+	* pthread.h: Remove #include <semaphore.h>.
+	(PTW32_ATTR_VALID): Add cast.
+	(struct pthread_t_): Add sigmask element.
+
+	* dll.c: Add "extern C" for DLLMain.
+	(DllMain): Add cast.
+
+	* create.c (pthread_create): Set sigmask in thread.
+
+	* condvar.c: Remove #include. Change sem_* to ptw32_sem_*.
+
+	* attr.c: Changed #include.
+
+	* Makefile.in: Additional targets and changes to build the library
+	as a DLL.
+
+Fri Jan 29 11:56:28 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* Makefile.in (OBJS): Add semaphore.o to list.
+
+	* semaphore.c (ptw32_sem_timedwait): Move from private.c.
+	Rename sem_* to ptw32_sem_*.
+
+	* pthread.h (pthread_cond_t): Change type of sem_t.
+	_POSIX_SEMAPHORES no longer defined.
+
+	* semaphore.h: Contents moved to implement.h.
+	Removed from source tree.
+
+	* implement.h: Add semaphore function prototypes and rename all
+	functions to prepend 'ptw32_'. They are
+	now private to the pthreads-win32 implementation.
+
+	* private.c: Change #warning.
+	Move ptw32_sem_timedwait() to semaphore.c.
+
+	* cleanup.c: Change #warning.
+
+	* misc.c: Remove #include <errno.h>
+
+	* pthread.def: Cleanup CVS merge conflicts.
+
+	* global.c: Ditto.
+
+	* ChangeLog: Ditto.
+
+	* cleanup.c: Ditto.
+
+Sun Jan 24 01:34:52 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* semaphore.c (sem_wait): Remove second arg to 
+	pthreadCancelableWait() call.
+
+Sat Jan 23 17:36:40 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.def: Add new functions to export list.
+
+	* pthread.h (PTHREAD_MUTEX_AUTO_CS_NP): New.
+	(PTHREAD_MUTEX_FORCE_CS_NP): New.
+
+	* README: Updated.
+
+Fri Jan 22 14:31:59 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* Makefile.in (CFLAGS): Remove -fhandle-exceptions. Not needed
+	with egcs. Add -g for debugging.
+
+	* create.c (pthread_create): Replace __stdcall with PT_STDCALL
+	macro. This is a hack and must be fixed.
+
+	* misc.c (CancelableWait): Remove redundant statement.
+
+	* mutex.c (pthread_mutexattr_init): Cast calloc return value.
+
+	* misc.c (CancelableWait): Add cast.
+	(pthread_self): Add cast.
+
+	* exit.c (pthread_exit): Add cast.
+
+	* condvar.c (pthread_condattr_init): Cast calloc return value.
+
+	* cleanup.c: Reorganise conditional compilation.
+
+	* attr.c (pthread_attr_init): Remove unused 'result'.
+	Cast malloc return value.
+
+	* private.c (ptw32_callUserDestroyRoutines): Redo conditional
+	compilation.
+
+	* misc.c (CancelableWait): C++ version uses 'throw'.
+
+	* cancel.c (pthread_testcancel): Ditto.
+
+	* implement.h (class ptw32_exception): Define for C++.
+
+	* pthread.h: Fix C, C++, and Win32 SEH condition compilation
+	mayhem around pthread_cleanup_* defines. C++ version now uses John
+	Bossom's cleanup handlers.
+	(pthread_attr_t): Make 'valid' unsigned.
+	Define '_timeb' as 'timeb' for Ming32.
+	Define PT_STDCALL as nothing for Mingw32. May be temporary.
+
+	* cancel.c (pthread_testcancel): Cast return value.
+
+Wed Jan 20 09:31:28 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (pthread_mutexattr_t): Changed to a pointer.
+
+	* mutex.c (pthread_mutex_init): Conditionally create Win32 mutex
+	- from John Bossom's implementation.
+	(pthread_mutex_destroy): Conditionally close Win32 mutex
+	- from John Bossom's implementation.
+	(pthread_mutexattr_init): Replaced by John Bossom's version.
+	(pthread_mutexattr_destroy): Ditto.
+	(pthread_mutexattr_getpshared): New function from John Bossom's
+	implementation.
+	(pthread_mutexattr_setpshared): New function from John Bossom's
+	implementation.
+
+Tue Jan 19 18:27:42 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* pthread.h (pthreadCancelableTimedWait): New prototype.
+	(pthreadCancelableWait): Remove second argument.
+
+	* misc.c (CancelableWait): New static function is 
+	pthreadCancelableWait() renamed.
+	(pthreadCancelableWait): Now just calls CancelableWait() with
+	INFINITE timeout.
+	(pthreadCancelableTimedWait): Just calls CancelableWait()
+	with passed in timeout.
+
+Tue Jan 19 18:27:42 1999  Scott Lightner <scott at curriculum.com>
+
+	* private.c (ptw32_sem_timedwait): 'abstime' arg really is
+	absolute time. Calculate relative time to wait from current
+	time before passing timeout to new routine 
+	pthreadCancelableTimedWait().
+
+Tue Jan 19 10:27:39 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (pthread_mutexattr_setforcecs_np): New prototype.
+	
+	* mutex.c (pthread_mutexattr_init): Init 'pshared' and 'forcecs'
+	attributes to 0.
+	(pthread_mutexattr_setforcecs_np): New function (not portable).
+
+	* pthread.h (pthread_mutex_t): 
+	Add 'mutex' element. Set to NULL in PTHREAD_MUTEX_INITIALIZER.
+	The pthread_mutex_*() routines will try to optimise performance
+	by choosing either mutexes or critical sections as the basis
+	for pthread mutexes for each indevidual mutex.
+	(pthread_mutexattr_t_): Add 'forcecs' element.
+	Some applications may choose to force use of critical sections
+	if they know that:-
+	     the mutex is PROCESS_PRIVATE and, 
+	         either the OS supports TryEnterCriticalSection() or
+	         pthread_mutex_trylock() will never be called on the mutex.
+	This attribute will be setable via a non-portable routine.
+
+	Note: We don't yet support PROCESS_SHARED mutexes, so the
+	implementation as it stands will default to Win32 mutexes only if
+	the OS doesn't support TryEnterCriticalSection. On Win9x, and early
+	versions of NT 'forcecs' will need to be set in order to get
+	critical section based mutexes.
+
+Sun Jan 17 12:01:26 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (PTHREAD_MUTEX_INITIALIZER): Init new 'staticinit'
+	value to '1' and existing 'valid' value to '1'.
+
+	* global.c (ptw32_mutex_test_init_lock): Add.
+
+	* implement.h (ptw32_mutex_test_init_lock.): Add extern.
+
+	* private.c (ptw32_processInitialize): Init critical section for
+	global lock used by _mutex_check_need_init().
+	(ptw32_processTerminate): Ditto (:s/Init/Destroy/).
+
+	* dll.c (dllMain): Move call to FreeLibrary() so that it is only
+	called once when the process detaches.
+
+	* mutex.c (_mutex_check_need_init): New static function to test
+	and init PTHREAD_MUTEX_INITIALIZER mutexes. Provides serialised
+	access to the internal state of the uninitialised static mutex. 
+	Called from pthread_mutex_trylock() and pthread_mutex_lock() which
+	do a quick unguarded test to check if _mutex_check_need_init()
+	needs to be called. This is safe as the test is conservative
+ 	and is repeated inside the guarded section of 
+	_mutex_check_need_init(). Thus in all calls except the first
+	calls to lock static mutexes, the additional overhead to lock any
+	mutex is a single memory fetch and test for zero.
+
+	* pthread.h (pthread_mutex_t_): Add 'staticinit' member. Mutexes
+	initialised by PTHREAD_MUTEX_INITIALIZER aren't really initialised
+	until the first attempt to lock it. Using the 'valid'
+	flag (which flags the mutex as destroyed or not) to record this
+	information would be messy. It is possible for a statically
+	initialised mutex such as this to be destroyed before ever being
+	used.
+
+	* mutex.c (pthread_mutex_trylock): Call _mutex_check_need_init()
+	to test/init PTHREAD_MUTEX_INITIALIZER mutexes.
+	(pthread_mutex_lock): Ditto.
+	(pthread_mutex_unlock): Add check to ensure we don't try to unlock
+	an unitialised static mutex.
+	(pthread_mutex_destroy): Add check to ensure we don't try to delete
+	a critical section that we never created. Allows us to destroy
+	a static mutex that has never been locked (and hence initialised).
+	(pthread_mutex_init): Set 'staticinit' flag to 0 for the new mutex.
+
+Sun Jan 17 12:01:26 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_sem_timedwait): Move from semaphore.c.
+
+	* semaphore.c : Remove redundant #includes.
+	(ptw32_sem_timedwait): Move to private.c.
+	(sem_wait): Add missing abstime arg to pthreadCancelableWait() call.
+
+Fri Jan 15 23:38:05 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* condvar.c (cond_timedwait): Remove comment.
+
+Fri Jan 15 15:41:28 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* pthread.h: Add new 'abstime' arg to pthreadCancelableWait()
+	prototype.
+
+	* condvar.c (cond_timedwait): New generalised function called by
+	both pthread_cond_wait() and pthread_cond_timedwait(). This is
+	essentially pthread_cond_wait() renamed and modified to add the
+	'abstime' arg and call the new ptw32_sem_timedwait() instead of
+	sem_wait().
+	(pthread_cond_wait): Now just calls the internal static
+	function cond_timedwait() with an INFINITE wait.
+	(pthread_cond_timedwait): Now implemented. Calls the internal
+	static function cond_timedwait().
+
+	* implement.h (ptw32_sem_timedwait): New internal function
+	prototype.
+
+	* misc.c (pthreadCancelableWait): Added new 'abstime' argument
+	to allow shorter than INFINITE wait.
+
+	* semaphore.c (ptw32_sem_timedwait): New function for internal
+	use.  This is essentially sem_wait() modified to add the
+        'abstime' arg and call the modified (see above)
+        pthreadCancelableWait().
+
+Thu Jan 14 14:27:13 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cleanup.c: Correct _cplusplus to __cplusplus wherever used.
+
+	* Makefile.in: Add CC=g++ and add -fhandle-exceptions to CFLAGS.
+	The derived Makefile will compile all units of the package as C++
+	so that those which include try/catch exception handling should work
+	properly. The package should compile ok if CC=gcc, however, exception
+	handling will not be included and thus thread cancellation, for
+ 	example, will not work.
+
+	* cleanup.c (ptw32_pop_cleanup): Add #warning to compile this
+ 	file as C++ if using a cygwin32 environment. Perhaps the whole package
+	should be compiled using g++ under cygwin.
+
+	* private.c (ptw32_threadStart): Change #error directive
+	into #warning and bracket for __CYGWIN__ and derivative compilers.
+
+Wed Jan 13 09:34:52 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* build.bat: Delete old binaries before compiling/linking.
+
+Tue Jan 12 09:58:38 1999  Tor Lillqvist <tml at iki.fi>
+
+	* dll.c: The Microsoft compiler pragmas probably are more
+	appropriately protected by _MSC_VER than by _WIN32.
+
+	* pthread.h: Define ETIMEDOUT. This should be returned by
+	pthread_cond_timedwait which is not implemented yet as of
+	snapshot-1999-01-04-1305. It was implemented in the older version.
+	The Microsoft compiler pragmas probably are more appropriately
+	protected by _MSC_VER than by _WIN32.
+
+	* pthread.def: pthread_mutex_destroy was missing from the def file
+
+	* condvar.c (pthread_cond_broadcast): Ensure we only wait on threads
+	if there were any waiting on the condition.
+	I think pthread_cond_broadcast should do the WaitForSingleObject
+	only if cv->waiters > 0? Otherwise it seems to hang, at least in the
+	testg thread program from glib.
+
+Tue Jan 12 09:58:38 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* condvar.c (pthread_cond_timedwait): Fix function description
+	comments.
+
+	* semaphore.c (sem_post): Correct typo in comment.
+
+Mon Jan 11 20:33:19 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h: Re-arrange conditional compile of pthread_cleanup-*
+	macros.
+
+	* cleanup.c (ptw32_push_cleanup): Provide conditional 
+	compile of cleanup->prev.
+
+1999-01-11  Tor Lillqvist <tml at iki.fi>
+
+	* condvar.c (pthread_cond_init): Invert logic when testing the
+	return value from calloc().
+
+Sat Jan  9 14:32:08 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Compile-time switch for CYGWIN derived environments
+	to use CreateThread instead of _beginthreadex. Ditto for ExitThread.
+	Patch provided by Anders Norlander  <anorland at hem2.passagen.se>.
+
+Tue Jan  5 16:33:04 1999  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cleanup.c (ptw32_pop_cleanup): Add C++ version of __try/__except
+	block. Move trailing "}" out of #ifdef _WIN32 block left there by
+	(rpj's) mistake.
+
+	* private.c: Remove #include <errno.h> which is included by pthread.h.
+
+1998-12-11  Ben Elliston  <bje at toilet.to.cygnus.com>
+
+	* README: Update info about subscribing to the mailing list.
+
+Mon Jan  4 11:23:40 1999  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* all: No code changes, just cleanup.
+	- remove #if 0 /* Pre Bossom */ enclosed code.
+	- Remove some redundant #includes.
+	* pthread.h: Update implemented/unimplemented routines list.
+	* Tag the bossom merge branch getting ready to merge back to main
+	trunk.
+
+Tue Dec 29 13:11:16 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Move the following struct definitions to pthread.h:
+	pthread_t_, pthread_attr_t_, pthread_mutex_t_, pthread_mutex_t_,
+	pthread_mutexattr_t_, pthread_key_t_, pthread_cond_t_,
+	pthread_condattr_t_, pthread_once_t_.
+
+	* pthread.h: Add "_" prefix to pthread_push_cleanup and 
+	pthread_pop_cleanup internal routines, and associated struct and
+	typedefs.
+
+	* buildlib.bat: Add compile command for semaphore.c
+
+	* pthread.def: Comment out pthread_atfork routine name. 
+	Now unimplemented.
+
+	* tsd.c (pthread_setspecific): Rename tkAssocCreate to
+	ptw32_tkAssocCreate.
+	(pthread_key_delete): Rename tkAssocDestroy to
+	ptw32_tkAssocDestroy.
+
+	* sync.c (pthread_join): Rename threadDestroy to ptw32_threadDestroy
+
+	* sched.c (is_attr): attr is now **attr (was *attr), so add extra
+	NULL pointer test.
+	(pthread_attr_setschedparam): Increase redirection for attr which is
+	now a **.
+	(pthread_attr_getschedparam): Ditto.
+	(pthread_setschedparam): Change thread validation and rename "thread"
+ 	Win32 thread Handle element name to match John Bossom's version.
+	(pthread_getschedparam): Ditto.
+
+	* private.c (ptw32_threadDestroy): Rename call to
+	callUserDestroyRoutines() as ptw32_callUserDestroyRoutines()
+
+	* misc.c: Add #include "implement.h".
+
+	* dll.c: Remove defined(KLUDGE) wrapped code.
+
+	* fork.c: Remove redefinition of ENOMEM.
+	Remove pthread_atfork() and fork() with #if 0/#endif.
+
+	* create.c (pthread_create): Rename threadStart and threadDestroy calls
+	to ptw32_threadStart and ptw32_threadDestroy.
+
+	* implement.h: Rename "detachedstate" to "detachstate".
+
+	* attr.c: Rename "detachedstate" to "detachstate".
+
+Mon Dec 28 09:54:39 1998  John Bossom
+
+	* semaphore.c: Initial version.
+	* semaphore.h: Initial version.
+
+Mon Dec 28 09:54:39 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.h (pthread_attr_t_): Change to *pthread_attr_t.
+
+Mon Dec 28 09:54:39 1998  John Bossom, Ben Elliston
+
+	* attr.c (pthread_attr_setstacksize): Merge with John's version.
+	(pthread_attr_getstacksize): Merge with John's version.
+	(pthread_attr_setstackaddr): Merge with John's version.
+	(pthread_attr_getstackaddr): Merge with John's version.
+	(pthread_attr_init): Merge with John's version.
+	(pthread_attr_destroy): Merge with John's version.
+	(pthread_attr_getdetachstate): Merge with John's version.
+	(pthread_attr_setdetachstate): Merge with John's version.
+	(is_attr): attr is now **attr (was *attr), so add extra NULL pointer
+	test.
+
+Mon Dec 28 09:54:39 1998  Ross Johnson
+
+	* implement.h (pthread_attr_t_): Add and rename elements in JEB's
+	version to correspond to original, so that it can be used with
+	original attr routines.
+
+	* pthread.h: Add #endif at end which was truncated in merging.
+
+Sun Dec 20 14:51:58 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* misc.c (pthreadCancelableWait): New function by John Bossom. Non-standard
+	but provides a hook that can be used to implement cancellation points in
+	applications that use this library.
+
+	* pthread.h (pthread_cleanup_pop): C++ (non-WIN32) version uses
+	try/catch to emulate John Bossom's WIN32 __try/__finally behaviour.
+	In the WIN32 version __finally block, add a test for AbnormalTermination otherwise
+	cleanup is only run if the cleanup_pop execute arg is non-zero. Cancellation
+	should cause the cleanup to run irrespective of the execute arg.
+
+	* condvar.c (pthread_condattr_init): Replaced by John Bossom's version.
+	(pthread_condattr_destroy): Replaced by John Bossom's version.
+	(pthread_condattr_getpshared): Replaced by John Bossom's version.
+	(pthread_condattr_setpshared): Replaced by John Bossom's version.
+	(pthread_cond_init): Replaced by John Bossom's version.
+	Fix comment (refered to mutex rather than condition variable).
+	(pthread_cond_destroy): Replaced by John Bossom's version.
+	(pthread_cond_wait): Replaced by John Bossom's version.
+	(pthread_cond_timedwait): Replaced by John Bossom's version.
+	(pthread_cond_signal): Replaced by John Bossom's version.
+	(pthread_cond_broadcast): Replaced by John Bossom's version.
+
+Thu Dec 17 19:10:46 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* tsd.c (pthread_key_create): Replaced by John Bossom's version.
+	(pthread_key_delete): Replaced by John Bossom's version.
+	(pthread_setspecific): Replaced by John Bossom's version.
+	(pthread_getspecific): Replaced by John Bossom's version.
+
+Mon Dec  7 09:44:40 1998  John Bossom
+
+	* cancel.c (pthread_setcancelstate): Replaced.
+	(pthread_setcanceltype): Replaced.
+	(pthread_testcancel): Replaced.
+	(pthread_cancel): Replaced.
+	
+	* exit.c (pthread_exit): Replaced.
+
+	* misc.c (pthread_self): Replaced.
+	(pthread_equal): Replaced.
+
+	* sync.c (pthread_detach): Replaced.
+	(pthread_join): Replaced.
+
+	* create.c (pthread_create): Replaced.
+
+	* private.c (ptw32_processInitialize): New.
+	(ptw32_processTerminate): New.
+	(ptw32_threadStart): New.
+ 	(ptw32_threadDestroy): New.
+	(ptw32_cleanupStack): New.
+	(ptw32_tkAssocCreate): New.
+	(ptw32_tkAssocDestroy): New.
+	(ptw32_callUserDestroyRoutines): New.
+
+	* implement.h: Added non-API structures and declarations.
+
+	* dll.c (PthreadsEntryPoint): Cast return value of GetProcAddress
+	to resolve compile warning from MSVC.
+
+	* dll.c (DLLmain): Replaced.
+	* dll.c (PthreadsEntryPoint):
+	Re-applied Anders Norlander's patch:-
+	Initialize ptw32_try_enter_critical_section at startup
+	and release kernel32 handle when DLL is being unloaded.
+
+Sun Dec  6 21:54:35 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* buildlib.bat: Fix args to CL when building the .DLL
+
+	* cleanup.c (ptw32_destructor_run_all): Fix TSD key management.
+	This is a tidy-up before TSD and Thread management is completely
+	replaced by John Bossom's code.
+
+	* tsd.c (pthread_key_create): Fix TSD key management.
+
+	* global.c (ptw32_key_virgin_next): Initialise.
+
+	* build.bat: New DOS script to compile and link a pthreads app
+	using Microsoft's CL compiler linker.
+	* buildlib.bat: New DOS script to compile all the object files
+	and create pthread.lib and pthread.dll using Microsoft's CL
+	compiler linker.
+
+1998-12-05  Anders Norlander  <anorland at hem2.passagen.se>
+
+	* implement.h (ptw32_try_enter_critical_section): New extern
+	* dll.c (ptw32_try_enter_critical_section): New pointer to
+	TryEnterCriticalSection if it exists; otherwise NULL.
+	* dll.c (PthreadsEntryPoint):
+	Initialize ptw32_try_enter_critical_section at startup
+	and release kernel32 handle when DLL is being unloaded.
+	* mutex.c (pthread_mutex_trylock): Replaced check for NT with
+	a check if ptw32_try_enter_critical_section is valid
+	pointer to a function. Call ptw32_try_enter_critical_section
+	instead of TryEnterCriticalSection to avoid errors on Win95.
+
+Thu Dec 3 13:32:00 1998  Ross Johnson  <rpj at ise.canberra.edu.au>
+
+	* README: Correct cygwin32 compatibility statement.
+
+Sun Nov 15 21:24:06 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* cleanup.c (ptw32_destructor_run_all): Declare missing void * arg.
+	Fixup CVS merge conflicts.
+
+1998-10-30  Ben Elliston  <bje at cygnus.com>
+
+	* condvar.c (cond_wait): Fix semantic error. Test for equality
+	instead of making an assignment.
+
+Fri Oct 30 15:15:50 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cleanup.c (ptw32_handler_push): Fixed bug appending new
+	handler to list reported by Peter Slacik
+	<Peter.Slacik at leibinger.freinet.de>.
+	(new_thread): Rename poorly named local variable to
+	"new_handler".
+
+Sat Oct 24 18:34:59 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* global.c: Add TSD key management array and index declarations.
+
+	* implement.h: Ditto for externs.
+
+Fri Oct 23 00:08:09 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h (PTW32_TSD_KEY_REUSE): Add enum.
+
+	* private.c (ptw32_delete_thread): Add call to
+	ptw32_destructor_run_all() to clean up the threads keys.
+
+	* cleanup.c (ptw32_destructor_run_all): Check for no more dirty
+	keys to run destructors on. Assume that the destructor call always
+	succeeds and set the key value to NULL.
+
+Thu Oct 22 21:44:44 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* tsd.c (pthread_setspecific): Add key management code.
+	(pthread_key_create): Ditto.
+	(pthread_key_delete): Ditto.
+
+	* implement.h (struct ptw32_tsd_key): Add status member.
+
+	* tsd.c: Add description of pthread_key_delete() from the
+	standard as a comment.
+
+Fri Oct 16 17:38:47 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cleanup.c (ptw32_destructor_run_all): Fix and improve
+	stepping through the key table.
+
+Thu Oct 15 14:05:01 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* private.c (ptw32_new_thread): Remove init of destructorstack.
+	No longer an element of pthread_t.
+
+	* tsd.c (pthread_setspecific): Fix type declaration and cast.
+	(pthread_getspecific): Ditto.
+	(pthread_getspecific): Change error return value to NULL if key
+	is not in use.
+
+Thu Oct 15 11:53:21 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* global.c (ptw32_tsd_key_table): Fix declaration.
+
+	* implement.h(ptw32_TSD_keys_TlsIndex): Add missing extern.
+	(ptw32_tsd_mutex): Ditto.
+
+	* create.c (ptw32_start_call): Fix "keys" array declaration.
+	Add comment.
+
+	* tsd.c (pthread_setspecific): Fix type declaration and cast.
+	(pthread_getspecific): Ditto.
+
+	* cleanup.c (ptw32_destructor_run_all): Declare missing loop
+	counter.
+
+Wed Oct 14 21:09:24 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_new_thread): Increment ptw32_threads_count.
+	(ptw32_delete_thread): Decrement ptw32_threads_count.
+	Remove some comments.
+
+	* exit.c (ptw32_exit): : Fix two pthread_mutex_lock() calls that
+ 	should have been pthread_mutex_unlock() calls.
+	(ptw32_vacuum): Remove call to ptw32_destructor_pop_all().
+
+	* create.c (pthread_create): Fix two pthread_mutex_lock() calls that
+ 	should have been pthread_mutex_unlock() calls.
+
+	* global.c (ptw32_tsd_mutex): Add mutex for TSD operations.
+
+	* tsd.c (pthread_key_create): Add critical section.
+	(pthread_setspecific): Ditto.
+	(pthread_getspecific): Ditto.
+	(pthread_key_delete): Ditto.
+
+	* sync.c (pthread_join): Fix two pthread_mutex_lock() calls that
+ 	should have been pthread_mutex_unlock() calls.
+
+Mon Oct 12 00:00:44 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h (ptw32_tsd_key_table): New.
+
+	* create.c (ptw32_start_call): Initialise per-thread TSD keys
+	to NULL.
+
+	* misc.c (pthread_once): Correct typo in comment.
+
+	* implement.h (ptw32_destructor_push): Remove.
+	(ptw32_destructor_pop): Remove.
+	(ptw32_destructor_run_all): Rename from ptw32_destructor_pop_all.
+	(PTW32_TSD_KEY_DELETED): Add enum.
+	(PTW32_TSD_KEY_INUSE): Add enum.
+
+	* cleanup.c (ptw32_destructor_push): Remove.
+	(ptw32_destructor_pop): Remove.
+	(ptw32_destructor_run_all): Totally revamped TSD.
+
+	* dll.c (ptw32_TSD_keys_TlsIndex): Initialise.
+
+	* tsd.c (pthread_setspecific): Totally revamped TSD.
+	(pthread_getspecific): Ditto.
+	(pthread_create): Ditto.
+	(pthread_delete): Ditto.
+
+Sun Oct 11 22:44:55 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* global.c (ptw32_tsd_key_table): Add new global.
+
+	* implement.h (ptw32_tsd_key_t and struct ptw32_tsd_key):
+	Add.
+	(struct _pthread): Remove destructorstack.
+
+	* cleanup.c (ptw32_destructor_run_all): Rename from
+ 	ptw32_destructor_pop_all. The key destructor stack was made
+ 	global rather than per-thread. No longer removes destructor nodes
+	from the stack. Comments updated.
+
+1998-10-06  Ben Elliston  <bje at cygnus.com>
+
+	* condvar.c (cond_wait): Use POSIX, not Win32 mutex calls.
+	(pthread_cond_broadcast): Likewise.
+	(pthread_cond_signal): Likewise.
+
+1998-10-05  Ben Elliston  <bje at cygnus.com>
+
+	* pthread.def: Update. Some functions aren't available yet, others
+	are macros in <pthread.h>.
+
+	* tests/join.c: Remove; useless.
+
+Mon Oct  5 14:25:08 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* pthread.def: New file for building the DLL.
+
+1998-10-05  Ben Elliston  <bje at cygnus.com>
+
+	* misc.c (pthread_equal): Correct inverted logic bug.
+	(pthread_once): Use the POSIX mutex primitives, not Win32. Remove
+	irrelevant FIXME comment.
+
+	* global.c (PTHREAD_MUTEX_INITIALIZER): Move to pthread.h.
+
+	* pthread.h (PTHREAD_MUTEX_INITIALIZER): Define.
+	(pthread_mutex_t): Reimplement as a struct containing a valid
+	flag. If the flag is ever down upon entry to a mutex operation,
+	we call pthread_mutex_create() to initialise the object. This
+	fixes the problem of how to handle statically initialised objects
+	that can't call InitializeCriticalSection() due to their context.
+	(PTHREAD_ONCE_INIT): Define.
+
+	* mutex.c (pthread_mutex_init): Set valid flag.
+	(pthread_mutex_destroy): Clear valid flag.
+	(pthread_mutex_lock): Check and handle the valid flag.
+	(pthread_mutex_unlock): Likewise.
+	(pthread_mutex_trylock): Likewise.
+
+	* tests/mutex3.c: New file; test for the static initialisation
+	macro. Passes.
+
+	* tests/create1.c: New file; test pthread_create(). Passes.
+	
+	* tests/equal.c: Poor test; remove.
+	
+	* tests/equal1.c New file; test pthread_equal(). Passes.
+
+	* tests/once1.c: New file; test for pthread_once(). Passes.
+
+	* tests/self.c: Remove; rename to self1.c.
+
+	* tests/self1.c: This is the old self.c.
+
+	* tests/self2.c: New file. Test pthread_self() with a single
+	thread. Passes.
+
+	* tests/self3.c: New file. Test pthread_self() with a couple of
+	threads to ensure their thread IDs differ. Passes.
+	
+1998-10-04  Ben Elliston  <bje at cygnus.com>
+
+	* tests/mutex2.c: Test pthread_mutex_trylock(). Passes.
+
+	* tests/mutex1.c: New basic test for mutex functions (it passes).
+	(main): Eliminate warning.
+
+	* configure.in: Test for __stdcall, not _stdcall. Typo.
+
+	* configure: Regenerate.
+
+	* attr.c (pthread_attr_setstackaddr): Remove FIXME comment. Win32
+	does know about ENOSYS after all.
+	(pthread_attr_setstackaddr): Likewise.
+
+1998-10-03  Ben Elliston  <bje at cygnus.com>
+
+	* configure.in: Test for the `_stdcall' keyword.  Define `STDCALL'
+	to `_stdcall' if we have it, null otherwise.
+
+	* configure: Regenerate.
+
+	* acconfig.h (STDCALL): New define.
+
+	* config.h.in: Regenerate.
+
+	* create.c (ptw32_start_call): Add STDCALL prefix.
+	
+	* mutex.c (pthread_mutex_init): Correct function signature.
+
+	* attr.c (pthread_attr_init): Only zero out the `sigmask' member
+	if we have the sigset_t type.
+
+	* pthread.h: No need to include <unistd.h>.  It doesn't even exist
+	on Win32! Again, an artifact of cross-compilation.	
+	(pthread_sigmask): Only provide if we have the sigset_t type.
+
+	* process.h: Remove. This was a stand-in before we started doing
+	native compilation under Win32.
+
+	* pthread.h (pthread_mutex_init): Make `attr' argument const.
+
+1998-10-02  Ben Elliston  <bje at cygnus.com>
+
+	* COPYING: Remove.
+
+	* COPYING.LIB: Add. This library is under the LGPL.
+
+1998-09-13  Ben Elliston  <bje at cygnus.com>
+
+	* configure.in: Test for required system features.
+
+	* configure: Generate. 
+
+	* acconfig.h: New file.
+
+	* config.h.in: Generate.
+
+	* Makefile.in: Renamed from Makefile.
+
+	* COPYING: Import from a recent GNU package.
+
+	* config.guess: Likewise.
+
+	* config.sub: Likewise.
+
+	* install-sh: Likewise.
+
+	* config.h: Remove.  
+
+	* Makefile: Likewise.
+
+1998-09-12  Ben Elliston  <bje at cygnus.com>
+
+	* windows.h: No longer needed; remove.
+
+	* windows.c: Likewise.
+
+Sat Sep 12 20:09:24 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* windows.h: Remove error number definitions. These are in <errno.h>
+	
+	* tsd.c: Add comment explaining rationale for not building
+	POSIX TSD on top of Win32 TLS.
+
+1998-09-12  Ben Elliston  <bje at cygnus.com>
+
+	* {most}.c: Include <errno.h> to get POSIX error values.
+
+	* signal.c (pthread_sigmask): Only provide if HAVE_SIGSET_T is
+	defined.
+ 
+	* config.h: #undef features, don't #define them.  This will be
+	generated by autoconf very soon.
+	
+1998-08-11  Ben Elliston  <bje at cygnus.com>
+
+	* Makefile (LIB): Define.
+	(clean): Define target.
+	(all): Build a library not just the object files.
+
+	* pthread.h: Provide a definition for struct timespec if we don't
+	already have one.
+
+	* windows.c (TlsGetValue): Bug fix.
+	
+Thu Aug  6 15:19:22 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* misc.c (pthread_once): Fix arg 1 of EnterCriticalSection()
+ 	and LeaveCriticalSection() calls to pass address-of lock.
+
+	* fork.c (pthread_atfork): Typecast (void (*)(void *)) funcptr
+	in each ptw32_handler_push() call.
+
+	* exit.c (ptw32_exit): Fix attr arg in 
+	pthread_attr_getdetachstate() call.
+
+	* private.c (ptw32_new_thread): Typecast (HANDLE) NULL.
+	(ptw32_delete_thread): Ditto.
+
+	* implement.h: (PTW32_MAX_THREADS): Add define. This keeps
+	changing in an attempt to make thread administration data types
+	opaque and cleanup DLL startup.
+
+	* dll.c (PthreadsEntryPoint): 
+	(ptw32_virgins): Remove malloc() and free() calls.
+	(ptw32_reuse): Ditto.
+	(ptw32_win32handle_map): Ditto.
+	(ptw32_threads_mutex_table): Ditto.
+
+	* global.c (_POSIX_THREAD_THREADS_MAX): Initialise with 
+	PTW32_MAX_THREADS.
+	(ptw32_virgins): Ditto.
+	(ptw32_reuse): Ditto.
+	(ptw32_win32handle_map): Ditto.
+	(ptw32_threads_mutex_table): Ditto.
+
+	* create.c (pthread_create): Typecast (HANDLE) NULL.
+	Typecast (unsigned (*)(void *)) start_routine.
+
+	* condvar.c (pthread_cond_init): Add address-of operator & to
+	arg 1 of pthread_mutex_init() call.
+	(pthread_cond_destroy): Add address-of operator & to
+	arg 1 of pthread_mutex_destroy() call. 
+
+	* cleanup.c (ptw32_destructor_pop_all): Add (int) cast to 
+	pthread_getspecific() arg.
+	(ptw32_destructor_pop): Add (void *) cast to "if" conditional.
+	(ptw32_destructor_push): Add (void *) cast to
+	ptw32_handler_push() "key" arg.
+	(malloc.h): Add include.
+
+	* implement.h (ptw32_destructor_pop): Add prototype.
+
+	* tsd.c (implement.h): Add include.
+
+	* sync.c (pthread_join): Remove target_thread_mutex and it's
+	initialisation. Rename getdetachedstate to getdetachstate.
+	Remove unused variable "exitcode".
+	(pthread_detach): Remove target_thread_mutex and it's
+	initialisation. Rename getdetachedstate to getdetachstate.
+	Rename setdetachedstate to setdetachstate.
+
+	* signal.c (pthread_sigmask): Rename SIG_SET to SIG_SETMASK.
+	Cast "set" to (long *) in assignment to passify compiler warning.
+	Add address-of operator & to thread->attr.sigmask in memcpy() call
+	and assignment.
+	(pthread_sigmask): Add address-of operator & to thread->attr.sigmask
+	in memcpy() call and assignment.
+
+	* windows.h (THREAD_PRIORITY_ERROR_RETURN): Add.
+	(THREAD_PRIORITY_LOWEST): Add.
+	(THREAD_PRIORITY_HIGHEST): Add.
+
+	* sched.c (is_attr): Add function.
+	(implement.h): Add include.
+	(pthread_setschedparam): Rename all instances of "sched_policy"
+	to "sched_priority".
+	(pthread_getschedparam): Ditto.
+
+Tue Aug  4 16:57:58 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* private.c (ptw32_delete_thread): Fix typo. Add missing ';'.
+
+	* global.c (ptw32_virgins): Change types from pointer to 
+	array pointer.
+	(ptw32_reuse): Ditto.
+	(ptw32_win32handle_map): Ditto.
+	(ptw32_threads_mutex_table): Ditto.
+
+	* implement.h(ptw32_virgins): Change types from pointer to 
+	array pointer.
+	(ptw32_reuse): Ditto.
+	(ptw32_win32handle_map): Ditto.
+	(ptw32_threads_mutex_table): Ditto.
+
+	* private.c (ptw32_delete_thread): Fix "entry" should be "thread".
+
+	* misc.c (pthread_self): Add extern for ptw32_threadID_TlsIndex.
+
+	* global.c: Add comment.
+
+	* misc.c (pthread_once): Fix member -> dereferences.
+	Change ptw32_once_flag to once_control->flag in "if" test.
+
+Tue Aug  4 00:09:30 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h(ptw32_virgins): Add extern.
+	(ptw32_virgin_next): Ditto.
+	(ptw32_reuse): Ditto.
+	(ptw32_reuse_top): Ditto.
+	(ptw32_win32handle_map): Ditto.
+	(ptw32_threads_mutex_table): Ditto.
+
+	* global.c (ptw32_virgins): Changed from array to pointer.
+	Storage allocation for the array moved into dll.c.
+	(ptw32_reuse): Ditto.
+	(ptw32_win32handle_map): Ditto.
+	(ptw32_threads_mutex_table): Ditto.
+
+	* dll.c (PthreadsEntryPoint): Set up thread admin storage when
+	DLL is loaded.
+
+	* fork.c (pthread_atfork): Fix function pointer arg to all
+	ptw32_handler_push() calls. Change "arg" arg to NULL in child push.
+
+	* exit.c: Add windows.h and process.h includes.
+	(ptw32_exit): Add local detachstate declaration.
+	(ptw32_exit): Fix incorrect name for pthread_attr_getdetachstate().
+
+	* pthread.h (_POSIX_THREAD_ATTR_STACKSIZE): Move from global.c
+	(_POSIX_THREAD_ATTR_STACKADDR): Ditto.
+
+	* create.c (pthread_create): Fix #if should be #ifdef.
+	(ptw32_start_call): Remove usused variables.
+
+	* process.h: Create.
+
+	* windows.h: Move _beginthreadex and _endthreadex into
+	process.h
+
+Mon Aug  3 21:19:57 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* condvar.c (pthread_cond_init): Add NULL attr to
+	pthread_mutex_init() call - default attributes will be used.
+	(cond_wait): Fix typo.
+	(cond_wait): Fix typo - cv was ev.
+	(pthread_cond_broadcast): Fix two identical typos.
+
+	* cleanup.c (ptw32_destructor_pop_all): Remove _ prefix from
+	PTHREAD_DESTRUCTOR_ITERATIONS.
+
+	* pthread.h: Move _POSIX_* values into posix.h
+
+	* pthread.h: Fix typo in pthread_mutex_init() prototype.
+
+	* attr.c (pthread_attr_init): Fix error in priority member init.
+
+	* windows.h (THREAD_PRIORITY_NORMAL): Add.
+
+	* pthread.h (sched_param): Add missing ';' to struct definition. 
+
+	* attr.c (pthread_attr_init): Remove obsolete pthread_attr_t
+	member initialisation - cancelstate, canceltype, cancel_pending.
+	(is_attr): Make arg "attr" a const.
+
+	* implement.h (PTW32_HANDLER_POP_LIFO): Remove definition.
+	(PTW32_HANDLER_POP_FIFO): Ditto.
+	(PTW32_VALID): Add missing newline escape (\).
+	(ptw32_handler_node): Make element "next" a pointer.
+
+1998-08-02  Ben Elliston  <bje at cygnus.com>
+
+	* windows.h: Remove duplicate TlsSetValue() prototype.  Add 
+	TlsGetValue() prototype.
+	(FALSE): Define.
+	(TRUE): Likewise.
+	Add forgotten errno values.  Guard against multiple #includes.
+
+	* windows.c: New file.  Implement stubs for Win32 functions.
+
+	* Makefile (SRCS): Remove.  Not explicitly needed.
+	(CFLAGS): Add -Wall for all warnings with GCC.
+
+Sun Aug  2 19:03:42 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* config.h: Create. This is a temporary stand-in for autoconf yet
+	to be done.
+ 	(HAVE_SIGNAL_H): Add.
+
+	* pthread.h: Minor rearrangement for temporary config.h.
+
+Fri Jul 31 14:00:29 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* cleanup.c (ptw32_destructor_pop): Implement. Removes
+	destructors associated with a key without executing them.
+	(ptw32_destructor_pop_all): Add FIXME comment.
+
+	* tsd.c (pthread_key_delete): Add call to ptw32_destructor_pop().
+
+Fri Jul 31 00:05:45 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* tsd.c (pthread_key_create): Update to properly associate
+	the destructor routine with the key.
+	(pthread_key_delete): Add FIXME comment.
+
+	* exit.c (ptw32_vacuum): Add call to
+	ptw32_destructor_pop_all().
+
+	* implement.h (ptw32_handler_pop_all): Add prototype.
+	(ptw32_destructor_pop_all): Ditto.
+
+	* cleanup.c (ptw32_destructor_push): Implement. This is just a
+	call to ptw32_handler_push().
+	(ptw32_destructor_pop_all): Implement. This is significantly
+	different to ptw32_handler_pop_all().
+
+	* Makefile (SRCS): Create. Preliminary.
+
+	* windows.h: Create. Contains Win32 definitions for compile
+	testing. This is just a standin for the real one.
+
+	* pthread.h (SIG_UNBLOCK): Fix typo. Was SIG_BLOCK.
+	(windows.h): Add include. Required for CRITICAL_SECTION.
+	(pthread_cond_t): Move enum declaration outside of struct
+	definition.
+	(unistd.h): Add include - may be temporary.
+
+	* condvar.c (windows.h): Add include.
+
+	* implement.h (PTW32_THIS): Remove - no longer required.
+	(PTW32_STACK): Use pthread_self() instead of PTW32_THIS.
+
+Thu Jul 30 23:12:45 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Remove ptw32_find_entry() prototype.
+
+	* private.c: Extend comments.
+	Remove ptw32_find_entry() - no longer needed.
+
+	* create.c (ptw32_start_call): Add call to TlsSetValue() to
+	store the thread ID.
+
+	* dll.c (PthreadsEntryPoint): Implement. This is called
+	whenever a process loads the DLL. Used to initialise thread
+	local storage.
+
+	* implement.h: Add ptw32_threadID_TlsIndex.
+	Add ()s around PTW32_VALID expression.
+
+	* misc.c (pthread_self): Re-implement using Win32 TLS to store
+	the threads own ID.
+
+Wed Jul 29 11:39:03 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c: Corrections in comments.
+	(ptw32_new_thread): Alter "if" flow to be more natural.
+
+	* cleanup.c (ptw32_handler_push): Same as below.
+
+	* create.c (pthread_create): Same as below.
+
+	* private.c (ptw32_new_thread): Rename "new" to "new_thread".
+	Since when has a C programmer been required to know C++?
+
+Tue Jul 28 14:04:29 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* implement.h: Add PTW32_VALID macro.
+
+	* sync.c (pthread_join): Modify to use the new thread
+	type and ptw32_delete_thread(). Rename "target" to "thread".
+	Remove extra local variable "target".
+	(pthread_detach): Ditto.
+
+	* signal.c (pthread_sigmask): Move init of "us" out of inner block.
+	Fix instance of "this" should have been "us". Rename "us" to "thread".
+
+	* sched.c (pthread_setschedparam): Modify to use the new thread
+	type.
+	(pthread_getschedparam): Ditto.
+
+	* private.c (ptw32_find_thread): Fix return type and arg.
+
+	* implement.h: Remove PTW32_YES and PTW32_NO.
+	(ptw32_new_thread): Add prototype.
+	(ptw32_find_thread): Ditto.
+	(ptw32_delete_thread): Ditto.
+	(ptw32_new_thread_entry): Remove prototype.
+	(ptw32_find_thread_entry): Ditto.
+	(ptw32_delete_thread_entry): Ditto.
+	(  PTW32_NEW, PTW32_INUSE, PTW32_EXITED, PTW32_REUSE):
+	Add.
+
+
+	* create.c (pthread_create): Minor rename "us" to "new" (I need
+	these cues but it doesn't stop me coming out with some major bugs
+	at times).
+	Load start_routine and arg into the thread so the wrapper can
+	call it.
+
+	* exit.c (pthread_exit): Fix pthread_this should be pthread_self.
+
+	* cancel.c (pthread_setcancelstate): Change
+ 	ptw32_threads_thread_t * to pthread_t and init with
+ 	pthread_this().
+	(pthread_setcanceltype): Ditto.
+
+	* exit.c (ptw32_exit): Add new pthread_t arg.
+	Rename ptw32_delete_thread_entry to ptw32_delete_thread.
+	Rename "us" to "thread".
+	(pthread_exit): Call ptw32_exit with added thread arg.
+
+	* create.c (ptw32_start_call): Insert missing ")".
+	Add "us" arg to ptw32_exit() call.
+	(pthread_create): Modify to use new thread allocation scheme.
+
+	* private.c: Added detailed explanation of the new thread
+	allocation scheme.
+	(ptw32_new_thread): Totally rewritten to use
+	new thread allocation scheme.
+	(ptw32_delete_thread): Ditto.
+	(ptw32_find_thread): Obsolete.
+
+Mon Jul 27 17:46:37 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* create.c (pthread_create): Start of rewrite. Not completed yet.
+
+	* private.c (ptw32_new_thread_entry): Start of rewrite. Not
+	complete.
+
+	* implement.h (ptw32_threads_thread): Rename, remove thread
+	member, add win32handle and ptstatus members.
+	(ptw32_t): Add.
+
+	* pthread.h: pthread_t is no longer mapped directly to a Win32
+	HANDLE type. This is so we can let the Win32 thread terminate and
+	reuse the HANDLE while pthreads holds it's own thread ID until
+	the last waiting join exits.
+
+Mon Jul 27 00:20:37 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_delete_thread_entry): Destroy the thread
+ 	entry attribute object before deleting the thread entry itself.
+
+	* attr.c (pthread_attr_init): Initialise cancel_pending = FALSE.
+	(pthread_attr_setdetachstate): Rename "detached" to "detachedstate".
+	(pthread_attr_getdetachstate): Ditto.
+
+	* exit.c (ptw32_exit): Fix incorrect check for detachedstate.
+
+	* implement.h (ptw32_call_t): Remove env member. 
+
+Sun Jul 26 13:06:12 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h (ptw32_new_thread_entry): Fix prototype.
+	(ptw32_find_thread_entry): Ditto.
+	(ptw32_delete_thread_entry): Ditto.
+	(ptw32_exit): Add prototype.
+
+	* exit.c (ptw32_exit): New function. Called from pthread_exit()
+	and ptw32_start_call() to exit the thread. It allows an extra
+	argument which is the return code passed to _endthreadex().
+	(ptw32_exit): Move thread entry delete call from ptw32_vacuum()
+	into here. Add more explanation of thread entry deletion.
+	(ptw32_exit): Clarify comment.
+
+	* create.c (ptw32_start_call): Change pthread_exit() call to
+	ptw32_exit() call.
+
+	* exit.c (ptw32_vacuum): Add thread entry deletion code
+	moved from ptw32_start_call(). See next item.
+	(pthread_exit): Remove longjmp(). Add mutex lock around thread table
+	manipulation code. This routine now calls _enthreadex().
+
+	* create.c (ptw32_start_call): Remove setjmp() call and move
+	cleanup code out. Call pthread_exit(NULL) to terminate the thread.
+
+1998-07-26  Ben Elliston  <bje at cygnus.com>
+
+	* tsd.c (pthread_getspecific): Update comments.
+
+	* mutex.c (pthread_mutexattr_setpshared): Not supported; remove.
+	(pthread_mutexattr_getpshared): Likewise.
+
+	* pthread.h (pthread_mutexattr_setpshared): Remove prototype.
+	(pthread_mutexattr_getpshared): Likewise.
+
+Sun Jul 26 00:09:59 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sync.c: Rename all instances of ptw32_count_mutex to
+	ptw32_table_mutex.
+
+	* implement.h: Rename ptw32_count_mutex to
+	ptw32_table_mutex.
+
+	* global.c: Rename ptw32_count_mutex to
+	ptw32_table_mutex.
+
+	* create.c (pthread_create): Add critical sections.
+	(ptw32_start_call): Rename ptw32_count_mutex to
+	ptw32_table_mutex.
+
+	* cancel.c (pthread_setcancelstate): Fix indirection bug and rename
+	"this" to "us".
+
+	* signal.c (pthread_sigmask): Rename "this" to "us" and fix some
+	minor syntax errors. Declare "us" and initialise it.
+
+	* sync.c (pthread_detach): Rename "this" to "target".
+
+	* pthread.h: Converting PTHREAD_* defines to alias the (const int)
+	values in global.c.
+
+	* global.c: Started converting PTHREAD_* defines to (const int) as
+ 	a part of making the eventual pthreads DLL binary compatible
+ 	through version changes.
+
+	* condvar.c (cond_wait): Add cancelation point. This applies the
+	point to both pthread_cond_wait() and pthread_cond_timedwait().
+
+	* exit.c (pthread_exit): Rename "this" to "us".
+
+	* implement.h: Add comment.
+
+	* sync.c (pthread_join): I've satisfied myself that pthread_detach()
+	does set the detached attribute in the thread entry attributes
+	to PTHREAD_CREATE_DETACHED. "if" conditions were changed to test
+	that attribute instead of a separate flag.
+
+	* create.c (pthread_create): Rename "this" to "us".
+	(pthread_create): cancelstate and canceltype are not attributes
+	so the copy to thread entry attribute storage was removed.
+	Only the thread itself can change it's cancelstate or canceltype,
+	ie. the thread must exist already.
+
+	* private.c (ptw32_delete_thread_entry): Mutex locks removed.
+	Mutexes must be applied at the caller level.
+	(ptw32_new_thread_entry): Ditto.
+	(ptw32_new_thread_entry): Init cancelstate, canceltype, and
+	cancel_pending to default values.
+	(ptw32_new_thread_entry): Rename "this" to "new".
+	(ptw32_find_thread_entry): Rename "this" to "entry".
+	(ptw32_delete_thread_entry): Rename "thread_entry" to "entry".
+
+	* create.c (ptw32_start_call): Mutexes changed to
+	ptw32_count_mutex. All access to the threads table entries is
+	under the one mutex. Otherwise chaos reigns.
+
+Sat Jul 25 23:16:51 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h (ptw32_threads_thread): Move cancelstate and
+ 	canceltype members out of pthread_attr_t into here.
+
+	* fork.c (fork): Add comment.
+
+1998-07-25  Ben Elliston  <bje at cygnus.com>
+
+	* fork.c (fork): Autoconfiscate.
+
+Sat Jul 25 00:00:13 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* create.c (ptw32_start_call): Set thread priority.  Ensure our
+ 	thread entry is removed from the thread table but only if
+ 	pthread_detach() was called and there are no waiting joins.
+	(pthread_create): Set detach flag in thread entry if the 
+	thread is created PTHREAD_CREATE_DETACHED.
+
+	* pthread.h (pthread_attr_t): Rename member "detachedstate".
+
+	* attr.c (pthread_attr_init): Rename attr members.
+
+	* exit.c (pthread_exit): Fix indirection mistake.
+
+	* implement.h (PTW32_THREADS_TABLE_INDEX): Add.
+
+	* exit.c (ptw32_vacuum): Fix incorrect args to
+	ptw32_handler_pop_all() calls.
+	Make thread entry removal conditional.
+
+	* sync.c (pthread_join): Add multiple join and async detach handling.
+
+	* implement.h (PTW32_THREADS_TABLE_INDEX): Add.
+
+	* global.c (ptw32_threads_mutex_table): Add.
+
+	* implement.h (ptw32_once_flag): Remove.
+	(ptw32_once_lock): Ditto.
+	(ptw32_threads_mutex_table): Add.
+
+	* global.c (ptw32_once_flag): Remove.
+	(ptw32_once_lock): Ditto.
+
+	* sync.c (pthread_join): Fix tests involving new return value
+	from ptw32_find_thread_entry().
+	(pthread_detach): Ditto.
+
+	* private.c (ptw32_find_thread_entry): Failure return code
+	changed from -1 to NULL.
+
+Fri Jul 24 23:09:33 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* create.c (pthread_create): Change . to -> in sigmask memcpy() args.
+
+	* pthread.h: (pthread_cancel): Add function prototype.
+	(pthread_testcancel): Ditto.
+
+1998-07-24  Ben Elliston  <bje at cygnus.com>
+
+	* pthread.h (pthread_condattr_t): Rename dummy structure member.
+	(pthread_mutexattr_t): Likewise.
+
+Fri Jul 24 21:13:55 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* cancel.c (pthread_cancel): Implement.
+	(pthread_testcancel): Implement.
+
+	* exit.c (pthread_exit): Add comment explaining the longjmp().
+
+	* implement.h (ptw32_threads_thread_t): New member cancelthread.
+	(PTW32_YES): Define.
+	(PTW32_NO): Define.
+	(RND_SIZEOF): Remove.
+
+	* create.c (pthread_create): Rename cancelability to cancelstate.
+
+	* pthread.h (pthread_attr_t): Rename cancelability to cancelstate.
+	(PTHREAD_CANCELED): Define.
+
+1998-07-24  Ben Elliston  <bje at cygnus.com>
+
+	* pthread.h (SIG_BLOCK): Define if not already defined.
+	(SIG_UNBLOCK): Likewise.
+	(SIG_SETMASK): Likewise.
+	(pthread_attr_t): Add signal mask member.
+	(pthread_sigmask): Add function prototype.
+
+	* signal.c (pthread_sigmask): Implement.
+
+	* create.c: #include <string.h> to get a prototype for memcpy().
+	(pthread_create): New threads inherit their creator's signal
+	mask.  Copy the signal mask to the new thread structure if we know
+	about signals.
+	
+Fri Jul 24 16:33:17 1998  Ross Johnson  <rpj at swan.canberra.edu.au>
+
+	* fork.c (pthread_atfork): Add all the necessary push calls.
+	Local implementation semantics:
+	If we get an ENOMEM at any time then ALL handlers
+	(including those from previous pthread_atfork() calls) will be
+	popped off each of the three atfork stacks before we return.
+	(fork): Add all the necessary pop calls. Add the thread cancellation
+	and join calls to the child fork.
+	Add #includes.
+
+	* implement.h: (ptw32_handler_push): Fix return type and stack arg
+	type in prototype.
+	(ptw32_handler_pop): Fix stack arg type in prototype.
+	(ptw32_handler_pop_all): Fix stack arg type in prototype.
+
+	* cleanup.c (ptw32_handler_push): Change return type to int and
+	return ENOMEM if malloc() fails.
+
+	* sync.c (pthread_detach): Use equality test, not assignment.
+
+	* create.c (ptw32_start_call): Add call to Win32 CloseHandle()
+	if thread is detached.
+
+1998-07-24  Ben Elliston  <bje at cygnus.com>
+
+	* sync.c (pthread_detach): Close the Win32 thread handle to
+	emulate detached (or daemon) threads.
+
+Fri Jul 24 03:00:25 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sync.c (pthread_join): Save valueptr arg in joinvalueptr for
+	pthread_exit() to use.
+
+	* private.c (ptw32_new_thread_entry): Initialise joinvalueptr to
+	NULL.
+
+	* create.c (ptw32_start_call): Rewrite to facilitate joins.
+	pthread_exit() will do a longjmp() back to here. Does appropriate
+	cleanup and exit/return from the thread.
+	(pthread_create): _beginthreadex() now passes a pointer to our
+	thread table entry instead of just the call member of that entry.
+
+	* implement.h (ptw32_threads_thread): New member 
+	void ** joinvalueptr.
+	(ptw32_call_t): New member jmpbuf env.
+
+	* exit.c (pthread_exit): Major rewrite to handle joins and handing
+	value pointer to joining thread. Uses longjmp() back to 
+	ptw32_start_call().
+
+	* create.c (pthread_create): Ensure values of new attribute members
+	are copied to the thread attribute object.
+
+	* attr.c (pthread_attr_destroy):  Fix merge conflicts.
+	(pthread_attr_getdetachstate):  Fix merge conflicts.
+	(pthread_attr_setdetachstate):  Fix merge conflicts.
+
+	* pthread.h:  Fix merge conflicts.
+
+	* sync.c (pthread_join): Fix merge conflicts.
+
+Fri Jul 24 00:21:21 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* sync.c (pthread_join): Add check for valid and joinable
+	thread.
+	(pthread_detach): Implement. After checking for a valid and joinable
+	thread, it's still a no-op.
+
+	* private.c (ptw32_find_thread_entry): Bug prevented returning
+	an error value in some cases.
+
+	* attr.c (pthread_attr_setdetachedstate): Implement.
+	(pthread_attr_getdetachedstate): Implement.
+
+	* implement.h: Move more hidden definitions into here from
+	pthread.h.
+
+1998-07-24  Ben Elliston  <bje at cygnus.com>
+
+	* pthread.h (PTHREAD_CREATE_JOINABLE): Define.
+	(PTHREAD_CREATE_DETACHED): Likewise.
+	(pthread_attr_t): Add new structure member `detached'.
+	(pthread_attr_getdetachstate): Add function prototype.
+	(pthread_attr_setdetachstate): Likewise.
+
+	* sync.c (pthread_join): Return if the target thread is detached.
+
+	* attr.c (pthread_attr_init): Initialise cancelability and
+	canceltype structure members.
+	(pthread_attr_getdetachstate): Implement.
+	(pthread_attr_setdetachstate): Likewise.
+
+	* implement.h (PTW32_CANCEL_DEFAULTS): Remove.  Bit fields
+	proved to be too cumbersome.  Set the defaults in attr.c using the
+	public PTHREAD_CANCEL_* constants.
+
+	* cancel.c: New file.
+
+	* pthread.h (sched_param): Define this type.
+	(pthread_attr_getschedparam): Add function prototype.
+	(pthread_attr_setschedparam): Likewise.
+	(pthread_setcancelstate): Likewise.
+	(pthread_setcanceltype): Likewise.
+	(sched_get_priority_min): Likewise.
+	(sched_get_priority_max): Likewise.
+	(pthread_mutexattr_setprotocol): Remove; not supported.
+	(pthread_mutexattr_getprotocol): Likewise.
+	(pthread_mutexattr_setprioceiling): Likewise.
+	(pthread_mutexattr_getprioceiling): Likewise.
+	(pthread_attr_t): Add canceltype member.  Update comments.
+	(SCHED_OTHER): Define this scheduling policy constant.
+	(SCHED_FIFO): Likewise.
+	(SCHED_RR): Likewise.
+	(SCHED_MIN): Define the lowest possible value for this constant.
+	(SCHED_MAX): Likewise, the maximum possible value.
+	(PTHREAD_CANCEL_ASYNCHRONOUS): Redefine.
+	(PTHREAD_CANCEL_DEFERRED): Likewise.
+	
+	* sched.c: New file.
+	(pthread_setschedparam): Implement.
+	(pthread_getschedparam): Implement.
+	(sched_get_priority_max): Validate policy argument.
+	(sched_get_priority_min): Likewise.
+
+	* mutex.c (pthread_mutexattr_setprotocol): Remove; not supported.
+	(pthread_mutexattr_getprotocol): Likewise.
+	(pthread_mutexattr_setprioceiling): Likewise.
+	(pthread_mutexattr_getprioceiling): Likewise.
+
+Fri Jul 24 00:21:21 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* create.c (pthread_create): Arg to ptw32_new_thread_entry()
+	changed. See next entry. Move mutex locks out. Changes made yesterday
+	and today allow us to start the new thread running rather than
+	temporarily suspended.
+
+	* private.c (ptw32_new_thread_entry): ptw32_thread_table
+	was changed back to a table of thread structures rather than pointers.
+	As such we're trading storage for increaded speed. This routine
+	was modified to work with the new table. Mutex lock put in around
+	global data accesses.
+	(ptw32_find_thread_entry): Ditto
+	(ptw32_delete_thread_entry): Ditto
+
+Thu Jul 23 23:25:30 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* global.c: New. Global data objects declared here. These moved from
+	pthread.h.
+
+	* pthread.h: Move implementation hidden definitions into
+	implement.h.
+
+	* implement.h: Move implementation hidden definitions from
+	pthread.h. Add constants to index into the different handler stacks.
+
+	* cleanup.c (ptw32_handler_push): Simplify args. Restructure.
+	(ptw32_handler_pop): Simplify args. Restructure.
+	(ptw32_handler_pop_all): Simplify args. Restructure.
+
+Wed Jul 22 00:16:22 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* attr.c, implement.h, pthread.h, ChangeLog: Resolve CVS merge
+	conflicts.
+
+	* private.c (ptw32_find_thread_entry): Changes to return type
+	to support leaner ptw32_threads_table[] which now only stores
+	ptw32_thread_thread_t *.
+	(ptw32_new_thread_entry): Internal changes.
+	(ptw32_delete_thread_entry): Internal changes to avoid contention.
+ 	Calling routines changed accordingly.
+
+	* pthread.h: Modified cleanup macros to use new generic push and pop.
+	Added destructor and atfork stacks to ptw32_threads_thread_t.
+
+	* cleanup.c (ptw32_handler_push, ptw32_handler_pop,
+	ptw32_handler_pop_all): Renamed cleanup push and pop routines
+	and made generic to handle destructors and atfork handlers as
+	well.
+
+	* create.c (ptw32_start_call): New function is a wrapper for
+	all new threads. It allows us to do some cleanup when the thread
+	returns, ie. that is otherwise only done if the thread is cancelled.
+
+	* exit.c (ptw32_vacuum): New function contains code from 
+	pthread_exit() that we need in the new ptw32_start_call()
+	as well.
+
+	* implement.h: Various additions and minor changes.
+
+	* pthread.h: Various additions and minor changes.
+	Change cleanup handler macros to use generic handler push and pop
+	functions.
+
+	* attr.c: Minor mods to all functions.
+	(is_attr): Implemented missing function.
+
+	* create.c (pthread_create): More clean up.
+
+	* private.c (ptw32_find_thread_entry): Implement.
+	(ptw32_delete_thread_entry): Implement.
+	(ptw32_new_thread_entry): Implement.
+	These functions manipulate the implementations internal thread
+	table and are part of general code cleanup and modularisation.
+	They replace ptw32_getthreadindex() which was removed.
+
+	* exit.c (pthread_exit): Changed to use the new code above.
+
+	* pthread.h: Add cancelability constants. Update comments.
+
+1998-07-22  Ben Elliston  <bje at cygnus.com>
+
+	* attr.c (pthread_setstacksize): Update test of attr argument.
+	(pthread_getstacksize): Likewise.
+	(pthread_setstackaddr): Likewise.
+	(pthread_getstackaddr): Likewise.
+	(pthread_attr_init): No need to allocate any storage.
+	(pthread_attr_destroy): No need to free any storage.
+
+	* mutex.c (is_attr): Not likely to be needed; remove.
+	(remove_attr): Likewise.
+	(insert_attr): Likewise.
+
+	* implement.h (ptw32_mutexattr_t): Moved to a public definition
+	in pthread.h.  There was little gain in hiding these details.
+	(ptw32_condattr_t): Likewise.
+	(ptw32_attr_t): Likewise.
+
+	* pthread.h (pthread_atfork): Add function prototype.
+	(pthread_attr_t): Moved here from implement.h.
+
+	* fork.c (pthread_atfork): Preliminary implementation.
+	(ptw32_fork): Likewise.
+
+Wed Jul 22 00:16:22 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* cleanup.c (ptw32_cleanup_push): Implement.
+	(ptw32_cleanup_pop): Implement.
+	(ptw32_do_cancellation): Implement.
+	These are private to the implementation. The real cleanup functions
+	are macros. See below.
+
+	* pthread.h (pthread_cleanup_push): Implement as a macro.
+	(pthread_cleanup_pop): Implement as a macro.
+	Because these are macros which start and end a block, the POSIX scoping
+	requirement is observed. See the comment in the file.
+
+	* exit.c (pthread_exit): Refine the code.
+
+	* create.c (pthread_create): Code cleanup.
+
+	* implement.h (RND_SIZEOF): Add RND_SIZEOF(T) to round sizeof(T)
+	up to multiple of DWORD.
+	Add function prototypes.
+
+	* private.c (ptw32_getthreadindex): "*thread" should have been 
+	"thread". Detect empty slot fail condition.
+
+1998-07-20  Ben Elliston  <bje at cygnus.com>
+
+	* misc.c (pthread_once): Implement.  Don't use a per-application
+	flag and mutex--make `pthread_once_t' contain these elements in
+	their structure.  The earlier version had incorrect semantics.
+	
+	* pthread.h (ptw32_once_flag): Add new variable.  Remove.
+	(ptw32_once_lock): Add new mutex lock to ensure integrity of
+	access to ptw32_once_flag.  Remove.
+	(pthread_once): Add function prototype.
+	(pthread_once_t): Define this type.
+	
+Mon Jul 20 02:31:05 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* private.c (ptw32_getthreadindex): Implement.
+
+	* pthread.h: Add application static data dependent on
+	_PTHREADS_BUILD_DLL define. This is needed to avoid allocating
+	non-sharable static data within the pthread DLL.
+
+	* implement.h: Add ptw32_cleanup_stack_t, ptw32_cleanup_node_t
+	and PTW32_HASH_INDEX.
+
+	* exit.c (pthread_exit): Begin work on cleanup and de-allocate
+	thread-private storage.
+
+	* create.c (pthread_create): Add thread to thread table.
+	Keep a thread-private copy of the attributes with default values
+	filled in when necessary. Same for the cleanup stack. Make 
+	pthread_create C run-time library friendly by using _beginthreadex()
+	instead of CreateThread(). Fix error returns.
+
+Sun Jul 19 16:26:23 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Rename pthreads_thread_count to ptw32_threads_count.
+	Create ptw32_threads_thread_t struct to keep thread specific data.
+
+	* create.c: Rename pthreads_thread_count to ptw32_threads_count.
+	(pthread_create): Handle errors from CreateThread().
+
+1998-07-19  Ben Elliston  <bje at cygnus.com>
+
+	* condvar.c (pthread_cond_wait): Generalise.  Moved from here ..
+	(cond_wait): To here.
+	(pthread_cond_timedwait): Implement; use generalised cond_wait().
+
+	* pthread.h (pthread_key_t): Define this type.
+	(pthread_key_create): Add function prototype.
+	(pthread_setspecific): Likewise.
+	(pthread_getspecific): Likwise.
+	(pthread_key_delete): Likewise.
+
+	* tsd.c (pthread_key_create): Implement.
+	(pthread_setspecific): Likewise.
+	(pthread_getspecific): Likewise.
+	(pthread_key_delete): Likewise.
+
+	* mutex.c (pthread_mutex_trylock): Return ENOSYS if this function
+	is called on a Win32 platform which is not Windows NT.
+
+1998-07-18  Ben Elliston  <bje at cygnus.com>
+
+	* condvar.c (pthread_condattr_init): Do not attempt to malloc any
+	storage; none is needed now that condattr_t is an empty struct.
+	(pthread_condattr_destory): Likewise; do not free storage.
+	(pthread_condattr_setpshared): No longer supported; return ENOSYS.
+	(pthread_condattr_getpshared): Likewise.
+	(pthread_cond_init): Implement with help from Douglas Schmidt.
+	Remember to initialise the cv's internal mutex.
+	(pthread_cond_wait): Likewise.
+	(pthread_cond_signal): Likewise.
+	(pthread_cond_broadcast): Likewise.
+	(pthread_cond_timedwait): Preliminary implementation, but I need
+	to see some API documentation for `WaitForMultipleObject'.
+	(pthread_destory): Implement.
+
+	* pthread.h (pthread_cond_init): Add function protoype.
+	(pthread_cond_broadcast): Likewise.
+	(pthread_cond_signal): Likewise.
+	(pthread_cond_timedwait): Likewise.
+	(pthread_cond_wait): Likewise.
+	(pthread_cond_destroy): Likewise.
+	(pthread_cond_t): Define this type.  Fix for u_int.  Do not assume
+	that the mutex contained withing the pthread_cond_t structure will
+	be a critical section.  Use our new POSIX type!
+
+	* implement.h (ptw32_condattr_t): Remove shared attribute.
+
+1998-07-17  Ben Elliston  <bje at cygnus.com>
+
+	* pthread.h (PTHREADS_PROCESS_PRIVATE): Remove.
+	(PTHREAD_PROCESS_SHARED): Likewise.  No support for mutexes shared
+	across processes for now.
+	(pthread_mutex_t): Use a Win32 CRITICAL_SECTION type for better
+	performance.
+	
+	* implement.h (ptw32_mutexattr_t): Remove shared attribute.
+	
+	* mutex.c (pthread_mutexattr_setpshared): This optional function
+	is no longer supported, since we want to implement POSIX mutex
+	variables using the much more efficient Win32 critical section
+	primitives.  Critical section objects in Win32 cannot be shared
+	between processes.
+	(pthread_mutexattr_getpshared): Likewise.
+	(pthread_mutexattr_init): No need to malloc any storage; the
+	attributes structure is now empty.
+	(pthread_mutexattr_destroy): This is now a nop.
+	(pthread_mutex_init): Use InitializeCriticalSection().
+	(pthread_mutex_destroy): Use DeleteCriticalSection().
+	(pthread_mutex_lock): Use EnterCriticalSection().
+	(pthread_mutex_trylock): Use TryEnterCriticalSection().  This is
+	not supported by Windows 9x, but trylock is a hack anyway, IMHO.
+	(pthread_mutex_unlock): Use LeaveCriticalSection().
+
+1998-07-14  Ben Elliston  <bje at cygnus.com>
+
+	* attr.c (pthread_attr_setstacksize): Implement.
+	(pthread_attr_getstacksize): Likewise.
+	(pthread_attr_setstackaddr): Likewise.
+	(pthread_attr_getstackaddr): Likewise.
+	(pthread_attr_init): Likewise.
+	(pthread_attr_destroy): Likewise.
+	
+	* condvar.c (pthread_condattr_init): Add `_cond' to function name.
+
+	* mutex.c (pthread_mutex_lock): Add `_mutex' to function name.
+	(pthread_mutex_trylock): Likewise.
+	(pthread_mutex_unlock): Likewise.
+
+	* pthread.h (pthread_condattr_setpshared): Fix typo.
+	(pthread_attr_init): Add function prototype.
+	(pthread_attr_destroy): Likewise.
+	(pthread_attr_setstacksize): Likewise.
+	(pthread_attr_getstacksize): Likewise.
+	(pthread_attr_setstackaddr): Likewise.
+	(pthread_attr_getstackaddr): Likewise.
+	
+Mon Jul 13 01:09:55 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Wrap in #ifndef _IMPLEMENT_H
+
+	* create.c (pthread_create): Map stacksize attr to Win32.
+
+	* mutex.c: Include implement.h
+
+1998-07-13  Ben Elliston  <bje at cygnus.com>
+
+	* condvar.c (pthread_condattr_init): Implement.
+	(pthread_condattr_destroy): Likewise.
+	(pthread_condattr_setpshared): Likewise.
+	(pthread_condattr_getpshared): Likewise.
+	
+	* implement.h (PTHREAD_THREADS_MAX): Remove trailing semicolon.
+	(PTHREAD_STACK_MIN): Specify; needs confirming.
+	(ptw32_attr_t): Define this type.
+	(ptw32_condattr_t): Likewise.
+
+	* pthread.h (pthread_mutex_t): Define this type.
+	(pthread_condattr_t): Likewise.
+	(pthread_mutex_destroy): Add function prototype.
+	(pthread_lock): Likewise.
+	(pthread_trylock): Likewise.
+	(pthread_unlock): Likewise.
+	(pthread_condattr_init): Likewise.
+	(pthread_condattr_destroy): Likewise.
+	(pthread_condattr_setpshared): Likewise.
+	(pthread_condattr_getpshared): Likewise.
+
+	* mutex.c (pthread_mutex_init): Implement.
+	(pthread_mutex_destroy): Likewise.
+	(pthread_lock): Likewise.
+	(pthread_trylock): Likewise.
+	(pthread_unlock): Likewise.
+
+1998-07-12  Ben Elliston  <bje at cygnus.com>
+
+	* implement.h (ptw32_mutexattr_t): Define this implementation
+	internal type.  Application programmers only see a mutex attribute
+	object as a void pointer.
+
+	* pthread.h (pthread_mutexattr_t): Define this type.
+	(pthread_mutexattr_init): Add function prototype.
+	(pthread_mutexattr_destroy): Likewise.
+	(pthread_mutexattr_setpshared): Likewise.
+	(pthread_mutexattr_getpshared): Likewise.
+	(pthread_mutexattr_setprotocol): Likewise.
+	(pthread_mutexattr_getprotocol): Likewise.
+	(pthread_mutexattr_setprioceiling): Likewise.
+	(pthread_mutexattr_getprioceiling): Likewise.
+	(PTHREAD_PROCESS_PRIVATE): Define.
+	(PTHREAD_PROCESS_SHARED): Define.
+
+	* mutex.c (pthread_mutexattr_init): Implement.
+	(pthread_mutexattr_destroy): Implement.
+	(pthread_mutexattr_setprotocol): Implement.
+	(pthread_mutexattr_getprotocol): Likewise.
+	(pthread_mutexattr_setprioceiling): Likewise.
+	(pthread_mutexattr_getprioceiling): Likewise.
+	(pthread_mutexattr_setpshared): Likewise.
+	(pthread_mutexattr_getpshared): Likewise.
+	(insert_attr): New function; very preliminary implementation!
+	(is_attr): Likewise.
+	(remove_attr): Likewise.
+	
+Sat Jul 11 14:48:54 1998  Ross Johnson  <rpj at ixobrychus.canberra.edu.au>
+
+	* implement.h: Preliminary implementation specific defines.
+
+	* create.c (pthread_create): Preliminary implementation.
+
+1998-07-11  Ben Elliston  <bje at cygnus.com>
+
+	* sync.c (pthread_join): Implement.
+
+	* misc.c (pthread_equal): Likewise.
+	
+	* pthread.h (pthread_join): Add function prototype.
+	(pthread_equal): Likewise.
+	
+1998-07-10  Ben Elliston  <bje at cygnus.com>
+
+	* misc.c (pthread_self): Implement.
+
+	* exit.c (pthread_exit): Implement.
+
+	* pthread.h (pthread_exit): Add function prototype.
+	(pthread_self): Likewise.
+	(pthread_t): Define this type.
+
+1998-07-09  Ben Elliston  <bje at cygnus.com>
+
+	* create.c (pthread_create): A dummy stub right now.
+
+	* pthread.h (pthread_create): Add function prototype.
diff --git a/FAQ b/FAQ
index ee8968b..4f2d449 100644
--- a/FAQ
+++ b/FAQ
@@ -1,403 +1,403 @@
-		  =========================================
-		  PTHREADS-WIN32 Frequently Asked Questions
-		  =========================================
-
-INDEX
------
-
-Q 1	What is it?
-
-Q 2	Which of the several dll versions do I use?
-	or,
-	What are all these pthread*.dll and pthread*.lib files?
-
-Q 3	What is the library naming convention?
-
-Q 4	Cleanup code default style or: it used to work when I built
-	the library myself, but now it doesn't - why?
-
-Q 5	Why is the default library version now less exception-friendly?
-
-Q 6	Should I use Cygwin or Mingw32 as a development environment?
-
-Q 7	Now that pthreads-win32 builds under Mingw32, why do I get
-	memory access violations (segfaults)?
-
-Q 8	How do I use pthread.dll for Win32 (Visual C++ 5.0)
-
-Q 9	Cancelation doesn't work for me, why?
-
-Q 10	How do I generate pthreadGCE.dll and libpthreadw32.a for use
-	with Mingw32?
-
-=============================================================================
-
-Q 1	What is it?
----
-
-Pthreads-win32 is an Open Source Software implementation of the
-Threads component of the POSIX 1003.1c 1995 Standard for Microsoft's
-Win32 environment. Some functions from POSIX 1003.1b are also
-supported including semaphores. Other related functions include
-the set of read-write lock functions. The library also supports
-some of the functionality of the Open Group's Single Unix
-specification, version 2, namely mutex types.
-
-See the file "ANNOUNCE" for more information including standards
-conformance details and list of supported routines.
-
-
-------------------------------------------------------------------------------
-
-Q 2	Which of the several dll versions do I use?
----	or,
-	What are all these pthread*.dll and pthread*.lib files?
-
-Simply, you only use one of them, but you need to choose carefully.
-
-The most important choice you need to make is whether to use a
-version that uses exceptions internally, or not (there are versions
-of the library that use exceptions as part of the thread
-cancelation and cleanup implementation, and one that uses
-setjmp/longjmp instead).
-
-There is some contension amongst POSIX threads experts as
-to how POSIX threads cancelation and exit should work
-with languages that include exceptions and handlers, e.g.
-C++ and even C (Microsoft's Structured Exceptions).
-
-The issue is: should cancelation of a thread in, say,
-a C++ application cause object destructors and C++ exception
-handlers to be invoked as the stack unwinds during thread
-exit, or not?
-
-There seems to be more opinion in favour of using the
-standard C version of the library (no EH) with C++ applications
-since this appears to be the assumption commercial pthreads
-implementations make. Therefore, if you use an EH version
-of pthreads-win32 then you may be under the illusion that
-your application will be portable, when in fact it is likely to
-behave very differently linked with other pthreads libraries.
-
-Now you may be asking: why have you kept the EH versions of
-the library?
-
-There are a couple of reasons:
-- there is division amongst the experts and so the code may
-  be needed in the future. (Yes, it's in the repository and we
-  can get it out anytime in the future, but ...)
-- pthreads-win32 is one of the few implementations, and possibly
-  the only freely available one, that has EH versions. It may be
-  useful to people who want to play with or study application
-  behaviour under these conditions.
-
-
-------------------------------------------------------------------------------
-
-Q 3	What is the library naming convention?
----
-
-Because the library is being built using various exception
-handling schemes and compilers - and because the library
-may not work reliably if these are mixed in an application,
-each different version of the library has it's own name.
-
-Note 1: the incompatibility is really between EH implementations
-of the different compilers. It should be possible to use the
-standard C version from either compiler with C++ applications
-built with a different compiler. If you use an EH version of
-the library, then you must use the same compiler for the
-application. This is another complication and dependency that
-can be avoided by using only the standard C library version.
-
-Note 2: if you use a standard C pthread*.dll with a C++
-application, then any functions that you define that are
-intended to be called via pthread_cleanup_push() must be
-__cdecl.
-
-Note 3: the intention is to also name either the VC or GC
-version (it should be arbitrary) as pthread.dll, including
-pthread.lib and libpthread.a as appropriate.
-
-In general:
-	pthread[VG]{SE,CE,C}.dll
-	pthread[VG]{SE,CE,C}.lib
-
-where:
-	[VG] indicates the compiler
-	V	- MS VC
-	G	- GNU C
-
-	{SE,CE,C} indicates the exception handling scheme
-	SE	- Structured EH
-	CE	- C++ EH
-	C	- no exceptions - uses setjmp/longjmp
-
-For example:
-	pthreadVSE.dll	(MSVC/SEH)
-	pthreadGCE.dll	(GNUC/C++ EH)
-	pthreadGC.dll	(GNUC/not dependent on exceptions)
-
-The GNU library archive file names have changed to:
-
-	libpthreadGCE.a
-	libpthreadGC.a
-
-
-------------------------------------------------------------------------------
-
-Q 4	Cleanup code default style or: it used to work when I built
----	the library myself, but now it doesn't - why?
-
-Up to and including snapshot 2001-07-12, if not defined, the cleanup
-style was determined automatically from the compiler used, and one
-of the following was defined accordingly:
-
-	__CLEANUP_SEH	MSVC only
-	__CLEANUP_CXX	C++, including MSVC++, GNU G++
-	__CLEANUP_C		C, including GNU GCC, not MSVC
-
-These defines determine the style of cleanup (see pthread.h) and,
-most importantly, the way that cancelation and thread exit (via
-pthread_exit) is performed (see the routine ptw32_throw() in private.c).
-
-In short, the exceptions versions of the library throw an exception
-when a thread is canceled or exits (via pthread_exit()), which is
-caught by a handler in the thread startup routine, so that the
-the correct stack unwinding occurs regardless of where the thread
-is when it's canceled or exits via pthread_exit().
-
-After snapshot 2001-07-12, unless your build explicitly defines (e.g.
-via a compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
-the build now ALWAYS defaults to __CLEANUP_C style cleanup. This style
-uses setjmp/longjmp in the cancelation and pthread_exit implementations,
-and therefore won't do stack unwinding even when linked to applications
-that have it (e.g. C++ apps). This is for consistency with most/all
-commercial Unix POSIX threads implementations.
-
-Although it was not clearly documented before, it is still necessary to
-build your application using the same __CLEANUP_* define as was
-used for the version of the library that you link with, so that the
-correct parts of pthread.h are included. That is, the possible
-defines require the following library versions:
-
-	__CLEANUP_SEH	pthreadVSE.dll
-	__CLEANUP_CXX	pthreadVCE.dll or pthreadGCE.dll
-	__CLEANUP_C		pthreadVC.dll or pthreadGC.dll
-
-THE POINT OF ALL THIS IS: if you have not been defining one of these
-explicitly, then the defaults have been set according to the compiler
-and language you are using, as described at the top of this
-section.
-
-THIS NOW CHANGES, as has been explained above. For example:
-
-If you were building your application with MSVC++ i.e. using C++
-exceptions (rather than SEH) and not explicitly defining one of
-__CLEANUP_*, then __CLEANUP_C++ was defined for you in pthread.h.
-You should have been linking with pthreadVCE.dll, which does
-stack unwinding.
-
-If you now build your application as you had before, pthread.h will now
-set __CLEANUP_C as the default style, and you will need to link
-with pthreadVC.dll. Stack unwinding will now NOT occur when a
-thread is canceled, nor when the thread calls pthread_exit().
-
-Your application will now most likely behave differently to previous
-versions, and in non-obvious ways. Most likely is that local
-objects may not be destroyed or cleaned up after a thread
-is canceled.
-
-If you want the same behaviour as before, then you must now define
-__CLEANUP_C++ explicitly using a compiler option and link with
-pthreadVCE.dll as you did before.
-
-
-------------------------------------------------------------------------------
-
-Q 5	Why is the default library version now less exception-friendly?
----
-
-Because most commercial Unix POSIX threads implementations don't allow you to
-choose to have stack unwinding. (Compaq's TRU64 Unix is possibly an exception.)
-
-Therefore, providing it in pthread-win32 as a default could be dangerous
-and non-portable. We still provide the choice but you must now consciously
-make it.
-
-WHY NOT REMOVE THE EXCEPTIONS VERSIONS OF THE LIBRARY ALTOGETHER?
-There are a few reasons:
-- because there are well respected POSIX threads people who believe
-  that POSIX threads implementations should be exceptions-aware and
-  do the expected thing in that context. (There are equally respected
-  people who believe it should not be easily accessible, if it's there
-  at all.)
-- because pthreads-win32 is one of the few implementations that has
-  the choice, perhaps the only freely available one, and so offers
-  a laboratory to people who may want to explore the effects;
-- although the code will always be around somewhere for anyone who
-  wants it, once it's removed from the current version it will not be
-  nearly as visible to people who may have a use for it.
-
-
-------------------------------------------------------------------------------
-
-Q 6	Should I use Cygwin or Mingw32 as a development environment?
----
-
-Important: see Q7 also.
-
-Use Mingw32 with the MSVCRT library to build applications that use
-the pthreads DLL.
-
-Cygwin's own internal support for POSIX threads is growing.
-Consult that project's documentation for more information.
-
-------------------------------------------------------------------------------
-
-Q 7	Now that pthreads-win32 builds under Mingw32, why do I get
----	memory access violations (segfaults)?
-
-The latest Mingw32 package has thread-safe exception handling (see Q10).
-Also, see Q6 above.
-
-------------------------------------------------------------------------------
-
-Q 8	How do I use pthread.dll for Win32 (Visual C++ 5.0)
----	
-
->
-> I'm a "rookie" when it comes to your pthread implementation.	I'm currently
-> desperately trying to install the prebuilt .dll file into my MSVC compiler.
-> Could you please provide me with explicit instructions on how to do this (or
-> direct me to a resource(s) where I can acquire such information)?
->
-> Thank you,
->
-
-You should have a .dll, .lib, .def, and three .h files. It is recommended
-that you use pthreadVC.dll, rather than pthreadVCE.dll or pthreadVSE.dll
-(see Q2 above).
-
-The .dll can go in any directory listed in your PATH environment
-variable, so putting it into C:\WINDOWS should work.
-
-The .lib file can go in any directory listed in your LIB environment
-variable.
-
-The .h files can go in any directory listed in your INCLUDE
-environment variable.
-
-Or you might prefer to put the .lib and .h files into a new directory
-and add its path to LIB and INCLUDE. You can probably do this easiest
-by editing the file:-
-
-C:\Program Files\DevStudio\vc\bin\vcvars32.bat
-
-The .def file isn't used by anything in the pre-compiled version but 
-is included for information.
-
-Cheers.
-Ross
-
-------------------------------------------------------------------------------
-
-Q 9	Cancelation doesn't work for me, why?
----
-
-> I'm investigating a problem regarding thread cancelation. The thread I want
-> to cancel has PTHREAD_CANCEL_ASYNCHRONOUS, however, this piece of code
-> blocks on the join():
->
->		if ((retv = Pthread_cancel( recvThread )) == 0)
->		{
->			retv = Pthread_join( recvThread, 0 );
->		}
->
-> Pthread_* are just macro's; they call pthread_*.
->
-> The thread recvThread seems to block on a select() call. It doesn't get
-> cancelled.
->
-> Two questions:
->
-> 1) is this normal behaviour?
->
-> 2) if not, how does the cancel mechanism work? I'm not very familliar to
-> win32 programming, so I don't really understand how the *Event() family of
-> calls work.
-
-The answer to your first question is, normal POSIX behaviour would  
-be to asynchronously cancel the thread. However, even that doesn't
-guarantee cancelation as the standard only says it should be
-cancelled as soon as possible.
-
-Snapshot 99-11-02 or earlier only partially supports asynchronous cancellation.
-Snapshots since then simulate async cancelation by poking the address of
-a cancelation routine into the PC of the threads context. This requires
-the thread to be resumed in some way for the cancelation to actually
-proceed. This is not true async cancelation, but it is as close as we've
-been able to get to it.
-
-If the thread you're trying to cancel is blocked (for instance, it could be
-waiting for data from the network), it will only get cancelled when it unblocks
-(when the data arrives). For true pre-emptive cancelation in these cases,
-pthreads-win32 from snapshot 2004-05-16 can automatically recognise and use the
-QueueUserAPCEx package by Panagiotis E. Hadjidoukas. This package is available
-from the pthreads-win32 ftp site and is included in the pthreads-win32
-self-unpacking zip from 2004-05-16 onwards.
-
-Using deferred cancelation would normally be the way to go, however,
-even though the POSIX threads standard lists a number of C library
-functions that are defined as deferred cancelation points, there is
-no hookup between those which are provided by Windows and the
-pthreads-win32 library.
-
-Incidently, it's worth noting for code portability that the older POSIX
-threads standards cancelation point lists didn't include "select" because
-(as I read in Butenhof) it wasn't part of POSIX. However, it does appear in
-the SUSV3.
-
-Effectively, the only mandatory cancelation points that pthreads-win32
-recognises are those the library implements itself, ie.
-	
-	pthread_testcancel
-	pthread_cond_wait
-	pthread_cond_timedwait
-	pthread_join
-	sem_wait
-	sem_timedwait
-	pthread_delay_np
-
-The following routines from the non-mandatory list in SUSV3 are
-cancelation points in pthreads-win32:
-
-	pthread_rwlock_wrlock
-	pthread_rwlock_timedwrlock
-
-The following routines from the non-mandatory list in SUSV3 are not
-cancelation points in pthreads-win32:
-
-	pthread_rwlock_rdlock
-	pthread_rwlock_timedrdlock
-
-Pthreads-win32 also provides two functions that allow you to create
-cancelation points within your application, but only for cases where
-a thread is going to block on a Win32 handle. These are:
-
-	pthreadCancelableWait(HANDLE waitHandle) /* Infinite wait */
- 
-	pthreadCancelableTimedWait(HANDLE waitHandle, DWORD timeout)
-
-------------------------------------------------------------------------------
- 
-
-Q 10	How do I create thread-safe applications using
-----	pthreadGCE.dll, libpthreadw32.a and Mingw32?
-
-This should not be a problem with recent versions of MinGW32.
-
-For early versions, see Thomas Pfaff's email at:
-http://sources.redhat.com/ml/pthreads-win32/2002/msg00000.html
-------------------------------------------------------------------------------
- 
+		  =========================================
+		  PTHREADS-WIN32 Frequently Asked Questions
+		  =========================================
+
+INDEX
+-----
+
+Q 1	What is it?
+
+Q 2	Which of the several dll versions do I use?
+	or,
+	What are all these pthread*.dll and pthread*.lib files?
+
+Q 3	What is the library naming convention?
+
+Q 4	Cleanup code default style or: it used to work when I built
+	the library myself, but now it doesn't - why?
+
+Q 5	Why is the default library version now less exception-friendly?
+
+Q 6	Should I use Cygwin or Mingw32 as a development environment?
+
+Q 7	Now that pthreads-win32 builds under Mingw32, why do I get
+	memory access violations (segfaults)?
+
+Q 8	How do I use pthread.dll for Win32 (Visual C++ 5.0)
+
+Q 9	Cancelation doesn't work for me, why?
+
+Q 10	How do I generate pthreadGCE.dll and libpthreadw32.a for use
+	with Mingw32?
+
+=============================================================================
+
+Q 1	What is it?
+---
+
+Pthreads-win32 is an Open Source Software implementation of the
+Threads component of the POSIX 1003.1c 1995 Standard for Microsoft's
+Win32 environment. Some functions from POSIX 1003.1b are also
+supported including semaphores. Other related functions include
+the set of read-write lock functions. The library also supports
+some of the functionality of the Open Group's Single Unix
+specification, version 2, namely mutex types.
+
+See the file "ANNOUNCE" for more information including standards
+conformance details and list of supported routines.
+
+
+------------------------------------------------------------------------------
+
+Q 2	Which of the several dll versions do I use?
+---	or,
+	What are all these pthread*.dll and pthread*.lib files?
+
+Simply, you only use one of them, but you need to choose carefully.
+
+The most important choice you need to make is whether to use a
+version that uses exceptions internally, or not (there are versions
+of the library that use exceptions as part of the thread
+cancelation and cleanup implementation, and one that uses
+setjmp/longjmp instead).
+
+There is some contension amongst POSIX threads experts as
+to how POSIX threads cancelation and exit should work
+with languages that include exceptions and handlers, e.g.
+C++ and even C (Microsoft's Structured Exceptions).
+
+The issue is: should cancelation of a thread in, say,
+a C++ application cause object destructors and C++ exception
+handlers to be invoked as the stack unwinds during thread
+exit, or not?
+
+There seems to be more opinion in favour of using the
+standard C version of the library (no EH) with C++ applications
+since this appears to be the assumption commercial pthreads
+implementations make. Therefore, if you use an EH version
+of pthreads-win32 then you may be under the illusion that
+your application will be portable, when in fact it is likely to
+behave very differently linked with other pthreads libraries.
+
+Now you may be asking: why have you kept the EH versions of
+the library?
+
+There are a couple of reasons:
+- there is division amongst the experts and so the code may
+  be needed in the future. (Yes, it's in the repository and we
+  can get it out anytime in the future, but ...)
+- pthreads-win32 is one of the few implementations, and possibly
+  the only freely available one, that has EH versions. It may be
+  useful to people who want to play with or study application
+  behaviour under these conditions.
+
+
+------------------------------------------------------------------------------
+
+Q 3	What is the library naming convention?
+---
+
+Because the library is being built using various exception
+handling schemes and compilers - and because the library
+may not work reliably if these are mixed in an application,
+each different version of the library has it's own name.
+
+Note 1: the incompatibility is really between EH implementations
+of the different compilers. It should be possible to use the
+standard C version from either compiler with C++ applications
+built with a different compiler. If you use an EH version of
+the library, then you must use the same compiler for the
+application. This is another complication and dependency that
+can be avoided by using only the standard C library version.
+
+Note 2: if you use a standard C pthread*.dll with a C++
+application, then any functions that you define that are
+intended to be called via pthread_cleanup_push() must be
+__cdecl.
+
+Note 3: the intention is to also name either the VC or GC
+version (it should be arbitrary) as pthread.dll, including
+pthread.lib and libpthread.a as appropriate.
+
+In general:
+	pthread[VG]{SE,CE,C}.dll
+	pthread[VG]{SE,CE,C}.lib
+
+where:
+	[VG] indicates the compiler
+	V	- MS VC
+	G	- GNU C
+
+	{SE,CE,C} indicates the exception handling scheme
+	SE	- Structured EH
+	CE	- C++ EH
+	C	- no exceptions - uses setjmp/longjmp
+
+For example:
+	pthreadVSE.dll	(MSVC/SEH)
+	pthreadGCE.dll	(GNUC/C++ EH)
+	pthreadGC.dll	(GNUC/not dependent on exceptions)
+
+The GNU library archive file names have changed to:
+
+	libpthreadGCE.a
+	libpthreadGC.a
+
+
+------------------------------------------------------------------------------
+
+Q 4	Cleanup code default style or: it used to work when I built
+---	the library myself, but now it doesn't - why?
+
+Up to and including snapshot 2001-07-12, if not defined, the cleanup
+style was determined automatically from the compiler used, and one
+of the following was defined accordingly:
+
+	__CLEANUP_SEH	MSVC only
+	__CLEANUP_CXX	C++, including MSVC++, GNU G++
+	__CLEANUP_C		C, including GNU GCC, not MSVC
+
+These defines determine the style of cleanup (see pthread.h) and,
+most importantly, the way that cancelation and thread exit (via
+pthread_exit) is performed (see the routine ptw32_throw() in private.c).
+
+In short, the exceptions versions of the library throw an exception
+when a thread is canceled or exits (via pthread_exit()), which is
+caught by a handler in the thread startup routine, so that the
+the correct stack unwinding occurs regardless of where the thread
+is when it's canceled or exits via pthread_exit().
+
+After snapshot 2001-07-12, unless your build explicitly defines (e.g.
+via a compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
+the build now ALWAYS defaults to __CLEANUP_C style cleanup. This style
+uses setjmp/longjmp in the cancelation and pthread_exit implementations,
+and therefore won't do stack unwinding even when linked to applications
+that have it (e.g. C++ apps). This is for consistency with most/all
+commercial Unix POSIX threads implementations.
+
+Although it was not clearly documented before, it is still necessary to
+build your application using the same __CLEANUP_* define as was
+used for the version of the library that you link with, so that the
+correct parts of pthread.h are included. That is, the possible
+defines require the following library versions:
+
+	__CLEANUP_SEH	pthreadVSE.dll
+	__CLEANUP_CXX	pthreadVCE.dll or pthreadGCE.dll
+	__CLEANUP_C		pthreadVC.dll or pthreadGC.dll
+
+THE POINT OF ALL THIS IS: if you have not been defining one of these
+explicitly, then the defaults have been set according to the compiler
+and language you are using, as described at the top of this
+section.
+
+THIS NOW CHANGES, as has been explained above. For example:
+
+If you were building your application with MSVC++ i.e. using C++
+exceptions (rather than SEH) and not explicitly defining one of
+__CLEANUP_*, then __CLEANUP_C++ was defined for you in pthread.h.
+You should have been linking with pthreadVCE.dll, which does
+stack unwinding.
+
+If you now build your application as you had before, pthread.h will now
+set __CLEANUP_C as the default style, and you will need to link
+with pthreadVC.dll. Stack unwinding will now NOT occur when a
+thread is canceled, nor when the thread calls pthread_exit().
+
+Your application will now most likely behave differently to previous
+versions, and in non-obvious ways. Most likely is that local
+objects may not be destroyed or cleaned up after a thread
+is canceled.
+
+If you want the same behaviour as before, then you must now define
+__CLEANUP_C++ explicitly using a compiler option and link with
+pthreadVCE.dll as you did before.
+
+
+------------------------------------------------------------------------------
+
+Q 5	Why is the default library version now less exception-friendly?
+---
+
+Because most commercial Unix POSIX threads implementations don't allow you to
+choose to have stack unwinding. (Compaq's TRU64 Unix is possibly an exception.)
+
+Therefore, providing it in pthread-win32 as a default could be dangerous
+and non-portable. We still provide the choice but you must now consciously
+make it.
+
+WHY NOT REMOVE THE EXCEPTIONS VERSIONS OF THE LIBRARY ALTOGETHER?
+There are a few reasons:
+- because there are well respected POSIX threads people who believe
+  that POSIX threads implementations should be exceptions-aware and
+  do the expected thing in that context. (There are equally respected
+  people who believe it should not be easily accessible, if it's there
+  at all.)
+- because pthreads-win32 is one of the few implementations that has
+  the choice, perhaps the only freely available one, and so offers
+  a laboratory to people who may want to explore the effects;
+- although the code will always be around somewhere for anyone who
+  wants it, once it's removed from the current version it will not be
+  nearly as visible to people who may have a use for it.
+
+
+------------------------------------------------------------------------------
+
+Q 6	Should I use Cygwin or Mingw32 as a development environment?
+---
+
+Important: see Q7 also.
+
+Use Mingw32 with the MSVCRT library to build applications that use
+the pthreads DLL.
+
+Cygwin's own internal support for POSIX threads is growing.
+Consult that project's documentation for more information.
+
+------------------------------------------------------------------------------
+
+Q 7	Now that pthreads-win32 builds under Mingw32, why do I get
+---	memory access violations (segfaults)?
+
+The latest Mingw32 package has thread-safe exception handling (see Q10).
+Also, see Q6 above.
+
+------------------------------------------------------------------------------
+
+Q 8	How do I use pthread.dll for Win32 (Visual C++ 5.0)
+---	
+
+>
+> I'm a "rookie" when it comes to your pthread implementation.	I'm currently
+> desperately trying to install the prebuilt .dll file into my MSVC compiler.
+> Could you please provide me with explicit instructions on how to do this (or
+> direct me to a resource(s) where I can acquire such information)?
+>
+> Thank you,
+>
+
+You should have a .dll, .lib, .def, and three .h files. It is recommended
+that you use pthreadVC.dll, rather than pthreadVCE.dll or pthreadVSE.dll
+(see Q2 above).
+
+The .dll can go in any directory listed in your PATH environment
+variable, so putting it into C:\WINDOWS should work.
+
+The .lib file can go in any directory listed in your LIB environment
+variable.
+
+The .h files can go in any directory listed in your INCLUDE
+environment variable.
+
+Or you might prefer to put the .lib and .h files into a new directory
+and add its path to LIB and INCLUDE. You can probably do this easiest
+by editing the file:-
+
+C:\Program Files\DevStudio\vc\bin\vcvars32.bat
+
+The .def file isn't used by anything in the pre-compiled version but 
+is included for information.
+
+Cheers.
+Ross
+
+------------------------------------------------------------------------------
+
+Q 9	Cancelation doesn't work for me, why?
+---
+
+> I'm investigating a problem regarding thread cancelation. The thread I want
+> to cancel has PTHREAD_CANCEL_ASYNCHRONOUS, however, this piece of code
+> blocks on the join():
+>
+>		if ((retv = Pthread_cancel( recvThread )) == 0)
+>		{
+>			retv = Pthread_join( recvThread, 0 );
+>		}
+>
+> Pthread_* are just macro's; they call pthread_*.
+>
+> The thread recvThread seems to block on a select() call. It doesn't get
+> cancelled.
+>
+> Two questions:
+>
+> 1) is this normal behaviour?
+>
+> 2) if not, how does the cancel mechanism work? I'm not very familliar to
+> win32 programming, so I don't really understand how the *Event() family of
+> calls work.
+
+The answer to your first question is, normal POSIX behaviour would  
+be to asynchronously cancel the thread. However, even that doesn't
+guarantee cancelation as the standard only says it should be
+cancelled as soon as possible.
+
+Snapshot 99-11-02 or earlier only partially supports asynchronous cancellation.
+Snapshots since then simulate async cancelation by poking the address of
+a cancelation routine into the PC of the threads context. This requires
+the thread to be resumed in some way for the cancelation to actually
+proceed. This is not true async cancelation, but it is as close as we've
+been able to get to it.
+
+If the thread you're trying to cancel is blocked (for instance, it could be
+waiting for data from the network), it will only get cancelled when it unblocks
+(when the data arrives). For true pre-emptive cancelation in these cases,
+pthreads-win32 from snapshot 2004-05-16 can automatically recognise and use the
+QueueUserAPCEx package by Panagiotis E. Hadjidoukas. This package is available
+from the pthreads-win32 ftp site and is included in the pthreads-win32
+self-unpacking zip from 2004-05-16 onwards.
+
+Using deferred cancelation would normally be the way to go, however,
+even though the POSIX threads standard lists a number of C library
+functions that are defined as deferred cancelation points, there is
+no hookup between those which are provided by Windows and the
+pthreads-win32 library.
+
+Incidently, it's worth noting for code portability that the older POSIX
+threads standards cancelation point lists didn't include "select" because
+(as I read in Butenhof) it wasn't part of POSIX. However, it does appear in
+the SUSV3.
+
+Effectively, the only mandatory cancelation points that pthreads-win32
+recognises are those the library implements itself, ie.
+	
+	pthread_testcancel
+	pthread_cond_wait
+	pthread_cond_timedwait
+	pthread_join
+	sem_wait
+	sem_timedwait
+	pthread_delay_np
+
+The following routines from the non-mandatory list in SUSV3 are
+cancelation points in pthreads-win32:
+
+	pthread_rwlock_wrlock
+	pthread_rwlock_timedwrlock
+
+The following routines from the non-mandatory list in SUSV3 are not
+cancelation points in pthreads-win32:
+
+	pthread_rwlock_rdlock
+	pthread_rwlock_timedrdlock
+
+Pthreads-win32 also provides two functions that allow you to create
+cancelation points within your application, but only for cases where
+a thread is going to block on a Win32 handle. These are:
+
+	pthreadCancelableWait(HANDLE waitHandle) /* Infinite wait */
+ 
+	pthreadCancelableTimedWait(HANDLE waitHandle, DWORD timeout)
+
+------------------------------------------------------------------------------
+ 
+
+Q 10	How do I create thread-safe applications using
+----	pthreadGCE.dll, libpthreadw32.a and Mingw32?
+
+This should not be a problem with recent versions of MinGW32.
+
+For early versions, see Thomas Pfaff's email at:
+http://sources.redhat.com/ml/pthreads-win32/2002/msg00000.html
+------------------------------------------------------------------------------
+ 
diff --git a/GNUmakefile b/GNUmakefile
index f479778..af70a56 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -46,8 +46,8 @@ CP	= cp -f
 
 AR	= ar
 
-#OPT	= -g
-#OPT	= -O3 -DTEST_ICE
+#OPT	= -g -O0
+#OPT	= -O3
 OPT	= -O3 -finline-functions
 XOPT	=
 
diff --git a/Makefile b/Makefile
index f39412e..8eccb96 100644
--- a/Makefile
+++ b/Makefile
@@ -14,9 +14,10 @@ DLLS	= pthreadVCE.dll pthreadVSE.dll pthreadVC.dll
 INLINED_STAMPS	= pthreadVCE.stamp pthreadVSE.stamp pthreadVC.stamp
 
 OPTIM	= /O2
+#OPTIM	=
 
-#CFLAGS	= /W3 /MD /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H /DTEST_ICE
-CFLAGS	= /W3 /MD /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H
+CFLAGS	= /W3 /MD /nologo /Yd /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H
+#CFLAGS	= /W3 /MD /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H
 
 # C++ Exceptions
 VCEFLAGS	= /GX /TP /D__CLEANUP_CXX $(CFLAGS)
diff --git a/NEWS b/NEWS
index 695ff5d..d299b17 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,69 @@
+SNAPSHOT 2004-11-03
+-------------------
+
+DLLs produced from this snapshot cannot be used with older applications without
+recompiling the application, due to a change to pthread_t to provide unique POSIX
+thread IDs.
+
+Although this snapshot passes the extended test suite, many of the changes are
+fairly major, and some applications may show different behaviour than previously,
+so adopt with care. Hopefully, any changed behaviour will be due to the library
+being better at it's job, not worse.
+
+Bug fixes
+---------
+
+* pthread_create() no longer accepts NULL as the thread reference arg.
+A segfault (memory access fault) will result, and no thread will be
+created.
+
+* pthread_barrier_wait() no longer acts as a cancelation point.
+
+* Fix potential race condition in pthread_once()
+- Tristan Savatier  <tristan at mpegtv.com>
+
+* Changes to pthread_cond_destroy() exposed some coding weaknesses in several
+test suite mini-apps because pthread_cond_destroy() now returns EBUSY if the CV
+is still in use.
+
+New features
+------------
+
+* Added for compatibility:
+PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
+PTHREAD_ERRORCHECK_MUTEX_INITIALIZER,
+PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
+PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+
+* Initial support for Digital Mars compiler
+- Anuj Goyal  <anuj.goyal at gmail.com>
+
+* Faster Mutexes. These have been been rewritten following a model provided by
+Alexander Terekhov that reduces kernel space checks, and eliminates some additional
+critical sections used to manage a race between timedlock expiration and unlock.
+Please be aware that the new mutexes do not enforce strict absolute FIFO scheduling
+of mutexes, however any out-of-order lock acquisition should be very rare.
+
+* Faster semaphores. Following a similar model to mutexes above, these have been
+rewritten to use preliminary users space checks.
+
+* sem_getvalue() now returns the number of waiters.
+
+* The POSIX thread ID now has much stronger uniqueness characteristics. The library
+garrantees not to reuse the same thread ID for at least 2^(wordsize) thread
+destruction/creation cycles.
+
+New tests
+---------
+
+* semaphore4.c: Tests cancelation of the new sem_wait().
+
+* semaphore4t.c: Likewise for sem_timedwait().
+
+* rwlock8.c: Tests and times the slow execution paths of r/w locks, and the CVs,
+mutexes, and semaphores that they're built on.
+
+
 SNAPSHOT 2004-05-16
 -------------------
 
diff --git a/PROGRESS b/PROGRESS
index 3e90bec..9abf0bc 100644
--- a/PROGRESS
+++ b/PROGRESS
@@ -1,4 +1,4 @@
-Please see the ANNOUNCE file "Level of Standards Conformance"
-or the web page:
-
-http://sources.redhat.com/pthreads-win32/conformance.html
+Please see the ANNOUNCE file "Level of Standards Conformance"
+or the web page:
+
+http://sources.redhat.com/pthreads-win32/conformance.html
diff --git a/README b/README
index 4f30a46..b7eafdf 100644
--- a/README
+++ b/README
@@ -1,479 +1,444 @@
-PTHREADS-WIN32
-==============
-
-Pthreads-win32 is free software, distributed under the GNU Lesser
-General Public License (LGPL). See the file 'COPYING.LIB' for terms
-and conditions. Also see the file 'COPYING' for information
-specific to pthreads-win32, copyrights and the LGPL.
-
-
-What is it?
------------
-
-Pthreads-win32 is an Open Source Software implementation of the
-Threads component of the POSIX 1003.1c 1995 Standard (or later)
-for Microsoft's Win32 environment. Some functions from POSIX
-1003.1b are also supported including semaphores. Other related
-functions include the set of read-write lock functions. The
-library also supports some of the functionality of the Open
-Group's Single Unix specification, version 2, namely mutex types,
-plus some common and pthreads-win32 specific non-portable
-routines (see README.NONPORTABLE).
-
-See the file "ANNOUNCE" for more information including standards
-conformance details and the list of supported and unsupported
-routines.
-
-
-Prerequisites
--------------
-MSVC or GNU C (MSys - MinGW32)
-	To build from source.
-
-QueueUserAPCEx by Panagiotis E. Hadjidoukas
-	For true async cancelation of threads (including blocked threads).
-	This is a DLL and Windows driver that provides pre-emptive APC
-	by forcing threads into an alertable state when the APC is queued.
-	Both the DLL and driver are provided with the pthreads-win32.exe
-	self-unpacking ZIP, and on the pthreads-win32 FTP site  (in source
-	and pre-built forms). Currently this is a separate LGPL package to
-	pthreads-win32. See the README in the QueueUserAPCEx folder for
-	installation instructions.
-
-	Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL
-	QuserEx.DLL is available and whether the driver AlertDrv.sys is
-	loaded. If it is not available, pthreads-win32 will simulate async
-	cancelation, which means that it cannot pre-empt blocked threads.
-
-
-Library naming
---------------
-
-Because the library is being built using various exception
-handling schemes and compilers - and because the library
-may not work reliably if these are mixed in an application,
-each different version of the library has it's own name.
-
-Note 1: the incompatibility is really between EH implementations
-of the different compilers. It should be possible to use the
-standard C version from either compiler with C++ applications
-built with a different compiler. If you use an EH version of
-the library, then you must use the same compiler for the
-application. This is another complication and dependency that
-can be avoided by using only the standard C library version.
-
-Note 2: if you use a standard C pthread*.dll with a C++
-application, then any functions that you define that are
-intended to be called via pthread_cleanup_push() must be
-__cdecl.
-
-Note 3: the intention is to also name either the VC or GC
-version (it should be arbitrary) as pthread.dll, including
-pthread.lib and libpthread.a as appropriate.
-
-In general:
-	pthread[VG]{SE,CE,C}.dll
-	pthread[VG]{SE,CE,C}.lib
-
-where:
-	[VG] indicates the compiler
-	V	- MS VC
-	G	- GNU C
-
-	{SE,CE,C} indicates the exception handling scheme
-	SE	- Structured EH
-	CE	- C++ EH
-	C	- no exceptions - uses setjmp/longjmp
-
-For example:
-	pthreadVSE.dll	(MSVC/SEH)
-	pthreadGCE.dll	(GNUC/C++ EH)
-	pthreadGC.dll	(GNUC/not dependent on exceptions)
-
-The GNU library archive file names have changed to:
-
-	libpthreadGCE.a
-	libpthreadGC.a
-
-
-Which of the several dll versions to use?
------------------------------------------
-or,
----
-What are all these pthread*.dll and pthread*.lib files?
--------------------------------------------------------
-
-Simple, use either pthreadGC.* if you use GCC, or pthreadVC.* if you
-use MSVC.
-
-Otherwise, you need to choose carefully and know WHY.
-
-The most important choice you need to make is whether to use a
-version that uses exceptions internally, or not. There are versions
-of the library that use exceptions as part of the thread
-cancelation and exit implementation. The default version uses
-setjmp/longjmp.
-
-There is some contension amongst POSIX threads experts as
-to how POSIX threads cancelation and exit should work
-with languages that use exceptions, e.g. C++ and even C
-(Microsoft's Structured Exceptions).
-
-The issue is: should cancelation of a thread in, say,
-a C++ application cause object destructors and C++ exception
-handlers to be invoked as the stack unwinds during thread
-exit, or not?
-
-There seems to be more opinion in favour of using the
-standard C version of the library (no EH) with C++ applications
-for the reason that this appears to be the assumption commercial
-pthreads implementations make. Therefore, if you use an EH version
-of pthreads-win32 then you may be under the illusion that
-your application will be portable, when in fact it is likely to
-behave differently when linked with other pthreads libraries.
-
-Now you may be asking: then why have you kept the EH versions of
-the library?
-
-There are a couple of reasons:
-- there is division amongst the experts and so the code may
-  be needed in the future. Yes, it's in the repository and we
-  can get it out anytime in the future, but it would be difficult
-  to find.
-- pthreads-win32 is one of the few implementations, and possibly
-  the only freely available one, that has EH versions. It may be
-  useful to people who want to play with or study application
-  behaviour under these conditions.
-
-Notes:
-
-[If you use either pthreadVCE or pthreadGCE]
-
-1. [See also the discussion in the FAQ file - Q2, Q4, and Q5]
-
-If your application contains catch(...) blocks in your POSIX
-threads then you will need to replace the "catch(...)" with the macro
-"PtW32Catch", eg.
-
-	#ifdef PtW32Catch
-		PtW32Catch {
-			...
-		}
-	#else
-		catch(...) {
-			...
-		}
-	#endif
-
-Otherwise neither pthreads cancelation nor pthread_exit() will work
-reliably when using versions of the library that use C++ exceptions
-for cancelation and thread exit.
-
-This is due to what is believed to be a C++ compliance error in VC++
-whereby you may not have multiple handlers for the same exception in
-the same try/catch block. GNU G++ doesn't have this restriction.
-
-
-Other name changes
-------------------
-
-All snapshots prior to and including snapshot 2000-08-13
-used "_pthread_" as the prefix to library internal
-functions, and "_PTHREAD_" to many library internal
-macros. These have now been changed to "ptw32_" and "PTW32_"
-respectively so as to not conflict with the ANSI standard's
-reservation of identifiers beginning with "_" and "__" for
-use by compiler implementations only.
-
-If you have written any applications and you are linking
-statically with the pthreads-win32 library then you may have
-included a call to _pthread_processInitialize. You will
-now have to change that to ptw32_processInitialize.
-
-
-Cleanup code default style
---------------------------
-
-Previously, if not defined, the cleanup style was determined automatically
-from the compiler used, and one of the following was defined accordingly:
-
-	__CLEANUP_SEH	MSVC only
-	__CLEANUP_CXX	C++, including MSVC++, GNU G++
-	__CLEANUP_C	C, including GNU GCC, not MSVC
-
-These defines determine the style of cleanup (see pthread.h) and,
-most importantly, the way that cancelation and thread exit (via
-pthread_exit) is performed (see the routine ptw32_throw() in private.c).
-
-In short, the exceptions versions of the library throw an exception
-when a thread is canceled or exits (via pthread_exit()), which is
-caught by a handler in the thread startup routine, so that the
-the correct stack unwinding occurs regardless of where the thread
-is when it's canceled or exits via pthread_exit().
-
-In this snapshot, unless the build explicitly defines (e.g. via a
-compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
-the build NOW always defaults to __CLEANUP_C style cleanup. This style
-uses setjmp/longjmp in the cancelation and pthread_exit implementations,
-and therefore won't do stack unwinding even when linked to applications
-that have it (e.g. C++ apps). This is for consistency with most/all
-commercial Unix POSIX threads implementations.
-
-Although it was not clearly documented before, it is still necessary to
-build your application using the same __CLEANUP_* define as was
-used for the version of the library that you link with, so that the
-correct parts of pthread.h are included. That is, the possible
-defines require the following library versions:
-
-	__CLEANUP_SEH	pthreadVSE.dll
-	__CLEANUP_CXX	pthreadVCE.dll or pthreadGCE.dll
-	__CLEANUP_C	pthreadVC.dll or pthreadGC.dll
-
-THE POINT OF ALL THIS IS: if you have not been defining one of these
-explicitly, then the defaults as described at the top of this
-section were being used.
-
-THIS NOW CHANGES, as has been explained above, but to try to make this
-clearer here's an example:
-
-If you were building your application with MSVC++ i.e. using C++
-exceptions (rather than SEH) and not explicitly defining one of
-__CLEANUP_*, then __CLEANUP_C++ was defined for you in pthread.h.
-You should have been linking with pthreadVCE.dll, which does
-stack unwinding.
-
-If you now build your application as you had before, pthread.h will now
-set __CLEANUP_C as the default style, and you will need to link
-with pthreadVC.dll. Stack unwinding will now NOT occur when a thread
-is canceled, or the thread calls pthread_exit().
-
-Your application will now most likely behave differently to previous
-versions, and in non-obvious ways. Most likely is that locally
-instantiated objects may not be destroyed or cleaned up after a thread
-is canceled.
-
-If you want the same behaviour as before, then you must now define
-__CLEANUP_C++ explicitly using a compiler option and link with
-pthreadVCE.dll as you did before.
-
-
-WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY?
-Because no commercial Unix POSIX threads implementation allows you to
-choose to have stack unwinding. Therefore, providing it in pthread-win32
-as a default is dangerous. We still provide the choice but unless
-you consciously choose to do otherwise, your pthreads applications will
-now run or crash in similar ways irrespective of the threads platform
-you use. Or at least this is the hope.
-
-
-
-Building under VC++ using C++ EH, Structured EH, or just C
-----------------------------------------------------------
-
-From the source directory run one of the following:
-
-nmake clean VC	(builds the VC setjmp/longjmp version of pthreadVC.dll)
-
-or:
-
-nmake clean VCE (builds the VC++ C++ EH version pthreadVCE.dll)
-
-or:
-
-nmake clean VSE (builds the VC++ structured EH version pthreadVSE.dll)
-
-You can run the testsuite by changing to the "tests" directory and
-running the target corresponding to the DLL version you built:
-
-nmake clean VC
-
-or:
-
-nmake clean VCE
-
-or:
-
-nmake clean VSE
-
-or:
-
-nmake clean VCX (tests the VC version of the library with C++ (EH)
-			 applications)
-
-
-Building under Mingw32
-----------------------
-
-The dll can be built easily with recent versions of Mingw32.
-(The distributed versions are built using Mingw32 and MsysDTK
-from www.mingw32.org.)
-
-From the source directory, run
-
-make clean GC
-
-or:
-
-make clean GCE
-
-You can run the testsuite by changing to the "tests" directory and
-running
-
-make clean GC
-
-or:
-
-make clean GCE
-
-or:
-
-make clean GCX	(tests the GC version of the library with C++ (EH)
-			 applications)
-
-
-Building the library under Cygwin
----------------------------------
-
-Not tested by me although I think some people have done this.
-Not sure how successfully though.
-
-Cygwin is implementing it's own POSIX threads routines and these
-will be the ones to use if you develop using Cygwin.
-
-
-Ready to run binaries
----------------------
-
-For convenience, the following ready-to-run files can be downloaded
-from the FTP site (see under "Availability" below):
-
-	pthread.h
-	semaphore.h
-	sched.h
-	pthread.def
-	pthreadVC.dll	- built with MSVC compiler using C setjmp/longjmp
-	pthreadVC.lib
-	pthreadVCE.dll	- built with MSVC++ compiler using C++ EH
-	pthreadVCE.lib
-	pthreadVSE.dll	- built with MSVC compiler using SEH
-	pthreadVSE.lib
-	pthreadGC.dll	- built with Mingw32 GCC
-	libpthreadGC.a	- derived from pthreadGC.dll
-	pthreadGCE.dll	- built with Mingw32 G++
-	libpthreadGCE.a	- derived from pthreadGCE.dll
-
-As of August 2003 pthreads-win32 pthreadG* versions are built and tested
-using the MinGW + MsysDTK environment current as of that date or later.
-The following file MAY be needed for older MinGW environments.
-
-	gcc.dll 	- needed to build and run applications that use
-			  pthreadGCE.dll.
-
-
-Building applications with GNU compilers
-----------------------------------------
-
-If you're using pthreadGC.dll:
-
-With the three header files, pthreadGC.dll and libpthreadGC.a in the
-same directory as your application myapp.c, you could compile, link
-and run myapp.c under Mingw32 as follows:
-
-	gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC
-	myapp
-
-Or put pthreadGC.dll in an appropriate directory in your PATH,
-put libpthreadGC.a in your system lib directory, and
-put the three header files in your system include directory,
-then use:
-
-	gcc -o myapp.exe myapp.c -lpthreadGC
-	myapp
-
-
-If you're using pthreadGCE.dll:
-
-With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a
-in the same directory as your application myapp.c, you could compile,
-link and run myapp.c under Mingw32 as follows:
-
-	gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE
-	myapp
-
-Or put pthreadGCE.dll and gcc.dll in an appropriate directory in
-your PATH, put libpthreadGCE.a in your system lib directory, and
-put the three header files in your system include directory,
-then use:
-
-	gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE
-	myapp
-
-
-Availability
-------------
-
-The complete source code in either unbundled, self-extracting
-Zip file, or tar/gzipped format can be found at:
-
-	ftp://sources.redhat.com/pub/pthreads-win32
-
-The pre-built DLL, export libraries and matching pthread.h can
-be found at:
-
-	ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
-
-Home page:
-
-	http://sources.redhat.com/pthreads-win32/
-
-
-Mailing list
-------------
-
-There is a mailing list for discussing pthreads on Win32.
-To join, send email to:
-
-	pthreads-win32-subscribe@sources.redhat.com
-
-Unsubscribe by sending mail to:
-
-	pthreads-win32-unsubscribe@sources.redhat.com
-
-
-Acknowledgements
-----------------
-
-Pthreads-win32 is based substantially on a Win32 Pthreads
-implementation contributed by John E. Bossom.
-
-Many others have contributed important new code,
-improvements and bug fixes. Thanks go to Alexander Terekhov
-and Louis Thomas for their implementation of condition variables
-(see README.CV).
-
-Thanks also to the authors of the following paper, which served as
-the first CV design, and which identifies the important issues:
-"Strategies for Implementing POSIX Condition Variables on Win32"
-- http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
-
-See the 'CONTRIBUTORS' file for the list of contributors.
-
-As much as possible, the ChangeLog file attributes
-contributions and patches that have been incorporated
-in the library to the individuals responsible.
-
-Finally, thanks to all those who work on and contribute to the
-POSIX and Single Unix Specification standards. The maturity of an
-industry can be measured by it's open standards.
-
-----
-Ross Johnson
-<rpj@callisto.canberra.edu.au>
-
-
-
-
-
-
-
-
+PTHREADS-WIN32
+==============
+
+Pthreads-win32 is free software, distributed under the GNU Lesser
+General Public License (LGPL). See the file 'COPYING.LIB' for terms
+and conditions. Also see the file 'COPYING' for information
+specific to pthreads-win32, copyrights and the LGPL.
+
+
+What is it?
+-----------
+
+Pthreads-win32 is an Open Source Software implementation of the
+Threads component of the POSIX 1003.1c 1995 Standard (or later)
+for Microsoft's Win32 environment. Some functions from POSIX
+1003.1b are also supported including semaphores. Other related
+functions include the set of read-write lock functions. The
+library also supports some of the functionality of the Open
+Group's Single Unix specification, version 2, namely mutex types,
+plus some common and pthreads-win32 specific non-portable
+routines (see README.NONPORTABLE).
+
+See the file "ANNOUNCE" for more information including standards
+conformance details and the list of supported and unsupported
+routines.
+
+
+Prerequisites
+-------------
+MSVC or GNU C (MinGW32 MSys development kit)
+	To build from source.
+
+QueueUserAPCEx by Panagiotis E. Hadjidoukas
+	For true async cancelation of threads (including blocked threads).
+	This is a DLL and Windows driver that provides pre-emptive APC
+	by forcing threads into an alertable state when the APC is queued.
+	Both the DLL and driver are provided with the pthreads-win32.exe
+	self-unpacking ZIP, and on the pthreads-win32 FTP site  (in source
+	and pre-built forms). Currently this is a separate LGPL package to
+	pthreads-win32. See the README in the QueueUserAPCEx folder for
+	installation instructions.
+
+	Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL
+	QuserEx.DLL is available and whether the driver AlertDrv.sys is
+	loaded. If it is not available, pthreads-win32 will simulate async
+	cancelation, which means that it cannot pre-empt blocked threads.
+
+
+Library naming
+--------------
+
+Because the library is being built using various exception
+handling schemes and compilers - and because the library
+may not work reliably if these are mixed in an application,
+each different version of the library has it's own name.
+
+Note 1: the incompatibility is really between EH implementations
+of the different compilers. It should be possible to use the
+standard C version from either compiler with C++ applications
+built with a different compiler. If you use an EH version of
+the library, then you must use the same compiler for the
+application. This is another complication and dependency that
+can be avoided by using only the standard C library version.
+
+Note 2: if you use a standard C pthread*.dll with a C++
+application, then any functions that you define that are
+intended to be called via pthread_cleanup_push() must be
+__cdecl.
+
+Note 3: the intention is to also name either the VC or GC
+version (it should be arbitrary) as pthread.dll, including
+pthread.lib and libpthread.a as appropriate.
+
+In general:
+	pthread[VG]{SE,CE,C}.dll
+	pthread[VG]{SE,CE,C}.lib
+
+where:
+	[VG] indicates the compiler
+	V	- MS VC
+	G	- GNU C
+
+	{SE,CE,C} indicates the exception handling scheme
+	SE	- Structured EH
+	CE	- C++ EH
+	C	- no exceptions - uses setjmp/longjmp
+
+For example:
+	pthreadVSE.dll	(MSVC/SEH)
+	pthreadGCE.dll	(GNUC/C++ EH)
+	pthreadGC.dll	(GNUC/not dependent on exceptions)
+
+The GNU library archive file names have changed to:
+
+	libpthreadGCE.a
+	libpthreadGC.a
+
+
+Which of the several dll versions to use?
+-----------------------------------------
+or,
+---
+What are all these pthread*.dll and pthread*.lib files?
+-------------------------------------------------------
+
+Simple, use either pthreadGC.* if you use GCC, or pthreadVC.* if you
+use MSVC.
+
+Otherwise, you need to choose carefully and know WHY.
+
+The most important choice you need to make is whether to use a
+version that uses exceptions internally, or not. There are versions
+of the library that use exceptions as part of the thread
+cancelation and exit implementation. The default version uses
+setjmp/longjmp.
+
+There is some contension amongst POSIX threads experts as
+to how POSIX threads cancelation and exit should work
+with languages that use exceptions, e.g. C++ and even C
+(Microsoft's Structured Exceptions).
+
+The issue is: should cancelation of a thread in, say,
+a C++ application cause object destructors and C++ exception
+handlers to be invoked as the stack unwinds during thread
+exit, or not?
+
+There seems to be more opinion in favour of using the
+standard C version of the library (no EH) with C++ applications
+for the reason that this appears to be the assumption commercial
+pthreads implementations make. Therefore, if you use an EH version
+of pthreads-win32 then you may be under the illusion that
+your application will be portable, when in fact it is likely to
+behave differently when linked with other pthreads libraries.
+
+Now you may be asking: then why have you kept the EH versions of
+the library?
+
+There are a couple of reasons:
+- there is division amongst the experts and so the code may
+  be needed in the future. Yes, it's in the repository and we
+  can get it out anytime in the future, but it would be difficult
+  to find.
+- pthreads-win32 is one of the few implementations, and possibly
+  the only freely available one, that has EH versions. It may be
+  useful to people who want to play with or study application
+  behaviour under these conditions.
+
+Notes:
+
+[If you use either pthreadVCE or pthreadGCE]
+
+1. [See also the discussion in the FAQ file - Q2, Q4, and Q5]
+
+If your application contains catch(...) blocks in your POSIX
+threads then you will need to replace the "catch(...)" with the macro
+"PtW32Catch", eg.
+
+	#ifdef PtW32Catch
+		PtW32Catch {
+			...
+		}
+	#else
+		catch(...) {
+			...
+		}
+	#endif
+
+Otherwise neither pthreads cancelation nor pthread_exit() will work
+reliably when using versions of the library that use C++ exceptions
+for cancelation and thread exit.
+
+This is due to what is believed to be a C++ compliance error in VC++
+whereby you may not have multiple handlers for the same exception in
+the same try/catch block. GNU G++ doesn't have this restriction.
+
+
+Other name changes
+------------------
+
+All snapshots prior to and including snapshot 2000-08-13
+used "_pthread_" as the prefix to library internal
+functions, and "_PTHREAD_" to many library internal
+macros. These have now been changed to "ptw32_" and "PTW32_"
+respectively so as to not conflict with the ANSI standard's
+reservation of identifiers beginning with "_" and "__" for
+use by compiler implementations only.
+
+If you have written any applications and you are linking
+statically with the pthreads-win32 library then you may have
+included a call to _pthread_processInitialize. You will
+now have to change that to ptw32_processInitialize.
+
+
+Cleanup code default style
+--------------------------
+
+Previously, if not defined, the cleanup style was determined automatically
+from the compiler used, and one of the following was defined accordingly:
+
+	__CLEANUP_SEH	MSVC only
+	__CLEANUP_CXX	C++, including MSVC++, GNU G++
+	__CLEANUP_C	C, including GNU GCC, not MSVC
+
+These defines determine the style of cleanup (see pthread.h) and,
+most importantly, the way that cancelation and thread exit (via
+pthread_exit) is performed (see the routine ptw32_throw()).
+
+In short, the exceptions versions of the library throw an exception
+when a thread is canceled, or exits via pthread_exit(). This exception is
+caught by a handler in the thread startup routine, so that the
+the correct stack unwinding occurs regardless of where the thread
+is when it's canceled or exits via pthread_exit().
+
+In this snapshot, unless the build explicitly defines (e.g. via a
+compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
+the build NOW always defaults to __CLEANUP_C style cleanup. This style
+uses setjmp/longjmp in the cancelation and pthread_exit implementations,
+and therefore won't do stack unwinding even when linked to applications
+that have it (e.g. C++ apps). This is for consistency with most/all
+commercial Unix POSIX threads implementations.
+
+Although it was not clearly documented before, it is still necessary to
+build your application using the same __CLEANUP_* define as was
+used for the version of the library that you link with, so that the
+correct parts of pthread.h are included. That is, the possible
+defines require the following library versions:
+
+	__CLEANUP_SEH	pthreadVSE.dll
+	__CLEANUP_CXX	pthreadVCE.dll or pthreadGCE.dll
+	__CLEANUP_C	pthreadVC.dll or pthreadGC.dll
+
+It is recommended that you let pthread.h use it's default __CLEANUP_C
+for both library and application builds. That is, don't define any of
+the above, and then link with pthreadVC.lib (MSVC or MSVC++) and
+libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but
+another reason is that the prebuilt pthreadVCE.dll is currently broken.
+Versions built with MSVC++ later than version 6 may not be broken, but I
+can't verify this yet.
+
+WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY?
+Because no commercial Unix POSIX threads implementation allows you to
+choose to have stack unwinding. Therefore, providing it in pthread-win32
+as a default is dangerous. We still provide the choice but unless
+you consciously choose to do otherwise, your pthreads applications will
+now run or crash in similar ways irrespective of the pthreads platform
+you use. Or at least this is the hope.
+
+
+Building under VC++ using C++ EH, Structured EH, or just C
+----------------------------------------------------------
+
+From the source directory run one of the following:
+
+nmake clean VC-inlined	(builds the VC setjmp/longjmp version of
+pthreadVC.dll)
+
+or:
+
+nmake clean VCE-inlined (builds the VC++ C++ EH version pthreadVCE.dll)
+
+or:
+
+nmake clean VSE-inlined (builds the VC++ structured EH version
+pthreadVSE.dll)
+
+You can run the testsuite by changing to the "tests" directory and
+running the target corresponding to the DLL version you built:
+
+nmake clean VC
+
+or:
+
+nmake clean VCE
+
+or:
+
+nmake clean VSE
+
+or:
+
+nmake clean VCX (tests the VC version of the library with C++ (EH)
+			 applications)
+
+
+Building under Mingw32
+----------------------
+
+The dll can be built easily with recent versions of Mingw32.
+(The distributed versions are built using Mingw32 and MsysDTK
+from www.mingw32.org.)
+
+From the source directory, run
+
+make clean GC-inlined
+
+or:
+
+make clean GCE-inlined
+
+You can run the testsuite by changing to the "tests" directory and
+running
+
+make clean GC
+
+or:
+
+make clean GCE
+
+or:
+
+make clean GCX	(tests the GC version of the library with C++ (EH)
+			 applications)
+
+
+Building the library under Cygwin
+---------------------------------
+
+Cygwin is implementing it's own POSIX threads routines and these
+will be the ones to use if you develop using Cygwin.
+
+
+Ready to run binaries
+---------------------
+
+For convenience, the following ready-to-run files can be downloaded
+from the FTP site (see under "Availability" below):
+
+	pthread.h
+	semaphore.h
+	sched.h
+	pthreadVC.dll	- built with MSVC compiler using C setjmp/longjmp
+	pthreadVC.lib
+	pthreadVCE.dll	- built with MSVC++ compiler using C++ EH
+	pthreadVCE.lib
+	pthreadVSE.dll	- built with MSVC compiler using SEH
+	pthreadVSE.lib
+	pthreadGC.dll	- built with Mingw32 GCC
+	libpthreadGC.a	- derived from pthreadGC.dll
+	pthreadGCE.dll	- built with Mingw32 G++
+	libpthreadGCE.a	- derived from pthreadGCE.dll
+
+As of August 2003 pthreads-win32 pthreadG* versions are built and tested
+using the MinGW + MsysDTK environment current as of that date or later.
+The following file MAY be needed for older MinGW environments.
+
+	gcc.dll 	- needed to build and run applications that use
+			  pthreadGCE.dll.
+
+
+Building applications with GNU compilers
+----------------------------------------
+
+If you're using pthreadGC.dll:
+
+With the three header files, pthreadGC.dll and libpthreadGC.a in the
+same directory as your application myapp.c, you could compile, link
+and run myapp.c under Mingw32 as follows:
+
+	gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC
+	myapp
+
+Or put pthreadGC.dll in an appropriate directory in your PATH,
+put libpthreadGC.a in your system lib directory, and
+put the three header files in your system include directory,
+then use:
+
+	gcc -o myapp.exe myapp.c -lpthreadGC
+	myapp
+
+
+If you're using pthreadGCE.dll:
+
+With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a
+in the same directory as your application myapp.c, you could compile,
+link and run myapp.c under Mingw32 as follows:
+
+	gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE
+	myapp
+
+Or put pthreadGCE.dll and gcc.dll in an appropriate directory in
+your PATH, put libpthreadGCE.a in your system lib directory, and
+put the three header files in your system include directory,
+then use:
+
+	gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE
+	myapp
+
+
+Availability
+------------
+
+The complete source code in either unbundled, self-extracting
+Zip file, or tar/gzipped format can be found at:
+
+	ftp://sources.redhat.com/pub/pthreads-win32
+
+The pre-built DLL, export libraries and matching pthread.h can
+be found at:
+
+	ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
+
+Home page:
+
+	http://sources.redhat.com/pthreads-win32/
+
+
+Mailing list
+------------
+
+There is a mailing list for discussing pthreads on Win32.
+To join, send email to:
+
+	pthreads-win32-subscribe@sources.redhat.com
+
+Unsubscribe by sending mail to:
+
+	pthreads-win32-unsubscribe@sources.redhat.com
+
+
+Acknowledgements
+----------------
+
+See the ANNOUNCE file for acknowledgements.
+See the 'CONTRIBUTORS' file for the list of contributors.
+
+As much as possible, the ChangeLog file attributes
+contributions and patches that have been incorporated
+in the library to the individuals responsible.
+
+Finally, thanks to all those who work on and contribute to the
+POSIX and Single Unix Specification standards. The maturity of an
+industry can be measured by it's open standards.
+
+----
+Ross Johnson
+<rpj@callisto.canberra.edu.au>
+
+
+
+
+
+
+
+
diff --git a/README.NONPORTABLE b/README.NONPORTABLE
index ae76862..aa43297 100644
--- a/README.NONPORTABLE
+++ b/README.NONPORTABLE
@@ -1,285 +1,285 @@
-This file documents non-portable functions and other issues.
-
-Non-portable functions included in pthreads-win32
--------------------------------------------------
-
-BOOL
-pthread_win32_test_features_np(int mask)
-
-	This routine allows an application to check which
-	run-time auto-detected features are available within
-	the library.
-
-	The possible features are:
-
-		PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE
-			Return TRUE if the native version of
-			InterlockedCompareExchange() is being used.
-		PTW32_ALERTABLE_ASYNC_CANCEL
-			Return TRUE is the QueueUserAPCEx package
-			QUSEREX.DLL is available and the AlertDrv.sys
-			driver is loaded into Windows, providing
-			alertable (pre-emptive) asyncronous threads
-			cancelation. If this feature returns FALSE
-			then the default async cancel scheme is in
-			use, which cannot cancel blocked threads.
-
-	Features may be Or'ed into the mask parameter, in which case
-	the routine returns TRUE if any of the Or'ed features would
-	return TRUE. At this stage it doesn't make sense to Or features
-	but it may some day.
-
-
-void *
-pthread_timechange_handler_np(void *)
-
-        To improve tolerance against operator or time service
-        initiated system clock changes.
-
-        This routine can be called by an application when it
-        receives a WM_TIMECHANGE message from the system. At
-        present it broadcasts all condition variables so that
-        waiting threads can wake up and re-evaluate their
-        conditions and restart their timed waits if required.
-
-        It has the same return type and argument type as a
-        thread routine so that it may be called directly
-        through pthread_create(), i.e. as a separate thread.
-
-        Parameters
-
-        Although a parameter must be supplied, it is ignored.
-        The value NULL can be used.
-
-        Return values
-
-        It can return an error EAGAIN to indicate that not
-        all condition variables were broadcast for some reason.
-        Otherwise, 0 is returned.
-
-        If run as a thread, the return value is returned
-        through pthread_join().
-
-        The return value should be cast to an integer.
-
-
-HANDLE
-pthread_getw32threadhandle_np(pthread_t thread);
-
-	Returns the win32 thread handle that the POSIX
-	thread "thread" is running as.
-
-	Applications can use the win32 handle to set
-	win32 specific attributes of the thread.
-
-
-int
-pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind)
-
-int
-pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind)
-
-        These two routines are included for Linux compatibility
-        and are direct equivalents to the standard routines
-                pthread_mutexattr_settype
-                pthread_mutexattr_gettype
-
-        pthread_mutexattr_setkind_np accepts the following
-        mutex kinds:
-                PTHREAD_MUTEX_FAST_NP
-                PTHREAD_MUTEX_ERRORCHECK_NP
-                PTHREAD_MUTEX_RECURSIVE_NP
-
-        These are really just equivalent to (respectively):
-                PTHREAD_MUTEX_NORMAL
-                PTHREAD_MUTEX_ERRORCHECK
-                PTHREAD_MUTEX_RECURSIVE
-
-int
-pthread_delay_np (const struct timespec *interval);
-
-        This routine causes a thread to delay execution for a specific period of time.
-        This period ends at the current time plus the specified interval. The routine
-        will not return before the end of the period is reached, but may return an
-        arbitrary amount of time after the period has gone by. This can be due to
-        system load, thread priorities, and system timer granularity.
-
-        Specifying an interval of zero (0) seconds and zero (0) nanoseconds is
-        allowed and can be used to force the thread to give up the processor or to
-        deliver a pending cancelation request.
-
-        This routine is a cancelation point.
-
-        The timespec structure contains the following two fields:
-
-                tv_sec is an integer number of seconds.
-                tv_nsec is an integer number of nanoseconds. 
-
-        Return Values
-
-        If an error condition occurs, this routine returns an integer value
-        indicating the type of error. Possible return values are as follows:
-
-        0          Successful completion. 
-        [EINVAL]   The value specified by interval is invalid. 
-
-int
-pthread_num_processors_np
-
-        This routine (found on HPUX systems) returns the number of processors
-        in the system. This implementation actually returns the number of
-        processors available to the process, which can be a lower number
-        than the system's number, depending on the process's affinity mask.
-
-BOOL
-pthread_win32_process_attach_np (void);
-
-BOOL
-pthread_win32_process_detach_np (void);
-
-BOOL
-pthread_win32_thread_attach_np (void);
-
-BOOL
-pthread_win32_thread_detach_np (void);
-
-	These functions contain the code normally run via dllMain
-	when the library is used as a dll but which need to be
-	called explicitly by an application when the library
-	is statically linked.
-
-	You will need to call pthread_win32_process_attach_np() before
-	you can call any pthread routines when statically linking.
-	You should call pthread_win32_process_detach_np() before
-	exiting your application to clean up.
-
-	pthread_win32_thread_attach_np() is currently a no-op, but
-	pthread_win32_thread_detach_np() is needed to clean up
-	the implicit pthread handle that is allocated to a Win32 thread if
-	it calls certain pthreads routines. Call this routine when the
-	Win32 thread exits.
-
-	These functions invariably return TRUE except for
-	pthread_win32_process_attach_np() which will return FALSE
-	if pthreads-win32 initialisation fails.
-
-int
-pthreadCancelableWait (HANDLE waitHandle);
-
-int
-pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout);
-
-	These two functions provide hooks into the pthread_cancel
-	mechanism that will allow you to wait on a Windows handle
-	and make it a cancellation point. Both functions block
-	until either the given w32 handle is signaled, or
-	pthread_cancel has been called. It is implemented using
-	WaitForMultipleObjects on 'waitHandle' and a manually
-	reset w32 event used to implement pthread_cancel.
-
-
-Non-portable issues
--------------------
-
-Thread priority
-
-	POSIX defines a single contiguous range of numbers that determine a
-	thread's priority. Win32 defines priority classes and priority
-	levels relative to these classes. Classes are simply priority base
-	levels that the defined priority levels are relative to such that,
-	changing a process's priority class will change the priority of all
-	of it's threads, while the threads retain the same relativity to each
-	other.
-
-	A Win32 system defines a single contiguous monotonic range of values
-	that define system priority levels, just like POSIX. However, Win32
-	restricts individual threads to a subset of this range on a
-	per-process basis.
-
-	The following table shows the base priority levels for combinations
-	of priority class and priority value in Win32.
-	
-	 Process Priority Class               Thread Priority Level
-	 -----------------------------------------------------------------
-	 1 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_IDLE
-	 1 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_IDLE
-	 1 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_IDLE
-	 1 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_IDLE
-	 1 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_IDLE
-	 2 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_LOWEST
-	 3 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_BELOW_NORMAL
-	 4 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_NORMAL
-	 4 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_LOWEST
-	 5 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_ABOVE_NORMAL
-	 5 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_BELOW_NORMAL
-	 5 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_LOWEST
-	 6 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_HIGHEST
-	 6 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_NORMAL
-	 6 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_BELOW_NORMAL
-	 7 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_ABOVE_NORMAL
-	 7 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_NORMAL
-	 7 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_LOWEST
- 	 8 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_HIGHEST
-	 8 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_ABOVE_NORMAL
-	 8 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_BELOW_NORMAL
-	 8 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_LOWEST
-	 9 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_HIGHEST
-	 9 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_NORMAL
-	 9 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_BELOW_NORMAL
-	10 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_ABOVE_NORMAL
-	10 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_NORMAL
-	11 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_HIGHEST
-	11 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_ABOVE_NORMAL
-	11 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_LOWEST
-	12 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_HIGHEST
-	12 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_BELOW_NORMAL
-	13 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_NORMAL
-	14 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_ABOVE_NORMAL
-	15 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_HIGHEST
-	15 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_TIME_CRITICAL
-	15 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_TIME_CRITICAL
-	15 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_TIME_CRITICAL
-	15 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_TIME_CRITICAL
-	15 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_TIME_CRITICAL
-	16 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_IDLE
-	17 REALTIME_PRIORITY_CLASS            -7
-	18 REALTIME_PRIORITY_CLASS            -6
-	19 REALTIME_PRIORITY_CLASS            -5
-	20 REALTIME_PRIORITY_CLASS            -4
-	21 REALTIME_PRIORITY_CLASS            -3
-	22 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_LOWEST
-	23 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_BELOW_NORMAL
-	24 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_NORMAL
-	25 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_ABOVE_NORMAL
-	26 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_HIGHEST
-	27 REALTIME_PRIORITY_CLASS             3
-	28 REALTIME_PRIORITY_CLASS             4
-	29 REALTIME_PRIORITY_CLASS             5
-	30 REALTIME_PRIORITY_CLASS             6
-	31 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_TIME_CRITICAL
-	
-	Windows NT:  Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.
-
-
-	As you can see, the real priority levels available to any individual
-	Win32 thread are non-contiguous.
-
-	An application using pthreads-win32 should not make assumptions about
-	the numbers used to represent thread priority levels, except that they
-	are monotonic between the values returned by sched_get_priority_min()
-	and sched_get_priority_max(). E.g. Windows 95, 98, NT, 2000, XP make
-	available a non-contiguous range of numbers between -15 and 15, while
-	at least one version of WinCE (3.0) defines the minimum priority
-	(THREAD_PRIORITY_LOWEST) as 5, and the maximum priority
-	(THREAD_PRIORITY_HIGHEST) as 1.
-
-	Internally, pthreads-win32 maps any priority levels between
-	THREAD_PRIORITY_IDLE and THREAD_PRIORITY_LOWEST to THREAD_PRIORITY_LOWEST,
-	or between THREAD_PRIORITY_TIME_CRITICAL and THREAD_PRIORITY_HIGHEST to
-	THREAD_PRIORITY_HIGHEST. Currently, this also applies to
-	REALTIME_PRIORITY_CLASSi even if levels -7, -6, -5, -4, -3, 3, 4, 5, and 6
-	are supported.
-
-	If it wishes, a Win32 application using pthreads-win32 can use the Win32
-	defined priority macros THREAD_PRIORITY_IDLE through
-	THREAD_PRIORITY_TIME_CRITICAL.
+This file documents non-portable functions and other issues.
+
+Non-portable functions included in pthreads-win32
+-------------------------------------------------
+
+BOOL
+pthread_win32_test_features_np(int mask)
+
+	This routine allows an application to check which
+	run-time auto-detected features are available within
+	the library.
+
+	The possible features are:
+
+		PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE
+			Return TRUE if the native version of
+			InterlockedCompareExchange() is being used.
+		PTW32_ALERTABLE_ASYNC_CANCEL
+			Return TRUE is the QueueUserAPCEx package
+			QUSEREX.DLL is available and the AlertDrv.sys
+			driver is loaded into Windows, providing
+			alertable (pre-emptive) asyncronous threads
+			cancelation. If this feature returns FALSE
+			then the default async cancel scheme is in
+			use, which cannot cancel blocked threads.
+
+	Features may be Or'ed into the mask parameter, in which case
+	the routine returns TRUE if any of the Or'ed features would
+	return TRUE. At this stage it doesn't make sense to Or features
+	but it may some day.
+
+
+void *
+pthread_timechange_handler_np(void *)
+
+        To improve tolerance against operator or time service
+        initiated system clock changes.
+
+        This routine can be called by an application when it
+        receives a WM_TIMECHANGE message from the system. At
+        present it broadcasts all condition variables so that
+        waiting threads can wake up and re-evaluate their
+        conditions and restart their timed waits if required.
+
+        It has the same return type and argument type as a
+        thread routine so that it may be called directly
+        through pthread_create(), i.e. as a separate thread.
+
+        Parameters
+
+        Although a parameter must be supplied, it is ignored.
+        The value NULL can be used.
+
+        Return values
+
+        It can return an error EAGAIN to indicate that not
+        all condition variables were broadcast for some reason.
+        Otherwise, 0 is returned.
+
+        If run as a thread, the return value is returned
+        through pthread_join().
+
+        The return value should be cast to an integer.
+
+
+HANDLE
+pthread_getw32threadhandle_np(pthread_t thread);
+
+	Returns the win32 thread handle that the POSIX
+	thread "thread" is running as.
+
+	Applications can use the win32 handle to set
+	win32 specific attributes of the thread.
+
+
+int
+pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind)
+
+int
+pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind)
+
+        These two routines are included for Linux compatibility
+        and are direct equivalents to the standard routines
+                pthread_mutexattr_settype
+                pthread_mutexattr_gettype
+
+        pthread_mutexattr_setkind_np accepts the following
+        mutex kinds:
+                PTHREAD_MUTEX_FAST_NP
+                PTHREAD_MUTEX_ERRORCHECK_NP
+                PTHREAD_MUTEX_RECURSIVE_NP
+
+        These are really just equivalent to (respectively):
+                PTHREAD_MUTEX_NORMAL
+                PTHREAD_MUTEX_ERRORCHECK
+                PTHREAD_MUTEX_RECURSIVE
+
+int
+pthread_delay_np (const struct timespec *interval);
+
+        This routine causes a thread to delay execution for a specific period of time.
+        This period ends at the current time plus the specified interval. The routine
+        will not return before the end of the period is reached, but may return an
+        arbitrary amount of time after the period has gone by. This can be due to
+        system load, thread priorities, and system timer granularity.
+
+        Specifying an interval of zero (0) seconds and zero (0) nanoseconds is
+        allowed and can be used to force the thread to give up the processor or to
+        deliver a pending cancelation request.
+
+        This routine is a cancelation point.
+
+        The timespec structure contains the following two fields:
+
+                tv_sec is an integer number of seconds.
+                tv_nsec is an integer number of nanoseconds. 
+
+        Return Values
+
+        If an error condition occurs, this routine returns an integer value
+        indicating the type of error. Possible return values are as follows:
+
+        0          Successful completion. 
+        [EINVAL]   The value specified by interval is invalid. 
+
+int
+pthread_num_processors_np
+
+        This routine (found on HPUX systems) returns the number of processors
+        in the system. This implementation actually returns the number of
+        processors available to the process, which can be a lower number
+        than the system's number, depending on the process's affinity mask.
+
+BOOL
+pthread_win32_process_attach_np (void);
+
+BOOL
+pthread_win32_process_detach_np (void);
+
+BOOL
+pthread_win32_thread_attach_np (void);
+
+BOOL
+pthread_win32_thread_detach_np (void);
+
+	These functions contain the code normally run via dllMain
+	when the library is used as a dll but which need to be
+	called explicitly by an application when the library
+	is statically linked.
+
+	You will need to call pthread_win32_process_attach_np() before
+	you can call any pthread routines when statically linking.
+	You should call pthread_win32_process_detach_np() before
+	exiting your application to clean up.
+
+	pthread_win32_thread_attach_np() is currently a no-op, but
+	pthread_win32_thread_detach_np() is needed to clean up
+	the implicit pthread handle that is allocated to a Win32 thread if
+	it calls certain pthreads routines. Call this routine when the
+	Win32 thread exits.
+
+	These functions invariably return TRUE except for
+	pthread_win32_process_attach_np() which will return FALSE
+	if pthreads-win32 initialisation fails.
+
+int
+pthreadCancelableWait (HANDLE waitHandle);
+
+int
+pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout);
+
+	These two functions provide hooks into the pthread_cancel
+	mechanism that will allow you to wait on a Windows handle
+	and make it a cancellation point. Both functions block
+	until either the given w32 handle is signaled, or
+	pthread_cancel has been called. It is implemented using
+	WaitForMultipleObjects on 'waitHandle' and a manually
+	reset w32 event used to implement pthread_cancel.
+
+
+Non-portable issues
+-------------------
+
+Thread priority
+
+	POSIX defines a single contiguous range of numbers that determine a
+	thread's priority. Win32 defines priority classes and priority
+	levels relative to these classes. Classes are simply priority base
+	levels that the defined priority levels are relative to such that,
+	changing a process's priority class will change the priority of all
+	of it's threads, while the threads retain the same relativity to each
+	other.
+
+	A Win32 system defines a single contiguous monotonic range of values
+	that define system priority levels, just like POSIX. However, Win32
+	restricts individual threads to a subset of this range on a
+	per-process basis.
+
+	The following table shows the base priority levels for combinations
+	of priority class and priority value in Win32.
+	
+	 Process Priority Class               Thread Priority Level
+	 -----------------------------------------------------------------
+	 1 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_IDLE
+	 1 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_IDLE
+	 1 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_IDLE
+	 1 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_IDLE
+	 1 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_IDLE
+	 2 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_LOWEST
+	 3 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_BELOW_NORMAL
+	 4 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_NORMAL
+	 4 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_LOWEST
+	 5 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_ABOVE_NORMAL
+	 5 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_BELOW_NORMAL
+	 5 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_LOWEST
+	 6 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_HIGHEST
+	 6 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_NORMAL
+	 6 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_BELOW_NORMAL
+	 7 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_ABOVE_NORMAL
+	 7 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_NORMAL
+	 7 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_LOWEST
+ 	 8 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_HIGHEST
+	 8 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_ABOVE_NORMAL
+	 8 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_BELOW_NORMAL
+	 8 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_LOWEST
+	 9 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_HIGHEST
+	 9 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_NORMAL
+	 9 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_BELOW_NORMAL
+	10 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_ABOVE_NORMAL
+	10 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_NORMAL
+	11 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_HIGHEST
+	11 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_ABOVE_NORMAL
+	11 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_LOWEST
+	12 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_HIGHEST
+	12 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_BELOW_NORMAL
+	13 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_NORMAL
+	14 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_ABOVE_NORMAL
+	15 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_HIGHEST
+	15 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_TIME_CRITICAL
+	15 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_TIME_CRITICAL
+	15 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_TIME_CRITICAL
+	15 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_TIME_CRITICAL
+	15 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_TIME_CRITICAL
+	16 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_IDLE
+	17 REALTIME_PRIORITY_CLASS            -7
+	18 REALTIME_PRIORITY_CLASS            -6
+	19 REALTIME_PRIORITY_CLASS            -5
+	20 REALTIME_PRIORITY_CLASS            -4
+	21 REALTIME_PRIORITY_CLASS            -3
+	22 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_LOWEST
+	23 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_BELOW_NORMAL
+	24 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_NORMAL
+	25 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_ABOVE_NORMAL
+	26 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_HIGHEST
+	27 REALTIME_PRIORITY_CLASS             3
+	28 REALTIME_PRIORITY_CLASS             4
+	29 REALTIME_PRIORITY_CLASS             5
+	30 REALTIME_PRIORITY_CLASS             6
+	31 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_TIME_CRITICAL
+	
+	Windows NT:  Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.
+
+
+	As you can see, the real priority levels available to any individual
+	Win32 thread are non-contiguous.
+
+	An application using pthreads-win32 should not make assumptions about
+	the numbers used to represent thread priority levels, except that they
+	are monotonic between the values returned by sched_get_priority_min()
+	and sched_get_priority_max(). E.g. Windows 95, 98, NT, 2000, XP make
+	available a non-contiguous range of numbers between -15 and 15, while
+	at least one version of WinCE (3.0) defines the minimum priority
+	(THREAD_PRIORITY_LOWEST) as 5, and the maximum priority
+	(THREAD_PRIORITY_HIGHEST) as 1.
+
+	Internally, pthreads-win32 maps any priority levels between
+	THREAD_PRIORITY_IDLE and THREAD_PRIORITY_LOWEST to THREAD_PRIORITY_LOWEST,
+	or between THREAD_PRIORITY_TIME_CRITICAL and THREAD_PRIORITY_HIGHEST to
+	THREAD_PRIORITY_HIGHEST. Currently, this also applies to
+	REALTIME_PRIORITY_CLASSi even if levels -7, -6, -5, -4, -3, 3, 4, 5, and 6
+	are supported.
+
+	If it wishes, a Win32 application using pthreads-win32 can use the Win32
+	defined priority macros THREAD_PRIORITY_IDLE through
+	THREAD_PRIORITY_TIME_CRITICAL.
diff --git a/TODO b/TODO
index f798e76..fa9efc4 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
-                   Things that aren't done yet
-                   ---------------------------
-
-1. Implement PTHREAD_PROCESS_SHARED for semaphores, mutexes,
-   condition variables, read/write locks, barriers.
-
-
+                   Things that aren't done yet
+                   ---------------------------
+
+1. Implement PTHREAD_PROCESS_SHARED for semaphores, mutexes,
+   condition variables, read/write locks, barriers.
+
+
diff --git a/cleanup.c b/cleanup.c
index 39f8404..3b82876 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -73,7 +73,7 @@ ptw32_pop_cleanup (int execute)
       * ------------------------------------------------------
       */
 {
-  ptw32_cleanup_t *cleanup = NULL;
+  ptw32_cleanup_t *cleanup;
 
   cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
 
@@ -106,7 +106,7 @@ ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
       *      popped and invoked with the argument 'arg' when
       *              a) the thread exits by calling 'pthread_exit',
       *              b) when the thread acts on a cancellation request,
-      *              c) or when the thrad calls pthread_cleanup_pop with a nonzero
+      *              c) or when the thread calls pthread_cleanup_pop with a nonzero
       *                 'execute' argument
       *
       * PARAMETERS
diff --git a/create.c b/create.c
index 048088b..e71ba38 100644
--- a/create.c
+++ b/create.c
@@ -84,6 +84,7 @@ pthread_create (pthread_t * tid,
       */
 {
   pthread_t thread;
+  ptw32_thread_t * tp;
   register pthread_attr_t a;
   HANDLE threadH = 0;
   int result = EAGAIN;
@@ -98,7 +99,7 @@ pthread_create (pthread_t * tid,
    * Make sure that the assignment below can't be optimised out by the compiler.
    * This is assured by conditionally assigning *tid again at the end.
    */
-  *tid = NULL;
+  tid->x = 0;
 
   if (attr != NULL)
     {
@@ -109,12 +110,14 @@ pthread_create (pthread_t * tid,
       a = NULL;
     }
 
-  if ((thread = ptw32_new ()) == NULL)
+  if ((thread = ptw32_new ()).p == NULL)
     {
       goto FAIL0;
     }
 
-  priority = thread->sched_priority;
+  tp = (ptw32_thread_t *) thread.p;
+
+  priority = tp->sched_priority;
 
   if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL)
     {
@@ -128,12 +131,12 @@ pthread_create (pthread_t * tid,
   if (a != NULL)
     {
       stackSize = a->stacksize;
-      thread->detachState = a->detachstate;
+      tp->detachState = a->detachstate;
       priority = a->param.sched_priority;
 
 #if HAVE_SIGSET_T
 
-      thread->sigmask = a->sigmask;
+      tp->sigmask = a->sigmask;
 
 #endif /* HAVE_SIGSET_T */
 
@@ -162,7 +165,7 @@ pthread_create (pthread_t * tid,
 	   * system adjustment. This is not the case for POSIX threads.
 	   */
 	  pthread_t self = pthread_self ();
-	  priority = self->sched_priority;
+	  priority = ((ptw32_thread_t *) self.p)->sched_priority;
 	}
 
 #endif
@@ -176,29 +179,30 @@ pthread_create (pthread_t * tid,
       stackSize = PTHREAD_STACK_MIN;
     }
 
-  thread->state = run ? PThreadStateInitial : PThreadStateSuspended;
+  tp->state = run ? PThreadStateInitial : PThreadStateSuspended;
 
-  thread->keys = NULL;
+  tp->keys = NULL;
 
   /*
    * Threads must be started in suspended mode and resumed if necessary
    * after _beginthreadex returns us the handle. Otherwise we set up a
    * race condition between the creating and the created threads.
    * Note that we also retain a local copy of the handle for use
-   * by us in case thread->threadH gets NULLed later but before we've
+   * by us in case thread.p->threadH gets NULLed later but before we've
    * finished with it here.
    */
 
 #if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) 
 
-  thread->threadH = threadH = (HANDLE) _beginthreadex ((void *) NULL,	/* No security info             */
-						       (unsigned) stackSize,	/* default stack size   */
-						       ptw32_threadStart,
-						       parms,
-						       (unsigned)
-						       CREATE_SUSPENDED,
-						       (unsigned *) &(thread->
-								      thread));
+  tp->threadH =
+    threadH =
+    (HANDLE) _beginthreadex ((void *) NULL,	/* No security info             */
+			     (unsigned) stackSize,	/* default stack size   */
+			     ptw32_threadStart,
+			     parms,
+			     (unsigned)
+			     CREATE_SUSPENDED,
+			     (unsigned *) &(tp->thread));
 
   if (threadH != 0)
     {
@@ -219,17 +223,19 @@ pthread_create (pthread_t * tid,
    * This lock will force pthread_threadStart() to wait until we have
    * the thread handle and have set the priority.
    */
-  (void) pthread_mutex_lock (&thread->cancelLock);
+  (void) pthread_mutex_lock (&tp->cancelLock);
 
-  thread->threadH = threadH = (HANDLE) _beginthread (ptw32_threadStart, (unsigned) stackSize,	/* default stack size   */
-						     parms);
+  tp->threadH =
+    threadH =
+    (HANDLE) _beginthread (ptw32_threadStart, (unsigned) stackSize,	/* default stack size   */
+			   parms);
 
   /*
    * Make the return code match _beginthreadex's.
    */
   if (threadH == (HANDLE) - 1L)
     {
-      thread->threadH = threadH = 0;
+      tp->threadH = threadH = 0;
     }
   else
     {
@@ -249,7 +255,7 @@ pthread_create (pthread_t * tid,
 	}
     }
 
-  (void) pthread_mutex_unlock (&thread->cancelLock);
+  (void) pthread_mutex_unlock (&tp->cancelLock);
 
 #endif /* __MINGW32__ && ! __MSVCRT__ */
 
@@ -270,7 +276,7 @@ FAIL0:
     {
 
       ptw32_threadDestroy (thread);
-      thread = NULL;
+      tp = NULL;
 
       if (parms != NULL)
 	{
diff --git a/dll.c b/dll.c
index d9c3176..ff75c68 100644
--- a/dll.c
+++ b/dll.c
@@ -37,10 +37,6 @@
 #include "pthread.h"
 #include "implement.h"
 
-#if 1
-#include <stdio.h>
-#endif
-
 #ifdef _MSC_VER
 /* 
  * lpvReserved yields an unreferenced formal parameter;
@@ -86,6 +82,7 @@ DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
       result = pthread_win32_process_detach_np ();
       break;
     }
+
   return (result);
 
 }				/* DllMain */
diff --git a/global.c b/global.c
index f3f18cb..d2f8252 100644
--- a/global.c
+++ b/global.c
@@ -40,7 +40,8 @@
 
 
 int ptw32_processInitialized = PTW32_FALSE;
-pthread_t ptw32_threadReuseTop = PTW32_THREAD_REUSE_BOTTOM;
+ptw32_thread_t * ptw32_threadReuseTop = PTW32_THREAD_REUSE_EMPTY;
+ptw32_thread_t * ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
 pthread_key_t ptw32_selfThreadKey = NULL;
 pthread_key_t ptw32_cleanupKey = NULL;
 pthread_cond_t ptw32_cond_list_head = NULL;
diff --git a/implement.h b/implement.h
index 1f6179e..ed8f2a0 100644
--- a/implement.h
+++ b/implement.h
@@ -38,6 +38,9 @@
 #ifndef _IMPLEMENT_H
 #define _IMPLEMENT_H
 
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
 #define _WIN32_WINNT 0x400
 
 #include <windows.h>
@@ -97,6 +100,8 @@ typedef enum
   PThreadStateInitial = 0,	/* Thread not running                   */
   PThreadStateRunning,		/* Thread alive & kicking               */
   PThreadStateSuspended,	/* Thread alive but suspended           */
+  PThreadStateCancelPending,	/* Thread alive but is                  */
+  /* has cancelation pending.        */
   PThreadStateCanceling,	/* Thread alive but is                  */
   /* in the process of terminating        */
   /* due to a cancellation request        */
@@ -107,15 +112,18 @@ typedef enum
 PThreadState;
 
 
-struct pthread_t_
+typedef struct ptw32_thread_t_ ptw32_thread_t;
+
+struct ptw32_thread_t_
 {
 #ifdef _UWIN
   DWORD dummy[5];
 #endif
   DWORD thread;
-  HANDLE threadH;		/* POSIX thread is invalid if threadH == 0 */
-  pthread_t prevReuse;		/* Links threads on reuse stack */
-  PThreadState state;
+  HANDLE threadH;		/* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
+  pthread_t ptHandle;		/* This thread's permanent pthread_t handle */
+  ptw32_thread_t * prevReuse;	/* Links threads on reuse stack */
+  volatile PThreadState state;
   void *exitStatus;
   void *parms;
   int ptErrno;
@@ -440,10 +448,11 @@ extern PTW32_INTERLOCKED_LONG (WINAPI *
 extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD);
 
 /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
-#define PTW32_THREAD_REUSE_BOTTOM ((pthread_t) 1)
+#define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *) 1)
 
 extern int ptw32_processInitialized;
-extern pthread_t ptw32_threadReuseTop;
+extern ptw32_thread_t * ptw32_threadReuseTop;
+extern ptw32_thread_t * ptw32_threadReuseBottom;
 extern pthread_key_t ptw32_selfThreadKey;
 extern pthread_key_t ptw32_cleanupKey;
 extern pthread_cond_t ptw32_cond_list_head;
diff --git a/pthread.h b/pthread.h
index 9975eb1..f2f6323 100644
--- a/pthread.h
+++ b/pthread.h
@@ -519,20 +519,30 @@ extern "C"
 #if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
 #   include     <sys/types.h>
 #else
-typedef struct pthread_t_ * volatile pthread_t;
-typedef struct pthread_attr_t_ * volatile pthread_attr_t;
+/*
+ * Generic handle type - intended to extend uniqueness beyond
+ * that available with a simple pointer. It should scale for either
+ * IA-32 or IA-64.
+ */
+typedef struct {
+    void * p;                   /* Pointer to actual object */
+    unsigned int x;             /* Extra information - reuse count etc */
+} ptw32_handle_t;
+
+typedef ptw32_handle_t pthread_t;
+typedef struct pthread_attr_t_ * pthread_attr_t;
 typedef struct pthread_once_t_ pthread_once_t;
-typedef struct pthread_key_t_ * volatile pthread_key_t;
-typedef struct pthread_mutex_t_ * volatile pthread_mutex_t;
-typedef struct pthread_mutexattr_t_ * volatile pthread_mutexattr_t;
-typedef struct pthread_cond_t_ * volatile pthread_cond_t;
-typedef struct pthread_condattr_t_ * volatile pthread_condattr_t;
+typedef struct pthread_key_t_ * pthread_key_t;
+typedef struct pthread_mutex_t_ * pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
+typedef struct pthread_cond_t_ * pthread_cond_t;
+typedef struct pthread_condattr_t_ * pthread_condattr_t;
 #endif
-typedef struct pthread_rwlock_t_ * volatile pthread_rwlock_t;
-typedef struct pthread_rwlockattr_t_ * volatile pthread_rwlockattr_t;
-typedef struct pthread_spinlock_t_ * volatile pthread_spinlock_t;
-typedef struct pthread_barrier_t_ * volatile pthread_barrier_t;
-typedef struct pthread_barrierattr_t_ * volatile pthread_barrierattr_t;
+typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
+typedef struct pthread_barrier_t_ * pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
 
 /*
  * ====================
diff --git a/pthread_cancel.c b/pthread_cancel.c
index 69cec3b..c12a44d 100644
--- a/pthread_cancel.c
+++ b/pthread_cancel.c
@@ -121,6 +121,7 @@ pthread_cancel (pthread_t thread)
   int result;
   int cancel_self;
   pthread_t self;
+  ptw32_thread_t * tp;
 
   /* This is the proper way to test thread validity. */
   result = pthread_kill (thread, 0);
@@ -129,7 +130,7 @@ pthread_cancel (pthread_t thread)
       return result;
     }
 
-  if ((self = pthread_self ()) == NULL)
+  if ((self = pthread_self ()).p == NULL)
     {
       return ENOMEM;
     };
@@ -150,35 +151,37 @@ pthread_cancel (pthread_t thread)
    */
   cancel_self = pthread_equal (thread, self);
 
+  tp = (ptw32_thread_t *) thread.p;
+
   /*
    * Lock for async-cancel safety.
    */
-  (void) pthread_mutex_lock (&thread->cancelLock);
+  (void) pthread_mutex_lock (&tp->cancelLock);
 
-  if (thread->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
-      && thread->cancelState == PTHREAD_CANCEL_ENABLE
-      && thread->state < PThreadStateCanceling)
+  if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
+      && tp->cancelState == PTHREAD_CANCEL_ENABLE
+      && tp->state < PThreadStateCanceling)
     {
       if (cancel_self)
 	{
-	  thread->state = PThreadStateCanceling;
-	  thread->cancelState = PTHREAD_CANCEL_DISABLE;
+	  tp->state = PThreadStateCanceling;
+	  tp->cancelState = PTHREAD_CANCEL_DISABLE;
 
-	  (void) pthread_mutex_unlock (&thread->cancelLock);
+	  (void) pthread_mutex_unlock (&tp->cancelLock);
 	  ptw32_throw (PTW32_EPS_CANCEL);
 
 	  /* Never reached */
 	}
       else
 	{
-	  HANDLE threadH = thread->threadH;
+	  HANDLE threadH = tp->threadH;
 
 	  SuspendThread (threadH);
 
 	  if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT)
 	    {
-	      thread->state = PThreadStateCanceling;
-	      thread->cancelState = PTHREAD_CANCEL_DISABLE;
+	      tp->state = PThreadStateCanceling;
+	      tp->cancelState = PTHREAD_CANCEL_DISABLE;
 	      /*
 	       * If alertdrv and QueueUserAPCEx is available then the following
 	       * will result in a call to QueueUserAPCEx with the args given, otherwise
@@ -186,7 +189,7 @@ pthread_cancel (pthread_t thread)
 	       * the threadH arg will be used.
 	       */
 	      ptw32_register_cancelation (ptw32_cancel_callback, threadH, 0);
-	      (void) pthread_mutex_unlock (&thread->cancelLock);
+	      (void) pthread_mutex_unlock (&tp->cancelLock);
 	      ResumeThread (threadH);
 	    }
 	}
@@ -196,13 +199,20 @@ pthread_cancel (pthread_t thread)
       /*
        * Set for deferred cancellation.
        */
-      if (thread->state >= PThreadStateCanceling
-	  || !SetEvent (thread->cancelEvent))
+      if (tp->state < PThreadStateCancelPending)
+	{
+	  tp->state = PThreadStateCancelPending;
+	  if (!SetEvent (tp->cancelEvent))
+	    {
+	      result = ESRCH;
+	    }
+	}
+      else if (tp->state >= PThreadStateCanceling)
 	{
 	  result = ESRCH;
 	}
 
-      (void) pthread_mutex_unlock (&thread->cancelLock);
+      (void) pthread_mutex_unlock (&tp->cancelLock);
     }
 
   return (result);
diff --git a/pthread_cond_destroy.c b/pthread_cond_destroy.c
index 7a34068..b788f9c 100644
--- a/pthread_cond_destroy.c
+++ b/pthread_cond_destroy.c
@@ -38,7 +38,6 @@
 #include "pthread.h"
 #include "implement.h"
 
-
 int
 pthread_cond_destroy (pthread_cond_t * cond)
      /*
diff --git a/pthread_cond_wait.c b/pthread_cond_wait.c
index 6db2a48..241f464 100644
--- a/pthread_cond_wait.c
+++ b/pthread_cond_wait.c
@@ -283,6 +283,17 @@ ptw32_cond_wait_cleanup (void *args)
   int nSignalsWasLeft;
   int result;
 
+  /*
+   * XSH: Upon successful return, the mutex has been locked and is owned
+   * by the calling thread. This must be done before any cancelation
+   * cleanup handlers are run.
+   */
+  if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0)
+    {
+      *resultPtr = result;
+      return;
+    }
+
   /*
    * Whether we got here as a result of signal/broadcast or because of
    * timeout on wait or thread cancellation we indicate that we are no
@@ -340,16 +351,6 @@ ptw32_cond_wait_cleanup (void *args)
 	  return;
 	}
     }
-
-  /*
-   * XSH: Upon successful return, the mutex has been locked and is owned
-   * by the calling thread
-   */
-  if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0)
-    {
-      *resultPtr = result;
-    }
-
 }				/* ptw32_cond_wait_cleanup */
 
 static INLINE int
diff --git a/pthread_delay_np.c b/pthread_delay_np.c
index ee9b2d9..c699a31 100644
--- a/pthread_delay_np.c
+++ b/pthread_delay_np.c
@@ -86,6 +86,7 @@ pthread_delay_np (struct timespec *interval)
   DWORD millisecs;
   DWORD status;
   pthread_t self;
+  ptw32_thread_t * sp;
 
   if (interval == NULL)
     {
@@ -124,34 +125,36 @@ pthread_delay_np (struct timespec *interval)
 #pragma enable_message (124)
 #endif
 
-  if (NULL == (self = pthread_self ()))
+  if (NULL == (self = pthread_self ()).p)
     {
       return ENOMEM;
     }
 
-  if (self->cancelState == PTHREAD_CANCEL_ENABLE)
+  sp = (ptw32_thread_t *) self.p;
+
+  if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
     {
       /*
        * Async cancelation won't catch us until wait_time is up.
        * Deferred cancelation will cancel us immediately.
        */
       if (WAIT_OBJECT_0 ==
-	  (status = WaitForSingleObject (self->cancelEvent, wait_time)))
+	  (status = WaitForSingleObject (sp->cancelEvent, wait_time)))
 	{
 	  /*
 	   * Canceling!
 	   */
-	  (void) pthread_mutex_lock (&self->cancelLock);
-	  if (self->state < PThreadStateCanceling)
+	  (void) pthread_mutex_lock (&sp->cancelLock);
+	  if (sp->state < PThreadStateCanceling)
 	    {
-	      self->state = PThreadStateCanceling;
-	      self->cancelState = PTHREAD_CANCEL_DISABLE;
-	      (void) pthread_mutex_unlock (&self->cancelLock);
+	      sp->state = PThreadStateCanceling;
+	      sp->cancelState = PTHREAD_CANCEL_DISABLE;
+	      (void) pthread_mutex_unlock (&sp->cancelLock);
 
 	      ptw32_throw (PTW32_EPS_CANCEL);
 	    }
 
-	  (void) pthread_mutex_unlock (&self->cancelLock);
+	  (void) pthread_mutex_unlock (&sp->cancelLock);
 	  return ESRCH;
 	}
       else if (status != WAIT_TIMEOUT)
diff --git a/pthread_detach.c b/pthread_detach.c
index a376cf2..df2c542 100644
--- a/pthread_detach.c
+++ b/pthread_detach.c
@@ -75,6 +75,7 @@ pthread_detach (pthread_t thread)
       */
 {
   int result;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
 
   /* This is the proper way to test for a valid thread. */
   result = pthread_kill (thread, 0);
@@ -83,14 +84,14 @@ pthread_detach (pthread_t thread)
       return result;
     }
 
-  if (thread->detachState == PTHREAD_CREATE_DETACHED)
+  if (tp->detachState == PTHREAD_CREATE_DETACHED)
     {
       result = EINVAL;
     }
   else
     {
       result = 0;
-      thread->detachState = PTHREAD_CREATE_DETACHED;
+      tp->detachState = PTHREAD_CREATE_DETACHED;
     }
 
   return (result);
diff --git a/pthread_equal.c b/pthread_equal.c
index f7965e4..377316b 100644
--- a/pthread_equal.c
+++ b/pthread_equal.c
@@ -69,7 +69,7 @@ pthread_equal (pthread_t t1, pthread_t t2)
    * We also accept NULL == NULL - treating NULL as a thread
    * for this special case, because there is no error that we can return.
    */
-  result = ( t1 == t2 );
+  result = ( t1.p == t2.p && t1.x == t2.x );
 
   return (result);
 
diff --git a/pthread_exit.c b/pthread_exit.c
index c8fb4fb..aadff5c 100644
--- a/pthread_exit.c
+++ b/pthread_exit.c
@@ -65,20 +65,20 @@ pthread_exit (void *value_ptr)
       * ------------------------------------------------------
       */
 {
-  pthread_t self;
+  ptw32_thread_t * sp;
 
   /*
    * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
    * unnecessarily.
    */
-  self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
+  sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
 
 #ifdef _UWIN
   if (--pthread_count <= 0)
     exit ((int) value_ptr);
 #endif
 
-  if (NULL == self)
+  if (NULL == sp)
     {
       /*
        * A POSIX thread handle was never created. I.e. this is a
@@ -97,7 +97,7 @@ pthread_exit (void *value_ptr)
       /* Never reached */
     }
 
-  self->exitStatus = value_ptr;
+  sp->exitStatus = value_ptr;
 
   ptw32_throw (PTW32_EPS_EXIT);
 
diff --git a/pthread_getschedparam.c b/pthread_getschedparam.c
index d968aa5..edeb5b4 100644
--- a/pthread_getschedparam.c
+++ b/pthread_getschedparam.c
@@ -69,7 +69,7 @@ pthread_getschedparam (pthread_t thread, int *policy,
    * for the target thread. It must not return the actual thread
    * priority as altered by any system priority adjustments etc.
    */
-  param->sched_priority = thread->sched_priority;
+  param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority;
 
   return 0;
 }
diff --git a/pthread_getw32threadhandle_np.c b/pthread_getw32threadhandle_np.c
index fcf1288..9ac81a7 100644
--- a/pthread_getw32threadhandle_np.c
+++ b/pthread_getw32threadhandle_np.c
@@ -49,5 +49,5 @@
 HANDLE
 pthread_getw32threadhandle_np (pthread_t thread)
 {
-  return (thread != NULL) ? (thread->threadH) : 0;
+  return ((ptw32_thread_t *)thread.p)->threadH;
 }
diff --git a/pthread_join.c b/pthread_join.c
index 89ee1a5..ba2d3da 100644
--- a/pthread_join.c
+++ b/pthread_join.c
@@ -82,6 +82,7 @@ pthread_join (pthread_t thread, void **value_ptr)
 {
   int result;
   pthread_t self;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
 
   /*
    * Possibilities for the target thread on entry to pthread_join():
@@ -134,13 +135,13 @@ pthread_join (pthread_t thread, void **value_ptr)
    * so that we can use the reuse_lock to ensure the thread isn't destroyed
    * and reused before we've finished with the POSIX thread struct.
    */
-  if (NULL == thread
-      || NULL == thread->threadH
-      || THREAD_PRIORITY_ERROR_RETURN == GetThreadPriority (thread->threadH))
+  if (tp == NULL
+      || NULL == tp->threadH
+      || THREAD_PRIORITY_ERROR_RETURN == GetThreadPriority (tp->threadH))
     {
       result = ESRCH;
     }
-  else if (PTHREAD_CREATE_DETACHED == thread->detachState)
+  else if (PTHREAD_CREATE_DETACHED == tp->detachState)
     {
       result = EINVAL;
     }
@@ -152,7 +153,9 @@ pthread_join (pthread_t thread, void **value_ptr)
 
       LeaveCriticalSection (&ptw32_thread_reuse_lock);
 
-      if (NULL == (self = pthread_self ()))
+      self = pthread_self();
+
+      if (NULL == self.p)
 	{
 	  result = ENOENT;
 	}
@@ -169,7 +172,7 @@ pthread_join (pthread_t thread, void **value_ptr)
 	   * pthreadCancelableWait will not return if we
 	   * are canceled.
 	   */
-	  result = pthreadCancelableWait (thread->threadH);
+	  result = pthreadCancelableWait (tp->threadH);
 
 	  if (0 == result)
 	    {
@@ -177,7 +180,7 @@ pthread_join (pthread_t thread, void **value_ptr)
 #if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
 
 	      if (value_ptr != NULL
-		  && !GetExitCodeThread (thread->threadH, (LPDWORD) value_ptr))
+		  && !GetExitCodeThread (tp->threadH, (LPDWORD) value_ptr))
 		{
 		  result = ESRCH;
 		}
@@ -198,7 +201,7 @@ pthread_join (pthread_t thread, void **value_ptr)
 	       */
 	      if (value_ptr != NULL)
 		{
-		  *value_ptr = thread->exitStatus;
+		  *value_ptr = tp->exitStatus;
 		}
 
 	      /*
diff --git a/pthread_kill.c b/pthread_kill.c
index c40235c..4cb62c1 100644
--- a/pthread_kill.c
+++ b/pthread_kill.c
@@ -74,12 +74,16 @@ pthread_kill (pthread_t thread, int sig)
       */
 {
   int result = 0;
+  ptw32_thread_t * tp;
 
   EnterCriticalSection (&ptw32_thread_reuse_lock);
 
-  if (NULL == thread
-      || NULL == thread->threadH
-      || THREAD_PRIORITY_ERROR_RETURN == GetThreadPriority (thread->threadH))
+  tp = (ptw32_thread_t *) thread.p;
+
+  if (NULL == tp
+      || thread.x != tp->ptHandle.x
+      || NULL == tp->threadH
+      || THREAD_PRIORITY_ERROR_RETURN == GetThreadPriority (tp->threadH))
     {
       result = ESRCH;
     }
diff --git a/pthread_mutex_init.c b/pthread_mutex_init.c
index 0709690..4a6a47b 100644
--- a/pthread_mutex_init.c
+++ b/pthread_mutex_init.c
@@ -84,7 +84,7 @@ pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
       mx->recursive_count = 0;
       mx->kind = (attr == NULL || *attr == NULL
 		  ? PTHREAD_MUTEX_DEFAULT : (*attr)->kind);
-      mx->ownerThread = NULL;
+      mx->ownerThread.p = NULL;
 
       mx->event = CreateEvent (NULL, PTW32_FALSE,    /* manual reset = No */
                               PTW32_FALSE,           /* initial state = not signaled */
diff --git a/pthread_mutex_unlock.c b/pthread_mutex_unlock.c
index 9002df5..113ca68 100644
--- a/pthread_mutex_unlock.c
+++ b/pthread_mutex_unlock.c
@@ -73,7 +73,7 @@ pthread_mutex_unlock (pthread_mutex_t * mutex)
 		   * release one waiter if possible, otherwise
 		   * it will just reset the event.
 		   */
-		  if (PulseEvent (mx->event) == 0)
+		  if (SetEvent (mx->event) == 0)
 		    {
 		      result = EINVAL;
 		    }
@@ -94,13 +94,13 @@ pthread_mutex_unlock (pthread_mutex_t * mutex)
 	      if (mx->kind != PTHREAD_MUTEX_RECURSIVE
 		  || 0 == --mx->recursive_count)
 		{
-		  mx->ownerThread = NULL;
+		  mx->ownerThread.p = NULL;
 
 		  if ((LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx,
 							 (LONG) 0) < 0)
 		    {
 		      /* Someone may be waiting on that mutex */
-		      if (PulseEvent (mx->event) == 0)
+		      if (SetEvent (mx->event) == 0)
 			{
 			  result = EINVAL;
 			}
diff --git a/pthread_self.c b/pthread_self.c
index 5cad22a..a505a8f 100644
--- a/pthread_self.c
+++ b/pthread_self.c
@@ -37,7 +37,6 @@
 #include "pthread.h"
 #include "implement.h"
 
-
 pthread_t
 pthread_self (void)
      /*
@@ -61,23 +60,30 @@ pthread_self (void)
       */
 {
   pthread_t self;
+  pthread_t nil = {NULL, 0};
+  ptw32_thread_t * sp;
 
 #ifdef _UWIN
   if (!ptw32_selfThreadKey)
-    return (NULL);
+    return nil;
 #endif
 
-  self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
+  sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
 
-  if (self == NULL)
+  if (sp != NULL)
+    {
+      self = sp->ptHandle;
+    }
+  else
     {
       /*
        * Need to create an implicit 'self' for the currently
        * executing thread.
        */
       self = ptw32_new ();
+      sp = (ptw32_thread_t *) self.p;
 
-      if (self != NULL)
+      if (sp != NULL)
 	{
 	  /*
 	   * This is a non-POSIX thread which has chosen to call
@@ -85,9 +91,9 @@ pthread_self (void)
 	   * it isn't joinable, but we do assume that it's
 	   * (deferred) cancelable.
 	   */
-	  self->implicit = 1;
-	  self->detachState = PTHREAD_CREATE_DETACHED;
-	  self->thread = GetCurrentThreadId ();
+	  sp->implicit = 1;
+	  sp->detachState = PTHREAD_CREATE_DETACHED;
+	  sp->thread = GetCurrentThreadId ();
 
 #ifdef NEED_DUPLICATEHANDLE
 	  /*
@@ -99,17 +105,21 @@ pthread_self (void)
 	   * Therefore, you should not pass the handle to
 	   * other threads for whatever purpose.
 	   */
-	  self->threadH = GetCurrentThread ();
+	  sp->threadH = GetCurrentThread ();
 #else
 	  if (!DuplicateHandle (GetCurrentProcess (),
 				GetCurrentThread (),
 				GetCurrentProcess (),
-				&self->threadH,
+				&sp->threadH,
 				0, FALSE, DUPLICATE_SAME_ACCESS))
 	    {
-	      /* Thread structs are never freed. */
+	      /*
+	       * Should not do this, but we have no alternative if
+	       * we can't get a Win32 thread handle.
+	       * Thread structs are never freed.
+	       */
 	      ptw32_threadReusePush (self);
-	      return (NULL);
+	      return nil;
 	    }
 #endif
 
@@ -117,10 +127,10 @@ pthread_self (void)
 	   * No need to explicitly serialise access to sched_priority
 	   * because the new handle is not yet public.
 	   */
-	  self->sched_priority = GetThreadPriority (self->threadH);
-	}
+	  sp->sched_priority = GetThreadPriority (sp->threadH);
 
-      pthread_setspecific (ptw32_selfThreadKey, self);
+          pthread_setspecific (ptw32_selfThreadKey, (void *) sp);
+	}
     }
 
   return (self);
diff --git a/pthread_setcancelstate.c b/pthread_setcancelstate.c
index 4432a6f..337fb58 100644
--- a/pthread_setcancelstate.c
+++ b/pthread_setcancelstate.c
@@ -81,8 +81,9 @@ pthread_setcancelstate (int state, int *oldstate)
 {
   int result = 0;
   pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
 
-  if (self == NULL
+  if (sp == NULL
       || (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE))
     {
       return EINVAL;
@@ -91,32 +92,32 @@ pthread_setcancelstate (int state, int *oldstate)
   /*
    * Lock for async-cancel safety.
    */
-  (void) pthread_mutex_lock (&self->cancelLock);
+  (void) pthread_mutex_lock (&sp->cancelLock);
 
   if (oldstate != NULL)
     {
-      *oldstate = self->cancelState;
+      *oldstate = sp->cancelState;
     }
 
-  self->cancelState = state;
+  sp->cancelState = state;
 
   /*
    * Check if there is a pending asynchronous cancel
    */
   if (state == PTHREAD_CANCEL_ENABLE
-      && self->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
-      && WaitForSingleObject (self->cancelEvent, 0) == WAIT_OBJECT_0)
+      && sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
+      && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
     {
-      self->state = PThreadStateCanceling;
-      self->cancelState = PTHREAD_CANCEL_DISABLE;
-      ResetEvent (self->cancelEvent);
-      (void) pthread_mutex_unlock (&self->cancelLock);
+      sp->state = PThreadStateCanceling;
+      sp->cancelState = PTHREAD_CANCEL_DISABLE;
+      ResetEvent (sp->cancelEvent);
+      (void) pthread_mutex_unlock (&sp->cancelLock);
       ptw32_throw (PTW32_EPS_CANCEL);
 
       /* Never reached */
     }
 
-  (void) pthread_mutex_unlock (&self->cancelLock);
+  (void) pthread_mutex_unlock (&sp->cancelLock);
 
   return (result);
 
diff --git a/pthread_setcanceltype.c b/pthread_setcanceltype.c
index 9486353..5f88251 100644
--- a/pthread_setcanceltype.c
+++ b/pthread_setcanceltype.c
@@ -81,8 +81,9 @@ pthread_setcanceltype (int type, int *oldtype)
 {
   int result = 0;
   pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
 
-  if (self == NULL
+  if (sp == NULL
       || (type != PTHREAD_CANCEL_DEFERRED
 	  && type != PTHREAD_CANCEL_ASYNCHRONOUS))
     {
@@ -92,32 +93,32 @@ pthread_setcanceltype (int type, int *oldtype)
   /*
    * Lock for async-cancel safety.
    */
-  (void) pthread_mutex_lock (&self->cancelLock);
+  (void) pthread_mutex_lock (&sp->cancelLock);
 
   if (oldtype != NULL)
     {
-      *oldtype = self->cancelType;
+      *oldtype = sp->cancelType;
     }
 
-  self->cancelType = type;
+  sp->cancelType = type;
 
   /*
    * Check if there is a pending asynchronous cancel
    */
-  if (self->cancelState == PTHREAD_CANCEL_ENABLE
+  if (sp->cancelState == PTHREAD_CANCEL_ENABLE
       && type == PTHREAD_CANCEL_ASYNCHRONOUS
-      && WaitForSingleObject (self->cancelEvent, 0) == WAIT_OBJECT_0)
+      && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
     {
-      self->state = PThreadStateCanceling;
-      self->cancelState = PTHREAD_CANCEL_DISABLE;
-      ResetEvent (self->cancelEvent);
-      (void) pthread_mutex_unlock (&self->cancelLock);
+      sp->state = PThreadStateCanceling;
+      sp->cancelState = PTHREAD_CANCEL_DISABLE;
+      ResetEvent (sp->cancelEvent);
+      (void) pthread_mutex_unlock (&sp->cancelLock);
       ptw32_throw (PTW32_EPS_CANCEL);
 
       /* Never reached */
     }
 
-  (void) pthread_mutex_unlock (&self->cancelLock);
+  (void) pthread_mutex_unlock (&sp->cancelLock);
 
   return (result);
 
diff --git a/pthread_setschedparam.c b/pthread_setschedparam.c
index d23e5d0..d3af098 100644
--- a/pthread_setschedparam.c
+++ b/pthread_setschedparam.c
@@ -72,6 +72,7 @@ ptw32_setthreadpriority (pthread_t thread, int policy, int priority)
 {
   int prio;
   int result;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
 
   prio = priority;
 
@@ -99,12 +100,12 @@ ptw32_setthreadpriority (pthread_t thread, int policy, int priority)
 
 #endif
 
-  result = pthread_mutex_lock (&thread->threadLock);
+  result = pthread_mutex_lock (&tp->threadLock);
 
   if (0 == result)
     {
       /* If this fails, the current priority is unchanged. */
-      if (0 == SetThreadPriority (thread->threadH, prio))
+      if (0 == SetThreadPriority (tp->threadH, prio))
 	{
 	  result = EINVAL;
 	}
@@ -114,10 +115,10 @@ ptw32_setthreadpriority (pthread_t thread, int policy, int priority)
 	   * Must record the thread's sched_priority as given,
 	   * not as finally adjusted.
 	   */
-	  thread->sched_priority = priority;
+	  tp->sched_priority = priority;
 	}
 
-      (void) pthread_mutex_unlock (&thread->threadLock);
+      (void) pthread_mutex_unlock (&tp->threadLock);
     }
 
   return result;
diff --git a/pthread_setspecific.c b/pthread_setspecific.c
index b7c82d0..ed8253f 100644
--- a/pthread_setspecific.c
+++ b/pthread_setspecific.c
@@ -76,7 +76,7 @@ pthread_setspecific (pthread_key_t key, const void *value)
        * thread if one wasn't explicitly created
        */
       self = pthread_self ();
-      if (self == NULL)
+      if (self.p == NULL)
 	{
 	  return ENOENT;
 	}
@@ -87,11 +87,21 @@ pthread_setspecific (pthread_key_t key, const void *value)
        * Resolve catch-22 of registering thread with selfThread
        * key
        */
-      self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
-      if (self == NULL)
-	{
-	  self = (pthread_t) value;
-	}
+      ptw32_thread_t * sp;
+
+      sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+      if (sp == NULL)
+        {
+	  if (value == NULL)
+	    {
+	      return ENOENT;
+	    }
+          self = *((pthread_t *) value);
+        }
+      else
+        {
+	  self = sp->ptHandle;
+        }
     }
 
   result = 0;
@@ -100,8 +110,10 @@ pthread_setspecific (pthread_key_t key, const void *value)
     {
       ThreadKeyAssoc *assoc;
 
-      if (self != NULL && key->destructor != NULL && value != NULL)
+      if (self.p != NULL && key->destructor != NULL && value != NULL)
 	{
+          ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
 	  /*
 	   * Only require associations if we have to
 	   * call user destroy routine.
@@ -111,7 +123,7 @@ pthread_setspecific (pthread_key_t key, const void *value)
 	   * on the association; setting assoc to NULL short
 	   * circuits the search.
 	   */
-	  assoc = (ThreadKeyAssoc *) self->keys;
+	  assoc = (ThreadKeyAssoc *) sp->keys;
 	  /*
 	   * Locate existing association
 	   */
diff --git a/pthread_testcancel.c b/pthread_testcancel.c
index 04c214a..2a1c080 100644
--- a/pthread_testcancel.c
+++ b/pthread_testcancel.c
@@ -69,21 +69,34 @@ pthread_testcancel (void)
       */
 {
   pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
 
-  (void) pthread_mutex_lock (&self->cancelLock);
+  if (sp == NULL)
+    {
+      return;
+    }
+
+  /*
+   * Pthread_cancel() will have set sp->state to PThreadStateCancelPending
+   * and set an event, so no need to enter kernel space if
+   * sp->state != PThreadStateCancelPending - that only slows us down.
+   */
+  if (sp->state != PThreadStateCancelPending)
+    {
+      return;
+    }
+
+  (void) pthread_mutex_lock (&sp->cancelLock);
 
-  if (self != NULL
-      && self->cancelState != PTHREAD_CANCEL_DISABLE
-      && WaitForSingleObject (self->cancelEvent, 0) == WAIT_OBJECT_0)
+  if (sp->cancelState != PTHREAD_CANCEL_DISABLE)
     {
-      /*
-       * Canceling!
-       */
-      self->state = PThreadStateCanceling;
-      self->cancelState = PTHREAD_CANCEL_DISABLE;
-      (void) pthread_mutex_unlock (&self->cancelLock);
+      ResetEvent(sp->cancelEvent);
+      sp->state = PThreadStateCanceling;
+      (void) pthread_mutex_unlock (&sp->cancelLock);
+      sp->cancelState = PTHREAD_CANCEL_DISABLE;
+      (void) pthread_mutex_unlock (&sp->cancelLock);
       ptw32_throw (PTW32_EPS_CANCEL);
     }
 
-  (void) pthread_mutex_unlock (&self->cancelLock);
+  (void) pthread_mutex_unlock (&sp->cancelLock);
 }				/* pthread_testcancel */
diff --git a/pthread_win32_attach_detach_np.c b/pthread_win32_attach_detach_np.c
index 4aedccc..6fd7f27 100644
--- a/pthread_win32_attach_detach_np.c
+++ b/pthread_win32_attach_detach_np.c
@@ -92,8 +92,6 @@ pthread_win32_process_attach_np ()
 
 #endif
 
-#ifndef TEST_ICE
-
   /*
    * Load KERNEL32 and try to get address of InterlockedCompareExchange
    */
@@ -136,12 +134,6 @@ pthread_win32_process_attach_np ()
       ptw32_features |= PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE;
     }
 
-#else /* TEST_ICE */
-
-  ptw32_interlocked_compare_exchange = ptw32_InterlockedCompareExchange;
-
-#endif /* TEST_ICE */
-
   /*
    * Load QUSEREX.DLL and try to get address of QueueUserAPCEx
    */
@@ -204,16 +196,19 @@ pthread_win32_process_detach_np ()
 {
   if (ptw32_processInitialized)
     {
-      pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
+      ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
 
-      /*
-       * Detached threads have their resources automatically
-       * cleaned up upon exit (others must be 'joined').
-       */
-      if (self != NULL && self->detachState == PTHREAD_CREATE_DETACHED)
+      if (sp != NULL)
 	{
-	  ptw32_threadDestroy (self);
-	  TlsSetValue (ptw32_selfThreadKey->key, NULL);
+	  /*
+	   * Detached threads have their resources automatically
+	   * cleaned up upon exit (others must be 'joined').
+	   */
+	  if (sp->detachState == PTHREAD_CREATE_DETACHED)
+	    {
+	      ptw32_threadDestroy (sp->ptHandle);
+	      TlsSetValue (ptw32_selfThreadKey->key, NULL);
+	    }
 	}
 
       /*
@@ -265,16 +260,19 @@ pthread_win32_thread_detach_np ()
        * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle
        * unnecessarily.
        */
-      pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
+      ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
 
-      /*
-       * Detached threads have their resources automatically
-       * cleaned up upon exit (others must be 'joined').
-       */
-      if (self != NULL && self->detachState == PTHREAD_CREATE_DETACHED)
+      if (sp != NULL)
 	{
-	  ptw32_threadDestroy (self);
-	  TlsSetValue (ptw32_selfThreadKey->key, NULL);
+	  /*
+	   * Detached threads have their resources automatically
+	   * cleaned up upon exit (others must be 'joined').
+	   */
+	  if (sp->detachState == PTHREAD_CREATE_DETACHED)
+	    {
+	      ptw32_threadDestroy (sp->ptHandle);
+	      TlsSetValue (ptw32_selfThreadKey->key, NULL);
+	    }
 	}
     }
 
diff --git a/ptw32_InterlockedCompareExchange.c b/ptw32_InterlockedCompareExchange.c
index 6da2bec..45f8d59 100644
--- a/ptw32_InterlockedCompareExchange.c
+++ b/ptw32_InterlockedCompareExchange.c
@@ -46,7 +46,7 @@
  * We now use this version wherever possible so we can inline it.
  */
 
-INLINE PTW32_INTERLOCKED_LONG WINAPI
+PTW32_INTERLOCKED_LONG WINAPI
 ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
 				  PTW32_INTERLOCKED_LONG value,
 				  PTW32_INTERLOCKED_LONG comparand)
@@ -159,7 +159,7 @@ ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
  * We now use this version wherever possible so we can inline it.
  */
 
-INLINE LONG WINAPI
+LONG WINAPI
 ptw32_InterlockedExchange (LPLONG location,
 			   LONG value)
 {
diff --git a/ptw32_callUserDestroyRoutines.c b/ptw32_callUserDestroyRoutines.c
index 90b0b73..081a60d 100644
--- a/ptw32_callUserDestroyRoutines.c
+++ b/ptw32_callUserDestroyRoutines.c
@@ -69,7 +69,7 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
   ThreadKeyAssoc *
     assoc;
 
-  if (thread != NULL)
+  if (thread.p != NULL)
     {
       /*
        * Run through all Thread<-->Key associations
@@ -82,7 +82,7 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
        *      by the current thread and must be released; otherwise
        *      the assoc will be destroyed when the key is destroyed.
        */
-      nextP = (ThreadKeyAssoc **) & (thread->keys);
+      nextP = (ThreadKeyAssoc **) &((ptw32_thread_t *)thread.p)->keys;
       assoc = *nextP;
 
       while (assoc != NULL)
@@ -90,8 +90,9 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
 
 	  if (pthread_mutex_lock (&(assoc->lock)) == 0)
 	    {
-	      pthread_key_t
-		k;
+	      pthread_key_t k;
+	      pthread_t nil = {NULL, 0};
+
 	      if ((k = assoc->key) != NULL)
 		{
 		  /*
@@ -101,8 +102,7 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
 		   * key is valid and we can call the destroy
 		   * routine;
 		   */
-		  void *
-		    value = NULL;
+		  void * value = NULL;
 
 		  value = pthread_getspecific (k);
 		  if (value != NULL && k->destructor != NULL)
@@ -146,7 +146,7 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
 	       * mark assoc->thread as NULL to indicate the
 	       * thread no longer references this association
 	       */
-	      assoc->thread = NULL;
+	      assoc->thread = nil;
 
 	      /*
 	       * Remove association from the pthread_t chain
diff --git a/ptw32_new.c b/ptw32_new.c
index c2da5d5..21d08ce 100644
--- a/ptw32_new.c
+++ b/ptw32_new.c
@@ -42,37 +42,48 @@ pthread_t
 ptw32_new (void)
 {
   pthread_t t;
+  pthread_t nil = {NULL, 0};
+  ptw32_thread_t * tp;
 
   /*
    * If there's a reusable pthread_t then use it.
    */
   t = ptw32_threadReusePop ();
 
-  if (NULL == t)
+  if (NULL != t.p)
     {
-      t = (pthread_t) calloc (1, sizeof (*t));
+      tp = (ptw32_thread_t *) t.p;
     }
-
-  if (t != NULL)
+  else
     {
-      t->sched_priority = THREAD_PRIORITY_NORMAL;
-      t->detachState = PTHREAD_CREATE_JOINABLE;
-      t->cancelState = PTHREAD_CANCEL_ENABLE;
-      t->cancelType = PTHREAD_CANCEL_DEFERRED;
-      t->cancelLock = PTHREAD_MUTEX_INITIALIZER;
-      t->threadLock = PTHREAD_MUTEX_INITIALIZER;
-      t->cancelEvent = CreateEvent (0, (int) PTW32_TRUE,	/* manualReset  */
-				    (int) PTW32_FALSE,	/* setSignaled  */
-				    NULL);
+      /* No reuse threads available */
+      tp = (ptw32_thread_t *) calloc (1, sizeof(ptw32_thread_t));
 
-      if (t->cancelEvent == NULL)
+      if (tp == NULL)
 	{
-	  /*
-	   * Thread ID structs are never freed.
-	   */
-	  ptw32_threadReusePush (t);
-	  t = NULL;
+	  return nil;
 	}
+
+      /* ptHandle.p needs to point to it's parent ptw32_thread_t. */
+      t.p = tp->ptHandle.p = tp;
+      t.x = tp->ptHandle.x = 0;
+    }
+
+  /* Set default state. */
+  tp->sched_priority = THREAD_PRIORITY_NORMAL;
+  tp->detachState = PTHREAD_CREATE_JOINABLE;
+  tp->cancelState = PTHREAD_CANCEL_ENABLE;
+  tp->cancelType = PTHREAD_CANCEL_DEFERRED;
+  tp->cancelLock = PTHREAD_MUTEX_INITIALIZER;
+  tp->threadLock = PTHREAD_MUTEX_INITIALIZER;
+  tp->cancelEvent = CreateEvent (0, (int) PTW32_TRUE,	/* manualReset  */
+				 (int) PTW32_FALSE,	/* setSignaled  */
+				 NULL);
+
+  if (tp->cancelEvent == NULL)
+    {
+      ptw32_threadReusePush (tp->ptHandle);
+      return nil;
     }
 
   return t;
diff --git a/ptw32_processTerminate.c b/ptw32_processTerminate.c
index 13d73aa..b36c5a7 100644
--- a/ptw32_processTerminate.c
+++ b/ptw32_processTerminate.c
@@ -62,10 +62,9 @@ ptw32_processTerminate (void)
       * ------------------------------------------------------
       */
 {
-  pthread_t thread, nextThread;
-
   if (ptw32_processInitialized)
     {
+      ptw32_thread_t * tp, * tpNext;
 
       if (ptw32_selfThreadKey != NULL)
 	{
@@ -89,12 +88,12 @@ ptw32_processTerminate (void)
 
       EnterCriticalSection (&ptw32_thread_reuse_lock);
 
-      thread = ptw32_threadReuseTop;
-      while (thread != PTW32_THREAD_REUSE_BOTTOM)
+      tp = ptw32_threadReuseTop;
+      while (tp != PTW32_THREAD_REUSE_EMPTY)
 	{
-	  nextThread = thread->prevReuse;
-	  free (thread);
-	  thread = nextThread;
+	  tpNext = tp->prevReuse;
+	  free (tp);
+	  tp = tpNext;
 	}
 
       LeaveCriticalSection (&ptw32_thread_reuse_lock);
diff --git a/ptw32_reuse.c b/ptw32_reuse.c
index a21737a..7056395 100644
--- a/ptw32_reuse.c
+++ b/ptw32_reuse.c
@@ -39,10 +39,34 @@
 
 
 /*
+ * How it works:
+ * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64)
+ * which is normally passed/returned by value to/from pthreads routines.
+ * Applications are therefore storing a copy of the struct as it is at that
+ * time.
+ *
+ * The original pthread_t struct plus all copies of it contain the address of
+ * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each
+ * ptw32_thread_t contains the original copy of it's pthread_t.
+ * Once malloced, a ptw2_thread_t_ struct is never freed.
+ * 
  * The thread reuse stack is a simple LIFO stack managed through a singly
- * linked list element in the pthread_t_ struct.
+ * linked list element in the ptw32_thread_t.
+ *
+ * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the
+ * reuse stack after it's ptHandle's reuse counter has been incremented.
+ * 
+ * The following can now be said from this:
+ * - two pthread_t's are identical if their ptw32_thread_t reference pointers
+ * are equal and their reuse couters are equal. That is,
+ *
+ *   equal = (a.p == b.p && a.x == b.x)
+ *
+ * - a pthread_t copy refers to a destroyed thread if the reuse counter in
+ * the copy is not equal to the reuse counter in the original.
+ *
+ *   threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x)
  *
- * All thread structs on the stack are clean and ready for reuse.
  */
 
 /*
@@ -51,20 +75,26 @@
 pthread_t
 ptw32_threadReusePop (void)
 {
-  pthread_t t;
+  pthread_t t = {NULL, 0};
 
   EnterCriticalSection (&ptw32_thread_reuse_lock);
 
-  t = ptw32_threadReuseTop;
-
-  if (PTW32_THREAD_REUSE_BOTTOM != t)
-    {
-      ptw32_threadReuseTop = t->prevReuse;
-      t->prevReuse = NULL;
-    }
-  else
+  if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop)
     {
-      t = NULL;
+      ptw32_thread_t * tp;
+
+      tp = ptw32_threadReuseTop;
+
+      ptw32_threadReuseTop = tp->prevReuse;
+
+      if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop)
+        {
+          ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
+        }
+
+      tp->prevReuse = NULL;
+
+      t = tp->ptHandle;
     }
 
   LeaveCriticalSection (&ptw32_thread_reuse_lock);
@@ -75,15 +105,39 @@ ptw32_threadReusePop (void)
 
 /*
  * Push a clean pthread_t struct onto the reuse stack.
+ * Must be re-initialised when reused.
+ * All object elements (mutexes, events etc) must have been either
+ * detroyed before this, or never initialised.
  */
 void
 ptw32_threadReusePush (pthread_t thread)
 {
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+  pthread_t t;
+
   EnterCriticalSection (&ptw32_thread_reuse_lock);
 
-  memset (thread, 0, sizeof (*thread));
-  thread->prevReuse = ptw32_threadReuseTop;
-  ptw32_threadReuseTop = thread;
+  t = tp->ptHandle;
+  memset(tp, 0, sizeof(ptw32_thread_t));
+
+  /* Must restore the original POSIX handle that we just wiped. */
+  tp->ptHandle = t;
+
+  /* Bump the reuse counter now */
+  tp->ptHandle.x++;
+
+  tp->prevReuse = PTW32_THREAD_REUSE_EMPTY;
+
+  if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom)
+    {
+      ptw32_threadReuseBottom->prevReuse = tp;
+    }
+  else
+    {
+      ptw32_threadReuseTop = tp;
+    }
+
+  ptw32_threadReuseBottom = tp;
 
   LeaveCriticalSection (&ptw32_thread_reuse_lock);
 }
diff --git a/ptw32_semwait.c b/ptw32_semwait.c
index e8b7ace..3956a17 100644
--- a/ptw32_semwait.c
+++ b/ptw32_semwait.c
@@ -41,7 +41,7 @@
 #include "implement.h"
 
 
-INLINE int
+int
 ptw32_semwait (sem_t * sem)
      /*
       * ------------------------------------------------------
diff --git a/ptw32_threadDestroy.c b/ptw32_threadDestroy.c
index 58b23ff..9bca1b4 100644
--- a/ptw32_threadDestroy.c
+++ b/ptw32_threadDestroy.c
@@ -42,20 +42,21 @@
 void
 ptw32_threadDestroy (pthread_t thread)
 {
-  struct pthread_t_ threadCopy;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+  ptw32_thread_t threadCopy;
 
-  if (thread != NULL)
+  if (tp != NULL)
     {
-      (void) pthread_mutex_lock (&thread->cancelLock);
-      thread->state = PThreadStateLast;
-      (void) pthread_mutex_unlock (&thread->cancelLock);
+      (void) pthread_mutex_lock (&tp->cancelLock);
+      tp->state = PThreadStateLast;
+      (void) pthread_mutex_unlock (&tp->cancelLock);
 
       ptw32_callUserDestroyRoutines (thread);
 
       /*
        * Copy thread state so that the thread can be atomically NULLed.
        */
-      memcpy (&threadCopy, thread, sizeof (threadCopy));
+      memcpy (&threadCopy, tp, sizeof (threadCopy));
 
       /*
        * Thread ID structs are never freed. They're NULLed and reused.
diff --git a/ptw32_threadStart.c b/ptw32_threadStart.c
index 8d48621..a067aa2 100644
--- a/ptw32_threadStart.c
+++ b/ptw32_threadStart.c
@@ -69,7 +69,7 @@ ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
 	 */
 	pthread_t self = pthread_self ();
 
-	(void) pthread_mutex_destroy (&self->cancelLock);
+	(void) pthread_mutex_destroy (&((ptw32_thread_t *)self.p)->cancelLock);
 	ptw32_callUserDestroyRoutines (self);
 
 	return EXCEPTION_CONTINUE_SEARCH;
@@ -109,10 +109,11 @@ static terminate_function
 void
 ptw32_terminate ()
 {
-  pthread_t
-    self = pthread_self ();
+  pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
   set_terminate (ptw32_oldTerminate);
-  (void) pthread_mutex_destroy (&self->cancelLock);
+  (void) pthread_mutex_destroy (&sp->cancelLock);
   ptw32_callUserDestroyRoutines (self);
   terminate ();
 }
@@ -127,13 +128,11 @@ void
 #endif
 ptw32_threadStart (void *vthreadParms)
 {
-  ThreadParms *
-    threadParms = (ThreadParms *) vthreadParms;
-  pthread_t
-    self;
+  ThreadParms * threadParms = (ThreadParms *) vthreadParms;
+  pthread_t self;
+  ptw32_thread_t * sp;
   void *(*start) (void *);
-  void *
-    arg;
+  void * arg;
 
 #ifdef __CLEANUP_SEH
   DWORD
@@ -141,14 +140,13 @@ ptw32_threadStart (void *vthreadParms)
 #endif
 
 #ifdef __CLEANUP_C
-  int
-    setjmp_rc;
+  int setjmp_rc;
 #endif
 
-  void *
-    status = (void *) 0;
+  void * status = (void *) 0;
 
   self = threadParms->tid;
+  sp = (ptw32_thread_t *) self.p;
   start = threadParms->start;
   arg = threadParms->arg;
 
@@ -159,21 +157,21 @@ ptw32_threadStart (void *vthreadParms)
    * beginthread does not return the thread id and is running
    * before it returns us the thread handle, and so we do it here.
    */
-  self->thread = GetCurrentThreadId ();
+  sp->thread = GetCurrentThreadId ();
   /*
    * Here we're using cancelLock as a general-purpose lock
    * to make the new thread wait until the creating thread
    * has the new handle.
    */
-  if (pthread_mutex_lock (&self->cancelLock) == 0)
+  if (pthread_mutex_lock (&sp->cancelLock) == 0)
     {
-      (void) pthread_mutex_unlock (&self->cancelLock);
+      (void) pthread_mutex_unlock (&sp->cancelLock);
     }
 #endif
 
-  pthread_setspecific (ptw32_selfThreadKey, self);
+  pthread_setspecific (ptw32_selfThreadKey, sp);
 
-  self->state = PThreadStateRunning;
+  sp->state = PThreadStateRunning;
 
 #ifdef __CLEANUP_SEH
 
@@ -182,7 +180,7 @@ ptw32_threadStart (void *vthreadParms)
     /*
      * Run the caller's routine;
      */
-    status = self->exitStatus = (*start) (arg);
+    status = sp->exitStatus = (*start) (arg);
 
 #ifdef _UWIN
     if (--pthread_count <= 0)
@@ -202,7 +200,7 @@ ptw32_threadStart (void *vthreadParms)
 #endif
 	break;
       case PTW32_EPS_EXIT:
-	status = self->exitStatus;
+	status = sp->exitStatus;
 	break;
       default:
 	status = PTHREAD_CANCELED;
@@ -214,7 +212,7 @@ ptw32_threadStart (void *vthreadParms)
 
 #ifdef __CLEANUP_C
 
-  setjmp_rc = setjmp (self->start_mark);
+  setjmp_rc = setjmp (sp->start_mark);
 
   if (0 == setjmp_rc)
     {
@@ -222,9 +220,8 @@ ptw32_threadStart (void *vthreadParms)
       /*
        * Run the caller's routine;
        */
-      status = self->exitStatus = (*start) (arg);
+      status = sp->exitStatus = (*start) (arg);
     }
-
   else
     {
       switch (setjmp_rc)
@@ -233,7 +230,7 @@ ptw32_threadStart (void *vthreadParms)
 	  status = PTHREAD_CANCELED;
 	  break;
 	case PTW32_EPS_EXIT:
-	  status = self->exitStatus;
+	  status = sp->exitStatus;
 	  break;
 	default:
 	  status = PTHREAD_CANCELED;
@@ -256,7 +253,7 @@ ptw32_threadStart (void *vthreadParms)
      */
     try
     {
-      status = self->exitStatus = (*start) (arg);
+      status = sp->exitStatus = (*start) (arg);
     }
     catch (ptw32_exception &)
     {
@@ -293,14 +290,14 @@ ptw32_threadStart (void *vthreadParms)
     /*
      * Thread was canceled.
      */
-    status = self->exitStatus = PTHREAD_CANCELED;
+    status = sp->exitStatus = PTHREAD_CANCELED;
   }
   catch (ptw32_exception_exit &)
   {
     /*
      * Thread was exited via pthread_exit().
      */
-    status = self->exitStatus;
+    status = sp->exitStatus;
   }
   catch (...)
   {
@@ -309,11 +306,11 @@ ptw32_threadStart (void *vthreadParms)
      * terminate routine. We get control back within this block - cleanup
      * and release the exception out of thread scope.
      */
-    status = self->exitStatus = PTHREAD_CANCELED;
-    (void) pthread_mutex_lock (&self->cancelLock);
-    self->state = PThreadStateException;
-    (void) pthread_mutex_unlock (&self->cancelLock);
-    (void) pthread_mutex_destroy (&self->cancelLock);
+    status = sp->exitStatus = PTHREAD_CANCELED;
+    (void) pthread_mutex_lock (&sp->cancelLock);
+    sp->state = PThreadStateException;
+    (void) pthread_mutex_unlock (&sp->cancelLock);
+    (void) pthread_mutex_destroy (&sp->cancelLock);
     (void) set_terminate (ptw32_oldTerminate);
     ptw32_callUserDestroyRoutines (self);
     throw;
@@ -333,7 +330,7 @@ ptw32_threadStart (void *vthreadParms)
 #endif /* __CLEANUP_C */
 #endif /* __CLEANUP_SEH */
 
-  if (self->detachState == PTHREAD_CREATE_DETACHED)
+  if (sp->detachState == PTHREAD_CREATE_DETACHED)
     {
       /*
        * We need to cleanup the pthread now in case we have
diff --git a/ptw32_throw.c b/ptw32_throw.c
index 8f67069..1a71b97 100644
--- a/ptw32_throw.c
+++ b/ptw32_throw.c
@@ -53,7 +53,7 @@ ptw32_throw (DWORD exception)
    * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
    * unnecessarily.
    */
-  pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
+  ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
 
 #ifdef __CLEANUP_SEH
   DWORD exceptionInformation[3];
@@ -65,7 +65,7 @@ ptw32_throw (DWORD exception)
       exit (1);
     }
 
-  if (NULL == self || self->implicit)
+  if (NULL == sp || sp->implicit)
     {
       /*
        * We're inside a non-POSIX initialised Win32 thread
@@ -81,7 +81,7 @@ ptw32_throw (DWORD exception)
 	  exitCode = (unsigned) PTHREAD_CANCELED;
 	  break;
 	case PTW32_EPS_EXIT:
-	  exitCode = (unsigned) self->exitStatus;;
+	  exitCode = (unsigned) sp->exitStatus;;
 	  break;
 	}
 
@@ -109,7 +109,7 @@ ptw32_throw (DWORD exception)
 #ifdef __CLEANUP_C
 
   ptw32_pop_cleanup_all (1);
-  longjmp (self->start_mark, exception);
+  longjmp (sp->start_mark, exception);
 
 #else /* __CLEANUP_C */
 
diff --git a/ptw32_tkAssocCreate.c b/ptw32_tkAssocCreate.c
index c2a5c81..1e3e3e6 100644
--- a/ptw32_tkAssocCreate.c
+++ b/ptw32_tkAssocCreate.c
@@ -112,13 +112,13 @@ ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP,
 
   pthread_mutex_unlock (&(key->threadsLock));
 
-  if (thread != NULL)
+  if (thread.p != NULL)
     {
       /*
        * Register assoc with thread
        */
-      assoc->nextKey = (ThreadKeyAssoc *) thread->keys;
-      thread->keys = (void *) assoc;
+      assoc->nextKey = (ThreadKeyAssoc *) ((ptw32_thread_t *)thread.p)->keys;
+      ((ptw32_thread_t *)thread.p)->keys = (void *) assoc;
     }
 
   *assocP = assoc;
diff --git a/ptw32_tkAssocDestroy.c b/ptw32_tkAssocDestroy.c
index 682b896..1022dea 100644
--- a/ptw32_tkAssocDestroy.c
+++ b/ptw32_tkAssocDestroy.c
@@ -56,7 +56,7 @@ ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
       */
 {
 
-  if ((assoc != NULL) && (assoc->key == NULL && assoc->thread == NULL))
+  if ((assoc != NULL) && (assoc->key == NULL && assoc->thread.p == NULL))
     {
 
       pthread_mutex_destroy (&(assoc->lock));
diff --git a/sem_timedwait.c b/sem_timedwait.c
index d1d9d37..59fcc18 100644
--- a/sem_timedwait.c
+++ b/sem_timedwait.c
@@ -52,15 +52,18 @@
 #include "semaphore.h"
 #include "implement.h"
 
-static inline void
+static void PTW32_CDECL
 ptw32_sem_timedwait_cleanup (void * sem)
 {
   sem_t s = (sem_t) sem;
 
   if (pthread_mutex_lock (&s->lock) == 0)
     {
-      s->value++;
-      ReleaseSemaphore(s->sem, 1, 0);
+      ++s->value;
+      /*
+       * Don't release the W32 sema, it doesn't need adjustment
+       * because it doesn't record the number of waiters.
+       */
       (void) pthread_mutex_unlock (&s->lock);
     }
 }
@@ -202,6 +205,8 @@ sem_timedwait (sem_t * sem, const struct timespec *abstime)
 
 #else /* NEED_SEM */
 
+      pthread_testcancel();
+
       if ((result = pthread_mutex_lock (&s->lock)) == 0)
 	{
 	  int v = --s->value;
@@ -210,15 +215,21 @@ sem_timedwait (sem_t * sem, const struct timespec *abstime)
 	  if (v < 0)
 	    {
 	      /* Must wait */
-              pthread_cleanup_push(ptw32_sem_timedwait_cleanup, s);
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+              pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) s);
 	      result = pthreadCancelableTimedWait (s->sem, milliseconds);
 	      /*
-	       * Restore the semaphore counters if no longer waiting
+	       * Restore the semaphore counter if no longer waiting
 	       * and not taking the semaphore. This will occur if the
 	       * thread is cancelled while waiting, or the wake was
 	       * not the result of a post event given to us, e.g. a timeout.
 	       */
               pthread_cleanup_pop(result);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
 	    }
 	}
 
diff --git a/sem_wait.c b/sem_wait.c
index cead2cd..68131bf 100644
--- a/sem_wait.c
+++ b/sem_wait.c
@@ -45,15 +45,16 @@
 #include "semaphore.h"
 #include "implement.h"
 
-static inline void
+
+static void PTW32_CDECL
 ptw32_sem_wait_cleanup(void * sem)
 {
   sem_t s = (sem_t) sem;
 
   if (pthread_mutex_lock (&s->lock) == 0)
     {
-      s->value++;
-      ReleaseSemaphore(s->sem, 1, 0);
+      ++s->value;
+      /* Don't release the W32 sema, it should always == 0. */
       (void) pthread_mutex_unlock (&s->lock);
     }
 }
@@ -105,6 +106,12 @@ sem_wait (sem_t * sem)
 
 #else /* NEED_SEM */
 
+      /*
+       * sem_wait is a cancelation point and it's easy to test before
+       * modifying the sem value
+       */
+      pthread_testcancel();
+
       if ((result = pthread_mutex_lock (&s->lock)) == 0)
 	{
 	  int v = --s->value;
@@ -114,18 +121,18 @@ sem_wait (sem_t * sem)
 	  if (v < 0)
 	    {
 	      /* Must wait */
-	      pthread_cleanup_push(ptw32_sem_wait_cleanup, s);
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+	      pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s);
 	      result = pthreadCancelableWait (s->sem);
-	      /*
-	       * Restore the semaphore counters if no longer waiting
-	       * and not taking the semaphore. This will occur if the
-	       * thread is cancelled while waiting, or the wake was
-	       * not the result of a post event given to us.
-	       */
-	      pthread_cleanup_pop(result);
+	      pthread_cleanup_pop(result != 0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
 	    }
 	}
-     
+
 #endif /* NEED_SEM */
 
     }
diff --git a/signal.c b/signal.c
index a7c3ef0..21747f6 100644
--- a/signal.c
+++ b/signal.c
@@ -101,7 +101,7 @@ pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
 {
   pthread_t thread = pthread_self ();
 
-  if (thread == NULL)
+  if (thread.p == NULL)
     {
       return ENOENT;
     }
@@ -126,7 +126,7 @@ pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
   /* Copy the old mask before modifying it. */
   if (oset != NULL)
     {
-      memcpy (oset, &(thread->sigmask), sizeof (sigset_t));
+      memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t));
     }
 
   if (set != NULL)
@@ -137,7 +137,7 @@ pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
          the size of a long integer. */
 
       unsigned long *src = (unsigned long const *) set;
-      unsigned long *dest = (unsigned long *) &(thread->sigmask);
+      unsigned long *dest = (unsigned long *) &(thread.p->sigmask);
 
       switch (how)
 	{
@@ -156,7 +156,7 @@ pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
 	    }
 	case SIG_SETMASK:
 	  /* Replace the whole sigmask. */
-	  memcpy (&(thread->sigmask), set, sizeof (sigset_t));
+	  memcpy (&(thread.p->sigmask), set, sizeof (sigset_t));
 	  break;
 	}
     }
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 27f4eea..abc8260 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,4 +1,17 @@
-2004-10-23  Ross Johnson  <rpj@callisto.canberra.edu.au>
+2004-10-29  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* semaphore4.c: New test.
+	* semaphore4t.c: New test.
+	* Debug.dsp (et al): Created MSVC Workspace project to aid debugging.
+	* All: Many tests have been modified to work with the new pthread
+	ID type; some other corrections were made after some library
+	functions were semantically strengthened. For example,
+	pthread_cond_destroy() no longer destroys a busy CV, which
+	required minor redesigns of some tests, including some where
+	the mutex associated with the CV was not locked during
+	signaling and broadcasting.
+
+2004-10-23  Ross Johnson  <rpj@callisto.canberra.edu.au>
 
 	* condvar3.c: Fixed mutex operations that were incorrectly
 	placed in relation to their condition variable operations.
@@ -15,791 +28,791 @@
 	* condvar8.c: Likewise.
 	* condvar9.c: Likewise.
 
-2004-10-19  Ross Johnson  <rpj@callisto.canberra.edu.au>
+2004-10-19  Ross Johnson  <rpj@callisto.canberra.edu.au>
 
 	* semaphore3.c: New test.
 
-2004-10-14  Ross Johnson  <rpj@callisto.canberra.edu.au>
+2004-10-14  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* rwlock7.c (main): Tidy up statistics reporting; randomise
+	update accesses.
+	* rwlock8.c: New test.
+
+2004-09-08  Alexandre Girao  <alexgirao@gmail.com>
+
+	* cancel7.c (main): Win98 wants a valid (non-NULL) location
+	for the last arg of _beginthreadex().
+	* cancel8.c (main): Likewise.
+	* exit4.c (main): Likewise.
+	* exit5.c (main): Likewise.
+
+2004-08-26  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* create3.c: New test.
+
+2004-06-21  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* mutex2r.c: New test.
+	* mutex2e.c: New test.
+	* mutex3r.c: New test.
+	* mutex3e.c: New test.
+	* mutex6s.c: New test.
+	* mutex6rs.c: New test.
+	* mutex6es.c: New test.
+
+2004-05-21  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* join3.c: New test.
+
+2004-05-16  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* condvar2.c (WIN32_WINNT): Define to avoid redefinition warning
+	from inclusion of implement.h.
+	* convar2_1.c: Likewise.
+	* condvar3_1.c: Likewise.
+	* condvar3_2.c: Likewise.
+	* context1.c: Likewise.
+	* sizes.c: Likewise.
+	* Makefile: Don't define _WIN32_WINNT on compiler command line.
+	* GNUmakefile: Likewise.
+	* priority1.c (main): Add column to output for actual win32
+	priority.
+
+2004-05-16  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* cancel9.c: New test.
+	* cancel3.c: Remove inappropriate conditional compilation;
+	GNU C version of test suite no longer quietly skips this test.
+	* cancel5.c: Likewise.
+	* GNUmakefile: Can now build individual test app using default
+	C version of library using 'make clean testname.c'.
+	* Makefile: Likewise for VC using 'nmake clean test testname.c'.
+
+2003-10-14  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* Wmakefile: New makefile for Watcom testing.
+
+2003-09-18  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* benchtest.h: Move old mutex code into benchlib.c.
+	* benchlib.c: New statically linked module to ensure that
+	bench apps don't inline the code and therefore have an unfair
+	advantage over the pthreads lib routines. Made little or no
+	difference.
+	* benchtest1.c: Minor change to avoid compiler warnings.
+	* benchtest5.c: Likewise.
+	* benchtest2.c: Fix misinformation in output report.
+	* README.BENCH: Add comments on results.
+
+2003-09-14  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* priority1.c: Reworked to comply with modified priority
+	management and provide additional output.
+	* priority2.c: Likewise.
+	* inherit1.c: Likewise.
+
+2003-09-03  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* exit4.c: New test.
+	* exit5.c: New test.
+	* cancel7.c: New test.
+	* cancel8.c: New test.
+
+2003-08-13  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+	* reuse1.c: New test.
+	* reuse1.c: New test.
+	* valid1.c: New test.
+	* valid2.c: New test.
+	* kill1.c: New test.
+ 	* create2.c: Now included in test regime.
+
+2003-07-19  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+	* eyal1.c (waste_time): Make threads do more work to ensure that
+	all threads get to do some work.
+	* semaphore1.c: Make it clear that certain errors are expected.
+	* exception2.c (non_MSVC code sections): Change to include
+	C++ standard include file, i.e. change <new.h> to <exception>.
+	* exception3.c (non_MSVC code sections): Likewise; qualify std::
+	namespace entities where necessary.
+	* GNUmakefile: modified to work in the MsysDTK (newer MinGW)
+	environment; define CC as gcc or g++ as appropriate because
+	using gcc -x c++ doesn't link with required c++ libs by default,
+	but g++ does.
+
+2002-12-11  Ross Johnson  <ross@special.ise.canberra.edu.au>
+
+	* mutex7e.c: Assert EBUSY return instead of EDEADLK.
+
+2002-06-03  Ross Johnson  <rpj@digit.ise.canberra.edu.au>
+
+	* semaphore2.c: New test.
+
+2002-03-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* Makefile (CFLAGS): Changed /MT to /MD to link with
+	the correct library MSVCRT.LIB. Otherwise errno doesn't
+	work.
+
+2002-02-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* exception3.c: Correct recent change.
+
+	* semaphore1.c: New test.
+
+	* Makefile: Add rule to generate pre-processor output.
+
+2002-02-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* exception3.c (terminateFunction): For MSVC++, call
+	exit() rather than pthread_exit(). Add comments to explain
+	why.
+	   * Notes from the MSVC++ manual:
+	   *       1) A term_func() should call exit(), otherwise
+	   *          abort() will be called on return to the caller.
+	   *          abort() raises SIGABRT. The default signal handler
+	   *          for all signals terminates the calling program with
+	   *          exit code 3.
+	   *       2) A term_func() must not throw an exception. Therefore
+	   *          term_func() should not call pthread_exit() if an
+	   *          an exception-using version of pthreads-win32 library
+	   *          is being used (i.e. either pthreadVCE or pthreadVSE).
+
+
+2002-02-23  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* rwlock2_t.c: New test.
+	* rwlock3_t.c: New test.
+	* rwlock4_t.c: New test.
+	* rwlock5_t.c: New test.
+	* rwlock6_t.c: New test.
+	* rwlock6_t2.c: New test.
+	* rwlock6.c (main): Swap thread and result variables
+	to correspond to actual thread functions.
+	* rwlock1.c: Change test description comment to correspond
+	to the actual test.
+
+	* condvar1_2.c: Loop over the test many times in the hope
+	of detecting any intermittent deadlocks. This is to
+	test a fixed problem in pthread_cond_destroy.c.
+
+	* spin4.c: Remove unused variable.
+
+2002-02-17  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* condvar1_1.c: New test.
+	* condvar1_2.c: New test.
+
+2002-02-07  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* delay1.c: New test.
+	* delay2.c: New test.
+	* exit4.c: New test.
+
+2002-02-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* mutex8: New test.
+	* mutex8n: New test.
+	* mutex8e: New test.
+	* mutex8r: New test.
+	* cancel6a: New test.
+	* cancel6d: New test.
+	* cleanup0.c: Add pragmas for inline optimisation control.
+	* cleanup1.c: Add pragmas for inline optimisation control.
+	* cleanup2.c: Add pragmas for inline optimisation control.
+	* cleanup3.c: Add pragmas for inline optimisation control.
+	* condvar7.c: Add pragmas for inline optimisation control.
+	* condvar8.c: Add pragmas for inline optimisation control.
+	* condvar9.c: Add pragmas for inline optimisation control.
+
+2002-01-30  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* cleanup1.c (): Must be declared __cdecl when compiled
+	as C++ AND testing the standard C library version.
+
+2002-01-16  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* spin4.c (main): Fix renamed function call.
+
+2002-01-14  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* exception3.c (main): Shorten wait time.
+
+2002-01-09  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* mutex7.c: New test.
+	* mutex7n.c: New test.
+	* mutex7e.c: New test.
+	* mutex7r.c: New test.
+	* mutex6.c: Modified to avoid leaving the locked mutex
+	around on exit.
+
+2001-10-25  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
+
+	* condvar2.c: Remove reference to cv->nWaitersUnblocked.
+	* condvar2_1.c: Likewise; lower NUMTHREADS from 60 to 30.
+	* condvar3_1.c: Likewise.
+	* condvar3_2.c: Likewise.
+	* count1.c: lower NUMTHREADS from 60 to 30.
+	* inherit1.c: Determine valid priority values and then
+	assert values returned by POSIX routines are the same.
+	* priority1.c: Likewise.
+	* priority2.c: Likewise.
+	
+2001-07-12  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
+
+	* barrier5.c: Assert that precisely one thread receives
+	PTHREAD_BARRIER_SERIAL_THREAD at each barrier.
+
+2001-07-09  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
+
+	* barrier3.c: Fixed.
+	* barrier4.c: Fixed.
+	* barrier5.c: New; proves that all threads in the group
+	reaching the barrier wait and then resume together. Repeats the test
+	using groups of 1 to 16 threads. Each group of threads must negotiate
+	a large number of barriers (10000).
+	* spin4.c: Fixed.
+	* test.h (error_string): Modified the success (0) value.
+
+2001-07-07  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
+
+	* spin3.c: Changed test and fixed.
+	* spin4.c: Fixed.
+	* barrier3.c: Fixed.
+	* barrier4.c: Fixed.
+
+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.
+	* benchtest4.c: New; time mutexes.
+	* condvar3_1.c: Fixed bug - Alexander Terekhov
+	* condvar3_3.c: New test.
+
+2001-06-25  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* priority1.c: New test.
+	* priority2.c: New test.
+	* inherit1.c: New test.
+	* benchtest1.c: New; timing mutexes.
+	* benchtest2.c: New; timing mutexes.
+	* mutex4.c: Modified to test all mutex types.
+
+2001-06-8  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* mutex5.c: Insert inert change to quell compiler warnings.
+	* condvar3_2.c: Remove unused variable.
+	
+2001-06-3  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* condvar2_1.c: New test.
+	* condvar3_1.c: New test.
+	* condvar3_2.c: New test.
+
+2001-05-30  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* mutex1n.c: New test.
+	* mutex1e.c: New test.
+	* mutex1r.c: New test.
+	* mutex4.c: Now locks and unlocks a mutex.
+	* mutex5.c: New test.
+	* mutex6.c: New test.
+	* mutex6n.c: New test.
+	* mutex6e.c: New test.
+	* mutex6r.c: New test.
+	* Makefile: Added new tests; reorganised.
+	* GNUmakefile: Likewise.
+	* rwlock6.c: Fix to properly prove read-while-write locking
+	and single writer locking.
+
+2001-05-29  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* Makefile: Reorganisation.
+	* GNUmakefile: Likewise.
+	- Thomas Pfaff <tpfaff@gmx.net>
+
+	* exception1.c: Add stdio.h include to define fprintf and stderr
+	in non-exception C version of main().
+	* exception2.c: Likewise.
+	* exception3.c: Likewise.
+
+	* Makefile (rwlock7): Add new test.
+	* GNUmakefile (rwlock7): Add new test.
+	* rwlock7.c: New test.
+	* rwlock6.c: Changed to test that writer has priority.
+
+	* eyal1.c (main): Unlock each mutex_start lock before destroying
+	it.
+
+2000-12-29  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* GNUmakefile: Add mutex4 test; ensure libpthreadw32.a is
+	removed for "clean" target.
+	* Makefile: Add mutex4 test.
+
+	* exception3.c: Remove SEH code; automatically pass the test
+	under SEH (which is an N/A environment).
+
+	* mutex4.c: New test.
+
+	* eyal1.c (do_work_unit): Add a dummy "if" to force the
+	optimiser to retain code; reduce thread work loads.
+
+	* condvar8.c (main): Add an additional "assert" for debugging;
+	increase pthread_cond_signal timeout.
+
+2000-12-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* eyal1.c: Increase thread work loads.
+	* exception2.c: New test.
+	* exception3.c: New test.
+	* Makefile: Add new tests exception2.c and exception3.c.
+	* GNUmakefile: Likewise.
+
+2000-12-11  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* cleanup3.c: Remove unused variable.
+	* cleanup2.c: Likewise.
+	* exception1.c: Throw an exception rather than use
+	a deliberate zero divide so that catch(...) will
+	handle it under Mingw32. Mingw32 now builds the
+	library correctly to pass all tests - see Thomas
+	Pfaff's detailed instructions re needed changes
+	to Mingw32 in the Pthreads-Win32 FAQ.
+
+2000-09-08  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* cancel5.c: New; tests calling pthread_cancel()
+	from the main thread without first creating a
+	POSIX thread struct for the non-POSIX main thread
+	- this forces pthread_cancel() to create one via
+	pthread_self().
+	* Makefile (cancel5): Add new test.
+	* GNUmakefile (cancel5): Likewise.
+
+2000-08-17  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* create2.c: New; Test that pthread_t contains
+	the W32 HANDLE before it calls the thread routine
+	proper.
+
+2000-08-13  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* condvar3.c: Minor change to eliminate compiler
+	warning.
+
+	* condvar4.c: ditto.
+
+	* condvar5.c: ditto.
+
+	* condvar6.c: ditto.
+
+	* condvar7.c: ditto.
+
+	* condvar8.c: ditto.
+
+	* condvar9.c: ditto.
+
+	* exit1.c: Function needed return statement.
+
+	* cleanup1.c: Remove unnecessary printf arg.
+
+	* cleanup2.c: Fix cast.
+
+	* rwlock6.c: Fix casts.
+
+	* exception1.c (PtW32CatchAll): Had the wrong name;
+	fix casts.
+
+	* cancel3.c: Remove unused waitLock variable.
+
+	* GNUmakefile: Change library/dll naming; add new tests;
+	general minor changes.
+
+	* Makefile: Change library/dll naming; add targets for
+	testing each of the two VC++ EH scheme versions;
+	default target now issues help message; compile warnings
+	now interpreted as errors to stop the make; add new
+	tests; restructure to remove prerequisites needed
+	otherwise.
+
+	* README: Updated.
+
+
+2000-08-10  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* eyal1.c (main): Change implicit cast to explicit
+	cast when passing "print_server" function pointer;
+	G++ no longer allows implicit func parameter casts.
+
+	* cleanup1.c: Remove unused "waitLock".
+	(main): Fix implicit parameter cast.
+
+	* cancel2.c (main): Fix implicit parameter cast.
+
+	* cancel4.c (main): Fix implicit parameter cast.
+
+	* cancel3.c (main): Fix implicit parameter cast.
+
+	* GNUmakefile: Renamed from Makefile; Add missing
+	cancel1 and cancel2 test targets.
+
+	* Makefile: Converted for use with MS nmake.
+
+2000-08-06  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* ccl.bat: Add /nologo to remove extraneous output.
+
+	* exception1.c (exceptionedThread): Init 'dummy';
+	put expression into if condition to prevent optimising away;
+	remove unused variable.
+
+	* cancel4.c (mythread): Cast return value to avoid warnings.
+
+	* cancel2.c (mythread): Missing #endif.
+
+	* condvar9.c (mythread): Cast return value to avoid warnings.
+
+	* condvar8.c (mythread): Cast return value to avoid warnings.
+
+	* condvar7.c (mythread): Cast return value to avoid warnings.
+
+	* cleanup3.c (mythread): Cast return value to avoid warnings.
+
+	* cleanup2.c (mythread): Cast return value to avoid warnings.
+
+	* cleanup1.c (mythread): Cast return value to avoid warnings.
+
+	* condvar5.c (mythread): Cast return value to avoid warnings.
+
+	* condvar3.c (mythread): Cast return value to avoid warnings.
+
+	* condvar6.c (mythread): Cast return value to avoid warnings.
+
+	* condvar4.c (mythread): Cast return value to avoid warnings.
+
+2000-08-05  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* cancel2.c: Use PtW32CatchAll macro if defined.
+
+	* exception1.c: Use PtW32CatchAll macro if defined.
+
+2000-08-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* tsd1.c: Fix typecasts of &result [g++ is now very fussy].
+	
+	* test.h (assert): Return 0's explicitly to allay
+	g++ errors.
+	
+	* join2.c: Add explicit typecasts.
+	
+	* join1.c: Add explicit typecasts.
+	
+	* join0.c: Add explicit typecasts.
+	
+	* eyal1.c: Add explicit typecasts.
+	
+	* count1.c (main): Add type cast to remove g++ parse warning
+	[gcc-2.95.2 seems to have tightened up on this].
+
+	* Makefile (GLANG): Use c++ explicitly.
+	Remove MSVC sections (was commented out).
+	Add target to generate cpp output.
+
+2000-07-25  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* runtest.bat: modified to work under W98.
+	
+	* runall.bat: Add new tests; modified to work under W98.
+	It was ok under NT.
+
+	* Makefile: Add new tests.
+
+	* exception1.c: New; Test passing exceptions back to the
+	application and retaining library internal exceptions.
+
+	* join0.c: New; Test a single join.
+
+2000-01-06  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* cleanup1.c: New; Test cleanup handler executes (when thread is
+	canceled).
+
+	* cleanup2.c: New; Test cleanup handler executes (when thread is
+	not canceled).
+
+	* cleanup3.c: New; Test cleanup handler does not execute
+	(when thread is not canceled).
+
+2000-01-04  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* cancel4.c: New; Test cancelation does not occur in deferred
+	cancelation threads with no cancelation points.
+
+	* cancel3.c: New; Test asynchronous cancelation.
+
+	* context1.c: New; Test context switching method for async
+	cancelation.
+
+1999-11-23  Ross Johnson  <rpj@special.ise.canberra.edu.au>
+
+	* test.h: Add header includes; include local header versions rather
+	than system versions; rearrange the assert macro defines.
+
+1999-11-07  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* loadfree.c: New. Test loading and freeing the library (DLL).
+
+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.
+	* condvar8.c: New. Test multiple broadcasts.
+	* condvar9.c: New. Test multiple broadcasts with thread
+	cancelation.
+	
+Sep 16 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* rwlock6.c: New test.
+
+Sep 15 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* rwlock1.c: New test.
+	* rwlock2.c: New test.
+	* rwlock3.c: New test.
+	* rwlock4.c: New test.
+	* rwlock5.c: New test.
+
+Aug 22 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* runall.bat (join2): Add test.
+
+Aug 19 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* join2.c: New test.
+
+Wed Aug 12 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* Makefile (LIBS): Add -L.
+
+Mon May 31 10:25:01 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* Makefile (GLANG): Add GCC language option.
+
+Sat May 29 23:29:04 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* runall.bat (condvar5): Add new test.
+
+	* runall.bat (condvar6): Add new test.
+
+	* Makefile (condvar5) : Add new test.
+	
+	* Makefile (condvar6) : Add new test.
+	
+	* condvar5.c: New test for pthread_cond_broadcast().
+
+	* condvar6.c: New test for pthread_cond_broadcast().
+
+Sun Apr  4 12:04:28 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* tsd1.c (mythread): Change Sleep(0) to sched_yield().
+	(sched.h): Include.
+
+	* condvar3.c (mythread): Remove redundant Sleep().
+
+	* runtest.bat: Re-organised to make more informative.
+
+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.
+
+	* count1.c: raise number of spawned threads to 60 (appears to
+	be the limit under Win98).
+
+Sun Mar 14 21:31:02 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* test.h (assert): add assertion trace option.
+	Use:
+	"#define ASSERT_TRACE 1" to turn it on,
+	"#define ASSERT_TRACE 0" to turn it off (default).
+
+	* condvar3.c (main): add more assertions.
+
+	* condvar4.c (main): add more assertions.
+
+	* condvar1.c (main): add more assertions.
+
+Fri Mar 12 08:34:15 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* condvar4.c (cvthing): switch the order of the INITIALIZERs.
+
+	* eyal1.c (main): Fix trylock loop; was not waiting for thread to lock
+	the "started" mutex.
+
+Wed Mar 10 10:41:52 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* tryentercs.c: Apply typo patch from bje.
+
+	* tryentercs2.c: Ditto.
+
+Sun Mar  7 10:41:52 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* Makefile (condvar3, condvar4): Add tests.
+
+	* condvar4.c (General): Reduce to simple test case; prerequisite
+	is condvar3.c; add description.
+
+	* condvar3.c (General): Reduce to simple test case; prerequisite
+	is condvar2.c; add description.
+
+	* condvar2.c (General): Reduce to simple test case; prerequisite
+	is condvar1.c; add description.
+
+	* condvar1.c (General): Reduce to simple test case; add
+	description.
+
+	* Template.c (Comments): Add generic test detail.
+
+1999-02-23  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+        * Template.c: Revamp.
+
+        * condvar1.c: Add.
+
+        * condvar2.c: Add.
+
+        * Makefile: Add condvar1 condvar2 tests.
+
+        * exit1.c, exit2.c, exit3.c: Cosmetic changes.
+
+1999-02-23  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+	* 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
+	version pops up a dialog but we want to run non-interactively.
+
+	* equal1.c: use assert a little more directly so that it
+	prints the actual call statement.
+
+	* exit1.c: Modify to return 0 on success, 1 on failure.
+
+1999-02-22  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+	* self2.c: Bring up to date.
+
+	* self3.c: Ditto.
+
+1999-02-21  Ben Elliston  <bje@cygnus.com>
+
+	* README: Update.
+
+	* Makefile: New file. Run all tests automatically. Primitive tests
+	are run first; more complex tests are run last.
+
+	* count1.c: New test. Validate the thread count.
+
+	* exit2.c: Perform a simpler test.
+	
+	* exit3.c: New test. Replaces exit2.c, since exit2.c needs to
+	perform simpler checking first.
+
+	* create1.c: Update to use the new testsuite exiting convention.
+	
+	* equal1.c: Likewise.
+
+	* mutex1.c: Likewise.
+
+	* mutex2.c: Likewise.
+
+	* once1.c: Likewise.
+
+	* self2.c: Likewise.
+
+	* self3.c: Likewise.
+
+	* tsd1.c: Likewise.
+
+1999-02-20  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+	* mutex2.c: Test static mutex initialisation.
+
+	* test.h: New. Declares a table mapping error numbers to
+	error names.
+
+1999-01-17  Ross Johnson  <rpj@ise.canberra.edu.au>
+
+	* runtest: New script to build and run a test in the tests directory.
+
+Wed Dec 30 11:22:44 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* tsd1.c: Re-written. See comments at start of file.
+	* Template.c: New. Contains skeleton code and comment template
+	intended to fully document the test.
+
+Fri Oct 16 17:59:49 1998  Ross Johnson  <rpj@swan.canberra.edu.au>
+
+	* tsd1.c (destroy_key): Add function. Change diagnostics.
+
+Thu Oct 15 17:42:37 1998  Ross Johnson  <rpj@swan.canberra.edu.au>
+
+	* tsd1.c (mythread): Fix some casts and add some message
+	output. Fix inverted conditional.
+
+Mon Oct 12 02:12:29 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
+
+	* tsd1.c: New. Test TSD using 1 key and 2 threads.
+
+1998-09-13  Ben Elliston  <bje@cygnus.com>
+
+	* eyal1.c: New file; contributed by Eyal Lebedinsky
+	<eyal@eyal.emu.id.au>.
+
+1998-09-12  Ben Elliston  <bje@cygnus.com>
+
+	* exit2.c (func): Return a value.
+	(main): Call the right thread entry function.
+
+1998-07-22  Ben Elliston  <bje@cygnus.com>
+
+	* exit2.c (main): Fix size of pthread_t array.
+
+1998-07-10  Ben Elliston  <bje@cygnus.com>
 
-	* rwlock7.c (main): Tidy up statistics reporting; randomise
-	update accesses.
-	* rwlock8.c: New test.
+	* exit2.c: New file; test pthread_exit() harder.
 
-2004-09-08  Alexandre Girao  <alexgirao@gmail.com>
-
-	* cancel7.c (main): Win98 wants a valid (non-NULL) location
-	for the last arg of _beginthreadex().
-	* cancel8.c (main): Likewise.
-	* exit4.c (main): Likewise.
-	* exit5.c (main): Likewise.
-
-2004-08-26  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* create3.c: New test.
-
-2004-06-21  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* mutex2r.c: New test.
-	* mutex2e.c: New test.
-	* mutex3r.c: New test.
-	* mutex3e.c: New test.
-	* mutex6s.c: New test.
-	* mutex6rs.c: New test.
-	* mutex6es.c: New test.
-
-2004-05-21  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* join3.c: New test.
-
-2004-05-16  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* condvar2.c (WIN32_WINNT): Define to avoid redefinition warning
-	from inclusion of implement.h.
-	* convar2_1.c: Likewise.
-	* condvar3_1.c: Likewise.
-	* condvar3_2.c: Likewise.
-	* context1.c: Likewise.
-	* sizes.c: Likewise.
-	* Makefile: Don't define _WIN32_WINNT on compiler command line.
-	* GNUmakefile: Likewise.
-	* priority1.c (main): Add column to output for actual win32
-	priority.
-
-2004-05-16  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* cancel9.c: New test.
-	* cancel3.c: Remove inappropriate conditional compilation;
-	GNU C version of test suite no longer quietly skips this test.
-	* cancel5.c: Likewise.
-	* GNUmakefile: Can now build individual test app using default
-	C version of library using 'make clean testname.c'.
-	* Makefile: Likewise for VC using 'nmake clean test testname.c'.
-
-2003-10-14  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* Wmakefile: New makefile for Watcom testing.
-
-2003-09-18  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* benchtest.h: Move old mutex code into benchlib.c.
-	* benchlib.c: New statically linked module to ensure that
-	bench apps don't inline the code and therefore have an unfair
-	advantage over the pthreads lib routines. Made little or no
-	difference.
-	* benchtest1.c: Minor change to avoid compiler warnings.
-	* benchtest5.c: Likewise.
-	* benchtest2.c: Fix misinformation in output report.
-	* README.BENCH: Add comments on results.
-
-2003-09-14  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* priority1.c: Reworked to comply with modified priority
-	management and provide additional output.
-	* priority2.c: Likewise.
-	* inherit1.c: Likewise.
-
-2003-09-03  Ross Johnson  <rpj@callisto.canberra.edu.au>
-
-	* exit4.c: New test.
-	* exit5.c: New test.
-	* cancel7.c: New test.
-	* cancel8.c: New test.
-
-2003-08-13  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-	* reuse1.c: New test.
-	* reuse1.c: New test.
-	* valid1.c: New test.
-	* valid2.c: New test.
-	* kill1.c: New test.
- 	* create2.c: Now included in test regime.
-
-2003-07-19  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-	* eyal1.c (waste_time): Make threads do more work to ensure that
-	all threads get to do some work.
-	* semaphore1.c: Make it clear that certain errors are expected.
-	* exception2.c (non_MSVC code sections): Change to include
-	C++ standard include file, i.e. change <new.h> to <exception>.
-	* exception3.c (non_MSVC code sections): Likewise; qualify std::
-	namespace entities where necessary.
-	* GNUmakefile: modified to work in the MsysDTK (newer MinGW)
-	environment; define CC as gcc or g++ as appropriate because
-	using gcc -x c++ doesn't link with required c++ libs by default,
-	but g++ does.
-
-2002-12-11  Ross Johnson  <ross@special.ise.canberra.edu.au>
-
-	* mutex7e.c: Assert EBUSY return instead of EDEADLK.
-
-2002-06-03  Ross Johnson  <rpj@digit.ise.canberra.edu.au>
-
-	* semaphore2.c: New test.
-
-2002-03-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* Makefile (CFLAGS): Changed /MT to /MD to link with
-	the correct library MSVCRT.LIB. Otherwise errno doesn't
-	work.
-
-2002-02-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* exception3.c: Correct recent change.
-
-	* semaphore1.c: New test.
-
-	* Makefile: Add rule to generate pre-processor output.
-
-2002-02-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* exception3.c (terminateFunction): For MSVC++, call
-	exit() rather than pthread_exit(). Add comments to explain
-	why.
-	   * Notes from the MSVC++ manual:
-	   *       1) A term_func() should call exit(), otherwise
-	   *          abort() will be called on return to the caller.
-	   *          abort() raises SIGABRT. The default signal handler
-	   *          for all signals terminates the calling program with
-	   *          exit code 3.
-	   *       2) A term_func() must not throw an exception. Therefore
-	   *          term_func() should not call pthread_exit() if an
-	   *          an exception-using version of pthreads-win32 library
-	   *          is being used (i.e. either pthreadVCE or pthreadVSE).
-
-
-2002-02-23  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* rwlock2_t.c: New test.
-	* rwlock3_t.c: New test.
-	* rwlock4_t.c: New test.
-	* rwlock5_t.c: New test.
-	* rwlock6_t.c: New test.
-	* rwlock6_t2.c: New test.
-	* rwlock6.c (main): Swap thread and result variables
-	to correspond to actual thread functions.
-	* rwlock1.c: Change test description comment to correspond
-	to the actual test.
-
-	* condvar1_2.c: Loop over the test many times in the hope
-	of detecting any intermittent deadlocks. This is to
-	test a fixed problem in pthread_cond_destroy.c.
-
-	* spin4.c: Remove unused variable.
-
-2002-02-17  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* condvar1_1.c: New test.
-	* condvar1_2.c: New test.
-
-2002-02-07  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* delay1.c: New test.
-	* delay2.c: New test.
-	* exit4.c: New test.
-
-2002-02-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* mutex8: New test.
-	* mutex8n: New test.
-	* mutex8e: New test.
-	* mutex8r: New test.
-	* cancel6a: New test.
-	* cancel6d: New test.
-	* cleanup0.c: Add pragmas for inline optimisation control.
-	* cleanup1.c: Add pragmas for inline optimisation control.
-	* cleanup2.c: Add pragmas for inline optimisation control.
-	* cleanup3.c: Add pragmas for inline optimisation control.
-	* condvar7.c: Add pragmas for inline optimisation control.
-	* condvar8.c: Add pragmas for inline optimisation control.
-	* condvar9.c: Add pragmas for inline optimisation control.
-
-2002-01-30  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* cleanup1.c (): Must be declared __cdecl when compiled
-	as C++ AND testing the standard C library version.
-
-2002-01-16  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* spin4.c (main): Fix renamed function call.
-
-2002-01-14  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* exception3.c (main): Shorten wait time.
-
-2002-01-09  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* mutex7.c: New test.
-	* mutex7n.c: New test.
-	* mutex7e.c: New test.
-	* mutex7r.c: New test.
-	* mutex6.c: Modified to avoid leaving the locked mutex
-	around on exit.
-
-2001-10-25  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
-
-	* condvar2.c: Remove reference to cv->nWaitersUnblocked.
-	* condvar2_1.c: Likewise; lower NUMTHREADS from 60 to 30.
-	* condvar3_1.c: Likewise.
-	* condvar3_2.c: Likewise.
-	* count1.c: lower NUMTHREADS from 60 to 30.
-	* inherit1.c: Determine valid priority values and then
-	assert values returned by POSIX routines are the same.
-	* priority1.c: Likewise.
-	* priority2.c: Likewise.
-	
-2001-07-12  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
-
-	* barrier5.c: Assert that precisely one thread receives
-	PTHREAD_BARRIER_SERIAL_THREAD at each barrier.
-
-2001-07-09  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
-
-	* barrier3.c: Fixed.
-	* barrier4.c: Fixed.
-	* barrier5.c: New; proves that all threads in the group
-	reaching the barrier wait and then resume together. Repeats the test
-	using groups of 1 to 16 threads. Each group of threads must negotiate
-	a large number of barriers (10000).
-	* spin4.c: Fixed.
-	* test.h (error_string): Modified the success (0) value.
-
-2001-07-07  Ross Johnson  <rpj@setup1.ise.canberra.edu.au>
-
-	* spin3.c: Changed test and fixed.
-	* spin4.c: Fixed.
-	* barrier3.c: Fixed.
-	* barrier4.c: Fixed.
-
-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.
-	* benchtest4.c: New; time mutexes.
-	* condvar3_1.c: Fixed bug - Alexander Terekhov
-	* condvar3_3.c: New test.
-
-2001-06-25  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* priority1.c: New test.
-	* priority2.c: New test.
-	* inherit1.c: New test.
-	* benchtest1.c: New; timing mutexes.
-	* benchtest2.c: New; timing mutexes.
-	* mutex4.c: Modified to test all mutex types.
-
-2001-06-8  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* mutex5.c: Insert inert change to quell compiler warnings.
-	* condvar3_2.c: Remove unused variable.
-	
-2001-06-3  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* condvar2_1.c: New test.
-	* condvar3_1.c: New test.
-	* condvar3_2.c: New test.
-
-2001-05-30  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* mutex1n.c: New test.
-	* mutex1e.c: New test.
-	* mutex1r.c: New test.
-	* mutex4.c: Now locks and unlocks a mutex.
-	* mutex5.c: New test.
-	* mutex6.c: New test.
-	* mutex6n.c: New test.
-	* mutex6e.c: New test.
-	* mutex6r.c: New test.
-	* Makefile: Added new tests; reorganised.
-	* GNUmakefile: Likewise.
-	* rwlock6.c: Fix to properly prove read-while-write locking
-	and single writer locking.
-
-2001-05-29  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* Makefile: Reorganisation.
-	* GNUmakefile: Likewise.
-	- Thomas Pfaff <tpfaff@gmx.net>
-
-	* exception1.c: Add stdio.h include to define fprintf and stderr
-	in non-exception C version of main().
-	* exception2.c: Likewise.
-	* exception3.c: Likewise.
-
-	* Makefile (rwlock7): Add new test.
-	* GNUmakefile (rwlock7): Add new test.
-	* rwlock7.c: New test.
-	* rwlock6.c: Changed to test that writer has priority.
-
-	* eyal1.c (main): Unlock each mutex_start lock before destroying
-	it.
-
-2000-12-29  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* GNUmakefile: Add mutex4 test; ensure libpthreadw32.a is
-	removed for "clean" target.
-	* Makefile: Add mutex4 test.
-
-	* exception3.c: Remove SEH code; automatically pass the test
-	under SEH (which is an N/A environment).
-
-	* mutex4.c: New test.
-
-	* eyal1.c (do_work_unit): Add a dummy "if" to force the
-	optimiser to retain code; reduce thread work loads.
-
-	* condvar8.c (main): Add an additional "assert" for debugging;
-	increase pthread_cond_signal timeout.
-
-2000-12-28  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* eyal1.c: Increase thread work loads.
-	* exception2.c: New test.
-	* exception3.c: New test.
-	* Makefile: Add new tests exception2.c and exception3.c.
-	* GNUmakefile: Likewise.
-
-2000-12-11  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* cleanup3.c: Remove unused variable.
-	* cleanup2.c: Likewise.
-	* exception1.c: Throw an exception rather than use
-	a deliberate zero divide so that catch(...) will
-	handle it under Mingw32. Mingw32 now builds the
-	library correctly to pass all tests - see Thomas
-	Pfaff's detailed instructions re needed changes
-	to Mingw32 in the Pthreads-Win32 FAQ.
-
-2000-09-08  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* cancel5.c: New; tests calling pthread_cancel()
-	from the main thread without first creating a
-	POSIX thread struct for the non-POSIX main thread
-	- this forces pthread_cancel() to create one via
-	pthread_self().
-	* Makefile (cancel5): Add new test.
-	* GNUmakefile (cancel5): Likewise.
-
-2000-08-17  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* create2.c: New; Test that pthread_t contains
-	the W32 HANDLE before it calls the thread routine
-	proper.
-
-2000-08-13  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* condvar3.c: Minor change to eliminate compiler
-	warning.
-
-	* condvar4.c: ditto.
-
-	* condvar5.c: ditto.
-
-	* condvar6.c: ditto.
-
-	* condvar7.c: ditto.
-
-	* condvar8.c: ditto.
-
-	* condvar9.c: ditto.
-
-	* exit1.c: Function needed return statement.
-
-	* cleanup1.c: Remove unnecessary printf arg.
-
-	* cleanup2.c: Fix cast.
-
-	* rwlock6.c: Fix casts.
-
-	* exception1.c (PtW32CatchAll): Had the wrong name;
-	fix casts.
-
-	* cancel3.c: Remove unused waitLock variable.
-
-	* GNUmakefile: Change library/dll naming; add new tests;
-	general minor changes.
-
-	* Makefile: Change library/dll naming; add targets for
-	testing each of the two VC++ EH scheme versions;
-	default target now issues help message; compile warnings
-	now interpreted as errors to stop the make; add new
-	tests; restructure to remove prerequisites needed
-	otherwise.
-
-	* README: Updated.
-
-
-2000-08-10  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* eyal1.c (main): Change implicit cast to explicit
-	cast when passing "print_server" function pointer;
-	G++ no longer allows implicit func parameter casts.
-
-	* cleanup1.c: Remove unused "waitLock".
-	(main): Fix implicit parameter cast.
-
-	* cancel2.c (main): Fix implicit parameter cast.
-
-	* cancel4.c (main): Fix implicit parameter cast.
-
-	* cancel3.c (main): Fix implicit parameter cast.
-
-	* GNUmakefile: Renamed from Makefile; Add missing
-	cancel1 and cancel2 test targets.
-
-	* Makefile: Converted for use with MS nmake.
-
-2000-08-06  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* ccl.bat: Add /nologo to remove extraneous output.
-
-	* exception1.c (exceptionedThread): Init 'dummy';
-	put expression into if condition to prevent optimising away;
-	remove unused variable.
-
-	* cancel4.c (mythread): Cast return value to avoid warnings.
-
-	* cancel2.c (mythread): Missing #endif.
-
-	* condvar9.c (mythread): Cast return value to avoid warnings.
-
-	* condvar8.c (mythread): Cast return value to avoid warnings.
-
-	* condvar7.c (mythread): Cast return value to avoid warnings.
-
-	* cleanup3.c (mythread): Cast return value to avoid warnings.
-
-	* cleanup2.c (mythread): Cast return value to avoid warnings.
-
-	* cleanup1.c (mythread): Cast return value to avoid warnings.
-
-	* condvar5.c (mythread): Cast return value to avoid warnings.
-
-	* condvar3.c (mythread): Cast return value to avoid warnings.
-
-	* condvar6.c (mythread): Cast return value to avoid warnings.
-
-	* condvar4.c (mythread): Cast return value to avoid warnings.
-
-2000-08-05  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* cancel2.c: Use PtW32CatchAll macro if defined.
-
-	* exception1.c: Use PtW32CatchAll macro if defined.
-
-2000-08-02  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* tsd1.c: Fix typecasts of &result [g++ is now very fussy].
-	
-	* test.h (assert): Return 0's explicitly to allay
-	g++ errors.
-	
-	* join2.c: Add explicit typecasts.
-	
-	* join1.c: Add explicit typecasts.
-	
-	* join0.c: Add explicit typecasts.
-	
-	* eyal1.c: Add explicit typecasts.
-	
-	* count1.c (main): Add type cast to remove g++ parse warning
-	[gcc-2.95.2 seems to have tightened up on this].
-
-	* Makefile (GLANG): Use c++ explicitly.
-	Remove MSVC sections (was commented out).
-	Add target to generate cpp output.
-
-2000-07-25  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* runtest.bat: modified to work under W98.
-	
-	* runall.bat: Add new tests; modified to work under W98.
-	It was ok under NT.
-
-	* Makefile: Add new tests.
-
-	* exception1.c: New; Test passing exceptions back to the
-	application and retaining library internal exceptions.
-
-	* join0.c: New; Test a single join.
-
-2000-01-06  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* cleanup1.c: New; Test cleanup handler executes (when thread is
-	canceled).
-
-	* cleanup2.c: New; Test cleanup handler executes (when thread is
-	not canceled).
-
-	* cleanup3.c: New; Test cleanup handler does not execute
-	(when thread is not canceled).
-
-2000-01-04  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* cancel4.c: New; Test cancelation does not occur in deferred
-	cancelation threads with no cancelation points.
-
-	* cancel3.c: New; Test asynchronous cancelation.
-
-	* context1.c: New; Test context switching method for async
-	cancelation.
-
-1999-11-23  Ross Johnson  <rpj@special.ise.canberra.edu.au>
-
-	* test.h: Add header includes; include local header versions rather
-	than system versions; rearrange the assert macro defines.
-
-1999-11-07  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* loadfree.c: New. Test loading and freeing the library (DLL).
-
-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.
-	* condvar8.c: New. Test multiple broadcasts.
-	* condvar9.c: New. Test multiple broadcasts with thread
-	cancelation.
-	
-Sep 16 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* rwlock6.c: New test.
-
-Sep 15 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* rwlock1.c: New test.
-	* rwlock2.c: New test.
-	* rwlock3.c: New test.
-	* rwlock4.c: New test.
-	* rwlock5.c: New test.
-
-Aug 22 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* runall.bat (join2): Add test.
-
-Aug 19 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* join2.c: New test.
-
-Wed Aug 12 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* Makefile (LIBS): Add -L.
-
-Mon May 31 10:25:01 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* Makefile (GLANG): Add GCC language option.
-
-Sat May 29 23:29:04 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* runall.bat (condvar5): Add new test.
-
-	* runall.bat (condvar6): Add new test.
-
-	* Makefile (condvar5) : Add new test.
-	
-	* Makefile (condvar6) : Add new test.
-	
-	* condvar5.c: New test for pthread_cond_broadcast().
-
-	* condvar6.c: New test for pthread_cond_broadcast().
-
-Sun Apr  4 12:04:28 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* tsd1.c (mythread): Change Sleep(0) to sched_yield().
-	(sched.h): Include.
-
-	* condvar3.c (mythread): Remove redundant Sleep().
-
-	* runtest.bat: Re-organised to make more informative.
-
-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.
-
-	* count1.c: raise number of spawned threads to 60 (appears to
-	be the limit under Win98).
-
-Sun Mar 14 21:31:02 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* test.h (assert): add assertion trace option.
-	Use:
-	"#define ASSERT_TRACE 1" to turn it on,
-	"#define ASSERT_TRACE 0" to turn it off (default).
-
-	* condvar3.c (main): add more assertions.
-
-	* condvar4.c (main): add more assertions.
-
-	* condvar1.c (main): add more assertions.
-
-Fri Mar 12 08:34:15 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* condvar4.c (cvthing): switch the order of the INITIALIZERs.
-
-	* eyal1.c (main): Fix trylock loop; was not waiting for thread to lock
-	the "started" mutex.
-
-Wed Mar 10 10:41:52 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* tryentercs.c: Apply typo patch from bje.
-
-	* tryentercs2.c: Ditto.
-
-Sun Mar  7 10:41:52 1999  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* Makefile (condvar3, condvar4): Add tests.
-
-	* condvar4.c (General): Reduce to simple test case; prerequisite
-	is condvar3.c; add description.
-
-	* condvar3.c (General): Reduce to simple test case; prerequisite
-	is condvar2.c; add description.
-
-	* condvar2.c (General): Reduce to simple test case; prerequisite
-	is condvar1.c; add description.
-
-	* condvar1.c (General): Reduce to simple test case; add
-	description.
-
-	* Template.c (Comments): Add generic test detail.
-
-1999-02-23  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-        * Template.c: Revamp.
-
-        * condvar1.c: Add.
-
-        * condvar2.c: Add.
-
-        * Makefile: Add condvar1 condvar2 tests.
-
-        * exit1.c, exit2.c, exit3.c: Cosmetic changes.
-
-1999-02-23  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-	* 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
-	version pops up a dialog but we want to run non-interactively.
-
-	* equal1.c: use assert a little more directly so that it
-	prints the actual call statement.
-
-	* exit1.c: Modify to return 0 on success, 1 on failure.
-
-1999-02-22  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-	* self2.c: Bring up to date.
-
-	* self3.c: Ditto.
-
-1999-02-21  Ben Elliston  <bje@cygnus.com>
-
-	* README: Update.
-
-	* Makefile: New file. Run all tests automatically. Primitive tests
-	are run first; more complex tests are run last.
-
-	* count1.c: New test. Validate the thread count.
-
-	* exit2.c: Perform a simpler test.
-	
-	* exit3.c: New test. Replaces exit2.c, since exit2.c needs to
-	perform simpler checking first.
-
-	* create1.c: Update to use the new testsuite exiting convention.
-	
-	* equal1.c: Likewise.
-
-	* mutex1.c: Likewise.
-
-	* mutex2.c: Likewise.
-
-	* once1.c: Likewise.
-
-	* self2.c: Likewise.
-
-	* self3.c: Likewise.
-
-	* tsd1.c: Likewise.
-
-1999-02-20  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-	* mutex2.c: Test static mutex initialisation.
-
-	* test.h: New. Declares a table mapping error numbers to
-	error names.
-
-1999-01-17  Ross Johnson  <rpj@ise.canberra.edu.au>
-
-	* runtest: New script to build and run a test in the tests directory.
-
-Wed Dec 30 11:22:44 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* tsd1.c: Re-written. See comments at start of file.
-	* Template.c: New. Contains skeleton code and comment template
-	intended to fully document the test.
-
-Fri Oct 16 17:59:49 1998  Ross Johnson  <rpj@swan.canberra.edu.au>
-
-	* tsd1.c (destroy_key): Add function. Change diagnostics.
-
-Thu Oct 15 17:42:37 1998  Ross Johnson  <rpj@swan.canberra.edu.au>
-
-	* tsd1.c (mythread): Fix some casts and add some message
-	output. Fix inverted conditional.
-
-Mon Oct 12 02:12:29 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
-
-	* tsd1.c: New. Test TSD using 1 key and 2 threads.
-
-1998-09-13  Ben Elliston  <bje@cygnus.com>
-
-	* eyal1.c: New file; contributed by Eyal Lebedinsky
-	<eyal@eyal.emu.id.au>.
-
-1998-09-12  Ben Elliston  <bje@cygnus.com>
-
-	* exit2.c (func): Return a value.
-	(main): Call the right thread entry function.
-
-1998-07-22  Ben Elliston  <bje@cygnus.com>
-
-	* exit2.c (main): Fix size of pthread_t array.
-
-1998-07-10  Ben Elliston  <bje@cygnus.com>
-
-	* exit2.c: New file; test pthread_exit() harder.
-
-	* exit1.c: New file; test pthread_exit().
+	* exit1.c: New file; test pthread_exit().
diff --git a/tests/Debug.dsp b/tests/Debug.dsp
new file mode 100644
index 0000000..0ba51bb
--- /dev/null
+++ b/tests/Debug.dsp
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="Debug" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Debug - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "Debug.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Debug.mak" CFG="Debug - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Debug - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Debug - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Debug - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0xc09 /d "NDEBUG"
+# ADD RSC /l 0xc09 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "Debug - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /Ze /W3 /WX /Gm /vd1 /GR- /GX- /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "CLEANUP_C" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0xc09 /d "_DEBUG"
+# ADD RSC /l 0xc09 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pthreadVC.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:".."
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Debug - Win32 Release"
+# Name "Debug - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\Debug.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\semaphore4.c
+# End Source File
+# End Target
+# End Project
diff --git a/tests/Debug.dsw b/tests/Debug.dsw
new file mode 100644
index 0000000..5fd6af3
--- /dev/null
+++ b/tests/Debug.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Debug"=.\Debug.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tests/Debug.ncb b/tests/Debug.ncb
new file mode 100644
index 0000000..68ecb6d
Binary files /dev/null and b/tests/Debug.ncb differ
diff --git a/tests/Debug.opt b/tests/Debug.opt
new file mode 100644
index 0000000..f263d4f
Binary files /dev/null and b/tests/Debug.opt differ
diff --git a/tests/Debug.plg b/tests/Debug.plg
new file mode 100644
index 0000000..9b26377
--- /dev/null
+++ b/tests/Debug.plg
@@ -0,0 +1,35 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: Debug - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8EA.tmp" with contents
+[
+/nologo /MDd /Ze /W3 /WX /Gm /vd1 /GR- /GX- /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "CLEANUP_C" /FR"Debug/" /Fp"Debug/Debug.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c 
+"E:\PTHREADS\pthreads\tests\semaphore4.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8EA.tmp" 
+Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8EB.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pthreadVC.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/Debug.pdb" /debug /machine:I386 /out:"Debug/Debug.exe" /pdbtype:sept /libpath:".." 
+.\Debug\semaphore4.obj
+]
+Creating command line "link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8EB.tmp"
+<h3>Output Window</h3>
+Compiling...
+semaphore4.c
+Linking...
+Creating command line "bscmake.exe /nologo /o"Debug/Debug.bsc"  .\Debug\semaphore4.sbr"
+Creating browse info file...
+<h3>Output Window</h3>
+
+
+
+<h3>Results</h3>
+Debug.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/tests/Debug.txt b/tests/Debug.txt
new file mode 100644
index 0000000..5323874
--- /dev/null
+++ b/tests/Debug.txt
@@ -0,0 +1,6 @@
+This project is used to debug individual test case programs.
+
+To build and debug a test case:
+- add the .c file to this project;
+- remove any .c files from other test cases from this project.
+- build and debug as usual.
\ No newline at end of file
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index aecd718..0e07abf 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -50,8 +50,8 @@ MAKE	= make
 #
 XXCFLAGS	= 
 XXLIBS	= -lws2_32
-CFLAGS	= -O3 -UNDEBUG -Wall $(XXCFLAGS)
-#CFLAGS	= -g -O0 -UNDEBUG -Wall $(XXCFLAGS)
+#CFLAGS	= -O3 -UNDEBUG -Wall $(XXCFLAGS)
+CFLAGS	= -g -UNDEBUG -Wall $(XXCFLAGS)
 BUILD_DIR	= ..
 INCLUDES	= -I.
 
@@ -81,7 +81,9 @@ TESTS	= sizes loadfree \
 	  mutex4 mutex6 mutex6n mutex6e mutex6r \
 	  mutex6s mutex6es mutex6rs \
 	  mutex7 mutex7n mutex7e mutex7r mutex8 mutex8n mutex8e mutex8r \
-	  count1 once1 tsd1 self2 cancel1 cancel2 \
+	  count1 once1 tsd1 self2 \
+	  cancel1 cancel2 \
+	  semaphore4 semaphore4t \
 	  delay1 delay2 eyal1 \
 	  condvar3 condvar3_1 condvar3_2 condvar3_3 \
 	  condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \
@@ -253,6 +255,8 @@ self2.pass: create1.pass
 semaphore1.pass:
 semaphore2.pass:
 semaphore3.pass: semaphore2.pass
+semaphore4.pass: semaphore3.pass cancel1.pass
+semaphore4t.pass: semaphore4.pass
 sizes.pass:
 spin1.pass:
 spin2.pass: spin1.pass
diff --git a/tests/Makefile b/tests/Makefile
index 71154b3..10dd7fe 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,349 +1,353 @@
-# Makefile for the pthreads test suite.
-# If all of the .pass files can be created, the test suite has passed.
-#
-# --------------------------------------------------------------------------
-#
-#      Pthreads-win32 - POSIX Threads Library for Win32
-#      Copyright(C) 1998 John E. Bossom
-#      Copyright(C) 1999,2003 Pthreads-win32 contributors
-# 
-#      Contact Email: rpj@callisto.canberra.edu.au
-# 
-#      The current list of contributors is contained
-#      in the file CONTRIBUTORS included with the source
-#      code distribution. The list can also be seen at the
-#     following World Wide Web location:
-#      http://sources.redhat.com/pthreads-win32/contributors.html
-# 
-#      This library is free software; you can redistribute it and/or
-#      modify it under the terms of the GNU Lesser General Public
-#      License as published by the Free Software Foundation; either
-#      version 2 of the License, or (at your option) any later version.
-# 
-#      This library is distributed in the hope that it will be useful,
-#      but WITHOUT ANY WARRANTY; without even the implied warranty of
-#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#      Lesser General Public License for more details.
-# 
-#      You should have received a copy of the GNU Lesser General Public
-#      License along with this library in the file COPYING.LIB;
-#      if not, write to the Free Software Foundation, Inc.,
-#      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-#
-
-
-CP	= copy
-RM	= erase
-CAT	= type
-MKDIR	= mkdir
-TOUCH	= echo Passed >
-ECHO	= @echo
-
-QAPC	= ..\QueueUserAPCEx\User\quserex.dll
-
-CPHDR	= pthread.h semaphore.h sched.h
-
-OPTIM	= /O2 /Ob0
-
-XXLIBS	= ws2_32.lib
-
-# C++ Exceptions
-VCEFLAGS	= /GX /TP /DPtW32NoCatchWarn /D__CLEANUP_CXX
-VCELIB	= pthreadVCE.lib
-VCEDLL	= pthreadVCE.dll
-# Structured Exceptions
-VSEFLAGS	= /D__CLEANUP_SEH
-VSELIB	= pthreadVSE.lib
-VSEDLL	= pthreadVSE.dll
-# C cleanup code
-VCFLAGS	= /D__CLEANUP_C
-VCLIB	= pthreadVC.lib
-VCDLL	= pthreadVC.dll
-# C++ Exceptions in application - using VC version of pthreads dll
-VCXFLAGS	= /GX /TP /D__CLEANUP_C
-
-# Defaults
-CPLIB	= pthreadVC.lib
-CPDLL	= pthreadVC.dll
-
-CFLAGS= $(OPTIM) /W3 /WX /MD /nologo /Yd /Zi
-LFLAGS= /INCREMENTAL:NO
-INCLUDES=-I.
-BUILD_DIR=..
-
-COPYFILES	= $(CPHDR) $(CPLIB) $(CPDLL) $(QAPC)
-
-TEST		=
-EHFLAGS	=
-
-# If a test case returns a non-zero exit code to the shell, make will
-# stop.
-
-PASSES= sizes.pass  loadfree.pass \
-	  self1.pass  mutex5.pass  \
+# Makefile for the pthreads test suite.
+# If all of the .pass files can be created, the test suite has passed.
+#
+# --------------------------------------------------------------------------
+#
+#      Pthreads-win32 - POSIX Threads Library for Win32
+#      Copyright(C) 1998 John E. Bossom
+#      Copyright(C) 1999,2003 Pthreads-win32 contributors
+# 
+#      Contact Email: rpj@callisto.canberra.edu.au
+# 
+#      The current list of contributors is contained
+#      in the file CONTRIBUTORS included with the source
+#      code distribution. The list can also be seen at the
+#     following World Wide Web location:
+#      http://sources.redhat.com/pthreads-win32/contributors.html
+# 
+#      This library is free software; you can redistribute it and/or
+#      modify it under the terms of the GNU Lesser General Public
+#      License as published by the Free Software Foundation; either
+#      version 2 of the License, or (at your option) any later version.
+# 
+#      This library is distributed in the hope that it will be useful,
+#      but WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#      Lesser General Public License for more details.
+# 
+#      You should have received a copy of the GNU Lesser General Public
+#      License along with this library in the file COPYING.LIB;
+#      if not, write to the Free Software Foundation, Inc.,
+#      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+#
+
+
+CP	= copy
+RM	= erase
+CAT	= type
+MKDIR	= mkdir
+TOUCH	= echo Passed >
+ECHO	= @echo
+
+QAPC	= ..\QueueUserAPCEx\User\quserex.dll
+
+CPHDR	= pthread.h semaphore.h sched.h
+
+OPTIM	= /O2 /Ob0
+
+XXLIBS	= ws2_32.lib
+
+# C++ Exceptions
+VCEFLAGS	= /GX /TP /DPtW32NoCatchWarn /D__CLEANUP_CXX
+VCELIB	= pthreadVCE.lib
+VCEDLL	= pthreadVCE.dll
+# Structured Exceptions
+VSEFLAGS	= /D__CLEANUP_SEH
+VSELIB	= pthreadVSE.lib
+VSEDLL	= pthreadVSE.dll
+# C cleanup code
+VCFLAGS	= /D__CLEANUP_C
+VCLIB	= pthreadVC.lib
+VCDLL	= pthreadVC.dll
+# C++ Exceptions in application - using VC version of pthreads dll
+VCXFLAGS	= /GX /TP /D__CLEANUP_C
+
+# Defaults
+CPLIB	= pthreadVC.lib
+CPDLL	= pthreadVC.dll
+
+CFLAGS= $(OPTIM) /W3 /WX /MD /nologo /Yd /Zi
+LFLAGS= /INCREMENTAL:NO
+INCLUDES=-I.
+BUILD_DIR=..
+
+COPYFILES	= $(CPHDR) $(CPLIB) $(CPDLL) $(QAPC)
+
+TEST		=
+EHFLAGS	=
+
+# If a test case returns a non-zero exit code to the shell, make will
+# stop.
+
+PASSES= sizes.pass  loadfree.pass \
+	  self1.pass  mutex5.pass  \
 	  mutex1.pass  mutex1n.pass  mutex1e.pass  mutex1r.pass  \
 	  semaphore1.pass  semaphore2.pass  semaphore3.pass  \
-	  mutex2.pass  mutex3.pass  \
-	  mutex2r.pass  mutex2e.pass  mutex3r.pass  mutex3e.pass  \
-	  condvar1.pass  condvar1_1.pass  condvar1_2.pass  condvar2.pass  condvar2_1.pass  \
-	  exit1.pass  create1.pass  create2.pass  reuse1.pass  reuse2.pass  equal1.pass  \
-	  kill1.pass  valid1.pass  valid2.pass  \
-	  exit2.pass  exit3.pass  exit4  exit5  \
-	  join0.pass  join1.pass  join2.pass join3.pass  \
-	  mutex4.pass  mutex6.pass  mutex6n.pass  mutex6e.pass  mutex6r.pass  \
-	  mutex6s.pass  mutex6es.pass  mutex6rs.pass  \
-	  mutex7.pass  mutex7n.pass  mutex7e.pass  mutex7r.pass  \
-	  mutex8.pass  mutex8n.pass  mutex8e.pass  mutex8r.pass  \
-	  count1.pass  once1.pass  tsd1.pass  \
-	  self2.pass  \
-	  cancel1.pass  cancel2.pass  \
-	  delay1.pass  delay2.pass  eyal1.pass  \
-	  condvar3.pass  condvar3_1.pass  condvar3_2.pass  condvar3_3.pass  \
-	  condvar4.pass  condvar5.pass  condvar6.pass  \
-	  condvar7.pass  condvar8.pass  condvar9.pass  \
-	  errno1.pass  \
-	  rwlock1.pass  rwlock2.pass  rwlock3.pass  rwlock4.pass  \
-	  rwlock5.pass  rwlock6.pass  rwlock7.pass  rwlock8.pass  \
-	  rwlock2_t.pass  rwlock3_t.pass  rwlock4_t.pass  rwlock5_t.pass  rwlock6_t.pass  rwlock6_t2.pass  \
-	  context1.pass  \
-	  cancel3.pass  cancel4.pass  cancel5.pass  cancel6a.pass  cancel6d.pass  \
-	  cancel7  cancel8  \
-	  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  barrier5.pass  \
-	  exception1.pass  exception2.pass  exception3.pass  \
-	  cancel9 create3
-
-BENCHRESULTS = \
-	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench
-
-help:
-	@ $(ECHO) Run one of the following command lines:
-	@ $(ECHO) nmake clean VC    (to test using VC dll with VC (no EH) applications)
-	@ $(ECHO) nmake clean VCX   (to test using VC dll with VC++ (EH) applications)
-	@ $(ECHO) nmake clean VCE   (to test using the VCE dll with VC++ EH applications)
-	@ $(ECHO) nmake clean VSE   (to test using VSE dll with VC (SEH) applications)
-	@ $(ECHO) nmake clean VC-bench    (to benchtest using VC dll with C bench app)
-	@ $(ECHO) nmake clean VCX-bench   (to benchtest using VC dll with C++ bench app)
-	@ $(ECHO) nmake clean VCE-bench   (to benchtest using VCE dll with C++ bench app)
-	@ $(ECHO) nmake clean VSE-bench   (to benchtest using VSE dll with SEH bench app)
-
-all:
-	@ nmake clean VC
-	@ nmake clean VCX
-	@ nmake clean VCE
-	@ nmake clean VSE
-	@ nmake clean VC-bench
-
-# This allows an individual test application to be made using the default lib.
-# e.g. nmake clean test cancel3.exe
-test: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC)
-
-tests: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) $(PASSES)
-	@ $(ECHO) ALL TESTS PASSED! Congratulations!
-
-benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(XXLIBS) $(BENCHRESULTS)
-	@ $(ECHO) ALL BENCH TESTS DONE.
-
-sizes.pass: sizes.exe
-	@ $(ECHO) ... Running $(TEST) test: $*.exe
-	@ .\$*.exe > SIZES.$(TEST)
-	@ $(CAT) SIZES.$(TEST)
-	@ $(ECHO) ...... Passed
-	@ $(TOUCH) $*.pass
-
-$(PASSES): $*.exe
-	@ $(ECHO) ... Running $(TEST) test: $*.exe
-	@ .\$*.exe
-	@ $(ECHO) ...... Passed
-	@ $(TOUCH) $*.pass
-
-$(BENCHRESULTS): $*.exe
-	@ $(ECHO) ... Running $(TEST) benchtest: $*.exe
-	@ .\$*.exe
-	@ $(ECHO) ...... Done
-	@ $(TOUCH) $*.bench
-
-VCE:
-	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" tests
-
-VSE:	
-	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" tests
-
-VC:
-	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests
-
-VCX:
-	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" tests
-
-VCE-bench:
-	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" XXLIBS="benchlib.o" benchtests
-
-VSE-bench:
-	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" XXLIBS="benchlib.o" benchtests
-
-VC-bench:
-	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" XXLIBS="benchlib.o" benchtests
-
-VCX-bench:
-	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" XXLIBS="benchlib.o" benchtests
-
-.c.exe:
-	@ $(ECHO) $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB) $(XXLIBS)
-	@ $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB) $(XXLIBS)
-
-.c.o:
-	@ $(ECHO) $(CC) $(EHFLAGS) /c $(CFLAGS) $(INCLUDES) $< /Fo$@
-	@ $(CC) $(EHFLAGS) $(CFLAGS) /c $(INCLUDES) $< /Fo$@
-
-.c.i:
-	@ $(CC) /P $(EHFLAGS) $(CFLAGS) $(INCLUDES) $<
-
-$(COPYFILES):
-	@ $(ECHO) Copying $@
-	@ $(CP) $(BUILD_DIR)\$@ .
-
-pthread.dll: $(CPDLL)
-	@ $(CP) $(CPDLL) pthread.dll
-	@ $(CP) $(CPLIB) pthread.lib
-
-clean:
-	- $(RM) *.dll
-	- $(RM) *.lib
-	- $(RM) pthread.h
-	- $(RM) semaphore.h
-	- $(RM) sched.h
-	- $(RM) *.e
-	- $(RM) *.i
-	- $(RM) *.obj
-	- $(RM) *.pdb
-	- $(RM) *.o
-	- $(RM) *.asm
-	- $(RM) *.exe
-	- $(RM) *.pass
-	- $(RM) *.bench
-	- $(RM) *.log
-
-benchtest1.bench:
-benchtest2.bench:
-benchtest3.bench:
-benchtest4.bench:
-benchtest5.bench:
-barrier1.pass:
-barrier2.pass: barrier1.pass
-barrier3.pass: barrier2.pass
-barrier4.pass: barrier3.pass
-barrier5.pass: barrier4.pass
-cancel1.pass: create1.pass
-cancel2.pass: cancel1.pass
-cancel3.pass: context1.pass
-cancel4.pass: cancel3.pass
-cancel5.pass: cancel3.pass
-cancel6a.pass: cancel3.pass
-cancel6d.pass: cancel3.pass
-cancel7.pass: kill1.pass
-cancel8.pass: cancel7.pass
-cleanup0.pass: cancel5.pass
-cleanup1.pass: cleanup0.pass
-cleanup2.pass: cleanup1.pass
-cleanup3.pass: cleanup2.pass
-condvar1.pass:
-condvar1_1.pass: condvar1.pass
-condvar1_2.pass: join2.pass
-condvar2.pass: condvar1.pass
-condvar2_1.pass: condvar2.pass join2.pass
-condvar3.pass: create1.pass condvar2.pass
-condvar3_1.pass: condvar3.pass join2.pass
-condvar3_2.pass: condvar3_1.pass
-condvar3_3.pass: condvar3_2.pass
-condvar4.pass: create1.pass
-condvar5.pass: condvar4.pass
-condvar6.pass: condvar5.pass
-condvar7.pass: condvar6.pass cleanup1.pass
-condvar8.pass: condvar7.pass
-condvar9.pass: condvar8.pass
-context1.pass: cancel2.pass
-count1.pass: join1.pass
-create1.pass: mutex2.pass
-create2.pass: create1.pass
-create3.pass:
-delay1.pass:
-delay2.pass: delay1.pass
-equal1.pass: create1.pass
-errno1.pass: mutex3.pass
-exception1.pass: cancel4.pass
-exception2.pass: exception1.pass
-exception3.pass: exception2.pass
-exit1.pass:
-exit2.pass: create1.pass
-exit3.pass: create1.pass
-exit4.pass:
-exit5.pass: kill1.pass
-eyal1.pass: tsd1.pass
-inherit1.pass: join1.pass priority1.pass
-join0.pass: create1.pass
-join1.pass: create1.pass
-join2.pass: create1.pass
-join3.pass: join2.pass
-kill1.pass: 
-loadfree.pass: pthread.dll
-mutex1.pass: self1.pass
-mutex1n.pass: mutex1.pass
-mutex1e.pass: mutex1.pass
-mutex1r.pass: mutex1.pass
-mutex2.pass: mutex1.pass
-mutex2r.pass: mutex2.pass
-mutex2e.pass: mutex2.pass
-mutex3.pass: create1.pass
-mutex3r.pass: mutex3.pass
-mutex3e.pass: mutex3.pass
-mutex4.pass: mutex3.pass
-mutex5.pass:
-mutex6.pass: mutex4.pass
-mutex6n.pass: mutex4.pass
-mutex6e.pass: mutex4.pass
-mutex6r.pass: mutex4.pass
-mutex6s.pass: mutex6.pass
-mutex6rs.pass: mutex6r.pass
-mutex6es.pass: mutex6e.pass
-mutex7.pass: mutex6.pass
-mutex7n.pass: mutex6n.pass
-mutex7e.pass: mutex6e.pass
-mutex7r.pass: mutex6r.pass
-mutex8.pass: mutex7.pass
-mutex8n.pass: mutex7n.pass
-mutex8e.pass: mutex7e.pass
-mutex8r.pass: mutex7r.pass
-once1.pass: create1.pass
-priority1.pass: join1.pass
-priority2.pass: priority1.pass barrier3.pass
-reuse1.pass: create2.pass
-reuse2.pass: reuse1.pass
-rwlock1.pass: condvar6.pass
-rwlock2.pass: rwlock1.pass
-rwlock3.pass: rwlock2.pass
-rwlock4.pass: rwlock3.pass
-rwlock5.pass: rwlock4.pass
-rwlock6.pass: rwlock5.pass
-rwlock7.pass: rwlock6.pass
-rwlock8.pass: rwlock7.pass
-rwlock2_t.pass: rwlock2.pass
-rwlock3_t.pass: rwlock2_t.pass
-rwlock4_t.pass: rwlock3_t.pass
-rwlock5_t.pass: rwlock4_t.pass
-rwlock6_t.pass: rwlock5_t.pass
-rwlock6_t2.pass: rwlock6_t.pass
-self1.pass:
-self2.pass: create1.pass
-semaphore1.pass:
-semaphore2.pass:
-sizes.pass:
-spin1.pass:
-spin2.pass: spin1.pass
-spin3.pass: spin2.pass
-spin4.pass: spin3.pass
-tsd1.pass: join1.pass
-valid1.pass: join1.pass
-valid2.pass: valid1.pass
-cancel9.pass: cancel8.pass
+	  mutex2.pass  mutex3.pass  \
+	  mutex2r.pass  mutex2e.pass  mutex3r.pass  mutex3e.pass  \
+	  condvar1.pass  condvar1_1.pass  condvar1_2.pass  condvar2.pass  condvar2_1.pass  \
+	  exit1.pass  create1.pass  create2.pass  reuse1.pass  reuse2.pass  equal1.pass  \
+	  kill1.pass  valid1.pass  valid2.pass  \
+	  exit2.pass  exit3.pass  exit4  exit5  \
+	  join0.pass  join1.pass  join2.pass join3.pass  \
+	  mutex4.pass  mutex6.pass  mutex6n.pass  mutex6e.pass  mutex6r.pass  \
+	  mutex6s.pass  mutex6es.pass  mutex6rs.pass  \
+	  mutex7.pass  mutex7n.pass  mutex7e.pass  mutex7r.pass  \
+	  mutex8.pass  mutex8n.pass  mutex8e.pass  mutex8r.pass  \
+	  count1.pass  once1.pass  tsd1.pass  \
+	  self2.pass  \
+	  cancel1.pass  cancel2.pass  \
+	  semaphore4.pass  semaphore4t.pass  \
+	  delay1.pass  delay2.pass  eyal1.pass  \
+	  condvar3.pass  condvar3_1.pass  condvar3_2.pass  condvar3_3.pass  \
+	  condvar4.pass  condvar5.pass  condvar6.pass  \
+	  condvar7.pass  condvar8.pass  condvar9.pass  \
+	  errno1.pass  \
+	  rwlock1.pass  rwlock2.pass  rwlock3.pass  rwlock4.pass  \
+	  rwlock5.pass  rwlock6.pass  rwlock7.pass  rwlock8.pass  \
+	  rwlock2_t.pass  rwlock3_t.pass  rwlock4_t.pass  rwlock5_t.pass  rwlock6_t.pass  rwlock6_t2.pass  \
+	  context1.pass  \
+	  cancel3.pass  cancel4.pass  cancel5.pass  cancel6a.pass  cancel6d.pass  \
+	  cancel7  cancel8  \
+	  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  barrier5.pass  \
+	  exception1.pass  exception2.pass  exception3.pass  \
+	  cancel9 create3
+
+BENCHRESULTS = \
+	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench
+
+help:
+	@ $(ECHO) Run one of the following command lines:
+	@ $(ECHO) nmake clean VC    (to test using VC dll with VC (no EH) applications)
+	@ $(ECHO) nmake clean VCX   (to test using VC dll with VC++ (EH) applications)
+	@ $(ECHO) nmake clean VCE   (to test using the VCE dll with VC++ EH applications)
+	@ $(ECHO) nmake clean VSE   (to test using VSE dll with VC (SEH) applications)
+	@ $(ECHO) nmake clean VC-bench    (to benchtest using VC dll with C bench app)
+	@ $(ECHO) nmake clean VCX-bench   (to benchtest using VC dll with C++ bench app)
+	@ $(ECHO) nmake clean VCE-bench   (to benchtest using VCE dll with C++ bench app)
+	@ $(ECHO) nmake clean VSE-bench   (to benchtest using VSE dll with SEH bench app)
+
+all:
+	@ nmake clean VC
+	@ nmake clean VCX
+	@ nmake clean VCE
+	@ nmake clean VSE
+	@ nmake clean VC-bench
+
+# This allows an individual test application to be made using the default lib.
+# e.g. nmake clean test cancel3.exe
+test: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC)
+
+tests: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) $(PASSES)
+	@ $(ECHO) ALL TESTS PASSED! Congratulations!
+
+benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(XXLIBS) $(BENCHRESULTS)
+	@ $(ECHO) ALL BENCH TESTS DONE.
+
+sizes.pass: sizes.exe
+	@ $(ECHO) ... Running $(TEST) test: $*.exe
+	@ .\$*.exe > SIZES.$(TEST)
+	@ $(CAT) SIZES.$(TEST)
+	@ $(ECHO) ...... Passed
+	@ $(TOUCH) $*.pass
+
+$(PASSES): $*.exe
+	@ $(ECHO) ... Running $(TEST) test: $*.exe
+	@ .\$*.exe
+	@ $(ECHO) ...... Passed
+	@ $(TOUCH) $*.pass
+
+$(BENCHRESULTS): $*.exe
+	@ $(ECHO) ... Running $(TEST) benchtest: $*.exe
+	@ .\$*.exe
+	@ $(ECHO) ...... Done
+	@ $(TOUCH) $*.bench
+
+VCE:
+	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" tests
+
+VSE:	
+	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" tests
+
+VC:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests
+
+VCX:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" tests
+
+VCE-bench:
+	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" XXLIBS="benchlib.o" benchtests
+
+VSE-bench:
+	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" XXLIBS="benchlib.o" benchtests
+
+VC-bench:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" XXLIBS="benchlib.o" benchtests
+
+VCX-bench:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" XXLIBS="benchlib.o" benchtests
+
+.c.exe:
+	@ $(ECHO) $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB) $(XXLIBS)
+	@ $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB) $(XXLIBS)
+
+.c.o:
+	@ $(ECHO) $(CC) $(EHFLAGS) /c $(CFLAGS) $(INCLUDES) $< /Fo$@
+	@ $(CC) $(EHFLAGS) $(CFLAGS) /c $(INCLUDES) $< /Fo$@
+
+.c.i:
+	@ $(CC) /P $(EHFLAGS) $(CFLAGS) $(INCLUDES) $<
+
+$(COPYFILES):
+	@ $(ECHO) Copying $@
+	@ $(CP) $(BUILD_DIR)\$@ .
+
+pthread.dll: $(CPDLL)
+	@ $(CP) $(CPDLL) pthread.dll
+	@ $(CP) $(CPLIB) pthread.lib
+
+clean:
+	- $(RM) *.dll
+	- $(RM) *.lib
+	- $(RM) pthread.h
+	- $(RM) semaphore.h
+	- $(RM) sched.h
+	- $(RM) *.e
+	- $(RM) *.i
+	- $(RM) *.obj
+	- $(RM) *.pdb
+	- $(RM) *.o
+	- $(RM) *.asm
+	- $(RM) *.exe
+	- $(RM) *.pass
+	- $(RM) *.bench
+	- $(RM) *.log
+
+benchtest1.bench:
+benchtest2.bench:
+benchtest3.bench:
+benchtest4.bench:
+benchtest5.bench:
+barrier1.pass:
+barrier2.pass: barrier1.pass
+barrier3.pass: barrier2.pass
+barrier4.pass: barrier3.pass
+barrier5.pass: barrier4.pass
+cancel1.pass: create1.pass
+cancel2.pass: cancel1.pass
+cancel3.pass: context1.pass
+cancel4.pass: cancel3.pass
+cancel5.pass: cancel3.pass
+cancel6a.pass: cancel3.pass
+cancel6d.pass: cancel3.pass
+cancel7.pass: kill1.pass
+cancel8.pass: cancel7.pass
+cleanup0.pass: cancel5.pass
+cleanup1.pass: cleanup0.pass
+cleanup2.pass: cleanup1.pass
+cleanup3.pass: cleanup2.pass
+condvar1.pass:
+condvar1_1.pass: condvar1.pass
+condvar1_2.pass: join2.pass
+condvar2.pass: condvar1.pass
+condvar2_1.pass: condvar2.pass join2.pass
+condvar3.pass: create1.pass condvar2.pass
+condvar3_1.pass: condvar3.pass join2.pass
+condvar3_2.pass: condvar3_1.pass
+condvar3_3.pass: condvar3_2.pass
+condvar4.pass: create1.pass
+condvar5.pass: condvar4.pass
+condvar6.pass: condvar5.pass
+condvar7.pass: condvar6.pass cleanup1.pass
+condvar8.pass: condvar7.pass
+condvar9.pass: condvar8.pass
+context1.pass: cancel2.pass
+count1.pass: join1.pass
+create1.pass: mutex2.pass
+create2.pass: create1.pass
+create3.pass:
+delay1.pass:
+delay2.pass: delay1.pass
+equal1.pass: create1.pass
+errno1.pass: mutex3.pass
+exception1.pass: cancel4.pass
+exception2.pass: exception1.pass
+exception3.pass: exception2.pass
+exit1.pass:
+exit2.pass: create1.pass
+exit3.pass: create1.pass
+exit4.pass:
+exit5.pass: kill1.pass
+eyal1.pass: tsd1.pass
+inherit1.pass: join1.pass priority1.pass
+join0.pass: create1.pass
+join1.pass: create1.pass
+join2.pass: create1.pass
+join3.pass: join2.pass
+kill1.pass: 
+loadfree.pass: pthread.dll
+mutex1.pass: self1.pass
+mutex1n.pass: mutex1.pass
+mutex1e.pass: mutex1.pass
+mutex1r.pass: mutex1.pass
+mutex2.pass: mutex1.pass
+mutex2r.pass: mutex2.pass
+mutex2e.pass: mutex2.pass
+mutex3.pass: create1.pass
+mutex3r.pass: mutex3.pass
+mutex3e.pass: mutex3.pass
+mutex4.pass: mutex3.pass
+mutex5.pass:
+mutex6.pass: mutex4.pass
+mutex6n.pass: mutex4.pass
+mutex6e.pass: mutex4.pass
+mutex6r.pass: mutex4.pass
+mutex6s.pass: mutex6.pass
+mutex6rs.pass: mutex6r.pass
+mutex6es.pass: mutex6e.pass
+mutex7.pass: mutex6.pass
+mutex7n.pass: mutex6n.pass
+mutex7e.pass: mutex6e.pass
+mutex7r.pass: mutex6r.pass
+mutex8.pass: mutex7.pass
+mutex8n.pass: mutex7n.pass
+mutex8e.pass: mutex7e.pass
+mutex8r.pass: mutex7r.pass
+once1.pass: create1.pass
+priority1.pass: join1.pass
+priority2.pass: priority1.pass barrier3.pass
+reuse1.pass: create2.pass
+reuse2.pass: reuse1.pass
+rwlock1.pass: condvar6.pass
+rwlock2.pass: rwlock1.pass
+rwlock3.pass: rwlock2.pass
+rwlock4.pass: rwlock3.pass
+rwlock5.pass: rwlock4.pass
+rwlock6.pass: rwlock5.pass
+rwlock7.pass: rwlock6.pass
+rwlock8.pass: rwlock7.pass
+rwlock2_t.pass: rwlock2.pass
+rwlock3_t.pass: rwlock2_t.pass
+rwlock4_t.pass: rwlock3_t.pass
+rwlock5_t.pass: rwlock4_t.pass
+rwlock6_t.pass: rwlock5_t.pass
+rwlock6_t2.pass: rwlock6_t.pass
+self1.pass:
+self2.pass: create1.pass
+semaphore1.pass:
+semaphore2.pass:
+semaphore3.pass: semaphore2.pass
+semaphore4.pass: semaphore3.pass cancel1.pass
+semaphore4t.pass: semaphore4.pass
+sizes.pass:
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
+tsd1.pass: join1.pass
+valid1.pass: join1.pass
+valid2.pass: valid1.pass
+cancel9.pass: cancel8.pass
diff --git a/tests/README b/tests/README
index b767f89..784c4f7 100644
--- a/tests/README
+++ b/tests/README
@@ -5,19 +5,19 @@ These make scripts expect to be able to copy the dll, libarary
 and header files from this directory's parent directory,
 which should be the pthreads-win32 source directory.
 
-MS VC++ nmake
+MS VC nmake
 -------------
 
 Run the target corresponding to the DLL version being tested:
  
-nmake clean VCE
+nmake clean VC
  
 or:
  
-nmake clean VSE
+nmake clean VS
 
 
-GNU G++ make
+GNU GCC make
 ------------
 
 Run "make clean" and then "make". See the "Known bugs" section
@@ -36,3 +36,9 @@ Tests written in this test suite should behave in the following manner:
 	* No diagnostic output should appear when the test is succeeding.
 	  Diagnostic output may be emitted if something in the test
 	  fails, to help determine the cause of the test failure.
+
+Notes:
+------
+
+Many test cases use knowledge of implementation internals which are supposed
+to be opaque to portable applications.
diff --git a/tests/README.benchtests b/tests/README.benchtests
index 01051a2..e02cb3e 100644
--- a/tests/README.benchtests
+++ b/tests/README.benchtests
@@ -1,97 +1,97 @@
-
-------------
-Benchmarking
-------------
-There is a new but growing set a benchmarking programs in the
-"tests" directory. These should be runnable using the
-following command-lines corresponding to each of the possible
-library builds:
-
-MSVC:
-nmake clean VC-bench
-nmake clean VCE-bench
-nmake clean VSE-bench
-
-Mingw32:
-make clean GC-bench
-make clean GCE-bench
-
-UWIN:
-The benchtests are run as part of the testsuite.
-
-
-Mutex benchtests
-----------------
-
-benchtest1 - Lock plus unlock on an unlocked mutex.
-benchtest2 - Lock plus unlock on a locked mutex.
-benchtest3 - Trylock on a locked mutex.
-benchtest4 - Trylock plus unlock on an unlocked mutex.
-
-
-Each test times up to three alternate synchronisation
-implementations as a reference, and then times each of
-the four mutex types provided by the library. Each is
-described below:
-
-Simple Critical Section
-- uses a simple Win32 critical section. There is no
-additional overhead for this case as there is in the
-remaining cases.
-
-POSIX mutex implemented using a Critical Section
-- The old implementation which uses runtime adaptation
-depending on the Windows variant being run on. When
-the pthreads DLL was run on WinNT or higher then
-POSIX mutexes would use Win32 Critical Sections.
-
-POSIX mutex implemented using a Win32 Mutex
-- The old implementation which uses runtime adaptation
-depending on the Windows variant being run on. When
-the pthreads DLL was run on Win9x then POSIX mutexes
-would use Win32 Mutexes (because TryEnterCriticalSection
-is not implemented on Win9x).
-
-PTHREAD_MUTEX_DEFAULT
-PTHREAD_MUTEX_NORMAL
-PTHREAD_MUTEX_ERRORCHECK
-PTHREAD_MUTEX_RECURSIVE
-- The current implementation supports these mutex types.
-The underlying basis of POSIX mutexes is now the same
-irrespective of the Windows variant, and should therefore
-have consistent performance.
-
-
-In all benchtests, the operation is repeated a large
-number of times and an average is calculated. Loop
-overhead is measured and subtracted from all test times.
-
-Comment on the results
-----------------------
-The gain in performance for Win9x systems is enormous - up to
-40 times faster for unlocked mutexes (2 times faster for locked
-mutexes).
-
-Pthread_mutex_trylock also appears to be faster for locked mutexes.
-
-The price for the new consistency between WinNT and Win9x is
-slower performance (up to twice as long) across a lock/unlock
-sequence. It is difficult to get a good split timing for lock
-and unlock operations, but by code inspection, it is the unlock
-operation that is slowing the pair down in comparison with the
-old-style CS mutexes, even for the fast PTHREAD_MUTEX_NORMAL mutex
-type with no other waiting threads. However, comparitive
-performance for operations on already locked mutexes is very close.
-
-When this is translated to real-world applications, the overall
-camparitive performance should be almost identical on NT class
-systems. That is, applications with heavy mutex contention should
-have almost equal performance, while applications with only light
-mutex contention should also have almost equal performance because
-the most critical operation in this case is the lock operation.
-
-Overall, the newer pthreads-win32 mutex routines are only slower
-(on NT class systems) where and when it is least critical.
-
-Thanks go to Thomas Pfaff for the current implementation of mutex
-routines.
+
+------------
+Benchmarking
+------------
+There is a new but growing set a benchmarking programs in the
+"tests" directory. These should be runnable using the
+following command-lines corresponding to each of the possible
+library builds:
+
+MSVC:
+nmake clean VC-bench
+nmake clean VCE-bench
+nmake clean VSE-bench
+
+Mingw32:
+make clean GC-bench
+make clean GCE-bench
+
+UWIN:
+The benchtests are run as part of the testsuite.
+
+
+Mutex benchtests
+----------------
+
+benchtest1 - Lock plus unlock on an unlocked mutex.
+benchtest2 - Lock plus unlock on a locked mutex.
+benchtest3 - Trylock on a locked mutex.
+benchtest4 - Trylock plus unlock on an unlocked mutex.
+
+
+Each test times up to three alternate synchronisation
+implementations as a reference, and then times each of
+the four mutex types provided by the library. Each is
+described below:
+
+Simple Critical Section
+- uses a simple Win32 critical section. There is no
+additional overhead for this case as there is in the
+remaining cases.
+
+POSIX mutex implemented using a Critical Section
+- The old implementation which uses runtime adaptation
+depending on the Windows variant being run on. When
+the pthreads DLL was run on WinNT or higher then
+POSIX mutexes would use Win32 Critical Sections.
+
+POSIX mutex implemented using a Win32 Mutex
+- The old implementation which uses runtime adaptation
+depending on the Windows variant being run on. When
+the pthreads DLL was run on Win9x then POSIX mutexes
+would use Win32 Mutexes (because TryEnterCriticalSection
+is not implemented on Win9x).
+
+PTHREAD_MUTEX_DEFAULT
+PTHREAD_MUTEX_NORMAL
+PTHREAD_MUTEX_ERRORCHECK
+PTHREAD_MUTEX_RECURSIVE
+- The current implementation supports these mutex types.
+The underlying basis of POSIX mutexes is now the same
+irrespective of the Windows variant, and should therefore
+have consistent performance.
+
+
+In all benchtests, the operation is repeated a large
+number of times and an average is calculated. Loop
+overhead is measured and subtracted from all test times.
+
+Comment on the results
+----------------------
+The gain in performance for Win9x systems is enormous - up to
+40 times faster for unlocked mutexes (2 times faster for locked
+mutexes).
+
+Pthread_mutex_trylock also appears to be faster for locked mutexes.
+
+The price for the new consistency between WinNT and Win9x is
+slower performance (up to twice as long) across a lock/unlock
+sequence. It is difficult to get a good split timing for lock
+and unlock operations, but by code inspection, it is the unlock
+operation that is slowing the pair down in comparison with the
+old-style CS mutexes, even for the fast PTHREAD_MUTEX_NORMAL mutex
+type with no other waiting threads. However, comparitive
+performance for operations on already locked mutexes is very close.
+
+When this is translated to real-world applications, the overall
+camparitive performance should be almost identical on NT class
+systems. That is, applications with heavy mutex contention should
+have almost equal performance, while applications with only light
+mutex contention should also have almost equal performance because
+the most critical operation in this case is the lock operation.
+
+Overall, the newer pthreads-win32 mutex routines are only slower
+(on NT class systems) where and when it is least critical.
+
+Thanks go to Thomas Pfaff for the current implementation of mutex
+routines.
diff --git a/tests/cancel1.c b/tests/cancel1.c
index 390db9f..55409d6 100644
--- a/tests/cancel1.c
+++ b/tests/cancel1.c
@@ -129,7 +129,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cancel2.c b/tests/cancel2.c
index d317ef9..dbc8c85 100644
--- a/tests/cancel2.c
+++ b/tests/cancel2.c
@@ -167,7 +167,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
   assert(pthread_mutex_lock(&waitLock) == 0);
 
   for (i = 1; i <= NUMTHREADS; i++)
diff --git a/tests/cancel3.c b/tests/cancel3.c
index c3657d6..3258fd0 100644
--- a/tests/cancel3.c
+++ b/tests/cancel3.c
@@ -126,7 +126,7 @@ main ()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert ((t[0] = pthread_self ()) != NULL);
+  assert ((t[0] = pthread_self ()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cancel4.c b/tests/cancel4.c
index b77f921..5b1b7e7 100644
--- a/tests/cancel4.c
+++ b/tests/cancel4.c
@@ -128,7 +128,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cancel6a.c b/tests/cancel6a.c
index 4aea81a..644cd4a 100644
--- a/tests/cancel6a.c
+++ b/tests/cancel6a.c
@@ -115,7 +115,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cancel6d.c b/tests/cancel6d.c
index 9a69adb..d0ad7ac 100644
--- a/tests/cancel6d.c
+++ b/tests/cancel6d.c
@@ -119,7 +119,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
@@ -167,11 +167,6 @@ main()
       int fail = 0;
       int result = 0;
 
-      /*
-       * The thread does not contain any cancelation points, so
-       * a return value of PTHREAD_CANCELED confirms that async
-       * cancelation succeeded.
-       */
       assert(pthread_join(t[i], (void **) &result) == 0);
 
       fail = (result != (int) PTHREAD_CANCELED);
diff --git a/tests/cancel7.c b/tests/cancel7.c
index 9ad7db0..0609710 100644
--- a/tests/cancel7.c
+++ b/tests/cancel7.c
@@ -109,7 +109,7 @@ Win32thread(void * arg)
   assert(bag->started == 0);
   bag->started = 1;
 
-  assert((bag->self = pthread_self()) != NULL);
+  assert((bag->self = pthread_self()).p != NULL);
   assert(pthread_kill(bag->self, 0) == 0);
 
   for (i = 0; i < 100; i++)
@@ -191,7 +191,7 @@ main()
       result = (int) PTHREAD_CANCELED;
 #endif
 
-      assert(threadbag[i].self != NULL);
+      assert(threadbag[i].self.p != NULL);
       assert(pthread_kill(threadbag[i].self, 0) == ESRCH);
 
       fail = (result != (int) PTHREAD_CANCELED);
diff --git a/tests/cancel8.c b/tests/cancel8.c
index 484472e..1a99640 100644
--- a/tests/cancel8.c
+++ b/tests/cancel8.c
@@ -111,7 +111,7 @@ Win32thread(void * arg)
   assert(bag->started == 0);
   bag->started = 1;
 
-  assert((bag->self = pthread_self()) != NULL);
+  assert((bag->self = pthread_self()).p != NULL);
   assert(pthread_kill(bag->self, 0) == 0);
 
   assert(pthread_mutex_lock(&CVLock) == 0);
@@ -192,7 +192,7 @@ main()
       result = (int) PTHREAD_CANCELED;
 #endif
 
-      assert(threadbag[i].self != NULL);
+      assert(threadbag[i].self.p != NULL);
       assert(pthread_kill(threadbag[i].self, 0) == ESRCH);
 
       fail = (result != (int) PTHREAD_CANCELED);
diff --git a/tests/cleanup0.c b/tests/cleanup0.c
index 03098d3..8171e8c 100644
--- a/tests/cleanup0.c
+++ b/tests/cleanup0.c
@@ -140,7 +140,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cleanup1.c b/tests/cleanup1.c
index 5397297..18518da 100644
--- a/tests/cleanup1.c
+++ b/tests/cleanup1.c
@@ -98,7 +98,6 @@ static void
 #ifdef __CLEANUP_C
 __cdecl
 #endif
-
 increment_pop_count(void * arg)
 {
   int * c = (int *) arg;
@@ -150,7 +149,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cleanup2.c b/tests/cleanup2.c
index 2549b0c..3f0f445 100644
--- a/tests/cleanup2.c
+++ b/tests/cleanup2.c
@@ -134,7 +134,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/cleanup3.c b/tests/cleanup3.c
index dd43ccc..9c29be7 100644
--- a/tests/cleanup3.c
+++ b/tests/cleanup3.c
@@ -137,7 +137,7 @@ main()
   int i;
   pthread_t t[NUMTHREADS + 1];
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/condvar1_2.c b/tests/condvar1_2.c
index 07b3816..884832a 100644
--- a/tests/condvar1_2.c
+++ b/tests/condvar1_2.c
@@ -79,8 +79,8 @@
 #include "test.h"
 
 enum {
-  NUM_CV = 100,
-  NUM_LOOPS = 100
+  NUM_CV = 5,
+  NUM_LOOPS = 5
 };
 
 static pthread_cond_t cv[NUM_CV];
diff --git a/tests/condvar3.c b/tests/condvar3.c
index 8fa9ef7..7a30531 100644
--- a/tests/condvar3.c
+++ b/tests/condvar3.c
@@ -120,7 +120,7 @@ main()
   assert(pthread_attr_init(&attr) == 0);
   assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(pthread_cond_init(&cv, NULL) == 0);
 
diff --git a/tests/condvar4.c b/tests/condvar4.c
index 15a32ba..2da6708 100644
--- a/tests/condvar4.c
+++ b/tests/condvar4.c
@@ -119,7 +119,7 @@ main()
 
   cvthing.shared = 0;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
 
diff --git a/tests/condvar5.c b/tests/condvar5.c
index ff5ad70..3b016b9 100644
--- a/tests/condvar5.c
+++ b/tests/condvar5.c
@@ -118,7 +118,7 @@ main()
 
   cvthing.shared = 0;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
 
diff --git a/tests/condvar6.c b/tests/condvar6.c
index d642f9c..0cf92a4 100644
--- a/tests/condvar6.c
+++ b/tests/condvar6.c
@@ -149,7 +149,7 @@ main()
 
   cvthing.shared = 0;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
 
@@ -164,7 +164,7 @@ main()
 
   abstime.tv_sec += 5;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   awoken = 0;
 
diff --git a/tests/condvar7.c b/tests/condvar7.c
index a5bf4bf..9e0b29c 100644
--- a/tests/condvar7.c
+++ b/tests/condvar7.c
@@ -159,7 +159,7 @@ main()
 
   cvthing.shared = 0;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
 
@@ -174,7 +174,7 @@ main()
 
   abstime.tv_sec += 10;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   awoken = 0;
 
@@ -196,15 +196,15 @@ main()
    */
   Sleep(1000);
 
-  assert(pthread_mutex_lock(&cvthing.lock) == 0);
-
-  cvthing.shared++;
-
   /*
    * Cancel one of the threads.
    */
-  assert(pthread_cancel(t[3]) == 0);
-  Sleep(500);
+  assert(pthread_cancel(t[1]) == 0);
+  assert(pthread_join(t[1], NULL) == 0);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+  cvthing.shared++;
 
   /*
    * Signal all remaining waiting threads.
@@ -214,9 +214,10 @@ main()
   assert(pthread_mutex_unlock(&cvthing.lock) == 0);
 
   /*
-   * Give threads time to complete.
+   * Wait for all threads to complete.
    */
-  Sleep(2000);
+  for (i = 2; i <= NUMTHREADS; i++)
+    assert(pthread_join(t[i], NULL) == 0);
 
   /* 
    * Cleanup the CV.
diff --git a/tests/condvar8.c b/tests/condvar8.c
index 2ab67b3..572a5ac 100644
--- a/tests/condvar8.c
+++ b/tests/condvar8.c
@@ -158,7 +158,7 @@ main()
   struct _timeb currSysTime;
   const DWORD NANOSEC_PER_MILLISEC = 1000000;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
 
@@ -171,7 +171,7 @@ main()
 
   abstime.tv_sec += 10;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   awoken = 0;
 
diff --git a/tests/condvar9.c b/tests/condvar9.c
index b24d71e..7eb9035 100644
--- a/tests/condvar9.c
+++ b/tests/condvar9.c
@@ -86,6 +86,7 @@ typedef struct bag_t_ bag_t;
 struct bag_t_ {
   int threadnum;
   int started;
+  int finished;
   /* Add more per-thread state variables here */
 };
 
@@ -127,8 +128,8 @@ mythread(void * arg)
   assert(pthread_mutex_lock(&cvthing.lock) == 0);
 
   /*
-   * pthread_cond_timedwait is a cancelation point and we
-   * going to cancel one deliberately.
+   * pthread_cond_timedwait is a cancelation point and we're
+   * going to cancel some threads deliberately.
    */
 #ifdef _MSC_VER
 #pragma inline_depth(0)
@@ -146,6 +147,7 @@ mythread(void * arg)
   assert(cvthing.shared > 0);
 
   awoken++;
+  bag->finished = 1;
 
   assert(pthread_mutex_unlock(&cvthing.lock) == 0);
 
@@ -164,7 +166,7 @@ main()
   struct _timeb currSysTime;
   const DWORD NANOSEC_PER_MILLISEC = 1000000;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
 
@@ -177,7 +179,7 @@ main()
 
   abstime.tv_sec += 5;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   awoken = 0;
 
@@ -185,14 +187,15 @@ main()
        first < NUMTHREADS;
        first = last + 1, last = NUMTHREADS)
     {
+      int ct;
+
       assert(pthread_mutex_lock(&start_flag) == 0);
 
       for (i = first; i <= last; i++)
 	{
-	  threadbag[i].started = 0;
+	  threadbag[i].started = threadbag[i].finished = 0;
 	  threadbag[i].threadnum = i;
 	  assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
-	  assert(pthread_detach(t[i]) == 0);
 	}
 
       /*
@@ -207,46 +210,47 @@ main()
        */
       Sleep(1000);
 
+      ct = (first + last) / 2;
+      assert(pthread_cancel(t[ct]) == 0);
+      canceledThreads++;
+      assert(pthread_join(t[ct], NULL) == 0);
+
       assert(pthread_mutex_lock(&cvthing.lock) == 0);
 
       cvthing.shared++;
 
-      assert(pthread_cancel(t[(first + last) / 2]) == 0);
-      canceledThreads++;
-
       assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
 
       assert(pthread_mutex_unlock(&cvthing.lock) == 0);
 
       /*
-       * Give threads time to complete.
+       * Standard check that all threads started - and wait for them to finish.
        */
-      Sleep(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);
+      for (i = first; i <= last; i++)
+	{ 
+	  failed = !threadbag[i].started;
+
+          if (failed)
+	    {
+	      fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	    }
+	  else
+	    {
+	      assert(pthread_join(t[i], NULL) == 0 || threadbag[i].finished == 0);
+//	      fprintf(stderr, "Thread %d: finished %d\n", i, threadbag[i].finished);
+	    }
 	}
     }
 
   /* 
    * Cleanup the CV.
    */
-  
+
   assert(pthread_mutex_destroy(&cvthing.lock) == 0);
 
   assert(cvthing.lock == NULL);
 
-  assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+  assert_e(pthread_cond_destroy(&cvthing.notbusy), ==, 0);
 
   assert(cvthing.notbusy == NULL);
 
diff --git a/tests/context1.c b/tests/context1.c
index 405f9da..fe36695 100644
--- a/tests/context1.c
+++ b/tests/context1.c
@@ -106,7 +106,7 @@ main()
 
   assert(pthread_create(&t, NULL, func, NULL) == 0);
 
-  hThread = t->threadH;
+  hThread = ((ptw32_thread_t *)t.p)->threadH;
 
   Sleep(500);
 
diff --git a/tests/errno1.c b/tests/errno1.c
index f3231f5..9e6b46d 100644
--- a/tests/errno1.c
+++ b/tests/errno1.c
@@ -125,7 +125,7 @@ main()
   pthread_mutex_lock(&stop_here);
   errno = 0;
 
-  assert((t[0] = pthread_self()) != NULL);
+  assert((t[0] = pthread_self()).p != NULL);
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
diff --git a/tests/exception1.c b/tests/exception1.c
index 9b52636..0e63806 100644
--- a/tests/exception1.c
+++ b/tests/exception1.c
@@ -196,7 +196,7 @@ main()
   pthread_t et[NUMTHREADS];
   pthread_t ct[NUMTHREADS];
 
-  assert((mt = pthread_self()) != NULL);
+  assert((mt = pthread_self()).p != NULL);
 
   for (i = 0; i < NUMTHREADS; i++)
     {
diff --git a/tests/exception2.c b/tests/exception2.c
index ed54a57..da835b5 100644
--- a/tests/exception2.c
+++ b/tests/exception2.c
@@ -129,7 +129,7 @@ main(int argc, char argv[])
       exit(0);
     }
 
-  assert((mt = pthread_self()) != NULL);
+  assert((mt = pthread_self()).p != NULL);
 
   for (i = 0; i < NUMTHREADS; i++)
     {
diff --git a/tests/exception3.c b/tests/exception3.c
index af47705..428cf5b 100644
--- a/tests/exception3.c
+++ b/tests/exception3.c
@@ -158,7 +158,7 @@ main()
   pthread_t et[NUMTHREADS];
   pthread_mutexattr_t ma;
 
-  assert((mt = pthread_self()) != NULL);
+  assert((mt = pthread_self()).p != NULL);
 
   printf("See the notes inside of exception3.c re term_funcs.\n");
 
diff --git a/tests/exit5.c b/tests/exit5.c
index e896bf4..4812cac 100644
--- a/tests/exit5.c
+++ b/tests/exit5.c
@@ -109,7 +109,7 @@ Win32thread(void * arg)
   assert(bag->started == 0);
   bag->started = 1;
 
-  assert((bag->self = pthread_self()) != NULL);
+  assert((bag->self = pthread_self()).p != NULL);
   assert(pthread_kill(bag->self, 0) == 0);
 
   /*
@@ -181,7 +181,7 @@ main()
       result = 1;
 #endif
 
-      assert(threadbag[i].self != NULL && pthread_kill(threadbag[i].self, 0) == ESRCH);
+      assert(threadbag[i].self.p != NULL && pthread_kill(threadbag[i].self, 0) == ESRCH);
 
       fail = (result != 1);
 
diff --git a/tests/reuse1.c b/tests/reuse1.c
index 2b74955..8e8ca54 100644
--- a/tests/reuse1.c
+++ b/tests/reuse1.c
@@ -82,7 +82,7 @@ static int washere = 0;
 void * func(void * arg)
 {
   washere = 1;
-  return (void *) 0; 
+  return arg; 
 }
  
 int
@@ -107,11 +107,16 @@ main()
   for (i = 1; i < NUMTHREADS; i++)
     {
       washere = 0;
-      assert(pthread_create(&t, &attr, func, NULL) == 0);
+      assert(pthread_create(&t, &attr, func, (void *) i) == 0);
       pthread_join(t, &result);
-      assert(result == 0);
+      assert((int) result == i);
       assert(washere == 1);
-      assert(t == last_t);
+      /* thread IDs should be unique */
+      assert(!pthread_equal(t, last_t));
+      /* thread struct pointers should be the same */
+      assert(t.p == last_t.p);
+      /* thread handle reuse counter should be different by one */
+      assert(t.x == last_t.x+1);
       last_t = t;
     }
 
diff --git a/tests/reuse2.c b/tests/reuse2.c
index 625611e..12aaa5f 100644
--- a/tests/reuse2.c
+++ b/tests/reuse2.c
@@ -53,7 +53,9 @@
  * -
  *
  * Environment:
- * -
+ * - This test is implementation specific
+ * because it uses knowledge of internals that should be
+ * opaque to an application.
  *
  * Input:
  * - None.
@@ -74,6 +76,9 @@
 
 #include "test.h"
 
+/*
+ */
+
 enum {
 	NUMTHREADS = 10000
 };
@@ -95,11 +100,11 @@ main()
 {
   pthread_t t[NUMTHREADS];
   pthread_attr_t attr;
-  int i, j;
-  int reuse,
-      reuseMax = 0,
-      reuseMin = NUMTHREADS,
-      idTotal = 0;
+  int i;
+  unsigned int notUnique = 0,
+	       totalHandles = 0,
+	       reuseMax = 0,
+	       reuseMin = NUMTHREADS;
 
   assert(pthread_attr_init(&attr) == 0);
   assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);
@@ -120,43 +125,39 @@ main()
    */
   for (i = 0; i < NUMTHREADS; i++)
     {
-      reuse = 0;
+      if (t[i].p != NULL)
+        {
+          unsigned int j, thisMax;
 
-      if (t[i] == NULL)
-        continue;
+          thisMax = t[i].x;
 
-      for (j = 0; j < i; j++)
-        {
-          if (t[j] == t[i])
-            {
-              reuse++;
-              t[j] = NULL;
-            }
-        }
-      for (j = i + 1; j < NUMTHREADS; j++)
-        {
-          if (t[j] == t[i])
-            {
-              reuse++;
-              t[j] = NULL;
-            }
+          for (j = i+1; j < NUMTHREADS; j++)
+            if (t[i].p == t[j].p)
+              {
+		if (t[i].x == t[j].x)
+		  notUnique++;
+                if (thisMax < t[j].x)
+                  thisMax = t[j].x;
+                t[j].p = NULL;
+              }
+
+          if (reuseMin > thisMax)
+            reuseMin = thisMax;
+
+          if (reuseMax < thisMax)
+            reuseMax = thisMax;
         }
-      if (reuseMax < reuse)
-        reuseMax = reuse;
-      if (reuseMin > reuse)
-        reuseMin = reuse;
     }
 
   for (i = 0; i < NUMTHREADS; i++)
-    {
-      if (t[i] != NULL)
-        idTotal++;
-    }
+    if (t[i].p != NULL)
+      totalHandles++;
 
   printf("For %d total threads:\n", NUMTHREADS);
-  printf("Reuse maximum = %d\n", reuseMax);
-  printf("Reuse minimum = %d\n", reuseMin);
-  printf("Total thread IDs allocated = %d\n", idTotal);
+  printf("Non-unique IDs = %d\n", notUnique);
+  printf("Reuse maximum  = %d\n", reuseMax);
+  printf("Reuse minimum  = %d\n", reuseMin);
+  printf("Total handles  = %d\n", totalHandles);
 
   return 0;
 }
diff --git a/tests/self1.c b/tests/self1.c
index 5cffac8..347fa79 100644
--- a/tests/self1.c
+++ b/tests/self1.c
@@ -52,7 +52,11 @@ main(int argc, char * argv[])
 	 * This should always succeed unless the system has no
 	 * resources (memory) left.
 	 */
-	assert(pthread_self() != NULL);
+	pthread_t self;
+
+	self = pthread_self();
+
+	assert(self.p != NULL);
 
 	return 0;
 }
diff --git a/tests/self2.c b/tests/self2.c
index f8a68c9..93be0c7 100644
--- a/tests/self2.c
+++ b/tests/self2.c
@@ -64,14 +64,9 @@ main()
 
   assert(pthread_create(&t, NULL, entry, NULL) == 0);
 
-  Sleep(2000);
+  Sleep(100);
 
-  /*
-   * 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);
+  assert(pthread_equal(t, me) != 0);
 
   /* Success. */
   return 0;
diff --git a/tests/semaphore3.c b/tests/semaphore3.c
index c6570f8..1b19494 100644
--- a/tests/semaphore3.c
+++ b/tests/semaphore3.c
@@ -80,9 +80,8 @@ sem_t s;
 void *
 thr (void * arg)
 {
-  assert(pthread_detach(pthread_self()) == 0);
   assert(sem_wait(&s) == 0);
-
+  assert(pthread_detach(pthread_self()) == 0);
   return NULL;
 }
 
@@ -91,19 +90,21 @@ main()
 {
 	int value = 0;
 	int i;
-	pthread_t t[MAX_COUNT];
+	pthread_t t[MAX_COUNT+1];
 
-  assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0);
+	assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0);
 	assert(sem_getvalue(&s, &value) == 0);
+//	printf("Value = %d\n", value);	fflush(stdout);
 	assert(value == 0);
-//	  printf("Value = %ld\n", value);
 
 	for (i = 1; i <= MAX_COUNT; i++)
 		{
-			assert(pthread_create(&t[i-1], NULL, thr, NULL) == 0);
-			sched_yield();
-			assert(sem_getvalue(&s, &value) == 0);
-//			  printf("Value = %ld\n", value);
+			assert(pthread_create(&t[i], NULL, thr, NULL) == 0);
+			do {
+			  sched_yield();
+			  assert(sem_getvalue(&s, &value) == 0);
+			} while (value != -i);
+//			printf("Value = %d\n", value); fflush(stdout);
 			assert(-value == i);
 		}
 
@@ -111,7 +112,7 @@ main()
 		{
 			assert(sem_post(&s) == 0);
 			assert(sem_getvalue(&s, &value) == 0);
-//			  printf("Value = %ld\n", value);
+//			printf("Value = %d\n", value);	fflush(stdout);
 			assert(-value == i);
 		}
 
diff --git a/tests/semaphore4.c b/tests/semaphore4.c
new file mode 100644
index 0000000..3ea0568
--- /dev/null
+++ b/tests/semaphore4.c
@@ -0,0 +1,138 @@
+/*
+ * File: semaphore4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2003 Pthreads-win32 contributors
+ * 
+ *      Contact Email: rpj@callisto.canberra.edu.au
+ * 
+ *      The current list of contributors is contained
+ *      in the file CONTRIBUTORS included with the source
+ *      code distribution. The list can also be seen at the
+ *      following World Wide Web location:
+ *      http://sources.redhat.com/pthreads-win32/contributors.html
+ * 
+ *      This library is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU Lesser General Public
+ *      License as published by the Free Software Foundation; either
+ *      version 2 of the License, or (at your option) any later version.
+ * 
+ *      This library is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *      Lesser General Public License for more details.
+ * 
+ *      You should have received a copy of the GNU Lesser General Public
+ *      License along with this library in the file COPYING.LIB;
+ *      if not, write to the Free Software Foundation, Inc.,
+ *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis: Verify sem_getvalue returns the correct number of waiters
+ * after threads are cancelled.
+ * - 
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * -
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+#define MAX_COUNT 100
+
+sem_t s;
+
+void *
+thr (void * arg)
+{
+  assert(sem_wait(&s) == 0);
+  return NULL;
+}
+
+int
+main()
+{
+	int value = 0;
+	int i;
+	pthread_t t[MAX_COUNT+1];
+
+	assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0);
+	assert(sem_getvalue(&s, &value) == 0);
+//	printf("Value = %d\n", value);	fflush(stdout);
+	assert(value == 0);
+
+	for (i = 1; i <= MAX_COUNT; i++)
+		{
+			assert(pthread_create(&t[i], NULL, thr, NULL) == 0);
+			do {
+			  sched_yield();
+			  assert(sem_getvalue(&s, &value) == 0);
+			} while (value != -i);
+//			printf("Value = %d\n", value); fflush(stdout);
+			assert(-value == i);
+		}
+
+	assert(sem_getvalue(&s, &value) == 0);
+	assert(-value == MAX_COUNT);
+//printf("value = %d\n", -value); fflush(stdout);
+	assert(pthread_cancel(t[50]) == 0);
+	  {
+	    int result;
+	    assert(pthread_join(t[50], (void **) &result) == 0);
+//	    printf("result = %d\n", result); fflush(stdout);
+	  }
+	assert(sem_getvalue(&s, &value) == 0);
+//printf("value = %d\n", -value); fflush(stdout);
+	assert(-value == (MAX_COUNT - 1));
+
+	for (i = MAX_COUNT - 2; i >= 0; i--)
+		{
+			assert(sem_post(&s) == 0);
+			assert(sem_getvalue(&s, &value) == 0);
+//			printf("Value = %d\n", value);	fflush(stdout);
+			assert(-value == i);
+		}
+
+	for (i = 1; i <= MAX_COUNT; i++)
+	  if (i != 50)
+	    assert(pthread_join(t[i], NULL) == 0);
+
+  return 0;
+}
+
diff --git a/tests/semaphore4t.c b/tests/semaphore4t.c
new file mode 100644
index 0000000..bb0535c
--- /dev/null
+++ b/tests/semaphore4t.c
@@ -0,0 +1,132 @@
+/*
+ * File: semaphore4t.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2003 Pthreads-win32 contributors
+ * 
+ *      Contact Email: rpj@callisto.canberra.edu.au
+ * 
+ *      The current list of contributors is contained
+ *      in the file CONTRIBUTORS included with the source
+ *      code distribution. The list can also be seen at the
+ *      following World Wide Web location:
+ *      http://sources.redhat.com/pthreads-win32/contributors.html
+ * 
+ *      This library is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU Lesser General Public
+ *      License as published by the Free Software Foundation; either
+ *      version 2 of the License, or (at your option) any later version.
+ * 
+ *      This library is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *      Lesser General Public License for more details.
+ * 
+ *      You should have received a copy of the GNU Lesser General Public
+ *      License along with this library in the file COPYING.LIB;
+ *      if not, write to the Free Software Foundation, Inc.,
+ *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis: Verify sem_getvalue returns the correct number of waiters
+ * after threads are cancelled.
+ * - 
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - sem_timedwait cancellation.
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * -
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+#define MAX_COUNT 100
+
+sem_t s;
+
+void *
+thr (void * arg)
+{
+  assert(sem_timedwait(&s, NULL) == 0);
+  return NULL;
+}
+
+int
+main()
+{
+	int value = 0;
+	int i;
+	pthread_t t[MAX_COUNT+1];
+
+	assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0);
+	assert(sem_getvalue(&s, &value) == 0);
+//	printf("Value = %d\n", value);	fflush(stdout);
+	assert(value == 0);
+
+	for (i = 1; i <= MAX_COUNT; i++)
+		{
+			assert(pthread_create(&t[i], NULL, thr, NULL) == 0);
+			do {
+			  sched_yield();
+			  assert(sem_getvalue(&s, &value) == 0);
+			} while (value != -i);
+//			printf("Value = %d\n", value); fflush(stdout);
+			assert(-value == i);
+		}
+
+	assert(sem_getvalue(&s, &value) == 0);
+	assert(-value == MAX_COUNT);
+	assert(pthread_cancel(t[50]) == 0);
+	assert(pthread_join(t[50], NULL) == 0);
+	assert(sem_getvalue(&s, &value) == 0);
+	assert(-value == MAX_COUNT - 1);
+
+	for (i = MAX_COUNT - 2; i >= 0; i--)
+		{
+			assert(sem_post(&s) == 0);
+			assert(sem_getvalue(&s, &value) == 0);
+//			printf("Value = %d\n", value);	fflush(stdout);
+			assert(-value == i);
+		}
+
+        for (i = 1; i <= MAX_COUNT; i++)
+          if (i != 50)
+            assert(pthread_join(t[i], NULL) == 0);
+
+  return 0;
+}
+
diff --git a/tests/sizes.c b/tests/sizes.c
index da7e115..6c077ad 100644
--- a/tests/sizes.c
+++ b/tests/sizes.c
@@ -8,7 +8,8 @@ main()
 {
   printf("Sizes of pthreads-win32 structs\n");
   printf("-------------------------------\n");
-  printf("%30s %4d\n", "pthread_t_", sizeof(struct pthread_t_));
+  printf("%30s %4d\n", "pthread_t", sizeof(pthread_t));
+  printf("%30s %4d\n", "ptw32_thread_t", sizeof(ptw32_thread_t));
   printf("%30s %4d\n", "pthread_attr_t_", sizeof(struct pthread_attr_t_));
   printf("%30s %4d\n", "sem_t_", sizeof(struct sem_t_));
   printf("%30s %4d\n", "pthread_mutex_t_", sizeof(struct pthread_mutex_t_));
diff --git a/tests/test.h b/tests/test.h
index 072b797..b337674 100644
--- a/tests/test.h
+++ b/tests/test.h
@@ -45,6 +45,8 @@
 #include <windows.h>
 #include <stdio.h>
 
+#define PTW32_THREAD_NULL_ID {NULL,0}
+
 char * error_string[] = {
   "ZERO_or_EOK",
   "EPERM",
@@ -122,6 +124,16 @@ char * error_string[] = {
           (fprintf(stderr, "Assertion failed: (%s), file %s, line %d\n", \
                    #e, __FILE__, (int) __LINE__), exit(1), 0))
 
+int assertE;
+# define assert_e(e, o, r) \
+   (((assertE = e) o (r)) ? ((ASSERT_TRACE) ? fprintf(stderr, \
+                                    "Assertion succeeded: (%s), file %s, line %d\n", \
+			            #e, __FILE__, (int) __LINE__), \
+	                            fflush(stderr) : \
+                             0) : \
+          (fprintf(stderr, "Assertion failed: (%s %s %s), file %s, line %d, error %s\n", \
+                   #e,#o,#r, __FILE__, (int) __LINE__, error_string[assertE]), exit(1), 0))
+
 #endif /* NDEBUG */
 
 
diff --git a/tests/valid2.c b/tests/valid2.c
index ad01b55..cef1020 100644
--- a/tests/valid2.c
+++ b/tests/valid2.c
@@ -76,15 +76,9 @@
 int
 main()
 {
-  pthread_t ptrToNull = NULL;
-  /* This should be bigger than a pthread handle. */
-  char corruptDummy[1000];
+  pthread_t NullThread = PTW32_THREAD_NULL_ID;
 
-  memset(corruptDummy, 0x5A, sizeof(corruptDummy));
-
-  assert(pthread_kill(NULL, 0) == ESRCH);
-  assert(pthread_kill(ptrToNull, 0) == ESRCH);
-  assert(pthread_kill((pthread_t) corruptDummy, 0) == ESRCH);
+  assert(pthread_kill(NullThread, 0) == ESRCH);
 
   return 0;
 }
diff --git a/w32_CancelableWait.c b/w32_CancelableWait.c
index a40fa4d..406bdbf 100644
--- a/w32_CancelableWait.c
+++ b/w32_CancelableWait.c
@@ -56,21 +56,25 @@ ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)
 {
   int result;
   pthread_t self;
+  ptw32_thread_t * sp;
   HANDLE handles[2];
   DWORD nHandles = 1;
   DWORD status;
 
   handles[0] = waitHandle;
 
-  if ((self = pthread_self ()) != NULL)
+  self = pthread_self();
+  sp = (ptw32_thread_t *) self.p;
+
+  if (sp != NULL)
     {
       /*
        * Get cancelEvent handle
        */
-      if (self->cancelState == PTHREAD_CANCEL_ENABLE)
+      if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
 	{
 
-	  if ((handles[1] = self->cancelEvent) != NULL)
+	  if ((handles[1] = sp->cancelEvent) != NULL)
 	    {
 	      nHandles++;
 	    }
@@ -83,7 +87,6 @@ ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)
 
   status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout);
 
-
   switch (status - WAIT_OBJECT_0)
     {
     case 0:
@@ -105,23 +108,23 @@ ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)
        */
       ResetEvent (handles[1]);
 
-      if (self != NULL)
+      if (sp != NULL)
 	{
 	  /*
 	   * Should handle POSIX and implicit POSIX threads..
 	   * Make sure we haven't been async-canceled in the meantime.
 	   */
-	  (void) pthread_mutex_lock (&self->cancelLock);
-	  if (self->state < PThreadStateCanceling)
+	  (void) pthread_mutex_lock (&sp->cancelLock);
+	  if (sp->state < PThreadStateCanceling)
 	    {
-	      self->state = PThreadStateCanceling;
-	      self->cancelState = PTHREAD_CANCEL_DISABLE;
-	      (void) pthread_mutex_unlock (&self->cancelLock);
+	      sp->state = PThreadStateCanceling;
+	      sp->cancelState = PTHREAD_CANCEL_DISABLE;
+	      (void) pthread_mutex_unlock (&sp->cancelLock);
 	      ptw32_throw (PTW32_EPS_CANCEL);
 
 	      /* Never reached */
 	    }
-	  (void) pthread_mutex_unlock (&self->cancelLock);
+	  (void) pthread_mutex_unlock (&sp->cancelLock);
 	}
 
       /* Should never get to here. */
-- 
cgit v1.2.3