Add pthreads-w32 2.8.0 source.

Change-Id: I386aecbdd387782ee9daed79bc01d5e3ccbbcc6d
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e5fcd84
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+/build
+/source/build
+*.mode1v3
+*.pbxuser
+*.pbxindex/
+!user.pbxuser
+/*.log
+*.user
+*.ncb
+*.suo
+*.pdb
+*.pdf
+*.html
+*.idb
+*.o
+*.lo
+*.a
+*.so
+*.so.0
+*.la
+.deps
+.libs
+*.pyc
+.DS_Store
+# Emacs and other editor backup files
+*~
+
+# builds on Windows
+Debug/
+Release/
+release/
+
+pthreads-*-release/
\ No newline at end of file
diff --git a/ANNOUNCE b/ANNOUNCE
new file mode 100644
index 0000000..97d94e7
--- /dev/null
+++ b/ANNOUNCE
@@ -0,0 +1,476 @@
+	     PTHREADS-WIN32 RELEASE 2.8.0 (2006-12-22)
+	     -----------------------------------------
+	 Web Site: http://sources.redhat.com/pthreads-win32/
+	FTP Site: ftp://sources.redhat.com/pub/pthreads-win32
+	 Maintainer: Ross Johnson <rpj@callisto.canberra.edu.au>
+
+
+We are pleased to announce the availability of a new release of
+Pthreads-win32, an Open Source Software implementation of the
+Threads component of the POSIX 1003.1 2001 Standard for Microsoft's
+Win32 environment. Some functions from other sections of POSIX
+1003.1 2001 are also supported including semaphores and scheduling
+functions.
+
+Some common non-portable functions are also implemented for
+additional compatibility, as are a few functions specific
+to pthreads-win32 for easier integration with Win32 applications.
+
+Pthreads-win32 is free software, distributed under the GNU Lesser
+General Public License (LGPL).
+
+
+Acknowledgements
+----------------
+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
+and later by Alexander Terekhov.
+
+The implementation of Spinlocks and Barriers was contributed
+by Ross Johnson.
+
+The implementation of read/write locks was contributed by
+Aurelio Medina and improved by Alexander Terekhov.
+
+Many others have contributed significant time and effort to solve crutial
+problems in order to make the library workable, robust and reliable.
+
+Thanks to Xavier Leroy for granting permission to use and modify his
+LinuxThreads manual pages.
+
+Thanks to The Open Group for making the Single Unix Specification
+publicly available - many of the manual pages included in the package
+were extracted from it.
+
+There is also a separate CONTRIBUTORS file. This file and others are
+on the web site:
+
+	http://sources.redhat.com/pthreads-win32
+
+As much as possible, the ChangeLog file acknowledges contributions to the
+code base in more detail.
+
+
+Changes since the last release
+------------------------------
+These are now documented in the NEWS file.
+See the ChangeLog file also.
+
+
+Known Bugs
+----------
+These are now documented in the BUGS file.
+
+
+Level of standards conformance
+------------------------------
+
+The following POSIX 1003.1 2001 options are defined and set to 200112L:
+
+      _POSIX_THREADS
+      _POSIX_THREAD_SAFE_FUNCTIONS
+      _POSIX_THREAD_ATTR_STACKSIZE
+      _POSIX_THREAD_PRIORITY_SCHEDULING
+      _POSIX_SEMAPHORES
+      _POSIX_READER_WRITER_LOCKS
+      _POSIX_SPIN_LOCKS
+      _POSIX_BARRIERS
+
+
+The following POSIX 1003.1 2001 options are defined and set to -1:
+
+      _POSIX_THREAD_ATTR_STACKADDR
+      _POSIX_THREAD_PRIO_INHERIT
+      _POSIX_THREAD_PRIO_PROTECT
+      _POSIX_THREAD_PROCESS_SHARED
+
+
+The following POSIX 1003.1 2001 limits are defined and set:
+
+      _POSIX_THREAD_THREADS_MAX
+      _POSIX_SEM_VALUE_MAX
+      _POSIX_SEM_NSEMS_MAX
+      _POSIX_THREAD_KEYS_MAX
+      _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+      PTHREAD_STACK_MIN
+      PTHREAD_THREADS_MAX
+      SEM_VALUE_MAX
+      SEM_NSEMS_MAX
+      PTHREAD_KEYS_MAX
+      PTHREAD_DESTRUCTOR_ITERATIONS
+
+
+The following functions are implemented:
+
+      ---------------------------
+      PThreads
+      ---------------------------
+      pthread_attr_init
+      pthread_attr_destroy
+      pthread_attr_getdetachstate
+      pthread_attr_getstackaddr
+      pthread_attr_getstacksize
+      pthread_attr_setdetachstate
+      pthread_attr_setstackaddr
+      pthread_attr_setstacksize
+
+      pthread_create
+      pthread_detach
+      pthread_equal
+      pthread_exit
+      pthread_join
+      pthread_once
+      pthread_self
+
+      pthread_cancel
+      pthread_cleanup_pop
+      pthread_cleanup_push
+      pthread_setcancelstate
+      pthread_setcanceltype
+      pthread_testcancel
+
+      ---------------------------
+      Thread Specific Data
+      ---------------------------
+      pthread_key_create
+      pthread_key_delete
+      pthread_setspecific
+      pthread_getspecific
+
+      ---------------------------
+      Mutexes
+      ---------------------------
+      pthread_mutexattr_init
+      pthread_mutexattr_destroy
+      pthread_mutexattr_getpshared
+      pthread_mutexattr_setpshared
+      pthread_mutexattr_gettype
+      pthread_mutexattr_settype (types: PTHREAD_MUTEX_DEFAULT
+					PTHREAD_MUTEX_NORMAL
+					PTHREAD_MUTEX_ERRORCHECK
+					PTHREAD_MUTEX_RECURSIVE  )
+      pthread_mutex_init
+      pthread_mutex_destroy
+      pthread_mutex_lock
+      pthread_mutex_trylock
+      pthread_mutex_timedlock
+      pthread_mutex_unlock
+
+      ---------------------------
+      Condition Variables
+      ---------------------------
+      pthread_condattr_init
+      pthread_condattr_destroy
+      pthread_condattr_getpshared
+      pthread_condattr_setpshared
+
+      pthread_cond_init
+      pthread_cond_destroy
+      pthread_cond_wait
+      pthread_cond_timedwait
+      pthread_cond_signal
+      pthread_cond_broadcast
+
+      ---------------------------
+      Read/Write Locks
+      ---------------------------
+      pthread_rwlock_init
+      pthread_rwlock_destroy
+      pthread_rwlock_tryrdlock
+      pthread_rwlock_trywrlock
+      pthread_rwlock_rdlock
+      pthread_rwlock_timedrdlock
+      pthread_rwlock_rwlock
+      pthread_rwlock_timedwrlock
+      pthread_rwlock_unlock
+      pthread_rwlockattr_init
+      pthread_rwlockattr_destroy
+      pthread_rwlockattr_getpshared
+      pthread_rwlockattr_setpshared
+
+      ---------------------------
+      Spin Locks
+      ---------------------------
+      pthread_spin_init
+      pthread_spin_destroy
+      pthread_spin_lock
+      pthread_spin_unlock
+      pthread_spin_trylock
+
+      ---------------------------
+      Barriers
+      ---------------------------
+      pthread_barrier_init
+      pthread_barrier_destroy
+      pthread_barrier_wait
+      pthread_barrierattr_init
+      pthread_barrierattr_destroy
+      pthread_barrierattr_getpshared
+      pthread_barrierattr_setpshared
+
+      ---------------------------
+      Semaphores
+      ---------------------------
+      sem_init
+      sem_destroy
+      sem_post
+      sem_wait
+      sem_trywait
+      sem_timedwait
+      sem_getvalue	     (# free if +ve, # of waiters if -ve)
+      sem_open		     (returns an error ENOSYS)
+      sem_close 	     (returns an error ENOSYS)
+      sem_unlink	     (returns an error ENOSYS)
+
+      ---------------------------
+      RealTime Scheduling
+      ---------------------------
+      pthread_attr_getschedparam
+      pthread_attr_setschedparam
+      pthread_attr_getinheritsched
+      pthread_attr_setinheritsched
+      pthread_attr_getschedpolicy (only supports SCHED_OTHER)
+      pthread_attr_setschedpolicy (only supports SCHED_OTHER)
+      pthread_getschedparam
+      pthread_setschedparam
+      pthread_getconcurrency
+      pthread_setconcurrency
+      pthread_attr_getscope
+      pthread_attr_setscope  (only supports PTHREAD_SCOPE_SYSTEM)
+      sched_get_priority_max
+      sched_get_priority_min
+      sched_rr_get_interval  (returns an error ENOTSUP)
+      sched_setscheduler     (only supports SCHED_OTHER)
+      sched_getscheduler     (only supports SCHED_OTHER)
+      sched_yield
+
+      ---------------------------
+      Signals
+      ---------------------------
+      pthread_sigmask
+      pthread_kill           (only supports zero sig value,
+                              for thread validity checking)
+
+      ---------------------------
+      Non-portable routines (see the README.NONPORTABLE file for usage)
+      ---------------------------
+      pthread_getw32threadhandle_np
+      pthread_timechange_handler_np
+      pthread_delay_np
+      pthread_mutexattr_getkind_np
+      pthread_mutexattr_setkind_np	(types: PTHREAD_MUTEX_FAST_NP,
+						PTHREAD_MUTEX_ERRORCHECK_NP,
+						PTHREAD_MUTEX_RECURSIVE_NP,
+						PTHREAD_MUTEX_ADAPTIVE_NP,
+						PTHREAD_MUTEX_TIMED_NP)
+      pthread_num_processors_np
+      pthread_win32_process_attach_np	(Required when statically linking
+                                         the library)
+      pthread_win32_process_detach_np	(Required when statically linking
+                                         the library)
+      pthread_win32_thread_attach_np	(Required when statically linking
+                                         the library)
+      pthread_win32_thread_detach_np	(Required when statically linking
+                                         the library)
+
+      ---------------------------
+      Static Initializers
+      ---------------------------
+      PTHREAD_ONCE_INIT
+      PTHREAD_MUTEX_INITIALIZER
+      PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+      PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+      PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+      PTHREAD_COND_INITIALIZER
+      PTHREAD_RWLOCK_INITIALIZER
+      PTHREAD_SPINLOCK_INITIALIZER
+
+      ---------------------------
+      Thread-Safe C Runtime Library (macros)
+      ---------------------------
+      strtok_r
+      asctime_r
+      ctime_r
+      gmtime_r
+      localtime_r
+      rand_r
+
+
+The following functions are not implemented:
+      
+      ---------------------------
+      RealTime Scheduling
+      ---------------------------
+      pthread_mutex_getprioceiling
+      pthread_mutex_setprioceiling
+      pthread_mutex_attr_getprioceiling
+      pthread_mutex_attr_getprotocol
+      pthread_mutex_attr_setprioceiling
+      pthread_mutex_attr_setprotocol
+
+      ---------------------------
+      Fork Handlers
+      ---------------------------
+      pthread_atfork
+
+      ---------------------------
+      Stdio
+      --------------------------- 
+      flockfile
+      ftrylockfile
+      funlockfile
+      getc_unlocked
+      getchar_unlocked	
+      putc_unlocked
+      putchar_unlocked
+
+      ---------------------------
+      Thread-Safe C Runtime Library
+      ---------------------------
+      readdir_r
+      getgrgid_r
+      getgrnam_r
+      getpwuid_r
+      getpwnam_r
+      
+      ---------------------------
+      Signals
+      ---------------------------
+      sigtimedwait
+      sigwait
+      sigwaitinfo
+
+      ---------------------------
+      General
+      ---------------------------
+      sysconf      
+
+The library includes two non-API functions for creating cancellation
+points in applications and libraries:
+      
+      pthreadCancelableWait
+      pthreadCancelableTimedWait
+
+      
+Availability
+------------ 
+
+The prebuilt DLL, export libs (for both MSVC and Mingw32), and the header
+files (pthread.h, semaphore.h, sched.h) are available along with the
+complete source code.
+
+The source code can be found at:
+
+	ftp://sources.redhat.com/pub/pthreads-win32
+
+and as individual source code files at
+
+	ftp://sources.redhat.com/pub/pthreads-win32/source
+
+The pre-built DLL, export libraries and include files can be found at:
+
+	ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
+
+
+      
+Mailing List 
+------------  
+      
+There is a mailing list for discussing pthreads on Win32. To join,
+send email to:
+
+	pthreads-win32-subscribe@sourceware.cygnus.com
+      
+
+Application Development Environments
+------------------------------------
+
+See the README file for more information.
+      
+MSVC:
+MSVC using SEH works. Distribute pthreadVSE.dll with your application.
+MSVC using C++ EH works. Distribute pthreadVCE.dll with your application.
+MSVC using C setjmp/longjmp works. Distribute pthreadVC.dll with your application.
+
+
+Mingw32:
+See the FAQ, Questions 6 and 10.
+
+Mingw using C++ EH works. Distribute pthreadGCE.dll with your application.
+Mingw using C setjmp/longjmp works. Distribute pthreadGC.dll with your application.
+
+
+Cygwin: (http://sourceware.cygnus.com/cygwin/)
+Developers using Cygwin will not need pthreads-win32 since it has POSIX threads
+support. Refer to its documentation for details and extent.
+
+
+UWIN:
+UWIN is a complete Unix-like environment for Windows from AT&T. Pthreads-win32
+doesn't currently support UWIN (and vice versa), but that may change in the
+future.
+
+Generally:
+For convenience, the following pre-built files are available on the FTP site
+(see Availability above):
+
+	pthread.h	- for POSIX 1c threads
+	semaphore.h	- for POSIX 1b semaphores
+	sched.h 	- for POSIX 1b scheduling
+	pthreadVCE.dll	- built with MSVC++ compiler using C++ EH
+	pthreadVCE.lib
+	pthreadVC.dll	- built with MSVC compiler using C setjmp/longjmp
+	pthreadVC.lib
+	pthreadVSE.dll	- built with MSVC compiler using SEH
+	pthreadVSE.lib
+	pthreadGCE.dll	- built with Mingw32 G++ 2.95.2-1
+	pthreadGC.dll	- built with Mingw32 GCC 2.95.2-1 using setjmp/longjmp
+	libpthreadGCE.a - derived from pthreadGCE.dll
+	libpthreadGC.a	- derived from pthreadGC.dll
+	gcc.dll 	- needed if distributing applications that use
+			  pthreadGCE.dll (but see the FAQ Q 10 for the latest
+			  related information)
+
+These are the only files you need in order to build POSIX threads
+applications for Win32 using either MSVC or Mingw32.
+
+See the FAQ file in the source tree for additional information.
+
+
+Documentation
+-------------
+
+For the authoritative reference, see the online POSIX
+standard reference at:
+
+       http://www.OpenGroup.org
+
+For POSIX Thread API programming, several reference books are
+available:
+
+       Programming with POSIX Threads
+       David R. Butenhof
+       Addison-Wesley (pub)
+
+       Pthreads Programming
+       By Bradford Nichols, Dick Buttlar & Jacqueline Proulx Farrell
+       O'Reilly (pub)
+
+On the web: see the links at the bottom of the pthreads-win32 site:
+
+       http://sources.redhat.com/pthreads-win32/
+
+       Currently, there is no documentation included in the package apart
+       from the copious comments in the source code.
+
+
+
+Enjoy!
+
+Ross Johnson
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..29cee00
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,133 @@
+----------
+Known bugs
+----------
+
+1. Not strictly a bug, more of a gotcha.
+
+   Under MS VC++ (only tested with version 6.0), a term_func
+   set via the standard C++ set_terminate() function causes the
+   application to abort.
+
+   Notes from the MSVC++ manual:
+         1) A term_func() should call exit(), otherwise
+            abort() will be called on return to the caller.
+            A call to abort() raises SIGABRT and 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(), which
+            works by throwing an exception (pthreadVCE or pthreadVSE)
+            or by calling longjmp (pthreadVC).
+
+   Workaround: avoid using pthread_exit() in C++ applications. Exit
+   threads by dropping through the end of the thread routine.
+
+2. Cancellation problems in optimised code
+   - Milan Gardian
+
+   This is suspected to be a compiler bug in VC6.0, and also seen in
+   VC7.0 and VS .NET 2003. The GNU C++ compiler does not have a problem
+   with this, and it has been reported that the Intel C++ 8.1 compiler
+   and Visual C++ 2005 Express Edition Beta2 pass tests\semaphore4.c
+   (which exposes the bug).
+
+   Workaround [rpj - 2 Feb 2002]
+   -----------------------------
+   [Please note: this workaround did not solve a similar problem in
+   snapshot-2004-11-03 or later, even though similar symptoms were seen.
+   tests\semaphore4.c fails in that snapshot for the VCE version of the
+   DLL.]
+
+   The problem disappears when /Ob0 is used, i.e. /O2 /Ob0 works OK,
+   but if you want to use inlining optimisation you can be much more
+   specific about where it's switched off and on by using a pragma.
+
+   So the inlining optimisation is interfering with the way that cleanup
+   handlers are run. It appears to relate to auto-inlining of class methods
+   since this is the only auto inlining that is performed at /O1 optimisation
+   (functions with the "inline" qualifier are also inlined, but the problem
+   doesn't appear to involve any such functions in the library or testsuite).
+
+   In order to confirm the inlining culprit, the following use of pragmas
+   eliminate the problem but I don't know how to make it transparent, putting
+   it in, say, pthread.h where pthread_cleanup_push defined as a macro.
+
+   #pragma inline_depth(0)
+     pthread_cleanup_push(handlerFunc, (void *) &arg);
+
+        /* ... */
+
+     pthread_cleanup_pop(0);
+   #pragma inline_depth()
+
+   Note the empty () pragma value after the pop macro. This resets depth to the
+   default. Or you can specify a non-zero depth here.
+
+   The pragma is also needed (and now used) within the library itself wherever
+   cleanup handlers are used (condvar.c and rwlock.c).
+
+   Use of these pragmas allows compiler optimisations /O1 and /O2 to be
+   used for either or both the library and applications.
+
+   Experimenting further, I found that wrapping the actual cleanup handler
+   function with #pragma auto_inline(off|on) does NOT work.
+
+   MSVC6.0 doesn't appear to support the C99 standard's _Pragma directive,
+   however, later versions may. This form is embeddable inside #define
+   macros, which would be ideal because it would mean that it could be added
+   to the push/pop macro definitions in pthread.h and hidden from the
+   application programmer.
+
+   [/rpj]
+
+   Original problem description
+   ----------------------------
+
+   The cancellation (actually, cleanup-after-cancel) tests fail when using VC
+   (professional) optimisation switches (/O1 or /O2) in pthreads library. I
+   have not investigated which concrete optimisation technique causes this
+   problem (/Og, /Oi, /Ot, /Oy, /Ob1, /Gs, /Gf, /Gy, etc.), but here is a
+   summary of builds and corresponding failures:
+
+     * pthreads VSE (optimised tests): OK
+     * pthreads VCE (optimised tests): Failed "cleanup1" test (runtime)
+
+     * pthreads VSE (DLL in CRT, optimised tests): OK
+     * pthreads VCE (DLL in CRT, optimised tests): Failed "cleanup1" test
+   (runtime)
+
+   Please note that while in VSE version of the pthreads library the
+   optimisation does not really have any impact on the tests (they pass OK), in
+   VCE version addition of optimisation (/O2 in this case) causes the tests to
+   fail uniformly - either in "cleanup0" or "cleanup1" test cases.
+
+   Please note that all the tests above use default pthreads DLL (no
+   optimisations, linked with either static or DLL CRT, based on test type).
+   Therefore the problem lies not within the pthreads DLL but within the
+   compiled client code (the application using pthreads -> involvement of
+   "pthread.h").
+
+   I think the message of this section is that usage of VCE version of pthreads
+   in applications relying on cancellation/cleanup AND using optimisations for
+   creation of production code is highly unreliable for the current version of
+   the pthreads library.
+
+3. The Borland Builder 5.5 version of the library produces memory read exceptions
+in some tests.
+
+4. pthread_barrier_wait() can deadlock if the number of potential calling
+threads for a particular barrier is greater than the barrier count parameter
+given to pthread_barrier_init() for that barrier.
+
+This is due to the very lightweight implementation of pthread-win32 barriers.
+To cope with more than "count" possible waiters, barriers must effectively
+implement all the same safeguards as condition variables, making them much
+"heavier" than at present.
+
+The workaround is to ensure that no more than "count" threads attempt to wait
+at the barrier.
+
+5. Canceling a thread blocked on pthread_once appears not to work in the MSVC++
+version of the library "pthreadVCE.dll". The test case "once3.c" hangs. I have no
+clues on this at present. All other versions pass this test ok - pthreadsVC.dll,
+pthreadsVSE.dll, pthreadsGC.dll and pthreadsGCE.dll. 
diff --git a/Bmakefile b/Bmakefile
new file mode 100644
index 0000000..66707bf
--- /dev/null
+++ b/Bmakefile
@@ -0,0 +1,266 @@
+# This makefile is compatible with BCB make.  Use "make -fBMakefile" to compile.
+# 
+# The variables $DLLDEST and $LIBDEST hold the destination directories for the
+# dll and the lib, respectively. Probably all that needs to change is $DEVROOT.
+#
+# Currently only the recommended pthreadBC.dll is built by this makefile.
+#
+
+
+DLL_VER	= 2
+
+DEVROOT	= .
+
+DLLDEST	= $(DEVROOT)\DLL
+LIBDEST	= $(DEVROOT)\DLL
+
+DLLS	= pthreadBC$(DLL_VER).dll
+
+OPTIM	= /O2
+
+RC	= brcc32
+RCFLAGS	= -i.
+
+CFLAGS	= /q /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H=1 /4 /tWD /tWM \
+	  /w-aus /w-asc /w-par
+
+#C cleanup code
+BCFLAGS	= $(PTW32_FLAGS) $(CFLAGS)
+
+# Agregate modules for inlinability
+DLL_OBJS	= \
+		attr.obj \
+		barrier.obj \
+		cancel.obj \
+		cleanup.obj \
+		condvar.obj \
+		create.obj \
+		dll.obj \
+		errno.obj \
+		exit.obj \
+		fork.obj \
+		global.obj \
+		misc.obj \
+		mutex.obj \
+		nonportable.obj \
+		private.obj \
+		rwlock.obj \
+		sched.obj \
+		semaphore.obj \
+		signal.obj \
+		spin.obj \
+		sync.obj \
+		tsd.obj
+
+INCL	= config.h implement.h semaphore.h pthread.h need_errno.h
+
+ATTR_SRCS	= \
+		pthread_attr_init.c \
+		pthread_attr_destroy.c \
+		pthread_attr_getdetachstate.c \
+		pthread_attr_setdetachstate.c \
+		pthread_attr_getstackaddr.c \
+		pthread_attr_setstackaddr.c \
+		pthread_attr_getstacksize.c \
+		pthread_attr_setstacksize.c \
+		pthread_attr_getscope.c \
+		pthread_attr_setscope.c
+
+BARRIER_SRCS = \
+		pthread_barrier_init.c \
+		pthread_barrier_destroy.c \
+		pthread_barrier_wait.c \
+		pthread_barrierattr_init.c \
+		pthread_barrierattr_destroy.c \
+		pthread_barrierattr_setpshared.c \
+		pthread_barrierattr_getpshared.c
+
+CANCEL_SRCS	= \
+		pthread_setcancelstate.c \
+		pthread_setcanceltype.c \
+		pthread_testcancel.c \
+		pthread_cancel.c 
+
+CONDVAR_SRCS	= \
+		ptw32_cond_check_need_init.c \
+		pthread_condattr_destroy.c \
+		pthread_condattr_getpshared.c \
+		pthread_condattr_init.c \
+		pthread_condattr_setpshared.c \
+		pthread_cond_destroy.c \
+		pthread_cond_init.c \
+		pthread_cond_signal.c \
+		pthread_cond_wait.c
+
+EXIT_SRCS	= \
+		pthread_exit.c
+
+MISC_SRCS	= \
+		pthread_equal.c \
+		pthread_getconcurrency.c \
+		pthread_once.c \
+		pthread_self.c \
+		pthread_setconcurrency.c \
+		ptw32_calloc.c \
+		ptw32_MCS_lock.c \
+		ptw32_new.c \
+		w32_CancelableWait.c
+
+MUTEX_SRCS	= \
+		ptw32_mutex_check_need_init.c \
+		pthread_mutex_init.c \
+		pthread_mutex_destroy.c \
+		pthread_mutexattr_init.c \
+		pthread_mutexattr_destroy.c \
+		pthread_mutexattr_getpshared.c \
+		pthread_mutexattr_setpshared.c \
+		pthread_mutexattr_settype.c \
+		pthread_mutexattr_gettype.c \
+		pthread_mutex_lock.c \
+		pthread_mutex_timedlock.c \
+		pthread_mutex_unlock.c \
+		pthread_mutex_trylock.c
+
+NONPORTABLE_SRCS = \
+		pthread_mutexattr_setkind_np.c \
+		pthread_mutexattr_getkind_np.c \
+		pthread_getw32threadhandle_np.c \
+		pthread_delay_np.c \
+		pthread_num_processors_np.c \
+		pthread_win32_attach_detach_np.c \
+		pthread_timechange_handler_np.c 
+
+PRIVATE_SRCS	= \
+		ptw32_is_attr.c \
+		ptw32_processInitialize.c \
+		ptw32_processTerminate.c \
+		ptw32_threadStart.c \
+		ptw32_threadDestroy.c \
+		ptw32_tkAssocCreate.c \
+		ptw32_tkAssocDestroy.c \
+		ptw32_callUserDestroyRoutines.c \
+		ptw32_timespec.c \
+		ptw32_relmillisecs.c \
+		ptw32_throw.c \
+		ptw32_InterlockedCompareExchange.c \
+		ptw32_getprocessors.c
+
+RWLOCK_SRCS	= \
+		ptw32_rwlock_check_need_init.c \
+		ptw32_rwlock_cancelwrwait.c \
+		pthread_rwlock_init.c \
+		pthread_rwlock_destroy.c \
+		pthread_rwlockattr_init.c \
+		pthread_rwlockattr_destroy.c \
+		pthread_rwlockattr_getpshared.c \
+		pthread_rwlockattr_setpshared.c \
+		pthread_rwlock_rdlock.c \
+		pthread_rwlock_timedrdlock.c \
+		pthread_rwlock_wrlock.c \
+		pthread_rwlock_timedwrlock.c \
+		pthread_rwlock_unlock.c \
+		pthread_rwlock_tryrdlock.c \
+		pthread_rwlock_trywrlock.c
+
+SCHED_SRCS	= \
+		pthread_attr_setschedpolicy.c \
+		pthread_attr_getschedpolicy.c \
+		pthread_attr_setschedparam.c \
+		pthread_attr_getschedparam.c \
+		pthread_attr_setinheritsched.c \
+		pthread_attr_getinheritsched.c \
+		pthread_setschedparam.c \
+		pthread_getschedparam.c \
+		sched_get_priority_max.c \
+		sched_get_priority_min.c \
+		sched_setscheduler.c \
+		sched_getscheduler.c \
+		sched_yield.c
+
+SEMAPHORE_SRCS = \
+		sem_init.c \
+		sem_destroy.c \
+		sem_trywait.c \
+		sem_timedwait.c \
+		sem_wait.c \
+		sem_post.c \
+		sem_post_multiple.c \
+		sem_getvalue.c \
+		sem_open.c \
+		sem_close.c \
+		sem_unlink.c
+
+SPIN_SRCS	= \
+		ptw32_spinlock_check_need_init.c \
+		pthread_spin_init.c \
+		pthread_spin_destroy.c \
+		pthread_spin_lock.c \
+		pthread_spin_unlock.c \
+		pthread_spin_trylock.c
+
+SYNC_SRCS	= \
+		pthread_detach.c \
+		pthread_join.c
+
+TSD_SRCS	= \
+		pthread_key_create.c \
+		pthread_key_delete.c \
+		pthread_setspecific.c \
+		pthread_getspecific.c
+
+
+all: clean $(DLLS)
+
+realclean: clean
+	if exist pthread*.dll del pthread*.dll
+	if exist pthread*.lib del pthread*.lib
+	if exist *.stamp del *.stamp
+
+clean:
+	if exist *.obj del *.obj
+	if exist *.ilk del *.ilk
+	if exist *.ilc del *.ilc
+	if exist *.ild del *.ild
+	if exist *.ilf del *.ilf
+	if exist *.ils del *.ils
+	if exist *.tds del *.tds
+	if exist *.pdb del *.pdb
+	if exist *.exp del *.exp
+	if exist *.map del *.map
+	if exist *.o del *.o
+	if exist *.i del *.i
+	if exist *.res del *.res
+
+
+install: $(DLLS)
+	copy pthread*.dll $(DLLDEST)
+	copy pthread*.lib $(LIBDEST)
+
+$(DLLS): $(DLL_OBJS) version.res
+	ilink32 /Tpd /Gi c0d32x.obj $(DLL_OBJS), \
+		$@, ,\
+		cw32mti.lib import32.lib, ,\
+		version.res
+
+.c.obj:
+	$(CC) $(OPTIM) $(BCFLAGS) -c $<
+
+.rc.res:
+	$(RC) $(RCFLAGS) $<
+
+attr.obj:	attr.c $(ATTR_SRCS) $(INCL)
+barrier.obj:	barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.obj:	cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.obj:	condvar.c $(CONDVAR_SRCS) $(INCL)
+exit.obj:	exit.c $(EXIT_SRCS) $(INCL)
+misc.obj:	misc.c $(MISC_SRCS) $(INCL)
+mutex.obj:	mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.obj:	nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.obj:	private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.obj:	rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.obj:	sched.c $(SCHED_SRCS) $(INCL)
+semaphore.obj:	semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.obj:	spin.c $(SPIN_SRCS) $(INCL)
+sync.obj:	sync.c $(SYNC_SRCS) $(INCL)
+tsd.obj:	tsd.c $(TSD_SRCS) $(INCL)
+version.res:	version.rc $(INCL)
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..e5b7325
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,129 @@
+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;
+					various enhancements;
+					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;
+					enhancements to mutexes;
+					new mutex implementation in 'futex' style;
+					suggested a robust implementation of pthread_once
+					similar to that implemented by V.Kliathcko;
+					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.
+Anuj Goyal		anuj dot goyal at gmail dot com
+					Port to Digital Mars compiler.
+Gottlob Frege		gottlobfrege at  gmail dot com
+					re-implemented pthread_once (version 2)
+					(pthread_once cancellation added by rpj).
+Vladimir Kliatchko	vladimir at kliatchko dot com
+					reimplemented pthread_once with the same form
+					as described by A.Terekhov (later version 2);
+					implementation of MCS (Mellor-Crummey/Scott) locks.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5cfea0d
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,150 @@
+	pthreads-win32 - a POSIX threads library for Microsoft Windows
+
+
+This file is Copyrighted
+------------------------
+
+    This file is covered under the following Copyright:
+
+	Copyright (C) 2001,2006 Ross P. Johnson
+	All rights reserved.
+
+	Everyone is permitted to copy and distribute verbatim copies
+	of this license document, but changing it is not allowed.
+
+Pthreads-win32 is covered by the GNU Lesser General Public License
+------------------------------------------------------------------
+
+    Pthreads-win32 is open 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 version 2.1 of the
+    License.
+
+    Pthreads-win32 is several binary link libraries, several modules,
+    associated interface definition files and scripts used to control
+    its compilation and installation.
+
+    Pthreads-win32 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.
+
+    A copy of the GNU Lesser General Public License is distributed with
+    pthreads-win32 under the filename:
+
+	    COPYING.LIB
+
+    You should have received a copy of the version 2.1 GNU Lesser General
+    Public License with pthreads-win32; if not, write to:
+
+	    Free Software Foundation, Inc.
+	    59 Temple Place
+	    Suite 330
+	    Boston, MA	02111-1307
+	    USA
+
+    The contact addresses for pthreads-win32 is as follows:
+
+        Web:	http://sources.redhat.com/pthreads-win32
+        Email:  Ross Johnson
+                Please use: Firstname.Lastname@homemail.com.au
+
+
+
+Pthreads-win32 copyrights and exception files
+---------------------------------------------
+
+    With the exception of the files listed below, Pthreads-win32
+    is covered under the following GNU Lesser General Public License
+    Copyrights:
+
+	Pthreads-win32 - POSIX Threads Library for Win32
+	Copyright(C) 1998 John E. Bossom
+	Copyright(C) 1999,2006 Pthreads-win32 contributors
+
+	The current list of contributors is contained
+        in the file CONTRIBUTORS included with the source
+	code distribution. The current list of CONTRIBUTORS
+	can also be seen at the following WWW location:
+        http://sources.redhat.com/pthreads-win32/contributors.html
+
+    Contact Email: Ross Johnson
+                   Please use: Firstname.Lastname@homemail.com.au
+
+    These files are not covered under one of the Copyrights listed above:
+
+            COPYING
+	    COPYING.LIB
+            tests/rwlock7.c
+
+    This file, COPYING, is distributed under the Copyright found at the
+    top of this file.  It is important to note that you may distribute
+    verbatim copies of this file but you may not modify this file.
+
+    The file COPYING.LIB, which contains a copy of the version 2.1
+    GNU Lesser General Public License, is itself copyrighted by the
+    Free Software Foundation, Inc.  Please note that the Free Software
+    Foundation, Inc. does NOT have a copyright over Pthreads-win32,
+    only the COPYING.LIB that is supplied with pthreads-win32.
+
+    The file tests/rwlock7.c is derived from code written by
+    Dave Butenhof for his book 'Programming With POSIX(R) Threads'.
+    The original code was obtained by free download from his website
+    http://home.earthlink.net/~anneart/family/Threads/source.html
+    and did not contain a copyright or author notice. It is assumed to
+    be freely distributable.
+
+    In all cases one may use and distribute these exception files freely.
+    And because one may freely distribute the LGPL covered files, the
+    entire pthreads-win32 source may be freely used and distributed.
+
+
+
+General Copyleft and License info
+---------------------------------
+
+    For general information on Copylefts, see:
+
+	http://www.gnu.org/copyleft/
+
+    For information on GNU Lesser General Public Licenses, see:
+
+	http://www.gnu.org/copyleft/lesser.html
+	http://www.gnu.org/copyleft/lesser.txt
+
+
+Why pthreads-win32 did not use the GNU General Public License
+-------------------------------------------------------------
+
+    The goal of the pthreads-win32 project has been to
+    provide a quality and complete implementation of the POSIX
+    threads API for Microsoft Windows within the limits imposed
+    by virtue of it being a stand-alone library and not
+    linked directly to other POSIX compliant libraries. For
+    example, some functions and features, such as those based
+    on POSIX signals, are missing.
+
+    Pthreads-win32 is a library, available in several different
+    versions depending on supported compilers, and may be used
+    as a dynamically linked module or a statically linked set of
+    binary modules. It is not an application on it's own.
+
+    It was fully intended that pthreads-win32 be usable with
+    commercial software not covered by either the GPL or the LGPL
+    licenses. Pthreads-win32 has many contributors to it's
+    code base, many of whom have done so because they have
+    used the library in commercial or proprietry software
+    projects.
+
+    Releasing pthreads-win32 under the LGPL ensures that the
+    library can be used widely, while at the same time ensures
+    that bug fixes and improvements to the pthreads-win32 code
+    itself is returned to benefit all current and future users
+    of the library.
+
+    Although pthreads-win32 makes it possible for applications
+    that use POSIX threads to be ported to Win32 platforms, the
+    broader goal of the project is to encourage the use of open
+    standards, and in particular, to make it just a little easier
+    for developers writing Win32 applications to consider
+    widening the potential market for their products.
diff --git a/COPYING.LIB b/COPYING.LIB
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/COPYING.LIB
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.1 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; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..b85d9f9
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4821 @@
+2006-12-20  Ross Johnson <ross.johnson@homemail.com.au>
+
+        * sem_destroy.c: Fix the race involving invalidation of the sema;
+        fix incorrect return of EBUSY resulting from the mutex trylock
+        on the private mutex guard.
+        * sem_wait.c: Add check for invalid sem_t after acquiring the
+        sem_t state guard mutex and before affecting changes to sema state.
+        * sem_trywait.c: Likewise.
+        * sem_timedwait.c: Likewise.
+        * sem_getvalue.c: Likewise.
+        * sem_post.c: Similar.
+        * sem_post_multiple.c: Likewise.
+        * sem_init.c: Set max Win32 semaphore count to SEM_VALUE_MAX (was
+        _POSIX_SEM_VALUE_MAX, which is a lower value - the minimum).
+
+	* pthread_win32_attach_detach_np.c (pthread_win32_process_attach_np):
+	Load COREDLL.DLL under WINCE to check existence of
+	InterlockedCompareExchange() routine. This used to be done to test
+	for TryEnterCriticalSection() but was removed when this was no
+	longer needed.
+
+2006-01-25  Prashant Thakre <prashant.thakre at gmail.com>
+
+	* pthread_cancel.c: Added _M_IA64 register context support.
+
+2005-05-13  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* pthread_kill.c (pthread_kill): Remove check for Win32 thread
+	priority (to confirm HANDLE validity). Useless since thread HANDLEs
+	a not recycle-unique.
+
+2005-05-30  Vladimir Kliatchko  <vladimir at kliatchko.com>
+
+	* pthread_once.c: Re-implement using an MCS queue-based lock. The form
+	of pthread_once is as proposed by Alexander Terekhov (see entry of
+	2005-03-13). The MCS lock implementation does not require a unique
+	'name' to identify the lock between threads. Attempts to get the Event
+	or Semaphore based versions of pthread_once to a satisfactory level
+	of robustness have thus far failed. The last problem (avoiding races
+	involving non recycle-unique Win32 HANDLEs) was giving everyone
+	grey hair trying to solve it.
+
+	* ptw32_MCS_lock.c: New MCS queue-based lock implementation. These
+	locks are efficient: they have very low overhead in the uncontended case;
+	are efficient in contention and minimise cache-coherence updates in
+	managing the user level FIFO queue; do not require an ABI change in the
+	library.
+
+2005-05-27  Alexander Gottwald <alexander.gottwald at s1999.tu-chemnitz.de>
+
+	* pthread.h: Some things, like HANDLE, were only defined if
+	PTW32_LEVEL was >= 3. They should always be defined.
+
+2005-05-25  Vladimir Kliatchko  <vladimir at kliatchko.com>
+
+	* pthread_once.c: Eliminate all priority operations and other
+	complexity by replacing the event with a semaphore. The advantage
+	of the change is the ability to release just one waiter if the
+	init_routine thread is cancelled yet still release all waiters when
+	done. Simplify once_control state checks to improve efficiency
+	further.
+
+2005-05-24  Mikael Magnusson  <mikaelmagnusson at glocalnet.net>
+
+	* GNUmakefile: Patched to allow cross-compile with mingw32 on Linux.
+	It uses macros instead of referencing dlltool, gcc and g++ directly;
+	added a call to ranlib. For example the GC static library can be
+	built with:
+	make CC=i586-mingw32msvc-gcc RC=i586-mingw32msvc-windres \
+	RANLIB=i586-mingw32msvc-ranlib clean GC-static
+
+2005-05-13  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np):
+	Move on-exit-only stuff from ptw32_threadDestroy() to here.
+	* ptw32_threadDestroy.c: It's purpose is now only to reclaim thread
+	resources for detached threads, or via pthread_join() or
+	pthread_detach() on joinable threads.
+	* ptw32_threadStart.c: Calling user destruct routines has moved to
+	pthread_win32_thread_detach_np(); call pthread_win32_thread_detach_np()
+	directly if statically linking, otherwise do so via dllMain; store
+	thread return value in thread struct for all cases, including
+	cancellation and exception exits; thread abnormal exits	go via
+	pthread_win32_thread_detach_np.
+	* pthread_join.c (pthread_join): Don't try to get return code from
+	Win32 thread - always get it from he thread struct.
+	* pthread_detach.c (pthread_detach): reduce extent of the thread
+	existence check since we now don't care if the Win32 thread HANDLE has
+	been closed; reclaim thread resources if the thread has exited already.
+	* ptw32_throw.c (ptw32_throw): For Win32 threads that are not implicit,
+	only Call thread cleanup if statically linking, otherwise leave it to
+	dllMain.
+	* sem_post.c (_POSIX_SEM_VALUE_MAX): Change to SEM_VALUE_MAX.
+	* sem_post_multiple.c: Likewise.
+	* sem_init.c: Likewise.
+
+2005-05-10  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* pthread_join.c (pthread_join): Add missing check for thread ID
+	reference count in thread existence test; reduce extent of the
+	existence test since we don't care if the Win32 thread HANDLE has
+	been closed.
+
+2005-05-09  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* ptw32_callUserDestroyRoutines.c: Run destructor process (i.e.
+	loop over all keys calling destructors) up to
+	PTHREAD_DESTRUCTOR_ITERATIONS times if TSD value isn't NULL yet;
+	modify assoc management.
+	* pthread_key_delete.c: Modify assoc management.
+	* ptw32_tkAssocDestroy.c: Fix error in assoc removal from chains.
+	* pthread.h
+	(_POSIX_THREAD_DESTRUCTOR_ITERATIONS): Define to value specified by
+	POSIX.
+	(_POSIX_THREAD_KEYS_MAX): Define to value specified by POSIX.
+	(PTHREAD_KEYS_MAX): Redefine [upward] to minimum required by POSIX.
+	(SEM_NSEMS_MAX): Define to implementation value.
+	(SEM_VALUE_MAX): Define to implementation value.
+	(_POSIX_SEM_NSEMS_MAX): Redefine to value specified by POSIX.
+	(_POSIX_SEM_VALUE_MAX): Redefine to value specified by POSIX.
+
+2005-05-06  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* signal.c (sigwait): Add a cancellation point to this otherwise
+	no-op.
+	* sem_init.c (sem_init): Check for and return ERANGE error.
+	* sem_post.c (sem_post): Likewise.
+	* sem_post_multiple.c (sem_post_multiple): Likewise.
+	* manual (directory): Added; see ChangeLog inside.
+
+2005-05-02  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* implement.h (struct pthread_key_t_): Change threadsLock to keyLock
+	so as not to be confused with the per thread lock 'threadlock';
+	change all references to it.
+	* implement.h (struct ThreadKeyAssoc): Remove lock; add prevKey
+	and prevThread pointers; re-implemented all routines that use this
+	struct. The effect of this is to save one handle per association,
+	which could potentially equal the number of keys multiplied by the
+	number of threads, accumulating over time - and to free the
+	association memory as soon as it is no longer referenced by either
+	the key or the thread. Previously, the handle and memory were
+	released only after BOTH key and thread no longer referenced the
+	association. That is, often no association resources were released
+	until the process itself exited. In addition, at least one race
+	condition has been removed - where two threads could attempt to
+	release the association resources simultaneously - one via
+	ptw32_callUserDestroyRoutines and the other via
+	pthread_key_delete.
+	- thanks to Richard Hughes at Aculab for discovering the problem.
+	* pthread_key_create.c: See above.
+	* pthread_key_delete.c: See above.
+	* pthread_setspecific.c: See above.
+	* ptw32_callUserDestroyRoutines.c: See above.
+	* ptw32_tkAssocCreate.c: See above.
+	* ptw32_tkAssocDestroy.c: See above.
+
+2005-04-27  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* sem_wait.c (ptw32_sem_wait_cleanup): after cancellation re-attempt
+	to acquire the semaphore to avoid a race with a late sem_post.
+	* sem_timedwait.c: Modify comments.
+
+2005-04-25  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* ptw32_relmillisecs.c: New module; converts future abstime to 
+	milliseconds relative to 'now'.
+	* pthread_mutex_timedlock.c: Use new ptw32_relmillisecs routine in
+	place of internal code; remove the NEED_SEM code - this routine is now
+	implemented for builds that define NEED_SEM (WinCE etc)
+	* sem_timedwait.c: Likewise; after timeout or cancellation,
+	re-attempt to acquire the semaphore in case one has been posted since
+	the timeout/cancel occurred. Thanks to Stefan Mueller.
+	* Makefile: Add ptw32_relmillisecs.c module; remove
+	ptw32_{in,de}crease_semaphore.c modules.
+	* GNUmakefile: Likewise.
+	* Bmakefile: Likewise.
+
+	* sem_init.c: Re-write the NEED_SEM code to be consistent with the
+	non-NEED_SEM code, but retaining use of an event in place of the w32 sema
+	for w32 systems that don't include semaphores (WinCE);
+	the NEED_SEM versions of semaphores has been broken for a long time but is
+	now fixed and supports all of the same routines as the non-NEED_SEM case.
+	* sem_destroy.c: Likewise.
+	* sem_wait.c: Likewise.
+	* sem_post.c: Likewise.
+	* sem_post_multple.c: Likewise.
+	* implement.h: Likewise.
+	* sem_timedwait.c: Likewise; this routine is now
+	implemented for builds that define NEED_SEM (WinCE etc).
+	* sem_trywait.c: Likewise.
+	* sem_getvalue.c: Likewise.
+
+	* pthread_once.c: Yet more changes, reverting closer to Gottlob Frege's
+	first design, but retaining cancellation, priority boosting, and adding
+	preservation of W32 error codes to make pthread_once transparent to
+	GetLastError.
+
+2005-04-11  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* pthread_once.c (pthread_once): Added priority boosting to
+	solve starvation problem after once_routine cancellation.
+	See notes in file.
+
+2005-04-06  Kevin Lussier <Kevin at codegreennetworks.com>
+
+	* Makefile: Added debug targets for all versions of the library.
+
+2005-04-01  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* GNUmakefile: Add target to build libpthreadGC1.a as a static link
+	library.
+	* Makefile: Likewise for pthreadGC1.lib.
+
+2005-04-01  Kevin Lussier <Kevin at codegreennetworks.com>
+
+	* sem_timedwait.c (sem_timedwait): Increase size of temp variables to
+	avoid int overflows for large timeout values.
+	* implement.h (int64_t): Include or define.
+
+2005-03-31   Dimitar Panayotov <develop at mail.bg>^M
+
+	* pthread.h: Fix conditional defines for static linking.
+	* sched.h: Liekwise.
+	* semaphore.h: Likewise.
+	* dll.c (PTW32_STATIC_LIB): Module is conditionally included
+	in the build.
+
+2005-03-16  Ross Johnson  <ross at callisto.canberra.edu.au>^M
+
+	* pthread_setcancelstate.c: Undo the last change.
+
+2005-03-16  Ross Johnson  <ross at callisto.canberra.edu.au>^M
+
+	* pthread_setcancelstate.c: Don't check for an async cancel event
+	if the library is using alertable async cancel..
+
+2005-03-14  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* pthread_once.c (pthread_once): Downgrade interlocked operations to simple
+	memory operations where these are protected by the critical section; edit
+	comments.
+
+2005-03-13  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_once.c (pthread_once): Completely redesigned; a change was
+	required to the ABI (pthread_once_t_), and resulting in a version
+	compatibility index increment.
+
+	NOTES:
+	The design (based on pseudo code contributed by Gottlob Frege) avoids
+	creating a kernel object if there is no contention. See URL for details:-
+	http://sources.redhat.com/ml/pthreads-win32/2005/msg00029.html
+	This uses late initialisation similar to the technique already used for
+	pthreads-win32 mutexes and semaphores (from Alexander Terekhov).
+
+	The subsequent cancelation cleanup additions (by rpj) could not be implemented
+	without sacrificing some of the efficiency in Gottlob's design. In particular,
+	although each once_control uses it's own event to block on, a global CS is
+	required to manage it - since the event must be either re-usable or
+	re-creatable under cancelation. This is not needed in the non-cancelable
+	design because it is able to mark the event as closed (forever).
+
+	When uncontested, a CS operation is equivalent to an Interlocked operation
+	in speed. So, in the final design with cancelability, an uncontested
+	once_control operation involves a minimum of five interlocked operations
+	(including the LeaveCS operation).
+	
+	ALTERNATIVES:
+	An alternative design from Alexander Terekhov proposed using a named mutex,
+	as sketched below:-
+
+	  if (!once_control) { // May be in TLS
+	    named_mutex::guard guard(&once_control2);
+	      if (!once_control2) {
+	         <init>
+	         once_control2 = true;
+	      }
+	    once_control = true;
+	  }
+	
+	A more detailed description of this can be found here:-
+	http://groups.yahoo.com/group/boost/message/15442
+
+	[Although the definition of a suitable PTHREAD_ONCE_INIT precludes use of the
+	TLS located flag, this is not critical.]
+	
+	There are three primary concerns though:-
+	1) The [named] mutex is 'created' even in the uncontended case.
+	2) A system wide unique name must be generated.
+	3) Win32 mutexes are VERY slow even in the uncontended 	case. An uncontested
+	Win32 mutex lock operation can be 50 (or more) times slower than an
+	uncontested EnterCS operation.
+
+	Ultimately, the named mutex trick is making use of the global locks maintained
+	by the kernel.
+
+	* pthread.h (pthread_once_t_): One flag and an event HANDLE added.
+	(PTHREAD_ONCE_INIT): Additional values included.
+
+2005-03-08  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_once.c (pthread_once): Redesigned to elliminate potential
+	starvation problem.
+	- reported by Gottlob Frege  <gottlobfrege at gmail.com>
+
+	* ptw32_threadDestroy.c (ptw32_threadDestroy): Implicit threads were
+	not closing their Win32 thread duplicate handle.
+	- reported by Dmitrii Semii <bogolt at gmail.com>
+
+2005-01-25  Ralf Kubis  <RKubis at mc.com>
+
+	* Attempted acquisition of recursive mutex was causing waiting
+	threads to not be woken when the mutex is released.
+
+	* GNUmakefile (GCE): Generate correct version resource comments.
+
+2005-01-01  Konstantin Voronkov  <beowinkle at yahoo.com>
+
+	* pthread_mutex_lock.c (pthread_mutex_lock): The new atomic exchange
+	mutex algorithm is known to allow a thread to steal the lock off
+	FIFO waiting threads. The next waiting FIFO thread gets a spurious
+	wake-up and must attempt to re-acquire the lock. The woken thread
+	was setting itself as the mutex's owner before the re-acquisition.
+
+2004-11-22  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* pthread_cond_wait.c (ptw32_cond_wait_cleanup): Undo change
+	from 2004-11-02.
+	* Makefile (DLL_VER): Added for DLL naming suffix - see README.
+	* GNUmakefile (DLL_VER): Likewise.
+	* Wmakefile (DLL_VER): Likewise.
+	* Bmakefile (DLL_VER): Likewise.
+	* pthread.dsw (version.rc): Added to MSVS workspace.
+
+2004-11-20  Boudewijn Dekker  <b.dekker at ellipsis.nl>
+
+	* pthread_getspecific.c (pthread_getspecific): Check for
+	invalid (NULL) key argument.
+
+2004-11-19  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* config.h (PTW32_THREAD_ID_REUSE_INCREMENT): Added to allow
+	building the library for either unique thread IDs like Solaris
+	or non-unique thread IDs like Linux; allows application developers
+	to override the library's default insensitivity to some apps
+	that may not be strictly POSIX compliant.
+	* version.rc: New resource module to encode version information
+	within the DLL.
+	* pthread.h: Added PTW32_VERSION* defines and grouped sections
+	required by resource compiler together; bulk of file is skipped
+	if RC_INVOKED. Defined some error numbers and other names for
+	Borland compiler.
+
+2004-11-02  Ross Johnson  <rpj at callisto.canberra.edu.au>
+
+	* 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-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.
+	* sem_wait.c (sem_wait): Use new 'lock'element.
+	* sem_timedwait.c (sem_timedwait): Likewise.
+	* sem_trywait.c (sem_trywait): Likewise.
+	* sem_post.c (sem_post): Likewise.
+	* sem_post_multiple.c (sem_post_multiple): Likewise.
+	* sem_getvalue.c (sem_getvalue): Likewise.
+	* ptw32_semwait.c (ptw32_semwait): Likewise.
+	* sem_destroy.c (sem_destroy): Likewise; also tightened the conditions
+	for semaphore destruction; in particular, a semaphore will not be
+	destroyed if it has waiters.
+	* sem_timedwait.c (sem_timedwait): Added cancel cleanup handler to
+	restore sema value when cancelled.
+	* sem_wait.c (sem_wait): Likewise.
+
+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>
+
+	* 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. 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.
+	* sem_timedwait.c (sem_timedwait): Likewise.
+	* sem_post_multiple.c (sem_post_multiple): Likewise.
+	* sem_getvalue.c (sem_getvalue): Likewise.
+	* 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 (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
new file mode 100644
index 0000000..4f2d449
--- /dev/null
+++ b/FAQ
@@ -0,0 +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
+------------------------------------------------------------------------------
+ 
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644
index 0000000..6c48fd2
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,583 @@
+#
+# --------------------------------------------------------------------------
+#
+#      Pthreads-win32 - POSIX Threads Library for Win32
+#      Copyright(C) 1998 John E. Bossom
+#      Copyright(C) 1999,2005 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
+#
+
+DLL_VER	= 2
+DLL_VERD= $(DLL_VER)d
+
+DEVROOT	= C:\PTHREADS
+
+DLLDEST	= $(DEVROOT)\DLL
+LIBDEST	= $(DEVROOT)\DLL
+
+# If Running MsysDTK
+RM	= rm -f
+MV	= mv -f
+CP	= cp -f
+
+# If not.
+#RM	= erase
+#MV	= rename
+#CP	= copy
+
+# For cross compiling use e.g.
+# make CROSS=i386-mingw32msvc- clean GC-inlined
+CROSS	= 
+
+AR	= $(CROSS)ar
+DLLTOOL = $(CROSS)dlltool
+CC      = $(CROSS)gcc
+CXX     = $(CROSS)g++
+RANLIB  = $(CROSS)ranlib
+RC	= $(CROSS)windres
+
+OPT	= $(CLEANUP) -O3 -finline-functions
+DOPT	= $(CLEANUP) -g -O0
+XOPT	=
+
+RCFLAGS		= --include-dir=.
+LFLAGS		= -lwsock32
+
+# ----------------------------------------------------------------------
+# The library can be built with some alternative behaviour to
+# facilitate development of applications on Win32 that will be ported
+# to other POSIX systems. Nothing definable here will make the library
+# non-compliant, but applications that make assumptions that POSIX
+# does not garrantee may fail or misbehave under some settings.
+#
+# PTW32_THREAD_ID_REUSE_INCREMENT
+# Purpose:
+# POSIX says that applications should assume that thread IDs can be
+# recycled. However, Solaris and some other systems use a [very large]
+# sequence number as the thread ID, which provides virtual uniqueness.
+# Pthreads-win32 provides pseudo-unique IDs when the default increment
+# (1) is used, but pthread_t is not a scalar type like Solaris's.
+#
+# Usage:
+# Set to any value in the range: 0 <= value <= 2^wordsize
+#
+# Examples:
+# Set to 0 to emulate non recycle-unique behaviour like Linux or *BSD.
+# Set to 1 for recycle-unique thread IDs (this is the default).
+# Set to some other +ve value to emulate smaller word size types
+# (i.e. will wrap sooner).
+#
+#PTW32_FLAGS	= "-DPTW32_THREAD_ID_REUSE_INCREMENT=0"
+#
+# ----------------------------------------------------------------------
+
+GC_CFLAGS	= $(PTW32_FLAGS) 
+GCE_CFLAGS	= $(PTW32_FLAGS) -mthreads
+
+## Mingw32
+MAKE		?= make
+CFLAGS	= $(OPT) $(XOPT) -I. -DHAVE_CONFIG_H -Wall
+
+DLL_INLINED_OBJS	= \
+		pthread.o \
+		version.o
+
+# Agregate modules for inlinability
+DLL_OBJS	= \
+		attr.o \
+		barrier.o \
+		cancel.o \
+		cleanup.o \
+		condvar.o \
+		create.o \
+		dll.o \
+		errno.o \
+		exit.o \
+		fork.o \
+		global.o \
+		misc.o \
+		mutex.o \
+		nonportable.o \
+		private.o \
+		rwlock.o \
+		sched.o \
+		semaphore.o \
+		signal.o \
+		spin.o \
+		sync.o \
+		tsd.o \
+		version.o
+
+# Separate modules for minimum size statically linked images
+SMALL_STATIC_OBJS	= \
+		pthread_attr_init.o \
+		pthread_attr_destroy.o \
+		pthread_attr_getdetachstate.o \
+		pthread_attr_setdetachstate.o \
+		pthread_attr_getstackaddr.o \
+		pthread_attr_setstackaddr.o \
+		pthread_attr_getstacksize.o \
+		pthread_attr_setstacksize.o \
+		pthread_attr_getscope.o \
+		pthread_attr_setscope.o \
+		pthread_attr_setschedpolicy.o \
+		pthread_attr_getschedpolicy.o \
+		pthread_attr_setschedparam.o \
+		pthread_attr_getschedparam.o \
+		pthread_attr_setinheritsched.o \
+		pthread_attr_getinheritsched.o \
+		pthread_barrier_init.o \
+		pthread_barrier_destroy.o \
+		pthread_barrier_wait.o \
+		pthread_barrierattr_init.o \
+		pthread_barrierattr_destroy.o \
+		pthread_barrierattr_setpshared.o \
+		pthread_barrierattr_getpshared.o \
+		pthread_setcancelstate.o \
+		pthread_setcanceltype.o \
+		pthread_testcancel.o \
+		pthread_cancel.o \
+		cleanup.o \
+		pthread_condattr_destroy.o \
+		pthread_condattr_getpshared.o \
+		pthread_condattr_init.o \
+		pthread_condattr_setpshared.o \
+		pthread_cond_destroy.o \
+		pthread_cond_init.o \
+		pthread_cond_signal.o \
+		pthread_cond_wait.o \
+		create.o \
+		dll.o \
+		errno.o \
+		pthread_exit.o \
+		fork.o \
+		global.o \
+		pthread_mutex_init.o \
+		pthread_mutex_destroy.o \
+		pthread_mutexattr_init.o \
+		pthread_mutexattr_destroy.o \
+		pthread_mutexattr_getpshared.o \
+		pthread_mutexattr_setpshared.o \
+		pthread_mutexattr_settype.o \
+		pthread_mutexattr_gettype.o \
+		pthread_mutex_lock.o \
+		pthread_mutex_timedlock.o \
+		pthread_mutex_unlock.o \
+		pthread_mutex_trylock.o \
+		pthread_mutexattr_setkind_np.o \
+		pthread_mutexattr_getkind_np.o \
+		pthread_getw32threadhandle_np.o \
+		pthread_delay_np.o \
+		pthread_num_processors_np.o \
+		pthread_win32_attach_detach_np.o \
+		pthread_equal.o \
+		pthread_getconcurrency.o \
+		pthread_once.o \
+		pthread_self.o \
+		pthread_setconcurrency.o \
+		pthread_rwlock_init.o \
+		pthread_rwlock_destroy.o \
+		pthread_rwlockattr_init.o \
+		pthread_rwlockattr_destroy.o \
+		pthread_rwlockattr_getpshared.o \
+		pthread_rwlockattr_setpshared.o \
+		pthread_rwlock_rdlock.o \
+		pthread_rwlock_wrlock.o \
+		pthread_rwlock_unlock.o \
+		pthread_rwlock_tryrdlock.o \
+		pthread_rwlock_trywrlock.o \
+		pthread_setschedparam.o \
+		pthread_getschedparam.o \
+		pthread_timechange_handler_np.o \
+		ptw32_is_attr.o \
+		ptw32_cond_check_need_init.o \
+		ptw32_MCS_lock.o \
+		ptw32_mutex_check_need_init.o \
+		ptw32_processInitialize.o \
+		ptw32_processTerminate.o \
+		ptw32_threadStart.o \
+		ptw32_threadDestroy.o \
+		ptw32_tkAssocCreate.o \
+		ptw32_tkAssocDestroy.o \
+		ptw32_callUserDestroyRoutines.o \
+		ptw32_timespec.o \
+		ptw32_throw.o \
+		ptw32_InterlockedCompareExchange.o \
+		ptw32_getprocessors.o \
+		ptw32_calloc.o \
+		ptw32_new.o \
+		ptw32_reuse.o \
+		ptw32_semwait.o \
+		ptw32_relmillisecs.o \
+		ptw32_rwlock_check_need_init.o \
+		sched_get_priority_max.o \
+		sched_get_priority_min.o \
+		sched_setscheduler.o \
+		sched_getscheduler.o \
+		sched_yield.o \
+		sem_init.o \
+		sem_destroy.o \
+		sem_trywait.o \
+		sem_timedwait.o \
+		sem_wait.o \
+		sem_post.o \
+		sem_post_multiple.o \
+		sem_getvalue.o \
+		sem_open.o \
+		sem_close.o \
+		sem_unlink.o \
+		signal.o \
+		pthread_kill.o \
+		ptw32_spinlock_check_need_init.o \
+		pthread_spin_init.o \
+		pthread_spin_destroy.o \
+		pthread_spin_lock.o \
+		pthread_spin_unlock.o \
+		pthread_spin_trylock.o \
+		pthread_detach.o \
+		pthread_join.o \
+		pthread_key_create.o \
+		pthread_key_delete.o \
+		pthread_setspecific.o \
+		pthread_getspecific.o \
+		w32_CancelableWait.o \
+		version.o
+
+INCL	= \
+		config.h \
+		implement.h \
+		semaphore.h \
+		pthread.h \
+		need_errno.h
+
+ATTR_SRCS	= \
+		pthread_attr_init.c \
+		pthread_attr_destroy.c \
+		pthread_attr_getdetachstate.c \
+		pthread_attr_setdetachstate.c \
+		pthread_attr_getstackaddr.c \
+		pthread_attr_setstackaddr.c \
+		pthread_attr_getstacksize.c \
+		pthread_attr_setstacksize.c \
+		pthread_attr_getscope.c \
+		pthread_attr_setscope.c
+
+BARRIER_SRCS = \
+		pthread_barrier_init.c \
+		pthread_barrier_destroy.c \
+		pthread_barrier_wait.c \
+		pthread_barrierattr_init.c \
+		pthread_barrierattr_destroy.c \
+		pthread_barrierattr_setpshared.c \
+		pthread_barrierattr_getpshared.c
+
+CANCEL_SRCS	= \
+		pthread_setcancelstate.c \
+		pthread_setcanceltype.c \
+		pthread_testcancel.c \
+		pthread_cancel.c 
+
+CONDVAR_SRCS	= \
+		ptw32_cond_check_need_init.c \
+		pthread_condattr_destroy.c \
+		pthread_condattr_getpshared.c \
+		pthread_condattr_init.c \
+		pthread_condattr_setpshared.c \
+		pthread_cond_destroy.c \
+		pthread_cond_init.c \
+		pthread_cond_signal.c \
+		pthread_cond_wait.c
+
+EXIT_SRCS	= \
+		pthread_exit.c
+
+MISC_SRCS	= \
+		pthread_equal.c \
+		pthread_getconcurrency.c \
+		pthread_kill.c \
+		pthread_once.c \
+		pthread_self.c \
+		pthread_setconcurrency.c \
+		ptw32_calloc.c \
+		ptw32_MCS_lock.c \
+		ptw32_new.c \
+		ptw32_reuse.c \
+		w32_CancelableWait.c
+
+MUTEX_SRCS	= \
+		ptw32_mutex_check_need_init.c \
+		pthread_mutex_init.c \
+		pthread_mutex_destroy.c \
+		pthread_mutexattr_init.c \
+		pthread_mutexattr_destroy.c \
+		pthread_mutexattr_getpshared.c \
+		pthread_mutexattr_setpshared.c \
+		pthread_mutexattr_settype.c \
+		pthread_mutexattr_gettype.c \
+		pthread_mutex_lock.c \
+		pthread_mutex_timedlock.c \
+		pthread_mutex_unlock.c \
+		pthread_mutex_trylock.c
+
+NONPORTABLE_SRCS = \
+		pthread_mutexattr_setkind_np.c \
+		pthread_mutexattr_getkind_np.c \
+		pthread_getw32threadhandle_np.c \
+		pthread_delay_np.c \
+		pthread_num_processors_np.c \
+		pthread_win32_attach_detach_np.c \
+		pthread_timechange_handler_np.c 
+
+PRIVATE_SRCS	= \
+		ptw32_is_attr.c \
+		ptw32_processInitialize.c \
+		ptw32_processTerminate.c \
+		ptw32_threadStart.c \
+		ptw32_threadDestroy.c \
+		ptw32_tkAssocCreate.c \
+		ptw32_tkAssocDestroy.c \
+		ptw32_callUserDestroyRoutines.c \
+		ptw32_semwait.c \
+		ptw32_relmillisecs.c \
+		ptw32_timespec.c \
+		ptw32_throw.c \
+		ptw32_InterlockedCompareExchange.c \
+		ptw32_getprocessors.c
+
+RWLOCK_SRCS	= \
+		ptw32_rwlock_check_need_init.c \
+		ptw32_rwlock_cancelwrwait.c \
+		pthread_rwlock_init.c \
+		pthread_rwlock_destroy.c \
+		pthread_rwlockattr_init.c \
+		pthread_rwlockattr_destroy.c \
+		pthread_rwlockattr_getpshared.c \
+		pthread_rwlockattr_setpshared.c \
+		pthread_rwlock_rdlock.c \
+		pthread_rwlock_timedrdlock.c \
+		pthread_rwlock_wrlock.c \
+		pthread_rwlock_timedwrlock.c \
+		pthread_rwlock_unlock.c \
+		pthread_rwlock_tryrdlock.c \
+		pthread_rwlock_trywrlock.c
+
+SCHED_SRCS	= \
+		pthread_attr_setschedpolicy.c \
+		pthread_attr_getschedpolicy.c \
+		pthread_attr_setschedparam.c \
+		pthread_attr_getschedparam.c \
+		pthread_attr_setinheritsched.c \
+		pthread_attr_getinheritsched.c \
+		pthread_setschedparam.c \
+		pthread_getschedparam.c \
+		sched_get_priority_max.c \
+		sched_get_priority_min.c \
+		sched_setscheduler.c \
+		sched_getscheduler.c \
+		sched_yield.c
+
+SEMAPHORE_SRCS = \
+		sem_init.c \
+		sem_destroy.c \
+		sem_trywait.c \
+		sem_timedwait.c \
+		sem_wait.c \
+		sem_post.c \
+		sem_post_multiple.c \
+		sem_getvalue.c \
+		sem_open.c \
+		sem_close.c \
+		sem_unlink.c
+
+SPIN_SRCS	= \
+		ptw32_spinlock_check_need_init.c \
+		pthread_spin_init.c \
+		pthread_spin_destroy.c \
+		pthread_spin_lock.c \
+		pthread_spin_unlock.c \
+		pthread_spin_trylock.c
+
+SYNC_SRCS	= \
+		pthread_detach.c \
+		pthread_join.c
+
+TSD_SRCS	= \
+		pthread_key_create.c \
+		pthread_key_delete.c \
+		pthread_setspecific.c \
+		pthread_getspecific.c
+
+
+GCE_DLL	= pthreadGCE$(DLL_VER).dll
+GCED_DLL= pthreadGCE$(DLL_VERD).dll
+GCE_LIB	= libpthreadGCE$(DLL_VER).a
+GCED_LIB= libpthreadGCE$(DLL_VERD).a
+GCE_INLINED_STAMP = pthreadGCE$(DLL_VER).stamp
+GCED_INLINED_STAMP = pthreadGCE$(DLL_VERD).stamp
+
+GC_DLL 	= pthreadGC$(DLL_VER).dll
+GCD_DLL	= pthreadGC$(DLL_VERD).dll
+GC_LIB	= libpthreadGC$(DLL_VER).a
+GCD_LIB	= libpthreadGC$(DLL_VERD).a
+GC_INLINED_STAMP = pthreadGC$(DLL_VER).stamp
+GCD_INLINED_STAMP = pthreadGC$(DLL_VERD).stamp
+GC_STATIC_STAMP = libpthreadGC$(DLL_VER).stamp
+GCD_STATIC_STAMP = libpthreadGC$(DLL_VERD).stamp
+
+PTHREAD_DEF	= pthread.def
+
+help:
+	@ echo "Run one of the following command lines:"
+	@ echo "make clean GC            (to build the GNU C dll with C cleanup code)"
+	@ echo "make clean GCE           (to build the GNU C dll with C++ exception handling)"
+	@ echo "make clean GC-inlined    (to build the GNU C inlined dll with C cleanup code)"
+	@ echo "make clean GCE-inlined   (to build the GNU C inlined dll with C++ exception handling)"
+	@ echo "make clean GC-static     (to build the GNU C inlined static lib with C cleanup code)"
+	@ echo "make clean GC-debug      (to build the GNU C debug dll with C cleanup code)"
+	@ echo "make clean GCE-debug     (to build the GNU C debug dll with C++ exception handling)"
+	@ echo "make clean GC-inlined-debug    (to build the GNU C inlined debug dll with C cleanup code)"
+	@ echo "make clean GCE-inlined-debug   (to build the GNU C inlined debug dll with C++ exception handling)"
+	@ echo "make clean GC-static-debug     (to build the GNU C inlined static debug lib with C cleanup code)"
+
+all:
+	@ $(MAKE) clean GCE
+	@ $(MAKE) clean GC
+
+GC:
+		$(MAKE) CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" $(GC_DLL)
+
+GC-debug:
+		$(MAKE) CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_DLL)
+
+GCE:
+		$(MAKE) CC=$(CXX) CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" $(GCE_DLL)
+
+GCE-debug:
+		$(MAKE) CC=$(CXX) CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCED_DLL)
+
+GC-inlined:
+		$(MAKE) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_INLINED_STAMP)
+
+GC-inlined-debug:
+		$(MAKE) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_INLINED_STAMP)
+
+GCE-inlined:
+		$(MAKE) CC=$(CXX) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GCE_INLINED_STAMP)
+
+GCE-inlined-debug:
+		$(MAKE) CC=$(CXX) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCED_INLINED_STAMP)
+
+GC-static:
+		$(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP)
+
+GC-static-debug:
+		$(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_STATIC_STAMP)
+
+tests:
+	@ cd tests
+	@ $(MAKE) auto
+
+%.pre: %.c
+	$(CC) -E -o $@ $(CFLAGS) $^
+
+%.s: %.c
+	$(CC) -c $(CFLAGS) -DPTW32_BUILD_INLINED -Wa,-ahl $^ > $@
+
+%.o: %.rc
+	$(RC) $(RCFLAGS) $(CLEANUP) -o $@ $<
+
+.SUFFIXES: .dll .rc .c .o
+
+.c.o:;		 $(CC) -c -o $@ $(CFLAGS) $(XC_FLAGS) $<
+
+
+$(GC_DLL) $(GCD_DLL): $(DLL_OBJS)
+	$(CC) $(OPT) -shared -o $(GC_DLL) $(DLL_OBJS) $(LFLAGS)
+	$(DLLTOOL) -z pthread.def $(DLL_OBJS)
+	$(DLLTOOL) -k --dllname $@ --output-lib $(GC_LIB) --def $(PTHREAD_DEF)
+
+$(GCE_DLL): $(DLL_OBJS)
+	$(CC) $(OPT) -mthreads -shared -o $(GCE_DLL) $(DLL_OBJS) $(LFLAGS)
+	$(DLLTOOL) -z pthread.def $(DLL_OBJS)
+	$(DLLTOOL) -k --dllname $@ --output-lib $(GCE_LIB) --def $(PTHREAD_DEF)
+
+$(GC_INLINED_STAMP) $(GCD_INLINED_STAMP): $(DLL_INLINED_OBJS)
+	$(CC) $(OPT) $(XOPT) -shared -o $(GC_DLL) $(DLL_INLINED_OBJS) $(LFLAGS)
+	$(DLLTOOL) -z pthread.def $(DLL_INLINED_OBJS)
+	$(DLLTOOL) -k --dllname $(GC_DLL) --output-lib $(GC_LIB) --def $(PTHREAD_DEF)
+	echo touched > $(GC_INLINED_STAMP)
+
+$(GCE_INLINED_STAMP) $(GCED_INLINED_STAMP): $(DLL_INLINED_OBJS)
+	$(CC) $(OPT) $(XOPT) -mthreads -shared -o $(GCE_DLL) $(DLL_INLINED_OBJS)  $(LFLAGS)
+	$(DLLTOOL) -z pthread.def $(DLL_INLINED_OBJS)
+	$(DLLTOOL) -k --dllname $(GCE_DLL) --output-lib $(GCE_LIB) --def $(PTHREAD_DEF)
+	echo touched > $(GCE_INLINED_STAMP)
+
+$(GC_STATIC_STAMP) $(GCD_STATIC_STAMP): $(DLL_INLINED_OBJS)
+	$(RM) $(GC_LIB)
+	$(AR) -rv $(GC_LIB) $(DLL_INLINED_OBJS)
+	$(RANLIB) $(GC_LIB)
+	echo touched > $(GC_STATIC_STAMP)
+
+clean:
+	-$(RM) *~
+	-$(RM) *.i
+	-$(RM) *.o
+	-$(RM) *.obj
+	-$(RM) *.exe
+	-$(RM) $(PTHREAD_DEF)
+
+realclean: clean
+	-$(RM) $(GC_LIB)
+	-$(RM) $(GCE_LIB)
+	-$(RM) $(GC_DLL)
+	-$(RM) $(GCE_DLL)
+	-$(RM) $(GC_INLINED_STAMP)
+	-$(RM) $(GCE_INLINED_STAMP)
+	-$(RM) $(GC_STATIC_STAMP)
+	-$(RM) $(GCD_LIB)
+	-$(RM) $(GCED_LIB)
+	-$(RM) $(GCD_DLL)
+	-$(RM) $(GCED_DLL)
+	-$(RM) $(GCD_INLINED_STAMP)
+	-$(RM) $(GCED_INLINED_STAMP)
+	-$(RM) $(GCD_STATIC_STAMP)
+
+attr.o:		attr.c $(ATTR_SRCS) $(INCL)
+barrier.o:	barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.o:	cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.o:	condvar.c $(CONDVAR_SRCS) $(INCL)
+exit.o:		exit.c $(EXIT_SRCS) $(INCL)
+misc.o:		misc.c $(MISC_SRCS) $(INCL)
+mutex.o:	mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.o:	nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.o:	private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.o:	rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.o:	sched.c $(SCHED_SRCS) $(INCL)
+semaphore.o:	semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.o:		spin.c $(SPIN_SRCS) $(INCL)
+sync.o:		sync.c $(SYNC_SRCS) $(INCL)
+tsd.o:		tsd.c $(TSD_SRCS) $(INCL)
+version.o:	version.rc $(INCL)
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 0000000..d253c1f
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,4 @@
+CVS Repository maintainers
+
+Ross Johnson		rpj@ise.canberra.edu.au
+Ben Elliston		bje@cygnus.com
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..162a08e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,504 @@
+# This makefile is compatible with MS nmake and can be used as a
+# replacement for buildlib.bat. I've changed the target from an ordinary dll
+# (/LD) to a debugging dll (/LDd).
+# 
+# The variables $DLLDEST and $LIBDEST hold the destination directories for the
+# dll and the lib, respectively. Probably all that needs to change is $DEVROOT.
+
+
+# DLL_VER:
+# See pthread.h and README - This number is computed as 'current - age'
+DLL_VER	= 2
+DLL_VERD= $(DLL_VER)d
+
+DEVROOT	= C:\pthreads
+
+DLLDEST	= $(DEVROOT)\DLL
+LIBDEST	= $(DEVROOT)\LIB
+HDRDEST	= $(DEVROOT)\INCLUDE
+
+DLLS	= pthreadVCE$(DLL_VER).dll pthreadVSE$(DLL_VER).dll pthreadVC$(DLL_VER).dll \
+		  pthreadVCE$(DLL_VERD).dll pthreadVSE$(DLL_VERD).dll pthreadVC$(DLL_VERD).dll
+INLINED_STAMPS	= pthreadVCE$(DLL_VER).stamp pthreadVSE$(DLL_VER).stamp pthreadVC$(DLL_VER).stamp \
+				  pthreadVCE$(DLL_VERD).stamp pthreadVSE$(DLL_VERD).stamp pthreadVC$(DLL_VERD).stamp
+STATIC_STAMPS	= pthreadVCE$(DLL_VER).static pthreadVSE$(DLL_VER).static pthreadVC$(DLL_VER).static \
+				  pthreadVCE$(DLL_VERD).static pthreadVSE$(DLL_VERD).static pthreadVC$(DLL_VERD).static
+
+OPTIM	= /O2 /Ob2
+OPTIMD	=
+
+CFLAGS	= /W3 /MD /nologo /Yd /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H
+CFLAGSD	= /Zi $(CFLAGS)
+
+
+# Default cleanup style
+CLEANUP	= __CLEANUP_C
+
+# C++ Exceptions
+VCEFLAGS	= /GX /TP $(CFLAGS)
+VCEFLAGSD	= /GX /TP $(CFLAGSD)
+#Structured Exceptions
+VSEFLAGS	= $(CFLAGS)
+VSEFLAGSD	= $(CFLAGSD)
+#C cleanup code
+VCFLAGS	= $(CFLAGS)
+VCFLAGSD= $(CFLAGSD)
+
+DLL_INLINED_OBJS = \
+		pthread.obj \
+		version.res
+
+# Aggregate modules for inlinability
+DLL_OBJS	= \
+		attr.obj \
+		barrier.obj \
+		cancel.obj \
+		cleanup.obj \
+		condvar.obj \
+		create.obj \
+		dll.obj \
+		errno.obj \
+		exit.obj \
+		fork.obj \
+		global.obj \
+		misc.obj \
+		mutex.obj \
+		nonportable.obj \
+		private.obj \
+		rwlock.obj \
+		sched.obj \
+		semaphore.obj \
+		signal.obj \
+		spin.obj \
+		sync.obj \
+		tsd.obj \
+		version.res
+
+# Separate modules for minimising the size of statically linked images
+SMALL_STATIC_OBJS	= \
+		pthread_attr_init.obj \
+		pthread_attr_destroy.obj \
+		pthread_attr_getdetachstate.obj \
+		pthread_attr_setdetachstate.obj \
+		pthread_attr_getstackaddr.obj \
+		pthread_attr_setstackaddr.obj \
+		pthread_attr_getstacksize.obj \
+		pthread_attr_setstacksize.obj \
+		pthread_attr_getscope.obj \
+		pthread_attr_setscope.obj \
+		pthread_attr_setschedpolicy.obj \
+		pthread_attr_getschedpolicy.obj \
+		pthread_attr_setschedparam.obj \
+		pthread_attr_getschedparam.obj \
+		pthread_attr_setinheritsched.obj \
+		pthread_attr_getinheritsched.obj \
+		pthread_barrier_init.obj \
+		pthread_barrier_destroy.obj \
+		pthread_barrier_wait.obj \
+		pthread_barrierattr_init.obj \
+		pthread_barrierattr_destroy.obj \
+		pthread_barrierattr_setpshared.obj \
+		pthread_barrierattr_getpshared.obj \
+		pthread_setcancelstate.obj \
+		pthread_setcanceltype.obj \
+		pthread_testcancel.obj \
+		pthread_cancel.obj \
+		cleanup.obj \
+		pthread_condattr_destroy.obj \
+		pthread_condattr_getpshared.obj \
+		pthread_condattr_init.obj \
+		pthread_condattr_setpshared.obj \
+		pthread_cond_destroy.obj \
+		pthread_cond_init.obj \
+		pthread_cond_signal.obj \
+		pthread_cond_wait.obj \
+		create.obj \
+		dll.obj \
+		errno.obj \
+		pthread_exit.obj \
+		fork.obj \
+		global.obj \
+		pthread_mutex_init.obj \
+		pthread_mutex_destroy.obj \
+		pthread_mutexattr_init.obj \
+		pthread_mutexattr_destroy.obj \
+		pthread_mutexattr_getpshared.obj \
+		pthread_mutexattr_setpshared.obj \
+		pthread_mutexattr_settype.obj \
+		pthread_mutexattr_gettype.obj \
+		pthread_mutex_lock.obj \
+		pthread_mutex_timedlock.obj \
+		pthread_mutex_unlock.obj \
+		pthread_mutex_trylock.obj \
+		pthread_mutexattr_setkind_np.obj \
+		pthread_mutexattr_getkind_np.obj \
+		pthread_getw32threadhandle_np.obj \
+		pthread_delay_np.obj \
+		pthread_num_processors_np.obj \
+		pthread_win32_attach_detach_np.obj \
+		pthread_equal.obj \
+		pthread_getconcurrency.obj \
+		pthread_once.obj \
+		pthread_self.obj \
+		pthread_setconcurrency.obj \
+		pthread_rwlock_init.obj \
+		pthread_rwlock_destroy.obj \
+		pthread_rwlockattr_init.obj \
+		pthread_rwlockattr_destroy.obj \
+		pthread_rwlockattr_getpshared.obj \
+		pthread_rwlockattr_setpshared.obj \
+		pthread_rwlock_rdlock.obj \
+		pthread_rwlock_wrlock.obj \
+		pthread_rwlock_unlock.obj \
+		pthread_rwlock_tryrdlock.obj \
+		pthread_rwlock_trywrlock.obj \
+		pthread_setschedparam.obj \
+		pthread_getschedparam.obj \
+		pthread_timechange_handler_np.obj \
+		ptw32_is_attr.obj \
+		ptw32_processInitialize.obj \
+		ptw32_processTerminate.obj \
+		ptw32_threadStart.obj \
+		ptw32_threadDestroy.obj \
+		ptw32_tkAssocCreate.obj \
+		ptw32_tkAssocDestroy.obj \
+		ptw32_callUserDestroyRoutines.obj \
+		ptw32_timespec.obj \
+		ptw32_throw.obj \
+		ptw32_InterlockedCompareExchange.obj \
+		ptw32_getprocessors.obj \
+		ptw32_calloc.obj \
+		ptw32_new.obj \
+		ptw32_reuse.obj \
+		ptw32_rwlock_check_need_init.obj \
+		ptw32_cond_check_need_init.obj \
+		ptw32_mutex_check_need_init.obj \
+		ptw32_semwait.obj \
+		ptw32_relmillisecs.obj \
+		ptw32_MCS_lock.obj \
+		sched_get_priority_max.obj \
+		sched_get_priority_min.obj \
+		sched_setscheduler.obj \
+		sched_getscheduler.obj \
+		sched_yield.obj \
+		sem_init.obj \
+		sem_destroy.obj \
+		sem_trywait.obj \
+		sem_timedwait.obj \
+		sem_wait.obj \
+		sem_post.obj \
+		sem_post_multiple.obj \
+		sem_getvalue.obj \
+		sem_open.obj \
+		sem_close.obj \
+		sem_unlink.obj \
+		signal.obj \
+		pthread_kill.obj \
+		ptw32_spinlock_check_need_init.obj \
+		pthread_spin_init.obj \
+		pthread_spin_destroy.obj \
+		pthread_spin_lock.obj \
+		pthread_spin_unlock.obj \
+		pthread_spin_trylock.obj \
+		pthread_detach.obj \
+		pthread_join.obj \
+		pthread_key_create.obj \
+		pthread_key_delete.obj \
+		pthread_setspecific.obj \
+		pthread_getspecific.obj \
+		w32_CancelableWait.obj \
+		version.res
+
+INCL	= config.h implement.h semaphore.h pthread.h need_errno.h
+
+ATTR_SRCS	= \
+		pthread_attr_init.c \
+		pthread_attr_destroy.c \
+		pthread_attr_getdetachstate.c \
+		pthread_attr_setdetachstate.c \
+		pthread_attr_getstackaddr.c \
+		pthread_attr_setstackaddr.c \
+		pthread_attr_getstacksize.c \
+		pthread_attr_setstacksize.c \
+		pthread_attr_getscope.c \
+		pthread_attr_setscope.c
+
+BARRIER_SRCS = \
+		pthread_barrier_init.c \
+		pthread_barrier_destroy.c \
+		pthread_barrier_wait.c \
+		pthread_barrierattr_init.c \
+		pthread_barrierattr_destroy.c \
+		pthread_barrierattr_setpshared.c \
+		pthread_barrierattr_getpshared.c
+
+CANCEL_SRCS	= \
+		pthread_setcancelstate.c \
+		pthread_setcanceltype.c \
+		pthread_testcancel.c \
+		pthread_cancel.c 
+
+CONDVAR_SRCS	= \
+		ptw32_cond_check_need_init.c \
+		pthread_condattr_destroy.c \
+		pthread_condattr_getpshared.c \
+		pthread_condattr_init.c \
+		pthread_condattr_setpshared.c \
+		pthread_cond_destroy.c \
+		pthread_cond_init.c \
+		pthread_cond_signal.c \
+		pthread_cond_wait.c
+
+EXIT_SRCS	= \
+		pthread_exit.c
+
+MISC_SRCS	= \
+		pthread_equal.c \
+		pthread_getconcurrency.c \
+		pthread_kill.c \
+		pthread_once.c \
+		pthread_self.c \
+		pthread_setconcurrency.c \
+		ptw32_calloc.c \
+		ptw32_MCS_lock.c \
+		ptw32_new.c \
+		ptw32_reuse.c \
+		ptw32_relmillisecs.c \
+		w32_CancelableWait.c
+
+MUTEX_SRCS	= \
+		ptw32_mutex_check_need_init.c \
+		pthread_mutex_init.c \
+		pthread_mutex_destroy.c \
+		pthread_mutexattr_init.c \
+		pthread_mutexattr_destroy.c \
+		pthread_mutexattr_getpshared.c \
+		pthread_mutexattr_setpshared.c \
+		pthread_mutexattr_settype.c \
+		pthread_mutexattr_gettype.c \
+		pthread_mutex_lock.c \
+		pthread_mutex_timedlock.c \
+		pthread_mutex_unlock.c \
+		pthread_mutex_trylock.c
+
+NONPORTABLE_SRCS = \
+		pthread_mutexattr_setkind_np.c \
+		pthread_mutexattr_getkind_np.c \
+		pthread_getw32threadhandle_np.c \
+		pthread_delay_np.c \
+		pthread_num_processors_np.c \
+		pthread_win32_attach_detach_np.c \
+		pthread_timechange_handler_np.c 
+
+PRIVATE_SRCS	= \
+		ptw32_is_attr.c \
+		ptw32_processInitialize.c \
+		ptw32_processTerminate.c \
+		ptw32_threadStart.c \
+		ptw32_threadDestroy.c \
+		ptw32_tkAssocCreate.c \
+		ptw32_tkAssocDestroy.c \
+		ptw32_callUserDestroyRoutines.c \
+		ptw32_semwait.c \
+		ptw32_timespec.c \
+		ptw32_throw.c \
+		ptw32_InterlockedCompareExchange.c \
+		ptw32_getprocessors.c
+
+RWLOCK_SRCS	= \
+		ptw32_rwlock_check_need_init.c \
+		ptw32_rwlock_cancelwrwait.c \
+		pthread_rwlock_init.c \
+		pthread_rwlock_destroy.c \
+		pthread_rwlockattr_init.c \
+		pthread_rwlockattr_destroy.c \
+		pthread_rwlockattr_getpshared.c \
+		pthread_rwlockattr_setpshared.c \
+		pthread_rwlock_rdlock.c \
+		pthread_rwlock_timedrdlock.c \
+		pthread_rwlock_wrlock.c \
+		pthread_rwlock_timedwrlock.c \
+		pthread_rwlock_unlock.c \
+		pthread_rwlock_tryrdlock.c \
+		pthread_rwlock_trywrlock.c
+
+SCHED_SRCS	= \
+		pthread_attr_setschedpolicy.c \
+		pthread_attr_getschedpolicy.c \
+		pthread_attr_setschedparam.c \
+		pthread_attr_getschedparam.c \
+		pthread_attr_setinheritsched.c \
+		pthread_attr_getinheritsched.c \
+		pthread_setschedparam.c \
+		pthread_getschedparam.c \
+		sched_get_priority_max.c \
+		sched_get_priority_min.c \
+		sched_setscheduler.c \
+		sched_getscheduler.c \
+		sched_yield.c
+
+SEMAPHORE_SRCS = \
+		sem_init.c \
+		sem_destroy.c \
+		sem_trywait.c \
+		sem_timedwait.c \
+		sem_wait.c \
+		sem_post.c \
+		sem_post_multiple.c \
+		sem_getvalue.c \
+		sem_open.c \
+		sem_close.c \
+		sem_unlink.c
+
+SPIN_SRCS	= \
+		ptw32_spinlock_check_need_init.c \
+		pthread_spin_init.c \
+		pthread_spin_destroy.c \
+		pthread_spin_lock.c \
+		pthread_spin_unlock.c \
+		pthread_spin_trylock.c
+
+SYNC_SRCS	= \
+		pthread_detach.c \
+		pthread_join.c
+
+TSD_SRCS	= \
+		pthread_key_create.c \
+		pthread_key_delete.c \
+		pthread_setspecific.c \
+		pthread_getspecific.c
+
+
+help:
+	@ echo Run one of the following command lines:
+	@ echo nmake clean VCE   (to build the MSVC dll with C++ exception handling)
+	@ echo nmake clean VSE   (to build the MSVC dll with structured exception handling)
+	@ echo nmake clean VC    (to build the MSVC dll with C cleanup code)
+	@ echo nmake clean VCE-inlined   (to build the MSVC inlined dll with C++ exception handling)
+	@ echo nmake clean VSE-inlined   (to build the MSVC inlined dll with structured exception handling)
+	@ echo nmake clean VC-inlined    (to build the MSVC inlined dll with C cleanup code)
+	@ echo nmake clean VC-static     (to build the MSVC static lib with C cleanup code)
+	@ echo nmake clean VCE-debug   (to build the debug MSVC dll with C++ exception handling)
+	@ echo nmake clean VSE-debug   (to build the debug MSVC dll with structured exception handling)
+	@ echo nmake clean VC-debug    (to build the debug MSVC dll with C cleanup code)
+	@ echo nmake clean VCE-inlined-debug   (to build the debug MSVC inlined dll with C++ exception handling)
+	@ echo nmake clean VSE-inlined-debug   (to build the debug MSVC inlined dll with structured exception handling)
+	@ echo nmake clean VC-inlined-debug    (to build the debug MSVC inlined dll with C cleanup code)
+	@ echo nmake clean VC-static-debug     (to build the debug MSVC static lib with C cleanup code)
+
+all:
+	@ nmake clean VCE-inlined
+	@ nmake clean VSE-inlined
+	@ nmake clean VC-inlined
+	@ nmake clean VCE-inlined-debug
+	@ nmake clean VSE-inlined-debug
+	@ nmake clean VC-inlined-debug
+
+VCE:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VCEFLAGS)" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VER).dll
+
+VCE-debug:
+	@ nmake /nologo EHFLAGS="$(OPTIMD) $(VCEFLAGSD)" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VERD).dll
+
+VSE:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VSEFLAGS)" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VER).dll
+
+VSE-debug:
+	@ nmake /nologo EHFLAGS="$(OPTIMD) $(VSEFLAGSD)" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VERD).dll
+
+VC:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VCFLAGS)" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).dll
+
+VC-debug:
+	@ nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD)" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).dll
+
+#
+# The so-called inlined DLL is just a single translation unit with
+# inlining optimisation turned on.
+#
+VCE-inlined:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VCEFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VER).stamp
+
+VCE-inlined-debug:
+	@ nmake /nologo EHFLAGS="$(OPTIMD) $(VCEFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VERD).stamp
+
+VSE-inlined:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VSEFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VER).stamp
+
+VSE-inlined-debug:
+	@ nmake /nologo EHFLAGS="$(OPTIMD) $(VSEFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VERD).stamp
+
+VC-inlined:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VCFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).stamp
+
+VC-inlined-debug:
+	nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).stamp
+
+VC-static:
+	@ nmake /nologo EHFLAGS="$(OPTIM) $(VCFLAGS) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).static
+
+VC-static-debug:
+	@ nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).static
+
+realclean: clean
+	if exist pthread*.dll del pthread*.dll
+	if exist pthread*.lib del pthread*.lib
+	if exist *.stamp del *.stamp
+
+clean:
+	if exist *.obj del *.obj
+	if exist *.ilk del *.ilk
+	if exist *.pdb del *.pdb
+	if exist *.exp del *.exp
+	if exist *.map del *.map
+	if exist *.o del *.o
+	if exist *.i del *.i
+	if exist *.res del *.res
+
+
+install: $(DLLS)
+	copy pthread*.dll $(DLLDEST)
+	copy pthread*.lib $(LIBDEST)
+	copy pthread.h $(HDRDEST)
+	copy sched.h $(HDRDEST)
+	copy semaphore.h $(HDRDEST)
+
+$(DLLS): $(DLL_OBJS)
+	cl /LDd /Zi /nologo $(DLL_OBJS) \
+		/link /nodefaultlib:libcmt /implib:$*.lib \
+		msvcrt.lib wsock32.lib /out:$@
+
+$(INLINED_STAMPS): $(DLL_INLINED_OBJS)
+	cl /LDd /Zi /nologo $(DLL_INLINED_OBJS) \
+		/link /nodefaultlib:libcmt /implib:$*.lib \
+		msvcrt.lib wsock32.lib /out:$*.dll
+
+$(STATIC_STAMPS): $(DLL_INLINED_OBJS)
+	if exist $*.lib del $*.lib
+	lib $(DLL_INLINED_OBJS) /out:$*.lib
+
+.c.obj:
+	cl $(EHFLAGS) /D$(CLEANUP) -c $<
+
+.rc.res:
+	rc /dPTW32_RC_MSC /d$(CLEANUP) $<
+
+.c.i:
+	cl /P /O2 /Ob1 $(VCFLAGS) $<
+
+attr.obj:	attr.c $(ATTR_SRCS) $(INCL)
+barrier.obj:	barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.obj:	cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.obj:	condvar.c $(CONDVAR_SRCS) $(INCL)
+exit.obj:	exit.c $(EXIT_SRCS) $(INCL)
+misc.obj:	misc.c $(MISC_SRCS) $(INCL)
+mutex.obj:	mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.obj:	nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.obj:	private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.obj:	rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.obj:	sched.c $(SCHED_SRCS) $(INCL)
+semaphore.obj:	semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.obj:	spin.c $(SPIN_SRCS) $(INCL)
+sync.obj:	sync.c $(SYNC_SRCS) $(INCL)
+tsd.obj:	tsd.c $(TSD_SRCS) $(INCL)
+version.res:	version.rc $(INCL)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..18fe543
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,1110 @@
+RELEASE 2.8.0
+-------------
+(2006-12-22)
+
+General
+-------
+New bug fixes in this release since 2.7.0 have not been applied to the
+version 1.x.x series. It is probably time to drop version 1.
+
+Testing and verification
+------------------------
+This release has not yet been tested on SMP architechtures. All tests pass
+on a uni-processor system.
+
+Bug fixes
+---------
+Sem_destroy could return EBUSY even though no threads were waiting on the 
+semaphore. Other races around invalidating semaphore structs (internally)
+have been removed as well.
+
+New tests
+---------
+semaphore5.c - tests the bug fix referred to above.
+
+
+RELEASE 2.7.0
+-------------
+(2005-06-04)
+
+General
+-------
+All new features in this release have been back-ported in release 1.11.0,
+including the incorporation of MCS locks in pthread_once, however, versions
+1 and 2 remain incompatible even though they are now identical in
+performance and functionality.
+
+Testing and verification
+------------------------
+This release has been tested (passed the test suite) on both uni-processor
+and multi-processor systems.
+- Tim Theisen
+
+Bug fixes
+---------
+Pthread_once has been re-implemented to remove priority boosting and other
+complexity to improve robustness. Races for Win32 handles that are not
+recycle-unique have been removed. The general form of pthread_once is now
+the same as that suggested earlier by Alexander Terekhov, but instead of the
+'named mutex', a queue-based lock has been implemented which has the required
+properties of dynamic self initialisation and destruction. This lock is also
+efficient. The ABI is unaffected in as much as the size of pthread_once_t has
+not changed and PTHREAD_ONCE_INIT has not changed, however, applications that
+peek inside pthread_once_t, which is supposed to be opaque, will break.
+- Vladimir Kliatchko
+
+New features
+------------
+* Support for Mingw cross development tools added to GNUmakefile.
+Mingw cross tools allow building the libraries on Linux.
+- Mikael Magnusson
+
+
+RELEASE 2.6.0
+-------------
+(2005-05-19)
+
+General
+-------
+All of the bug fixes and new features in this release have been
+back-ported in release 1.10.0.
+
+Testing and verification
+------------------------
+This release has been tested (passed the test suite) on both uni-processor
+and multi-processor systems. Thanks to Tim Theisen at TomoTherapy for
+exhaustively running the MP tests and for providing crutial observations
+and data when faults are detected.
+
+Bugs fixed
+----------
+
+* pthread_detach() now reclaims remaining thread resources if called after
+the target thread has terminated. Previously, this routine did nothing in
+this case.
+
+New tests
+---------
+
+* detach1.c - tests that pthread_detach properly invalidates the target
+thread, which indicates that the thread resources have been reclaimed.
+
+
+RELEASE 2.5.0
+-------------
+(2005-05-09)
+
+General
+-------
+
+The package now includes a reference documentation set consisting of
+HTML formatted Unix-style manual pages that have been edited for
+consistency with Pthreads-w32. The set can also be read online at:
+http://sources.redhat.com/pthreads-win32/manual/index.html
+
+Thanks again to Tim Theisen for running the test suite pre-release
+on an MP system.
+
+All of the bug fixes and new features in this release have been
+back-ported in release 1.9.0.
+
+Bugs fixed
+----------
+
+* Thread Specific Data (TSD) key management has been ammended to
+eliminate a source of (what was effectively) resource leakage (a HANDLE
+plus memory for each key destruct routine/thread association). This was
+not a true leak because these resources were eventually reclaimed when
+pthread_key_delete was run AND each thread referencing the key had exited.
+The problem was that these two conditions are often not met until very
+late, and often not until the process is about to exit.
+
+The ammended implementation avoids the need for the problematic HANDLE
+and reclaims the memory as soon as either the key is deleted OR the
+thread exits, whichever is first.
+
+Thanks to Richard Hughes at Aculab for identifying and locating the leak.
+
+* TSD key destructors are now processed up to PTHREAD_DESTRUCTOR_ITERATIONS
+times instead of just once. PTHREAD_DESTRUCTOR_ITERATIONS has been
+defined in pthread.h for some time but not used.
+
+* Fix a semaphore accounting race between sem_post/sem_post_multiple
+and sem_wait cancellation. This is the same issue as with
+sem_timedwait that was fixed in the last release.
+
+* sem_init, sem_post, and sem_post_multiple now check that the
+semaphore count never exceeds _POSIX_SEM_VALUE_MAX.
+
+* Although sigwait() is nothing more than a no-op, it should at least
+be a cancellation point to be consistent with the standard.
+
+New tests
+---------
+
+* stress1.c - attempts to expose problems in condition variable
+and semaphore timed wait logic. This test was inspired by Stephan
+Mueller's sample test code used to identify the sem_timedwait bug
+from the last release. It's not a part of the regular test suite
+because it can take awhile to run. To run it:
+nmake clean VC-stress
+
+* tsd2.c - tests that key destructors are re-run if the tsd key value is
+not NULL after the destructor routine has run. Also tests that
+pthread_setspecific() and pthread_getspecific() are callable from
+destructors.
+
+
+RELEASE 2.4.0
+-------------
+(2005-04-26)
+
+General
+-------
+
+There is now no plan to release a version 3.0.0 to fix problems in
+pthread_once(). Other possible implementations of pthread_once
+will still be investigated for a possible future release in an attempt
+to reduce the current implementation's complexity.
+
+All of the bug fixes and new features in this release have been
+back-ported for release 1.8.0.
+
+Bugs fixed
+----------
+
+* Fixed pthread_once race (failures on an MP system). Thanks to
+Tim Theisen for running exhaustive pre-release testing on his MP system
+using a range of compilers:
+  VC++ 6
+  VC++ 7.1
+  Intel C++ version 8.0
+All tests passed.
+Some minor speed improvements were also done.
+
+* Fix integer overrun error in pthread_mutex_timedlock() - missed when
+sem_timedwait() was fixed in release 2.2.0. This routine no longer returns
+ENOTSUP when NEED_SEM is defined - it is supported (NEED_SEM is only
+required for WinCE versions prior to 3.0).
+
+* Fix timeout bug in sem_timedwait().
+- Thanks to Stephan Mueller for reporting, providing diagnostic output
+and test code.
+
+* Fix several problems in the NEED_SEM conditionally included code.
+NEED_SEM included code is provided for systems that don't implement W32
+semaphores, such as WinCE prior to version 3.0. An alternate implementation
+of POSIX semaphores is built using W32 events for these systems when
+NEED_SEM is defined. This code has been completely rewritten in this
+release to reuse most of the default POSIX semaphore code, and particularly,
+to implement all of the sem_* routines supported by pthreads-win32. Tim
+Theisen also run the test suite over the NEED_SEM code on his MP system. All
+tests passed.
+
+* The library now builds without errors for the Borland Builder 5.5 compiler.
+
+New features
+------------
+
+* pthread_mutex_timedlock() and all sem_* routines provided by
+pthreads-win32 are now implemented for WinCE versions prior to 3.0. Those
+versions did not implement W32 semaphores. Define NEED_SEM in config.h when
+building the library for these systems.
+
+Known issues in this release
+----------------------------
+
+* pthread_once is too complicated - but it works as far as testing can
+determine..
+
+* The Borland version of the dll fails some of the tests with a memory read
+exception. The cause is not yet known but a compiler bug has not been ruled
+out.
+
+
+RELEASE 2.3.0
+-------------
+(2005-04-12)
+
+General
+-------
+
+Release 1.7.0 is a backport of features and bug fixes new in
+this release. See earlier notes under Release 2.0.0/General.
+
+Bugs fixed
+----------
+
+* Fixed pthread_once potential for post once_routine cancellation
+hanging due to starvation. See comments in pthread_once.c.
+Momentary priority boosting is used to ensure that, after a
+once_routine is cancelled, the thread that will run the
+once_routine is not starved by higher priority waiting threads at
+critical times. Priority boosting occurs only AFTER a once_routine 
+cancellation, and is applied only to that once_control. The
+once_routine is run at the thread's normal base priority.
+
+New tests
+---------
+
+* once4.c: Aggressively tests pthread_once() under realtime
+conditions using threads with varying priorities. Windows'
+random priority boosting does not occur for threads with realtime
+priority levels.
+
+
+RELEASE 2.2.0
+-------------
+(2005-04-04)
+
+General
+-------
+
+* Added makefile targets to build static link versions of the library.
+Both MinGW and MSVC. Please note that this does not imply any change
+to the LGPL licensing, which still imposes psecific conditions on
+distributing software that has been statically linked with this library.
+
+* There is a known bug in pthread_once(). Cancellation of the init_routine
+exposes a potential starvation (i.e. deadlock) problem if a waiting thread
+has a higher priority than the initting thread. This problem will be fixed
+in version 3.0.0 of the library.
+
+Bugs fixed
+----------
+
+* Fix integer overrun error in sem_timedwait().
+Kevin Lussier
+
+* Fix preprocessor directives for static linking.
+Dimitar Panayotov
+
+
+RELEASE 2.1.0
+-------------
+(2005-03-16)
+
+Bugs fixed
+----------
+
+* Reverse change to pthread_setcancelstate() in 2.0.0.
+
+
+RELEASE 2.0.0
+-------------
+(2005-03-16)
+
+General
+-------
+
+This release represents an ABI change and the DLL version naming has
+incremented from 1 to 2, e.g. pthreadVC2.dll.
+
+Version 1.4.0 back-ports the new functionality included in this
+release. Please distribute DLLs built from that version with updates
+to applications built on pthreads-win32 version 1.x.x.
+
+The package naming has changed, replacing the snapshot date with 
+the version number + descriptive information. E.g. this
+release is "pthreads-w32-2-0-0-release".
+
+Bugs fixed
+----------
+
+* pthread_setcancelstate() no longer checks for a pending
+async cancel event if the library is using alertable async
+cancel. See the README file (Prerequisites section) for info
+on adding alertable async cancelation.
+
+New features
+------------
+
+* pthread_once() now supports init_routine cancellability.
+
+New tests
+---------
+
+* Agressively test pthread_once() init_routine cancellability.
+
+
+SNAPSHOT 2005-03-08
+-------------------
+Version 1.3.0
+
+Bug reports (fixed)
+-------------------
+
+* Implicitly created threads leave Win32 handles behind after exiting.
+- Dmitrii Semii
+
+* pthread_once() starvation problem.
+- Gottlob Frege
+
+New tests
+---------
+
+* More intense testing of pthread_once().
+
+
+SNAPSHOT 2005-01-25
+-------------------
+Version 1.2.0
+
+Bug fixes
+---------
+
+* Attempted acquisition of a recursive mutex could cause waiting threads
+to not be woken when the mutex was released.
+- Ralf Kubis  <RKubis at mc.com>
+
+* Various package omissions have been fixed.
+
+
+SNAPSHOT 2005-01-03
+-------------------
+Version 1.1.0
+
+Bug fixes
+---------
+
+* Unlocking recursive or errorcheck mutexes would sometimes
+unexpectedly return an EPERM error (bug introduced in
+snapshot-2004-11-03).
+- Konstantin Voronkov  <beowinkle at yahoo.com>
+
+
+SNAPSHOT 2004-11-22
+-------------------
+Version 1.0.0
+
+This snapshot primarily fixes the condvar bug introduced in
+snapshot-2004-11-03. DLL versioning has also been included to allow
+applications to runtime check the Microsoft compatible DLL version
+information, and to extend the DLL naming system for ABI and major
+(non-backward compatible) API changes. See the README file for details.
+
+Bug fixes
+---------
+
+* Condition variables no longer deadlock (bug introduced in
+snapshot-2004-11-03).
+- Alexander Kotliarov and Nicolas at saintmac
+
+* DLL naming extended to avoid 'DLL hell' in the future, and to
+accommodate the ABI change introduced in snapshot-2004-11-03. Snapshot
+2004-11-03 will be removed from FTP sites.
+
+New features
+------------
+
+* A Microsoft-style version resource has been added to the DLL for
+applications that wish to check DLL compatibility at runtime.
+
+* Pthreads-win32 DLL naming has been extended to allow incompatible DLL
+versions to co-exist in the same filesystem. See the README file for details,
+but briefly: while the version information inside the DLL will change with
+each release from now on, the DLL version names will only change if the new
+DLL is not backward compatible with older applications.
+
+The versioning scheme has been borrowed from GNU Libtool, and the DLL
+naming scheme is from Cygwin. Provided the Libtool-style numbering rules are
+honoured, the Cygwin DLL naming scheme automatcally ensures that DLL name
+changes are minimal and that applications will not load an incompatible
+pthreads-win32 DLL.
+
+Those who use the pre-built DLLs will find that the DLL/LIB names have a new
+suffix (1) in this snapshot. E.g. pthreadVC1.dll etc.
+
+* The POSIX thread ID reuse uniqueness feature introduced in the last snapshot
+has been kept as default, but the behaviour can now be controlled when the DLL
+is built to effectively switch it off. This makes the library much more
+sensitive to applications that assume that POSIX thread IDs are unique, i.e.
+are not strictly compliant with POSIX. See the PTW32_THREAD_ID_REUSE_INCREMENT
+macro comments in config.h for details.
+
+Other changes
+-------------
+Certain POSIX macros have changed.
+
+These changes are intended to conform to the Single Unix Specification version 3,
+which states that, if set to 0 (zero) or not defined, then applications may use
+sysconf() to determine their values at runtime. Pthreads-win32 does not
+implement sysconf().
+
+The following macros are no longer undefined, but defined and set to -1
+(not implemented):
+
+      _POSIX_THREAD_ATTR_STACKADDR
+      _POSIX_THREAD_PRIO_INHERIT
+      _POSIX_THREAD_PRIO_PROTECT
+      _POSIX_THREAD_PROCESS_SHARED
+
+The following macros are defined and set to 200112L (implemented):
+
+      _POSIX_THREADS
+      _POSIX_THREAD_SAFE_FUNCTIONS
+      _POSIX_THREAD_ATTR_STACKSIZE
+      _POSIX_THREAD_PRIORITY_SCHEDULING
+      _POSIX_SEMAPHORES
+      _POSIX_READER_WRITER_LOCKS
+      _POSIX_SPIN_LOCKS
+      _POSIX_BARRIERS
+
+The following macros are defined and set to appropriate values:
+
+      _POSIX_THREAD_THREADS_MAX
+      _POSIX_SEM_VALUE_MAX
+      _POSIX_SEM_NSEMS_MAX
+      PTHREAD_DESTRUCTOR_ITERATIONS
+      PTHREAD_KEYS_MAX
+      PTHREAD_STACK_MIN
+      PTHREAD_THREADS_MAX
+
+
+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
+-------------------
+
+Attempt to add Watcom to the list of compilers that can build the library.
+This failed in the end due to it's non-thread-aware errno. The library
+builds but the test suite fails. See README.Watcom for more details.
+
+Bug fixes
+---------
+* Bug and memory leak in sem_init()
+- Alex Blanco  <Alex.Blanco at motorola.com>
+
+* ptw32_getprocessors() now returns CPU count of 1 for WinCE.
+- James Ewing  <james.ewing at sveasoft.com>
+
+* pthread_cond_wait() could be canceled at a point where it should not
+be cancelable. Fixed.
+- Alexander Terekhov  <TEREKHOV at de.ibm.com>
+
+* sem_timedwait() had an incorrect timeout calculation.
+- Philippe Di Cristo  <philipped at voicebox.com>
+
+* Fix a memory leak left behind after threads are destroyed.
+- P. van Bruggen  <pietvb at newbridges.nl>
+
+New features
+------------
+* Ported to AMD64.
+- Makoto Kato  <raven at oldskool.jp>
+
+* True pre-emptive asynchronous cancelation of threads. This is optional
+and requires that Panagiotis E. Hadjidoukas's QueueUserAPCEx package be
+installed. This package is included in the pthreads-win32 self-unpacking
+Zip archive starting from this snapshot. See the README.txt file inside
+the package for installation details.
+
+Note: If you don't use async cancelation in your application, or don't need
+to cancel threads that are blocked on system resources such as network I/O,
+then the default non-preemptive async cancelation is probably good enough.
+However, pthreads-win32 auto-detects the availability of these components
+at run-time, so you don't need to rebuild the library from source if you
+change your mind later.
+
+All of the advice available in books and elsewhere on the undesirability
+of using async cancelation in any application still stands, but this
+feature is a welcome addition with respect to the library's conformance to
+the POSIX standard.
+
+SNAPSHOT 2003-09-18
+-------------------
+
+Cleanup of thread priority management. In particular, setting of thread
+priority now attempts to map invalid Win32 values within the range returned
+by sched_get_priority_min/max() to useful values. See README.NONPORTABLE
+under "Thread priority".
+
+Bug fixes
+---------
+* pthread_getschedparam() now returns the priority given by the most recent
+call to pthread_setschedparam() or established by pthread_create(), as
+required by the standard. Previously, pthread_getschedparam() incorrectly
+returned the running thread priority at the time of the call, which may have
+been adjusted or temporarily promoted/demoted.
+
+* sched_get_priority_min() and sched_get_priority_max() now return -1 on error
+and set errno. Previously, they incorrectly returned the error value directly.
+
+
+SNAPSHOT 2003-09-04
+-------------------
+
+Bug fixes
+---------
+* ptw32_cancelableWait() now allows cancelation of waiting implicit POSIX
+threads.
+
+New test
+--------
+* cancel8.c tests cancelation of Win32 threads waiting at a POSIX cancelation
+point.
+
+
+SNAPSHOT 2003-09-03
+-------------------
+
+Bug fixes
+---------
+* pthread_self() would free the newly created implicit POSIX thread handle if
+DuplicateHandle failed instead of recycle it (very unlikely).
+
+* pthread_exit() was neither freeing nor recycling the POSIX thread struct
+for implicit POSIX threads.
+
+New feature - Cancelation of/by Win32 (non-POSIX) threads
+---------------------------------------------------------
+Since John Bossom's original implementation, the library has allowed non-POSIX
+initialised threads (Win32 threads) to call pthreads-win32 routines and
+therefore interact with POSIX threads. This is done by creating an on-the-fly
+POSIX thread ID for the Win32 thread that, once created, allows fully
+reciprical interaction. This did not extend to thread cancelation (async or
+deferred). Now it does.
+
+Any thread can be canceled by any other thread (Win32 or POSIX) if the former
+thread's POSIX pthread_t value is known. It's TSD destructors and POSIX
+cleanup handlers will be run before the thread exits with an exit code of
+PTHREAD_CANCELED (retrieved with GetExitCodeThread()).
+
+This allows a Win32 thread to, for example, call POSIX CV routines in the same way
+that POSIX threads would/should, with pthread_cond_wait() cancelability and
+cleanup handlers (pthread_cond_wait() is a POSIX cancelation point).
+
+By adding cancelation, Win32 threads should now be able to call all POSIX
+threads routines that make sense including semaphores, mutexes, condition
+variables, read/write locks, barriers, spinlocks, tsd, cleanup push/pop,
+cancelation, pthread_exit, scheduling, etc.
+
+Note that these on-the-fly 'implicit' POSIX thread IDs are initialised as detached
+(not joinable) with deferred cancelation type. The POSIX thread ID will be created
+automatically by any POSIX routines that need a POSIX handle (unless the routine
+needs a pthread_t as a parameter of course). A Win32 thread can discover it's own
+POSIX thread ID by calling pthread_self(), which will create the handle if
+necessary and return the pthread_t value.
+
+New tests
+---------
+Test the above new feature.
+
+
+SNAPSHOT 2003-08-19
+-------------------
+
+This snapshot fixes some accidental corruption to new test case sources.
+There are no changes to the library source code.
+
+
+SNAPSHOT 2003-08-15
+-------------------
+
+Bug fixes
+---------
+
+* pthread.dsp now uses correct compile flags (/MD).
+- Viv  <vcotirlea@hotmail.com>
+
+* pthread_win32_process_detach_np() fixed memory leak.
+- Steven Reddie  <Steven.Reddie@ca.com>
+
+* pthread_mutex_destroy() fixed incorrect return code.
+- Nicolas Barry  <boozai@yahoo.com>
+
+* pthread_spin_destroy() fixed memory leak.
+- Piet van Bruggen  <pietvb@newbridges.nl>
+
+* Various changes to tighten arg checking, and to work with later versions of
+MinGW32 and MsysDTK.
+
+* pthread_getschedparam() etc, fixed dangerous thread validity checking.
+- Nicolas Barry  <boozai@yahoo.com>
+
+* POSIX thread handles are now reused and their memory is not freed on thread exit.
+This allows for stronger thread validity checking.
+
+New standard routine
+--------------------
+
+* pthread_kill() added to provide thread validity checking to applications.
+It does not accept any non zero values for the signal arg.
+
+New test cases
+--------------
+
+* New test cases to confirm validity checking, pthread_kill(), and thread reuse.
+
+
+SNAPSHOT 2003-05-10
+-------------------
+
+Bug fixes
+---------
+
+* pthread_mutex_trylock() now returns correct error values.
+pthread_mutex_destroy() will no longer destroy a recursively locked mutex.
+pthread_mutex_lock() is no longer inadvertantly behaving as a cancelation point.
+- Thomas Pfaff  <tpfaff@gmx.net>
+
+* pthread_mutex_timedlock() no longer occasionally sets incorrect mutex
+ownership, causing deadlocks in some applications.
+- Robert Strycek <strycek@posam.sk> and Alexander Terekhov  <TEREKHOV@de.ibm.com>
+
+
+SNAPSHOT 2002-11-04
+-------------------
+
+Bug fixes
+---------
+
+* sem_getvalue() now returns the correct value under Win NT and WinCE.
+- Rob Fanner  <rfanner@stonethree.com>
+
+* sem_timedwait() now uses tighter checks for unreasonable
+abstime values - that would result in unexpected timeout values.
+
+* ptw32_cond_wait_cleanup() no longer mysteriously consumes
+CV signals but may produce more spurious wakeups. It is believed
+that the sem_timedwait() call is consuming a CV signal that it
+shouldn't.
+- Alexander Terekhov  <TEREKHOV@de.ibm.com>
+
+* Fixed a memory leak in ptw32_threadDestroy() for implicit threads.
+
+* Fixed potential for deadlock in pthread_cond_destroy().
+A deadlock could occur for statically declared CVs (PTHREAD_COND_INITIALIZER),
+when one thread is attempting to destroy the condition variable while another
+is attempting to dynamically initialize it.
+- Michael Johnson  <michaelj@maine.rr.com>
+
+
+SNAPSHOT 2002-03-02
+-------------------
+
+Cleanup code default style. (IMPORTANT)
+----------------------------------------------------------------------
+Previously, if not defined, the cleanup style was determined automatically
+from the compiler/language, 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 and future snapshots, 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
+current commercial Unix POSIX threads implementations. Compaq's TRU64
+may be an exception (no pun intended) and possible future trend.
+
+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
+
+E.g. regardless of whether your app is C or C++, if you link with
+pthreadVC.lib or libpthreadGC.a, then you must define __CLEANUP_C.
+
+
+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 and not explicitly defining one of __CLEANUP_*, then
+__CLEANUP_C++ was automatically 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
+automatically 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.
+
+
+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, for unconditional conformity to other implementations.)
+- 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.
+
+
+Source module splitting
+-----------------------
+In order to enable smaller image sizes to be generated
+for applications that link statically with the library,
+most routines have been separated out into individual
+source code files.
+
+This is being done in such a way as to be backward compatible.
+The old source files are reused to congregate the individual
+routine files into larger translation units (via a bunch of
+# includes) so that the compiler can still optimise wherever
+possible, e.g. through inlining, which can only be done
+within the same translation unit.
+
+It is also possible to build the entire library by compiling
+the single file named "pthread.c", which just #includes all
+the secondary congregation source files. The compiler
+may be able to use this to do more inlining of routines.
+
+Although the GNU compiler is able to produce libraries with
+the necessary separation (the -ffunction-segments switch),
+AFAIK, the MSVC and other compilers don't have this feature.
+
+Finally, since I use makefiles and command-line compilation,
+I don't know what havoc this reorganisation may wreak amongst
+IDE project file users. You should be able to continue
+using your existing project files without modification.
+
+
+New non-portable functions
+--------------------------
+pthread_num_processors_np():
+  Returns the number of processors in the system that are
+  available to the process, as determined from the processor
+  affinity mask.
+
+pthread_timechange_handler_np():
+  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.
+  - Suggested by Alexander Terekhov
+
+
+Platform dependence
+-------------------
+As Win95 doesn't provide one, the library now contains
+it's own InterlockedCompareExchange() routine, which is used
+whenever Windows doesn't provide it. InterlockedCompareExchange()
+is used to implement spinlocks and barriers, and also in mutexes.
+This routine relies on the CMPXCHG machine instruction which
+is not available on i386 CPUs. This library (from snapshot
+20010712 onwards) is therefore no longer supported on i386
+processor platforms.
+
+
+New standard routines
+---------------------
+For source code portability only - rwlocks cannot be process shared yet.
+
+        pthread_rwlockattr_init()
+        pthread_rwlockattr_destroy()
+        pthread_rwlockattr_setpshared()
+        pthread_rwlockattr_getpshared()
+
+As defined in the new POSIX standard, and the Single Unix Spec version 3:
+
+        sem_timedwait()
+        pthread_mutex_timedlock()    - Alexander Terekhov and Thomas Pfaff
+        pthread_rwlock_timedrdlock() - adapted from pthread_rwlock_rdlock()
+        pthread_rwlock_timedwrlock() - adapted from pthread_rwlock_wrlock()
+
+
+pthread.h no longer includes windows.h
+--------------------------------------
+[Not yet for G++]
+
+This was done to prevent conflicts.
+
+HANDLE, DWORD, and NULL are temporarily defined within pthread.h if
+they are not already.
+
+
+pthread.h, sched.h and semaphore.h now use dllexport/dllimport
+--------------------------------------------------------------
+Not only to avoid the need for the pthread.def file, but to
+improve performance. Apparently, declaring functions with dllimport
+generates a direct call to the function and avoids the overhead
+of a stub function call.
+
+Bug fixes
+---------
+* Fixed potential NULL pointer dereferences in pthread_mutexattr_init,
+pthread_mutexattr_getpshared, pthread_barrierattr_init,
+pthread_barrierattr_getpshared, and pthread_condattr_getpshared.
+- Scott McCaskill <scott@magruder.org>
+
+* Removed potential race condition in pthread_mutex_trylock and
+pthread_mutex_lock;
+- Alexander Terekhov <TEREKHOV@de.ibm.com>
+
+* The behaviour of pthread_mutex_trylock in relation to
+recursive mutexes was inconsistent with commercial implementations.
+Trylock would return EBUSY if the lock was owned already by the
+calling thread regardless of mutex type. Trylock now increments the
+recursion count and returns 0 for RECURSIVE mutexes, and will
+return EDEADLK rather than EBUSY for ERRORCHECK mutexes. This is
+consistent with Solaris.
+- Thomas Pfaff <tpfaff@gmx.net>
+
+* Found a fix for the library and workaround for applications for
+the known bug #2, i.e. where __CLEANUP_CXX or __CLEANUP_SEH is defined.
+See the "Known Bugs in this snapshot" section below.
+
+This could be made transparent to applications by replacing the macros that
+define the current C++ and SEH versions of pthread_cleanup_push/pop
+with the C version, but AFAIK cleanup handlers would not then run in the
+correct sequence with destructors and exception cleanup handlers when
+an exception occurs.
+
+* Cancelation once started in a thread cannot now be inadvertantly
+double canceled. That is, once a thread begins it's cancelation run,
+cancelation is disabled and a subsequent cancel request will
+return an error (ESRCH).
+
+* errno: An incorrect compiler directive caused a local version
+of errno to be used instead of the Win32 errno. Both instances are
+thread-safe but applications checking errno after a pthreads-win32
+call would be wrong. Fixing this also fixed a bad compiler
+option in the testsuite (/MT should have been /MD) which is
+needed to link with the correct library MSVCRT.LIB.
+
+
+SNAPSHOT 2001-07-12
+-------------------
+
+To be added
+
+
+SNAPSHOT 2001-07-03
+-------------------
+
+To be added
+
+
+SNAPSHOT 2000-08-13
+-------------------
+
+New:
+-       Renamed DLL and LIB files:
+                pthreadVSE.dll  (MS VC++/Structured EH)
+                pthreadVSE.lib
+                pthreadVCE.dll  (MS VC++/C++ EH)
+                pthreadVCE.lib
+                pthreadGCE.dll  (GNU G++/C++ EH)
+                libpthreadw32.a
+
+        Both your application and the pthread dll should use the
+        same exception handling scheme.
+
+Bugs fixed:
+-       MSVC++ C++ exception handling.
+
+Some new tests have been added.
+
+
+SNAPSHOT 2000-08-10
+-------------------
+
+New:
+-       asynchronous cancelation on X86 (Jason Nye)
+-       Makefile compatible with MS nmake to replace
+        buildlib.bat
+-       GNUmakefile for Mingw32
+-       tests/Makefile for MS nmake replaces runall.bat
+-       tests/GNUmakefile for Mingw32
+
+Bugs fixed:
+-       kernel32 load/free problem
+-       attempt to hide internel exceptions from application
+        exception handlers (__try/__except and try/catch blocks)
+-       Win32 thread handle leakage bug
+        (David Baggett/Paul Redondo/Eyal Lebedinsky)
+
+Some new tests have been added.
+
+
+SNAPSHOT 1999-11-02
+-------------------
+
+Bugs fixed:
+-       ctime_r macro had an incorrect argument (Erik Hensema),
+-       threads were not being created 
+        PTHREAD_CANCEL_DEFERRED. This should have
+        had little effect as deferred is the only
+        supported type. (Ross Johnson).
+
+Some compatibility improvements added, eg.
+-       pthread_setcancelstate accepts NULL pointer
+        for the previous value argument. Ditto for
+        pthread_setcanceltype. This is compatible
+        with Solaris but should not affect
+        standard applications (Erik Hensema)
+
+Some new tests have been added.
+
+
+SNAPSHOT 1999-10-17
+-------------------
+
+Bug fix - Cancelation of threads waiting on condition variables
+now works properly (Lorin Hochstein and Peter Slacik)
+
+
+SNAPSHOT 1999-08-12
+-------------------
+
+Fixed exception stack cleanup if calling pthread_exit()
+- (Lorin Hochstein and John Bossom).
+
+Fixed bugs in condition variables - (Peter Slacik):
+        - additional contention checks
+        - properly adjust number of waiting threads after timed
+          condvar timeout.
+
+
+SNAPSHOT 1999-05-30
+-------------------
+
+Some minor bugs have been fixed. See the ChangeLog file for details.
+
+Some more POSIX 1b functions are now included but ony return an
+error (ENOSYS) if called. They are:
+
+        sem_open
+        sem_close
+        sem_unlink
+        sem_getvalue
+
+
+SNAPSHOT 1999-04-07
+-------------------
+
+Some POSIX 1b functions which were internally supported are now
+available as exported functions:
+
+        sem_init
+        sem_destroy
+        sem_wait
+        sem_trywait
+        sem_post
+        sched_yield
+        sched_get_priority_min
+        sched_get_priority_max
+
+Some minor bugs have been fixed. See the ChangeLog file for details.
+
+
+SNAPSHOT 1999-03-16
+-------------------
+
+Initial release.
+
diff --git a/Nmakefile b/Nmakefile
new file mode 100644
index 0000000..e6c74dd
--- /dev/null
+++ b/Nmakefile
@@ -0,0 +1,24 @@
+/*
+ * nmake file for uwin pthread library
+ */
+
+VERSION 		= -
+CCFLAGS 		= -V -g $(CC.DLL)
+HAVE_CONFIG_H	== 1
+_MT			== 1
+_timeb		== timeb
+_ftime		== ftime
+_errno		== _ast_errno
+
+$(INCLUDEDIR)	:INSTALLDIR:	pthread.h sched.h
+
+pthread $(VERSION) :LIBRARY: attr.c barrier.c cancel.c cleanup.c condvar.c \
+	create.c dll.c exit.c fork.c global.c misc.c mutex.c private.c \
+	rwlock.c sched.c semaphore.c spin.c sync.c tsd.c nonportable.c
+
+:: ANNOUNCE CONTRIBUTORS COPYING.LIB ChangeLog FAQ GNUmakefile MAINTAINERS \
+	Makefile Makefile.in Makefile.vc NEWS PROGRESS README README.WinCE \
+	TODO WinCE-PORT install-sh errno.c tests tests.mk acconfig.h \
+	config.guess config.h.in config.sub configure configure.in signal.c \
+	README.CV README.NONPORTABLE pthread.dsp pthread.dsw
+
diff --git a/Nmakefile.tests b/Nmakefile.tests
new file mode 100644
index 0000000..203560b
--- /dev/null
+++ b/Nmakefile.tests
@@ -0,0 +1,260 @@
+/* for running tests */
+CCFLAGS 	= -g 
+_MT		== 1
+_timeb	== timeb
+_ftime	== ftime 
+
+.SOURCE:	tests
+/*
+:PACKAGE:	pthread
+*/
+
+set keepgoing
+
+":test:" : .MAKE .OPERATOR
+	local I
+	$(<:D:B:S=.pass) : .IMPLICIT $(>:D:B:S=.pass)
+	for I $(<) $(>)
+		$(I:D:B:S=.pass) : .VIRTUAL .FORCE $(I)
+			$(>)
+	end
+sizes::		sizes.c
+loadfree::	loadfree.c
+mutex1::	mutex1.c
+mutex1e::	mutex1e.c
+mutex1n::	mutex1n.c
+mutex1r::	mutex1r.c
+mutex2::	mutex2.c
+mutex2r::	mutex2r.c
+mutex2e::	mutex2e.c
+exit1::	exit1.c
+condvar1::	condvar1.c
+condvar1_1::	condvar1_1.c
+condvar1_2::	condvar1_2.c
+self1::		self1.c
+condvar2::	condvar2.c
+condvar2_1::	condvar2_1.c
+condvar3_1::	condvar3_1.c
+condvar3_2::	condvar3_2.c
+condvar3_3::	condvar3_3.c
+create1.::	create1.c
+create2.::	create2.c
+cancel1::	cancel1.c
+cancel2::	cancel2.c
+mutex3::	mutex3.c
+mutex3r::	mutex3r.c
+mutex3e::	mutex3e.c
+mutex4::	mutex4.c
+mutex5::	mutex5.c
+mutex6::	mutex6.c
+mutex6e::	mutex6e.c
+mutex6n::	mutex6n.c
+mutex6r::	mutex6r.c
+mutex7::	mutex7.c
+mutex6s::	mutex6s.c
+mutex6rs::	mutex6rs.c
+mutex6es::	mutex6es.c
+mutex7e::	mutex7e.c
+mutex7n::	mutex7n.c
+mutex7r::	mutex7r.c
+mutex8::	mutex8.c
+mutex8e::	mutex8e.c
+mutex8n::	mutex8n.c
+mutex8r::	mutex8r.c
+equal1::	equal1.c
+exit2::		exit2.c
+exit3::		exit3.c
+exit4::		exit4.c
+exit5::		exit5.c
+join0::		join0.c
+join1::		join1.c
+join2::		join2.c
+join3::		join3.c
+kill1::		kill1.c
+count1::	count1.c
+once1::		once1.c
+tsd1::		tsd1.c
+self2::		self2.c
+eyal1::		eyal1.c
+condvar3::	condvar3.c
+condvar4::	condvar4.c
+condvar5::	condvar5.c
+condvar6::	condvar6.c
+condvar7::	condvar7.c
+condvar8::	condvar8.c
+condvar9::	condvar9.c
+errno1::	errno1.c
+reuse1.::	reuse1.c
+reuse2.::	reuse2.c
+rwlock1::	rwlock1.c
+rwlock2::	rwlock2.c
+rwlock3::	rwlock3.c
+rwlock4::	rwlock4.c
+rwlock5::	rwlock5.c
+rwlock6::	rwlock6.c
+rwlock7::	rwlock7.c
+rwlock8::	rwlock8.c
+rwlock2_t::	rwlock2_t.c
+rwlock3_t::	rwlock3_t.c
+rwlock4_t::	rwlock4_t.c
+rwlock5_t::	rwlock5_t.c
+rwlock6_t::	rwlock6_t.c
+rwlock6_t2::	rwlock6_t2.c
+semaphore1::	semaphore1.c
+semaphore2::	semaphore2.c
+semaphore3::	semaphore3.c
+context1::	context1.c
+cancel3::	cancel3.c
+cancel4::	cancel4.c
+cancel5::	cancel5.c
+cancel6a::	cancel6a.c
+cancel6d::	cancel6d.c
+cancel7::	cancel7.c
+cleanup0::	cleanup0.c
+cleanup1::	cleanup1.c
+cleanup2::	cleanup2.c
+cleanup3::	cleanup3.c
+priority1::     priority1.c
+priority2::     priority2.c
+inherit1::      inherit1.c
+spin1::         spin1.c
+spin2::         spin2.c
+spin3::         spin3.c
+spin4::         spin4.c
+barrier1::      barrier1.c
+barrier2::      barrier2.c
+barrier3::      barrier3.c
+barrier4::      barrier4.c
+barrier5::      barrier5.c
+exception1::	exception1.c
+exception2::	exception2.c
+exception3::	exception3.c
+benchtest1::    benchtest1.c
+benchtest2::    benchtest2.c
+benchtest3::    benchtest3.c
+benchtest4::    benchtest4.c
+benchtest5::    benchtest5.c
+valid1::	valid1.c
+valid2::	valid2.c
+cancel9::	cancel9.c
+
+sizes:		:test:	sizes
+loadfree:	:test:
+mutex5		:test:	loadfree
+mutex1		:test:	loadfree
+mutex1n		:test:	loadfree
+mutex1r		:test:	loadfree
+mutex1e		:test:	loadfree
+semaphore1	:test:	loadfree
+semaphore2	:test:	loadfree
+semaphore3	:test:	loadfree
+mutex2		:test:	loadfree
+mutex2r		:test:	loadfree
+mutex2e		:test:	loadfree
+exit1		:test:	loadfree
+condvar1	:test:	loadfree
+kill1		:test:	loadfree
+condvar1_1	:test:	condvar1
+condvar1_2	:test:	join2
+self1		:test:	loadfree
+condvar2	:test:	condvar1
+condvar2_1	:test:	condvar2
+create1 	:test:	mutex2
+create2 	:test:	create1
+reuse1 		:test:	create2
+reuse2 		:test:	reuse1
+cancel1		:test:	create1
+cancel2		:test:	cancel1
+mutex3		:test:	create1
+mutex3r		:test:	create1
+mutex3e		:test:	create1
+mutex4		:test:	mutex3
+mutex6		:test:	mutex4
+mutex6n		:test:	mutex4
+mutex6e		:test:	mutex4
+mutex6r		:test:	mutex4
+mutex6s		:test:	mutex6
+mutex6rs	:test:	mutex6r
+mutex6es	:test:	mutex6e
+mutex7		:test:	mutex6
+mutex7n		:test:	mutex6n
+mutex7e		:test:	mutex6e
+mutex7r		:test:	mutex6r
+mutex8		:test:	mutex7
+mutex8n		:test:	mutex7n
+mutex8e		:test:	mutex7e
+mutex8r		:test:	mutex7r
+equal1		:test:	create1
+exit2		:test:	create1
+exit3		:test:	create1
+exit4		:test:	kill1
+exit5		:test:	exit4
+join0		:test:	create1
+join1		:test:	create1
+join2		:test:	create1
+join3		:test:	join2
+count1		:test:	join1
+once1		:test:	create1
+tsd1		:test:	join1
+self2		:test:	create1
+eyal1		:test:	tsd1
+condvar3	:test:	create1
+condvar3_1	:test:	condvar3
+condvar3_2	:test:	condvar3_1
+condvar3_3	:test:	condvar3_2
+condvar4	:test:	create1
+condvar5	:test:	condvar4
+condvar6	:test:	condvar5
+condvar7	:test:	condvar6	cleanup1
+condvar8	:test:	condvar7
+condvar9	:test:	condvar8
+errno1		:test:	mutex3
+rwlock1		:test:	condvar6
+rwlock2		:test:	rwlock1
+rwlock3		:test:	rwlock2
+rwlock4		:test:	rwlock3
+rwlock5		:test:	rwlock4
+rwlock6		:test:	rwlock5
+rwlock7		:test:	rwlock6
+rwlock8		:test:	rwlock7
+rwlock2_t	:test:	rwlock2
+rwlock3_t	:test:	rwlock2_t
+rwlock4_t	:test:	rwlock3_t
+rwlock5_t	:test:	rwlock4_t
+rwlock6_t	:test:	rwlock5_t
+rwlock6_t2	:test:	rwlock6_t
+context1	:test:	cancel2
+cancel3		:test:	context1
+cancel4		:test:	cancel3
+cancel5		:test:	cancel3
+cancel6a	:test:	cancel3
+cancel6d	:test:	cancel3
+cancel7		:test:	kill1
+cleanup0	:test:	cancel5
+cleanup1	:test:	cleanup0
+cleanup2	:test:	cleanup1
+cleanup3	:test:	cleanup2
+priority1       :test:  join1
+priority2       :test:  priority1
+inherit1        :test:  join1
+spin1           :test:
+spin2           :test:  spin1.c
+spin3           :test:  spin2.c
+spin4           :test:  spin3.c
+barrier1        :test:
+barrier2        :test:  barrier1.c
+barrier3        :test:  barrier2.c
+barrier4        :test:  barrier3.c
+barrier5        :test:  barrier4.c
+benchtest1      :test:  mutex3
+benchtest2      :test:  benchtest1
+benchtest3      :test:  benchtest2
+benchtest4      :test:  benchtest3
+benchtest5      :test:  benchtest4
+exception1	:test:	cancel4
+exception2	:test:	exception1
+exception3	:test:	exception2
+exit4		:test:	exit3
+valid1		:test:	join1
+valid2		:test:	valid1
+cancel9		:test:	cancel8
diff --git a/PROGRESS b/PROGRESS
new file mode 100644
index 0000000..9abf0bc
--- /dev/null
+++ b/PROGRESS
@@ -0,0 +1,4 @@
+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
new file mode 100644
index 0000000..5649333
--- /dev/null
+++ b/README
@@ -0,0 +1,593 @@
+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 can async cancel only threads that
+	are runnable. The simulated async cancellation cannot cancel 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 was to also name either the VC or GC
+version (it should be arbitrary) as pthread.dll, including
+pthread.lib and libpthread.a as appropriate. This is no longer
+likely to happen.
+
+Note 4: the compatibility number was added so that applications
+can differentiate between binary incompatible versions of the
+libs and dlls.
+
+In general:
+	pthread[VG]{SE,CE,C}c.dll
+	pthread[VG]{SE,CE,C}c.lib
+
+where:
+	[VG] indicates the compiler
+	V	- MS VC, or
+	G	- GNU C
+
+	{SE,CE,C} indicates the exception handling scheme
+	SE	- Structured EH, or
+	CE	- C++ EH, or
+	C	- no exceptions - uses setjmp/longjmp
+
+	c	- DLL compatibility number indicating ABI and API
+		  compatibility with applications built against
+		  any snapshot with the same compatibility number.
+		  See 'Version numbering' below.
+
+The name may also be suffixed by a 'd' to indicate a debugging version
+of the library. E.g. pthreadVC2d.lib. Debugging versions contain
+additional information for debugging (symbols etc) and are often not
+optimised in any way (compiled with optimisation turned off).
+
+For example:
+	pthreadVSE.dll	(MSVC/SEH)
+	pthreadGCE.dll	(GNUC/C++ EH)
+	pthreadGC.dll	(GNUC/not dependent on exceptions)
+	pthreadVC1.dll	(MSVC/not dependent on exceptions - not binary
+			compatible with pthreadVC.dll)
+	pthreadVC2.dll	(MSVC/not dependent on exceptions - not binary
+			compatible with pthreadVC1.dll or pthreadVC.dll)
+
+The GNU library archive file names have correspondingly changed to:
+
+	libpthreadGCEc.a
+	libpthreadGCc.a
+
+
+Versioning numbering
+--------------------
+
+Version numbering is separate from the snapshot dating system, and
+is the canonical version identification system embedded within the
+DLL using the Microsoft version resource system. The versioning
+system chosen follows the GNU Libtool system. See
+http://www.gnu.org/software/libtool/manual.html section 6.2.
+
+See the resource file 'version.rc'.
+
+Microsoft version numbers use 4 integers:
+
+	0.0.0.0
+
+Pthreads-win32 uses the first 3 following the Libtool convention.
+The fourth is commonly used for the build number, but will be reserved
+for future use.
+
+	current.revision.age.0
+
+The numbers are changed as follows:
+
+1. If the library source code has changed at all since the last update,
+   then increment revision (`c:r:a' becomes `c:r+1:a').
+2. If any interfaces have been added, removed, or changed since the last
+   update, increment current, and set revision to 0.
+3. If any interfaces have been added since the last public release, then
+   increment age.
+4. If any interfaces have been removed or changed since the last public
+   release, then set age to 0.
+
+
+DLL compatibility numbering is an attempt to ensure that applications
+always load a compatible pthreads-win32 DLL by using a DLL naming system
+that is consistent with the version numbering system. It also allows
+older and newer DLLs to coexist in the same filesystem so that older
+applications can continue to be used. For pre .NET Windows systems,
+this inevitably requires incompatible versions of the same DLLs to have
+different names.
+
+Pthreads-win32 has adopted the Cygwin convention of appending a single
+integer number to the DLL name. The number used is based on the library
+version number and is computed as 'current' - 'age'.
+
+(See http://home.att.net/~perlspinr/libversioning.html for a nicely
+detailed explanation.)
+
+Using this method, DLL name/s will only change when the DLL's
+backwards compatibility changes. Note that the addition of new
+'interfaces' will not of itself change the DLL's compatibility for older
+applications.
+
+
+Which of the several dll versions to use?
+-----------------------------------------
+or,
+---
+What are all these pthread*.dll and pthread*.lib files?
+-------------------------------------------------------
+
+Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you
+use MSVC - where 'v' is the DLL versioning (compatibility) number.
+
+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 nmake without any arguments to list
+help information. E.g.
+
+$ nmake
+
+Microsoft (R) Program Maintenance Utility   Version 6.00.8168.0
+Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
+
+Run one of the following command lines:
+nmake clean VCE (to build the MSVC dll with C++ exception handling)
+nmake clean VSE (to build the MSVC dll with structured exception handling)
+nmake clean VC (to build the MSVC dll with C cleanup code)
+nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling)
+nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling)
+nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code)
+nmake clean VC-static (to build the MSVC static lib with C cleanup code)
+nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling)
+nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling)
+nmake clean VC-debug (to build the debug MSVC dll with C cleanup code)
+nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling)
+nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling)
+nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code)
+nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code)
+
+
+The pre-built dlls are normally built using the *-inlined targets.
+
+You can run the testsuite by changing to the "tests" directory and
+running nmake. E.g.:
+
+$ cd tests
+$ nmake
+
+Microsoft (R) Program Maintenance Utility   Version 6.00.8168.0
+Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
+
+Run one of the following command lines:
+nmake clean VC (to test using VC dll with VC (no EH) applications)
+nmake clean VCX (to test using VC dll with VC++ (EH) applications)
+nmake clean VCE (to test using the VCE dll with VC++ EH applications)
+nmake clean VSE (to test using VSE dll with VC (SEH) applications)
+nmake clean VC-bench (to benchtest using VC dll with C bench app)
+nmake clean VCX-bench (to benchtest using VC dll with C++ bench app)
+nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app)
+nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app)
+nmake clean VC-static (to test using VC static lib with VC (no 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 for help information. E.g.:
+
+$ make
+Run one of the following command lines:
+make clean GC            (to build the GNU C dll with C cleanup code)
+make clean GCE           (to build the GNU C dll with C++ exception handling)
+make clean GC-inlined    (to build the GNU C inlined dll with C cleanup code)
+make clean GCE-inlined   (to build the GNU C inlined dll with C++ exception handling)
+make clean GC-static     (to build the GNU C inlined static lib with C cleanup code)
+make clean GC-debug      (to build the GNU C debug dll with C cleanup code)
+make clean GCE-debug     (to build the GNU C debug dll with C++ exception handling)
+make clean GC-inlined-debug    (to build the GNU C inlined debug dll with C cleanup code)
+make clean GCE-inlined-debug   (to build the GNU C inlined debug dll with C++ exception handling)
+make clean GC-static-debug     (to build the GNU C inlined static debug lib with C cleanup code)
+
+
+The pre-built dlls are normally built using the *-inlined targets.
+
+You can run the testsuite by changing to the "tests" directory and
+running make for help information. E.g.:
+
+$ cd tests
+$ make
+Run one of the following command lines:
+make clean GC    (to test using GC dll with C (no EH) applications)
+make clean GCX   (to test using GC dll with C++ (EH) applications)
+make clean GCE   (to test using GCE dll with C++ (EH) applications)
+make clean GC-bench       (to benchtest using GNU C dll with C cleanup code)
+make clean GCE-bench   (to benchtest using GNU C dll with C++ exception handling)
+make clean GC-static   (to test using GC static lib with C (no EH) applications)
+
+
+Building under Linux using the Mingw32 cross development tools
+--------------------------------------------------------------
+
+You can build the library without leaving Linux by using the Mingw32 cross
+development toolchain. See http://www.libsdl.org/extras/win32/cross/ for
+tools and info. The GNUmakefile contains some support for this, for example:
+
+make CROSS=i386-mingw32msvc- clean GC-inlined
+
+will build pthreadGCn.dll and libpthreadGCn.a (n=version#), provided your
+cross-tools/bin directory is in your PATH (or use the cross-make.sh script
+at the URL above).
+
+
+Building the library as a statically linkable library
+-----------------------------------------------------
+
+General: PTW32_STATIC_LIB must be defined for both the library build and the
+application build. The makefiles supplied and used by the following 'make'
+command lines will define this for you.
+
+MSVC (creates pthreadVCn.lib as a static link lib):
+
+nmake clean VC-static
+
+
+MinGW32 (creates libpthreadGCn.a as a static link lib):
+
+make clean GC-static
+
+
+Define PTW32_STATIC_LIB when building your application. Also, your
+application must call a two non-portable routines to initialise the
+some state on startup and cleanup before exit. One other routine needs
+to be called to cleanup after any Win32 threads have called POSIX API
+routines. See README.NONPORTABLE or the html reference manual pages for
+details on these routines:
+
+BOOL pthread_win32_process_attach_np (void);
+BOOL pthread_win32_process_detach_np (void);
+BOOL pthread_win32_thread_attach_np (void); // Currently a no-op
+BOOL pthread_win32_thread_detach_np (void);
+
+
+The tests makefiles have the same targets but only check that the
+static library is statically linkable. They don't run the full
+testsuite. To run the full testsuite, build the dlls and run the
+dll test targets.
+
+
+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.Borland b/README.Borland
new file mode 100644
index 0000000..a130d2b
--- /dev/null
+++ b/README.Borland
@@ -0,0 +1,57 @@
+In ptw32_InterlockedCompareExchange.c, I've added a section for
+Borland's compiler; it's identical to that for the MS compiler except
+that it uses /* ... */ comments instead of ; comments.
+
+[RPJ: need to define HAVE_TASM32 in config.h to use the above.]
+
+
+The other file is a makefile suitable for use with Borland's compiler
+(run "make -fBmakefile" in the directory).  It builds a single version
+of the library, pthreadBC.dll and the corresponding pthreadBC.lib
+import library, which is comparable to the pthreadVC version; I can't
+personally see any demand for the versions that include structured or
+C++ exception cancellation handling so I haven't attempted to build
+those versions of the library.  (I imagine a static version might be
+of use to some, but we can't legally use that on my commercial
+projects so I can't try that out, unfortunately.)
+
+[RPJ: Added tests\Bmakefile as well.]
+
+Borland C++ doesn't define the ENOSYS constant used by pthreads-win32;
+rather than make more extensive patches to the pthreads-win32 source I
+have a mostly-arbitrary constant for it in the makefile.  However this
+doesn't make it visible to the application using the library, so if
+anyone actually wants to use this constant in their apps (why?)
+someone might like to make a seperate NEED_BCC_something define to add
+this stuff.
+
+The makefile also #defines EDEADLK as EDEADLOCK, _timeb as timeb, and
+_ftime as ftime, to deal with the minor differences between the two
+RTLs' naming conventions, and sets the compiler flags as required to
+get a normal compile of the library.
+
+[RPJ: Moved errno values and _timeb etc to pthread.h, so apps will also
+use them.]
+
+(While I'm on the subject, the reason Borland users should recompile
+the library, rather than using the impdef/implib technique suggested
+previously on the mailing list, is that a) the errno constants are
+different, so the results returned by the pthread_* functions can be
+meaningless, and b) the errno variable/pseudo-variable itself is
+different in the MS & BCC runtimes, so you can't access the
+pthreadVC's errno from a Borland C++-compiled host application
+correctly - I imagine there are other potential problems from the RTL
+mismatch too.)
+
+[RPJ: Make sure you use the same RTL in both dll and application builds.
+The dll and tests Bmakefiles use cw32mti.lib. Having some trouble with
+memory read exceptions running the test suite using BCC55.]
+
+Best regards,
+Will
+
+-- 
+Will Bryant
+Systems Architect, eCOSM Limited
+Cell +64 21 655 443, office +64 3 365 4176
+http://www.ecosm.com/
diff --git a/README.CV b/README.CV
new file mode 100644
index 0000000..698728b
--- /dev/null
+++ b/README.CV
@@ -0,0 +1,3036 @@
+README.CV -- Condition Variables
+--------------------------------
+
+The original implementation of condition variables in
+pthreads-win32 was based on a discussion paper:
+
+"Strategies for Implementing POSIX Condition Variables
+on Win32": http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+
+The changes suggested below were made on Feb 6 2001. This
+file is included in the package for the benefit of anyone
+interested in understanding the pthreads-win32 implementation
+of condition variables and the (sometimes subtle) issues that
+it attempts to resolve.
+
+Thanks go to the individuals whose names appear throughout
+the following text.
+
+Ross Johnson
+
+--------------------------------------------------------------------
+
+fyi.. (more detailed problem description/demos + possible fix/patch)
+
+regards,
+alexander.
+
+
+Alexander Terekhov
+31.01.2001 17:43
+
+To:   ace-bugs@cs.wustl.edu
+cc:
+From: Alexander Terekhov/Germany/IBM@IBMDE
+Subject:  Implementation of POSIX CVs: spur.wakeups/lost
+      signals/deadlocks/unfairness
+
+
+
+    ACE VERSION:
+
+        5.1.12 (pthread-win32 snapshot 2000-12-29)
+
+    HOST MACHINE and OPERATING SYSTEM:
+
+        IBM IntelliStation Z Pro, 2 x XEON 1GHz, Win2K
+
+    TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
+    COMPILER NAME AND VERSION (AND PATCHLEVEL):
+
+        Microsoft Visual C++ 6.0
+
+    AREA/CLASS/EXAMPLE AFFECTED:
+
+        Implementation of POSIX condition variables - OS.cpp/.h
+
+    DOES THE PROBLEM AFFECT:
+
+        EXECUTION? YES!
+
+    SYNOPSIS:
+
+        a) spurious wakeups (minor problem)
+        b) lost signals
+        c) broadcast deadlock
+        d) unfairness (minor problem)
+
+    DESCRIPTION:
+
+        Please see attached copy of discussion thread
+        from comp.programming.threads for more details on
+        some reported problems. (i've also posted a "fyi"
+        message to ace-users a week or two ago but
+        unfortunately did not get any response so far).
+
+        It seems that current implementation suffers from
+        two essential problems:
+
+        1) cond.waiters_count does not accurately reflect
+           number of waiters blocked on semaphore - w/o
+           proper synchronisation that could result (in the
+           time window when counter is not accurate)
+           in spurious wakeups organised by subsequent
+           _signals  and _broadcasts.
+
+        2) Always having (with no e.g. copy_and_clear/..)
+           the same queue in use (semaphore+counter)
+           neither signal nor broadcast provide 'atomic'
+           behaviour with respect to other threads/subsequent
+           calls to signal/broadcast/wait.
+
+        Each problem and combination of both could produce
+        various nasty things:
+
+        a) spurious wakeups (minor problem)
+
+             it is possible that waiter(s) which was already
+             unblocked even so is still counted as blocked
+             waiter. signal and broadcast will release
+             semaphore which will produce a spurious wakeup
+             for a 'real' waiter coming later.
+
+        b) lost signals
+
+             signalling thread ends up consuming its own
+             signal. please see demo/discussion below.
+
+        c) broadcast deadlock
+
+             last_waiter processing code does not correctly
+             handle the case with multiple threads
+             waiting for the end of broadcast.
+             please see demo/discussion below.
+
+        d) unfairness (minor problem)
+
+             without SignalObjectAndWait some waiter(s)
+             may end up consuming broadcasted signals
+             multiple times (spurious wakeups) because waiter
+             thread(s) can be preempted before they call
+             semaphore wait (but after count++ and mtx.unlock).
+
+    REPEAT BY:
+
+        See below... run problem demos programs (tennis.cpp and
+        tennisb.cpp) number of times concurrently (on multiprocessor)
+        and in multiple sessions or just add a couple of "Sleep"s
+        as described in the attached copy of discussion thread
+        from comp.programming.threads
+
+    SAMPLE FIX/WORKAROUND:
+
+        See attached patch to pthread-win32.. well, I can not
+        claim that it is completely bug free but at least my
+        test and tests provided by pthreads-win32 seem to work.
+        Perhaps that will help.
+
+        regards,
+        alexander.
+
+
+>> Forum: comp.programming.threads
+>> Thread: pthread_cond_* implementation questions
+.
+.
+.
+David Schwartz <davids@webmaster.com> wrote:
+
+> terekhov@my-deja.com wrote:
+>
+>> BTW, could you please also share your view on other perceived
+>> "problems" such as nested broadcast deadlock, spurious wakeups
+>> and (the latest one) lost signals??
+>
+>I'm not sure what you mean. The standard allows an implementation
+>to do almost whatever it likes. In fact, you could implement
+>pthread_cond_wait by releasing the mutex, sleeping a random
+>amount of time, and then reacquiring the mutex. Of course,
+>this would be a pretty poor implementation, but any code that
+>didn't work under that implementation wouldn't be strictly
+>compliant.
+
+The implementation you suggested is indeed correct
+one (yes, now I see it :). However it requires from
+signal/broadcast nothing more than to "{ return 0; }"
+That is not the case for pthread-win32 and ACE
+implementations. I do think that these implementations
+(basically the same implementation) have some serious
+problems with wait/signal/broadcast calls. I am looking
+for help to clarify whether these problems are real
+or not. I think that I can demonstrate what I mean
+using one or two small sample programs.
+.
+.
+.
+==========
+tennis.cpp
+==========
+
+#include "ace/Synch.h"
+#include "ace/Thread.h"
+
+enum GAME_STATE {
+
+  START_GAME,
+  PLAYER_A,     // Player A playes the ball
+  PLAYER_B,     // Player B playes the ball
+  GAME_OVER,
+  ONE_PLAYER_GONE,
+  BOTH_PLAYERS_GONE
+
+};
+
+enum GAME_STATE             eGameState;
+ACE_Mutex*                  pmtxGameStateLock;
+ACE_Condition< ACE_Mutex >* pcndGameStateChange;
+
+void*
+  playerA(
+    void* pParm
+  )
+{
+
+  // For access to game state variable
+  pmtxGameStateLock->acquire();
+
+  // Play loop
+  while ( eGameState < GAME_OVER ) {
+
+    // Play the ball
+    cout << endl << "PLAYER-A" << endl;
+
+    // Now its PLAYER-B's turn
+    eGameState = PLAYER_B;
+
+    // Signal to PLAYER-B that now it is his turn
+    pcndGameStateChange->signal();
+
+    // Wait until PLAYER-B finishes playing the ball
+    do {
+
+      pcndGameStateChange->wait();
+
+      if ( PLAYER_B == eGameState )
+        cout << endl << "----PLAYER-A: SPURIOUS WAKEUP!!!" << endl;
+
+    } while ( PLAYER_B == eGameState );
+
+  }
+
+  // PLAYER-A gone
+  eGameState = (GAME_STATE)(eGameState+1);
+  cout << endl << "PLAYER-A GONE" << endl;
+
+  // No more access to state variable needed
+  pmtxGameStateLock->release();
+
+  // Signal PLAYER-A gone event
+  pcndGameStateChange->broadcast();
+
+  return 0;
+
+}
+
+void*
+  playerB(
+    void* pParm
+  )
+{
+
+  // For access to game state variable
+  pmtxGameStateLock->acquire();
+
+  // Play loop
+  while ( eGameState < GAME_OVER ) {
+
+    // Play the ball
+    cout << endl << "PLAYER-B" << endl;
+
+    // Now its PLAYER-A's turn
+    eGameState = PLAYER_A;
+
+    // Signal to PLAYER-A that now it is his turn
+    pcndGameStateChange->signal();
+
+    // Wait until PLAYER-A finishes playing the ball
+    do {
+
+      pcndGameStateChange->wait();
+
+      if ( PLAYER_A == eGameState )
+        cout << endl << "----PLAYER-B: SPURIOUS WAKEUP!!!" << endl;
+
+    } while ( PLAYER_A == eGameState );
+
+  }
+
+  // PLAYER-B gone
+  eGameState = (GAME_STATE)(eGameState+1);
+  cout << endl << "PLAYER-B GONE" << endl;
+
+  // No more access to state variable needed
+  pmtxGameStateLock->release();
+
+  // Signal PLAYER-B gone event
+  pcndGameStateChange->broadcast();
+
+  return 0;
+
+}
+
+
+int
+main (int, ACE_TCHAR *[])
+{
+
+  pmtxGameStateLock   = new ACE_Mutex();
+  pcndGameStateChange = new ACE_Condition< ACE_Mutex >( *pmtxGameStateLock
+);
+
+  // Set initial state
+  eGameState = START_GAME;
+
+  // Create players
+  ACE_Thread::spawn( playerA );
+  ACE_Thread::spawn( playerB );
+
+  // Give them 5 sec. to play
+  Sleep( 5000 );//sleep( 5 );
+
+  // Set game over state
+  pmtxGameStateLock->acquire();
+  eGameState = GAME_OVER;
+
+  // Let them know
+  pcndGameStateChange->broadcast();
+
+  // Wait for players to stop
+  do {
+
+    pcndGameStateChange->wait();
+
+  } while ( eGameState < BOTH_PLAYERS_GONE );
+
+  // Cleanup
+  cout << endl << "GAME OVER" << endl;
+  pmtxGameStateLock->release();
+  delete pcndGameStateChange;
+  delete pmtxGameStateLock;
+
+  return 0;
+
+}
+
+===========
+tennisb.cpp
+===========
+#include "ace/Synch.h"
+#include "ace/Thread.h"
+
+enum GAME_STATE {
+
+  START_GAME,
+  PLAYER_A,     // Player A playes the ball
+  PLAYER_B,     // Player B playes the ball
+  GAME_OVER,
+  ONE_PLAYER_GONE,
+  BOTH_PLAYERS_GONE
+
+};
+
+enum GAME_STATE             eGameState;
+ACE_Mutex*                  pmtxGameStateLock;
+ACE_Condition< ACE_Mutex >* pcndGameStateChange;
+
+void*
+  playerA(
+    void* pParm
+  )
+{
+
+  // For access to game state variable
+  pmtxGameStateLock->acquire();
+
+  // Play loop
+  while ( eGameState < GAME_OVER ) {
+
+    // Play the ball
+    cout << endl << "PLAYER-A" << endl;
+
+    // Now its PLAYER-B's turn
+    eGameState = PLAYER_B;
+
+    // Signal to PLAYER-B that now it is his turn
+    pcndGameStateChange->broadcast();
+
+    // Wait until PLAYER-B finishes playing the ball
+    do {
+
+      pcndGameStateChange->wait();
+
+      if ( PLAYER_B == eGameState )
+        cout << endl << "----PLAYER-A: SPURIOUS WAKEUP!!!" << endl;
+
+    } while ( PLAYER_B == eGameState );
+
+  }
+
+  // PLAYER-A gone
+  eGameState = (GAME_STATE)(eGameState+1);
+  cout << endl << "PLAYER-A GONE" << endl;
+
+  // No more access to state variable needed
+  pmtxGameStateLock->release();
+
+  // Signal PLAYER-A gone event
+  pcndGameStateChange->broadcast();
+
+  return 0;
+
+}
+
+void*
+  playerB(
+    void* pParm
+  )
+{
+
+  // For access to game state variable
+  pmtxGameStateLock->acquire();
+
+  // Play loop
+  while ( eGameState < GAME_OVER ) {
+
+    // Play the ball
+    cout << endl << "PLAYER-B" << endl;
+
+    // Now its PLAYER-A's turn
+    eGameState = PLAYER_A;
+
+    // Signal to PLAYER-A that now it is his turn
+    pcndGameStateChange->broadcast();
+
+    // Wait until PLAYER-A finishes playing the ball
+    do {
+
+      pcndGameStateChange->wait();
+
+      if ( PLAYER_A == eGameState )
+        cout << endl << "----PLAYER-B: SPURIOUS WAKEUP!!!" << endl;
+
+    } while ( PLAYER_A == eGameState );
+
+  }
+
+  // PLAYER-B gone
+  eGameState = (GAME_STATE)(eGameState+1);
+  cout << endl << "PLAYER-B GONE" << endl;
+
+  // No more access to state variable needed
+  pmtxGameStateLock->release();
+
+  // Signal PLAYER-B gone event
+  pcndGameStateChange->broadcast();
+
+  return 0;
+
+}
+
+
+int
+main (int, ACE_TCHAR *[])
+{
+
+  pmtxGameStateLock   = new ACE_Mutex();
+  pcndGameStateChange = new ACE_Condition< ACE_Mutex >( *pmtxGameStateLock
+);
+
+  // Set initial state
+  eGameState = START_GAME;
+
+  // Create players
+  ACE_Thread::spawn( playerA );
+  ACE_Thread::spawn( playerB );
+
+  // Give them 5 sec. to play
+  Sleep( 5000 );//sleep( 5 );
+
+  // Make some noise
+  pmtxGameStateLock->acquire();
+  cout << endl << "---Noise ON..." << endl;
+  pmtxGameStateLock->release();
+  for ( int i = 0; i < 100000; i++ )
+    pcndGameStateChange->broadcast();
+  cout << endl << "---Noise OFF" << endl;
+
+  // Set game over state
+  pmtxGameStateLock->acquire();
+  eGameState = GAME_OVER;
+  cout << endl << "---Stopping the game..." << endl;
+
+  // Let them know
+  pcndGameStateChange->broadcast();
+
+  // Wait for players to stop
+  do {
+
+    pcndGameStateChange->wait();
+
+  } while ( eGameState < BOTH_PLAYERS_GONE );
+
+  // Cleanup
+  cout << endl << "GAME OVER" << endl;
+  pmtxGameStateLock->release();
+  delete pcndGameStateChange;
+  delete pmtxGameStateLock;
+
+  return 0;
+
+}
+.
+.
+.
+David Schwartz <davids@webmaster.com> wrote:
+>> > It's compliant
+>>
+>> That is really good.
+>
+>> Tomorrow (I have to go urgently now) I will try to
+>> demonstrate the lost-signal "problem" of current
+>> pthread-win32 and ACE-(variant w/o SingleObjectAndWait)
+>> implementations: players start suddenly drop their balls :-)
+>> (with no change in source code).
+>
+>Signals aren't lost, they're going to the main thread,
+>which isn't coded correctly to handle them. Try this:
+>
+>  // Wait for players to stop
+>  do {
+>
+>    pthread_cond_wait( &cndGameStateChange,&mtxGameStateLock );
+>printf("Main thread stole a signal\n");
+>
+>  } while ( eGameState < BOTH_PLAYERS_GONE );
+>
+>I bet everytime you thing a signal is lost, you'll see that printf.
+>The signal isn't lost, it was stolen by another thread.
+
+well, you can probably loose your bet.. it was indeed stolen
+by "another" thread but not the one you seem to think of.
+
+I think that what actually happens is the following:
+
+H:\SA\UXX\pt\PTHREADS\TESTS>tennis3.exe
+
+PLAYER-A
+
+PLAYER-B
+
+----PLAYER-B: SPURIOUS WAKEUP!!!
+
+PLAYER-A GONE
+
+PLAYER-B GONE
+
+GAME OVER
+
+H:\SA\UXX\pt\PTHREADS\TESTS>
+
+here you can see that PLAYER-B after playing his first
+ball (which came via signal from PLAYER-A) just dropped
+it down. What happened is that his signal to player A
+was consumed as spurious wakeup by himself (player B).
+
+The implementation has a problem:
+
+================
+waiting threads:
+================
+
+{ /** Critical Section
+
+  inc cond.waiters_count
+
+}
+
+  /*
+  /* Atomic only if using Win32 SignalObjectAndWait
+  /*
+  cond.mtx.release
+
+  /*** ^^-- A THREAD WHICH DID SIGNAL MAY ACQUIRE THE MUTEX,
+  /***      GO INTO WAIT ON THE SAME CONDITION AND OVERTAKE
+  /***      ORIGINAL WAITER(S) CONSUMING ITS OWN SIGNAL!
+
+  cond.sem.wait
+
+Player-A after playing game's initial ball went into
+wait (called _wait) but was pre-empted before reaching
+wait semaphore. He was counted as waiter but was not
+actually waiting/blocked yet.
+
+===============
+signal threads:
+===============
+
+{ /** Critical Section
+
+  waiters_count = cond.waiters_count
+
+}
+
+  if ( waiters_count != 0 )
+
+    sem.post 1
+
+  endif
+
+Player-B after he received signal/ball from Player A
+called _signal. The _signal did see that there was
+one waiter blocked on the condition (Player-A) and
+released the semaphore.. (but it did not unblock
+Player-A because he was not actually blocked).
+Player-B thread continued its execution, called _wait,
+was counted as second waiter BUT was allowed to slip
+through opened semaphore gate (which was opened for
+Player-B) and received his own signal. Player B remained
+blocked followed by Player A. Deadlock happened which
+lasted until main thread came in and said game over.
+
+It seems to me that the implementation fails to
+correctly implement the following statement
+from specification:
+
+http://www.opengroup.org/
+onlinepubs/007908799/xsh/pthread_cond_wait.html
+
+"These functions atomically release mutex and cause
+the calling thread to block on the condition variable
+cond; atomically here means "atomically with respect
+to access by another thread to the mutex and then the
+condition variable". That is, if another thread is
+able to acquire the mutex after the about-to-block
+thread has released it, then a subsequent call to
+pthread_cond_signal() or pthread_cond_broadcast()
+in that thread behaves as if it were issued after
+the about-to-block thread has blocked."
+
+Question: Am I right?
+
+(I produced the program output above by simply
+adding ?Sleep( 1 )?:
+
+================
+waiting threads:
+================
+
+{ /** Critical Section
+
+  inc cond.waiters_count
+
+}
+
+  /*
+  /* Atomic only if using Win32 SignalObjectAndWait
+  /*
+  cond.mtx.release
+
+Sleep( 1 ); // Win32
+
+  /*** ^^-- A THREAD WHICH DID SIGNAL MAY ACQUIRE THE MUTEX,
+  /***      GO INTO WAIT ON THE SAME CONDITION AND OVERTAKE
+  /***      ORIGINAL WAITER(S) CONSUMING ITS OWN SIGNAL!
+
+  cond.sem.wait
+
+to the source code of pthread-win32 implementation:
+
+http://sources.redhat.com/cgi-bin/cvsweb.cgi/pthreads/
+condvar.c?rev=1.36&content-type=text/
+x-cvsweb-markup&cvsroot=pthreads-win32
+
+
+  /*
+  * We keep the lock held just long enough to increment the count of
+  * waiters by one (above).
+  * Note that we can't keep it held across the
+  * call to sem_wait since that will deadlock other calls
+  * to pthread_cond_signal
+  */
+  cleanup_args.mutexPtr = mutex;
+  cleanup_args.cv = cv;
+  cleanup_args.resultPtr = &result;
+
+  pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *)
+&cleanup_args);
+
+  if ((result = pthread_mutex_unlock (mutex)) == 0)
+    {((result
+Sleep( 1 ); // @AT
+
+      /*
+      * Wait to be awakened by
+      *              pthread_cond_signal, or
+      *              pthread_cond_broadcast, or
+      *              a timeout
+      *
+      * Note:
+      *      ptw32_sem_timedwait is a cancelation point,
+      *      hence providing the
+      *      mechanism for making pthread_cond_wait a cancelation
+      *      point. We use the cleanup mechanism to ensure we
+      *      re-lock the mutex and decrement the waiters count
+      *      if we are canceled.
+      */
+      if (ptw32_sem_timedwait (&(cv->sema), abstime) == -1)         {
+          result = errno;
+        }
+    }
+
+  pthread_cleanup_pop (1);  /* Always cleanup */
+
+
+BTW, on my system (2 CPUs) I can manage to get
+signals lost even without any source code modification
+if I run the tennis program many times in different
+shell sessions.
+.
+.
+.
+David Schwartz <davids@webmaster.com> wrote:
+>terekhov@my-deja.com wrote:
+>
+>> well, it might be that the program is in fact buggy.
+>> but you did not show me any bug.
+>
+>You're right. I was close but not dead on. I was correct, however,
+>that the code is buggy because it uses 'pthread_cond_signal' even
+>though not any thread waiting on the condition variable can do the
+>job. I was wrong in which thread could be waiting on the cv but
+>unable to do the job.
+
+Okay, lets change 'pthread_cond_signal' to 'pthread_cond_broadcast'
+but also add some noise from main() right before declaring the game
+to be over (I need it in order to demonstrate another problem of
+pthread-win32/ACE implementations - broadcast deadlock)...
+.
+.
+.
+It is my understanding of POSIX conditions,
+that on correct implementation added noise
+in form of unnecessary broadcasts from main,
+should not break the tennis program. The
+only 'side effect' of added noise on correct
+implementation would be 'spurious wakeups' of
+players (in fact they are not spurious,
+players just see them as spurious) unblocked,
+not by another player but by main before
+another player had a chance to acquire the
+mutex and change the game state variable:
+.
+.
+.
+
+PLAYER-B
+
+PLAYER-A
+
+---Noise ON...
+
+PLAYER-B
+
+PLAYER-A
+
+.
+.
+.
+
+PLAYER-B
+
+PLAYER-A
+
+----PLAYER-A: SPURIOUS WAKEUP!!!
+
+PLAYER-B
+
+PLAYER-A
+
+---Noise OFF
+
+PLAYER-B
+
+---Stopping the game...
+
+PLAYER-A GONE
+
+PLAYER-B GONE
+
+GAME OVER
+
+H:\SA\UXX\pt\PTHREADS\TESTS>
+
+On pthread-win32/ACE implementations the
+program could stall:
+
+.
+.
+.
+
+PLAYER-A
+
+PLAYER-B
+
+PLAYER-A
+
+PLAYER-B
+
+PLAYER-A
+
+PLAYER-B
+
+PLAYER-A
+
+PLAYER-B
+
+---Noise ON...
+
+PLAYER-A
+
+---Noise OFF
+^C
+H:\SA\UXX\pt\PTHREADS\TESTS>
+
+
+The implementation has problems:
+
+================
+waiting threads:
+================
+
+{ /** Critical Section
+
+  inc cond.waiters_count
+
+}
+
+  /*
+  /* Atomic only if using Win32 SignalObjectAndWait
+  /*
+  cond.mtx.release
+  cond.sem.wait
+
+  /*** ^^-- WAITER CAN BE PREEMPTED AFTER BEING UNBLOCKED...
+
+{ /** Critical Section
+
+  dec cond.waiters_count
+
+  /*** ^^- ...AND BEFORE DECREMENTING THE COUNT (1)
+
+  last_waiter = ( cond.was_broadcast &&
+                    cond.waiters_count == 0 )
+
+  if ( last_waiter )
+
+    cond.was_broadcast = FALSE
+
+  endif
+
+}
+
+  if ( last_waiter )
+
+    /*
+    /* Atomic only if using Win32 SignalObjectAndWait
+    /*
+    cond.auto_reset_event_or_sem.post /* Event for Win32
+    cond.mtx.acquire
+
+  /*** ^^-- ...AND BEFORE CALL TO mtx.acquire (2)
+
+  /*** ^^-- NESTED BROADCASTS RESULT IN A DEADLOCK
+
+
+  else
+
+    cond.mtx.acquire
+
+  /*** ^^-- ...AND BEFORE CALL TO mtx.acquire (3)
+
+  endif
+
+
+==================
+broadcast threads:
+==================
+
+{ /** Critical Section
+
+  waiters_count = cond.waiters_count
+
+  if ( waiters_count != 0 )
+
+    cond.was_broadcast = TRUE
+
+  endif
+
+}
+
+if ( waiters_count != 0 )
+
+  cond.sem.post waiters_count
+
+  /*** ^^^^^--- SPURIOUS WAKEUPS DUE TO (1)
+
+  cond.auto_reset_event_or_sem.wait /* Event for Win32
+
+  /*** ^^^^^--- DEADLOCK FOR FURTHER BROADCASTS IF THEY
+                HAPPEN TO GO INTO WAIT WHILE PREVIOUS
+                BROADCAST IS STILL IN PROGRESS/WAITING
+
+endif
+
+a) cond.waiters_count does not accurately reflect
+number of waiters blocked on semaphore - that could
+result (in the time window when counter is not accurate)
+in spurios wakeups organised by subsequent _signals
+and _broadcasts. From standard compliance point of view
+that is OK but that could be a real problem from
+performance/efficiency point of view.
+
+b) If subsequent broadcast happen to go into wait on
+cond.auto_reset_event_or_sem before previous
+broadcast was unblocked from cond.auto_reset_event_or_sem
+by its last waiter, one of two blocked threads will
+remain blocked because last_waiter processing code
+fails to unblock both threads.
+
+In the situation with tennisb.c the Player-B was put
+in a deadlock by noise (broadcast) coming from main
+thread. And since Player-B holds the game state
+mutex when it calls broadcast, the whole program
+stalled: Player-A was deadlocked on mutex and
+main thread after finishing with producing the noise
+was deadlocked on mutex too (needed to declare the
+game over)
+
+(I produced the program output above by simply
+adding ?Sleep( 1 )?:
+
+==================
+broadcast threads:
+==================
+
+{ /** Critical Section
+
+  waiters_count = cond.waiters_count
+
+  if ( waiters_count != 0 )
+
+    cond.was_broadcast = TRUE
+
+  endif
+
+}
+
+if ( waiters_count != 0 )
+
+Sleep( 1 ); //Win32
+
+  cond.sem.post waiters_count
+
+  /*** ^^^^^--- SPURIOUS WAKEUPS DUE TO (1)
+
+  cond.auto_reset_event_or_sem.wait /* Event for Win32
+
+  /*** ^^^^^--- DEADLOCK FOR FURTHER BROADCASTS IF THEY
+                HAPPEN TO GO INTO WAIT WHILE PREVIOUS
+                BROADCAST IS STILL IN PROGRESS/WAITING
+
+endif
+
+to the source code of pthread-win32 implementation:
+
+http://sources.redhat.com/cgi-bin/cvsweb.cgi/pthreads/
+condvar.c?rev=1.36&content-type=text/
+x-cvsweb-markup&cvsroot=pthreads-win32
+
+  if (wereWaiters)
+    {(wereWaiters)sroot=pthreads-win32eb.cgi/pthreads/Yem...m
+      /*
+      * Wake up all waiters
+      */
+
+Sleep( 1 ); //@AT
+
+#ifdef NEED_SEM
+
+      result = (ptw32_increase_semaphore( &cv->sema, cv->waiters )
+                 ? 0
+                : EINVAL);
+
+#else /* NEED_SEM */
+
+      result = (ReleaseSemaphore( cv->sema, cv->waiters, NULL )
+                 ? 0
+                : EINVAL);
+
+#endif /* NEED_SEM */
+
+    }
+
+  (void) pthread_mutex_unlock(&(cv->waitersLock));
+
+  if (wereWaiters && result == 0)
+    {(wereWaiters
+      /*
+       * Wait for all the awakened threads to acquire their part of
+       * the counting semaphore
+       */
+
+      if (WaitForSingleObject (cv->waitersDone, INFINITE)
+          == WAIT_OBJECT_0)
+        {
+          result = 0;
+        }
+      else
+        {
+          result = EINVAL;
+        }
+
+    }
+
+  return (result);
+
+}
+
+BTW, on my system (2 CPUs) I can manage to get
+the program stalled even without any source code
+modification if I run the tennisb program many
+times in different shell sessions.
+
+===================
+pthread-win32 patch
+===================
+struct pthread_cond_t_ {
+  long            nWaitersBlocked;   /* Number of threads blocked
+*/
+  long            nWaitersUnblocked; /* Number of threads unblocked
+*/
+  long            nWaitersToUnblock; /* Number of threads to unblock
+*/
+  sem_t           semBlockQueue;     /* Queue up threads waiting for the
+*/
+                                     /*   condition to become signalled
+*/
+  sem_t           semBlockLock;      /* Semaphore that guards access to
+*/
+                                     /* | waiters blocked count/block queue
+*/
+                                     /* +-> Mandatory Sync.LEVEL-1
+*/
+  pthread_mutex_t mtxUnblockLock;    /* Mutex that guards access to
+*/
+                                     /* | waiters (to)unblock(ed) counts
+*/
+                                     /* +-> Optional* Sync.LEVEL-2
+*/
+};                                   /* Opt*) for _timedwait and
+cancellation*/
+
+int
+pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
+  int result = EAGAIN;
+  pthread_cond_t cv = NULL;
+
+  if (cond == NULL)
+    {(cond
+      return EINVAL;
+    }
+
+  if ((attr != NULL && *attr != NULL) &&
+      ((*attr)->pshared == PTHREAD_PROCESS_SHARED))
+    {
+      /*
+       * Creating condition variable that can be shared between
+       * processes.
+       */
+      result = ENOSYS;
+
+      goto FAIL0;
+    }
+
+  cv = (pthread_cond_t) calloc (1, sizeof (*cv));
+
+  if (cv == NULL)
+    {(cv
+      result = ENOMEM;
+      goto FAIL0;
+    }
+
+  cv->nWaitersBlocked   = 0;
+  cv->nWaitersUnblocked = 0;
+  cv->nWaitersToUnblock = 0;
+
+  if (sem_init (&(cv->semBlockLock), 0, 1) != 0)
+    {(sem_init
+      goto FAIL0;
+    }
+
+  if (sem_init (&(cv->semBlockQueue), 0, 0) != 0)
+    {(sem_init
+      goto FAIL1;
+    }
+
+  if (pthread_mutex_init (&(cv->mtxUnblockLock), 0) != 0)
+    {(pthread_mutex_init
+      goto FAIL2;
+    }
+
+
+  result = 0;
+
+  goto DONE;
+
+  /*
+   * -------------
+   * Failed...
+   * -------------
+   */
+FAIL2:
+  (void) sem_destroy (&(cv->semBlockQueue));
+
+FAIL1:
+  (void) sem_destroy (&(cv->semBlockLock));
+
+FAIL0:
+DONE:
+  *cond = cv;
+
+  return (result);
+
+}                               /* pthread_cond_init */
+
+int
+pthread_cond_destroy (pthread_cond_t * cond)
+{
+  int result = 0;
+  pthread_cond_t cv;
+
+  /*
+   * Assuming any race condition here is harmless.
+   */
+  if (cond == NULL
+      || *cond == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*cond != (pthread_cond_t) PTW32_OBJECT_AUTO_INIT)
+    {(*cond
+      cv = *cond;
+
+      /*
+       * Synchronize access to waiters blocked count (LEVEL-1)
+       */
+      if (sem_wait(&(cv->semBlockLock)) != 0)
+        {(sem_wait(&(cv->semBlockLock))
+          return errno;
+        }
+
+      /*
+       * Synchronize access to waiters (to)unblock(ed) counts (LEVEL-2)
+       */
+      if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0)
+        {((result
+          (void) sem_post(&(cv->semBlockLock));
+          return result;
+        }
+
+      /*
+       * Check whether cv is still busy (still has waiters blocked)
+       */
+      if (cv->nWaitersBlocked - cv->nWaitersUnblocked > 0)
+        {(cv->nWaitersBlocked
+          (void) sem_post(&(cv->semBlockLock));
+          (void) pthread_mutex_unlock(&(cv->mtxUnblockLock));
+          return EBUSY;
+        }
+
+      /*
+       * Now it is safe to destroy
+       */
+      (void) sem_destroy (&(cv->semBlockLock));
+      (void) sem_destroy (&(cv->semBlockQueue));
+      (void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
+      (void) pthread_mutex_destroy (&(cv->mtxUnblockLock));
+
+      free(cv);
+      *cond = NULL;
+    }
+  else
+    {
+      /*
+       * See notes in ptw32_cond_check_need_init() above also.
+       */
+      EnterCriticalSection(&ptw32_cond_test_init_lock);
+
+      /*
+       * Check again.
+       */
+      if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT)
+        {(*cond
+          /*
+           * This is all we need to do to destroy a statically
+           * initialised cond that has not yet been used (initialised).
+           * If we get to here, another thread
+           * waiting to initialise this cond will get an EINVAL.
+           */
+          *cond = NULL;
+        }
+      else
+        {
+          /*
+           * The cv has been initialised while we were waiting
+           * so assume it's in use.
+           */
+          result = EBUSY;
+        }
+
+      LeaveCriticalSection(&ptw32_cond_test_init_lock);
+    }
+
+  return (result);
+}
+
+/*
+ * Arguments for cond_wait_cleanup, since we can only pass a
+ * single void * to it.
+ */
+typedef struct {
+  pthread_mutex_t * mutexPtr;
+  pthread_cond_t cv;
+  int * resultPtr;
+} ptw32_cond_wait_cleanup_args_t;
+
+static void
+ptw32_cond_wait_cleanup(void * args)
+{
+  ptw32_cond_wait_cleanup_args_t * cleanup_args =
+(ptw32_cond_wait_cleanup_args_t *) args;
+  pthread_cond_t cv = cleanup_args->cv;
+  int * resultPtr = cleanup_args->resultPtr;
+  int eLastSignal; /* enum: 1=yes 0=no -1=cancelled/timedout w/o signal(s)
+*/
+  int result;
+
+  /*
+   * 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
+   * longer waiting. The waiter is responsible for adjusting waiters
+   * (to)unblock(ed) counts (protected by unblock lock).
+   * Unblock lock/Sync.LEVEL-2 supports _timedwait and cancellation.
+   */
+  if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0)
+    {((result
+      *resultPtr = result;
+      return;
+    }
+
+  cv->nWaitersUnblocked++;
+
+  eLastSignal = (cv->nWaitersToUnblock == 0) ?
+                   -1 : (--cv->nWaitersToUnblock == 0);
+
+  /*
+   * No more LEVEL-2 access to waiters (to)unblock(ed) counts needed
+   */
+  if ((result = pthread_mutex_unlock(&(cv->mtxUnblockLock))) != 0)
+    {((result
+      *resultPtr = result;
+      return;
+    }
+
+  /*
+   * If last signal...
+   */
+  if (eLastSignal == 1)
+    {(eLastSignal
+     /*
+      * ...it means that we have end of 'atomic' signal/broadcast
+      */
+      if (sem_post(&(cv->semBlockLock)) != 0)
+        {(sem_post(&(cv->semBlockLock))
+          *resultPtr = errno;
+          return;
+        }
+    }
+  /*
+   * If not last signal and not timed out/cancelled wait w/o signal...
+   */
+  else if (eLastSignal == 0)
+    {
+     /*
+      * ...it means that next waiter can go through semaphore
+      */
+      if (sem_post(&(cv->semBlockQueue)) != 0)
+        {(sem_post(&(cv->semBlockQueue))
+          *resultPtr = errno;
+          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)
+    {((result
+      *resultPtr = result;
+    }
+
+}                               /* ptw32_cond_wait_cleanup */
+
+static int
+ptw32_cond_timedwait (pthread_cond_t * cond,
+                      pthread_mutex_t * mutex,
+                      const struct timespec *abstime)
+{
+  int result = 0;
+  pthread_cond_t cv;
+  ptw32_cond_wait_cleanup_args_t cleanup_args;
+
+  if (cond == NULL || *cond == NULL)
+    {(cond
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static condition variable. We check
+   * again inside the guarded section of ptw32_cond_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT)
+    {(*cond
+      result = ptw32_cond_check_need_init(cond);
+    }
+
+  if (result != 0 && result != EBUSY)
+    {(result
+      return result;
+    }
+
+  cv = *cond;
+
+  /*
+   * Synchronize access to waiters blocked count (LEVEL-1)
+   */
+  if (sem_wait(&(cv->semBlockLock)) != 0)
+    {(sem_wait(&(cv->semBlockLock))
+      return errno;
+    }
+
+  cv->nWaitersBlocked++;
+
+  /*
+   * Thats it. Counted means waiting, no more access needed
+   */
+  if (sem_post(&(cv->semBlockLock)) != 0)
+    {(sem_post(&(cv->semBlockLock))
+      return errno;
+    }
+
+  /*
+   * Setup this waiter cleanup handler
+   */
+  cleanup_args.mutexPtr = mutex;
+  cleanup_args.cv = cv;
+  cleanup_args.resultPtr = &result;
+
+  pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args);
+
+  /*
+   * Now we can release 'mutex' and...
+   */
+  if ((result = pthread_mutex_unlock (mutex)) == 0)
+    {((result
+
+      /*
+       * ...wait to be awakened by
+       *              pthread_cond_signal, or
+       *              pthread_cond_broadcast, or
+       *              timeout, or
+       *              thread cancellation
+       *
+       * Note:
+       *
+       *      ptw32_sem_timedwait is a cancellation point,
+       *      hence providing the mechanism for making
+       *      pthread_cond_wait a cancellation point.
+       *      We use the cleanup mechanism to ensure we
+       *      re-lock the mutex and adjust (to)unblock(ed) waiters
+       *      counts if we are cancelled, timed out or signalled.
+       */
+      if (ptw32_sem_timedwait (&(cv->semBlockQueue), abstime) != 0)
+        {(ptw32_sem_timedwait
+          result = errno;
+        }
+    }
+
+  /*
+   * Always cleanup
+   */
+  pthread_cleanup_pop (1);
+
+
+  /*
+   * "result" can be modified by the cleanup handler.
+   */
+  return (result);
+
+}                               /* ptw32_cond_timedwait */
+
+
+static int
+ptw32_cond_unblock (pthread_cond_t * cond,
+                    int unblockAll)
+{
+  int result;
+  pthread_cond_t cv;
+
+  if (cond == NULL || *cond == NULL)
+    {(cond
+      return EINVAL;
+    }
+
+  cv = *cond;
+
+  /*
+   * No-op if the CV is static and hasn't been initialised yet.
+   * Assuming that any race condition is harmless.
+   */
+  if (cv == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT)
+    {(cv
+      return 0;
+    }
+
+  /*
+   * Synchronize access to waiters blocked count (LEVEL-1)
+   */
+  if (sem_wait(&(cv->semBlockLock)) != 0)
+    {(sem_wait(&(cv->semBlockLock))
+      return errno;
+    }
+
+  /*
+   * Synchronize access to waiters (to)unblock(ed) counts (LEVEL-2)
+   * This sync.level supports _timedwait and cancellation
+   */
+  if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0)
+    {((result
+      return result;
+    }
+
+  /*
+   * Adjust waiters blocked and unblocked counts (collect garbage)
+   */
+  if (cv->nWaitersUnblocked != 0)
+    {(cv->nWaitersUnblocked
+      cv->nWaitersBlocked  -= cv->nWaitersUnblocked;
+      cv->nWaitersUnblocked = 0;
+    }
+
+  /*
+   * If (after adjustment) there are still some waiters blocked counted...
+   */
+  if ( cv->nWaitersBlocked > 0)
+    {(
+      /*
+       * We will unblock first waiter and leave semBlockLock/LEVEL-1 locked
+       * LEVEL-1 access is left disabled until last signal/unblock
+completes
+       */
+      cv->nWaitersToUnblock = (unblockAll) ? cv->nWaitersBlocked : 1;
+
+      /*
+       * No more LEVEL-2 access to waiters (to)unblock(ed) counts needed
+       * This sync.level supports _timedwait and cancellation
+       */
+      if ((result = pthread_mutex_unlock(&(cv->mtxUnblockLock))) != 0)
+        {((result
+          return result;
+        }
+
+
+      /*
+       * Now, with LEVEL-2 lock released let first waiter go through
+semaphore
+       */
+      if (sem_post(&(cv->semBlockQueue)) != 0)
+        {(sem_post(&(cv->semBlockQueue))
+          return errno;
+        }
+    }
+  /*
+   * No waiter blocked - no more LEVEL-1 access to blocked count needed...
+   */
+  else if (sem_post(&(cv->semBlockLock)) != 0)
+    {
+      return errno;
+    }
+  /*
+   * ...and no more LEVEL-2 access to waiters (to)unblock(ed) counts needed
+too
+   * This sync.level supports _timedwait and cancellation
+   */
+  else
+    {
+      result = pthread_mutex_unlock(&(cv->mtxUnblockLock));
+    }
+
+  return(result);
+
+}                               /* ptw32_cond_unblock */
+
+int
+pthread_cond_wait (pthread_cond_t * cond,
+                   pthread_mutex_t * mutex)
+{
+  /* The NULL abstime arg means INFINITE waiting. */
+  return(ptw32_cond_timedwait(cond, mutex, NULL));
+}                               /* pthread_cond_wait */
+
+
+int
+pthread_cond_timedwait (pthread_cond_t * cond,
+                        pthread_mutex_t * mutex,
+                        const struct timespec *abstime)
+{
+  if (abstime == NULL)
+    {(abstime
+      return EINVAL;
+    }
+
+  return(ptw32_cond_timedwait(cond, mutex, abstime));
+}                               /* pthread_cond_timedwait */
+
+
+int
+pthread_cond_signal (pthread_cond_t * cond)
+{
+  /* The '0'(FALSE) unblockAll arg means unblock ONE waiter. */
+  return(ptw32_cond_unblock(cond, 0));
+}                               /* pthread_cond_signal */
+
+int
+pthread_cond_broadcast (pthread_cond_t * cond)
+{
+  /* The '1'(TRUE) unblockAll arg means unblock ALL waiters. */
+  return(ptw32_cond_unblock(cond, 1));
+}                               /* pthread_cond_broadcast */
+
+
+
+
+TEREKHOV@de.ibm.com on 17.01.2001 01:00:57
+
+Please respond to TEREKHOV@de.ibm.com
+
+To:   pthreads-win32@sourceware.cygnus.com
+cc:   schmidt@uci.edu
+Subject:  win32 conditions: sem+counter+event = broadcast_deadlock +
+      spur.wakeup/unfairness/incorrectness ??
+
+
+
+
+
+
+
+Hi,
+
+Problem 1: broadcast_deadlock
+
+It seems that current implementation does not provide "atomic"
+broadcasts. That may lead to "nested" broadcasts... and it seems
+that nested case is not handled correctly -> producing a broadcast
+DEADLOCK as a result.
+
+Scenario:
+
+N (>1) waiting threads W1..N are blocked (in _wait) on condition's
+semaphore.
+
+Thread B1 calls pthread_cond_broadcast, which results in "releasing" N
+W threads via incrementing semaphore counter by N (stored in
+cv->waiters) BUT cv->waiters counter does not change!! The caller
+thread B1 remains blocked on cv->waitersDone event (auto-reset!!) BUT
+condition is not protected from starting another broadcast (when called
+on another thread) while still waiting for the "old" broadcast to
+complete on thread B1.
+
+M (>=0, <N) W threads are fast enough to go thru their _wait call and
+decrement cv->waiters counter.
+
+L (N-M) "late" waiter W threads are a) still blocked/not returned from
+their semaphore wait call or b) were preempted after sem_wait but before
+lock( &cv->waitersLock ) or c) are blocked on cv->waitersLock.
+
+cv->waiters is still > 0 (= L).
+
+Another thread B2 (or some W thread from M group) calls
+pthread_cond_broadcast and gains access to counter... neither a) nor b)
+prevent thread B2 in pthread_cond_broadcast from gaining access to
+counter and starting another broadcast ( for c) - it depends on
+cv->waitersLock scheduling rules: FIFO=OK, PRTY=PROBLEM,... )
+
+That call to pthread_cond_broadcast (on thread B2) will result in
+incrementing semaphore by cv->waiters (=L) which is INCORRECT (all
+W1..N were in fact already released by thread B1) and waiting on
+_auto-reset_ event cv->waitersDone which is DEADLY WRONG (produces a
+deadlock)...
+
+All late W1..L threads now have a chance to complete their _wait call.
+Last W_L thread sets an auto-reselt event cv->waitersDone which will
+release either B1 or B2 leaving one of B threads in a deadlock.
+
+Problem 2: spur.wakeup/unfairness/incorrectness
+
+It seems that:
+
+a) because of the same problem with counter which does not reflect the
+actual number of NOT RELEASED waiters, the signal call may increment
+a semaphore counter w/o having a waiter blocked on it. That will result
+in (best case) spurious wake ups - performance degradation due to
+unnecessary context switches and predicate re-checks and (in worth case)
+unfairness/incorrectness problem - see b)
+
+b) neither signal nor broadcast prevent other threads - "new waiters"
+(and in the case of signal, the caller thread as well) from going into
+_wait and overtaking "old" waiters (already released but still not returned
+from sem_wait on condition's semaphore). Win semaphore just [API DOC]:
+"Maintains a count between zero and some maximum value, limiting the number
+of threads that are simultaneously accessing a shared resource." Calling
+ReleaseSemaphore does not imply (at least not documented) that on return
+from ReleaseSemaphore all waiters will in fact become released (returned
+from their Wait... call) and/or that new waiters calling Wait... afterwards
+will become less importance. It is NOT documented to be an atomic release
+of
+waiters... And even if it would be there is still a problem with a thread
+being preempted after Wait on semaphore and before Wait on cv->waitersLock
+and scheduling rules for cv->waitersLock itself
+(??WaitForMultipleObjects??)
+That may result in unfairness/incorrectness problem as described
+for SetEvent impl. in "Strategies for Implementing POSIX Condition
+Variables
+on Win32": http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+
+Unfairness -- The semantics of the POSIX pthread_cond_broadcast function is
+to wake up all threads currently blocked in wait calls on the condition
+variable. The awakened threads then compete for the external_mutex. To
+ensure
+fairness, all of these threads should be released from their
+pthread_cond_wait calls and allowed to recheck their condition expressions
+before other threads can successfully complete a wait on the condition
+variable.
+
+Unfortunately, the SetEvent implementation above does not guarantee that
+all
+threads sleeping on the condition variable when cond_broadcast is called
+will
+acquire the external_mutex and check their condition expressions. Although
+the Pthreads specification does not mandate this degree of fairness, the
+lack of fairness can cause starvation.
+
+To illustrate the unfairness problem, imagine there are 2 threads, C1 and
+C2,
+that are blocked in pthread_cond_wait on condition variable not_empty_ that
+is guarding a thread-safe message queue. Another thread, P1 then places two
+messages onto the queue and calls pthread_cond_broadcast. If C1 returns
+from
+pthread_cond_wait, dequeues and processes the message, and immediately
+waits
+again then it and only it may end up acquiring both messages. Thus, C2 will
+never get a chance to dequeue a message and run.
+
+The following illustrates the sequence of events:
+
+1.   Thread C1 attempts to dequeue and waits on CV non_empty_
+2.   Thread C2 attempts to dequeue and waits on CV non_empty_
+3.   Thread P1 enqueues 2 messages and broadcasts to CV not_empty_
+4.   Thread P1 exits
+5.   Thread C1 wakes up from CV not_empty_, dequeues a message and runs
+6.   Thread C1 waits again on CV not_empty_, immediately dequeues the 2nd
+        message and runs
+7.   Thread C1 exits
+8.   Thread C2 is the only thread left and blocks forever since
+        not_empty_ will never be signaled
+
+Depending on the algorithm being implemented, this lack of fairness may
+yield
+concurrent programs that have subtle bugs. Of course, application
+developers
+should not rely on the fairness semantics of pthread_cond_broadcast.
+However,
+there are many cases where fair implementations of condition variables can
+simplify application code.
+
+Incorrectness -- A variation on the unfairness problem described above
+occurs
+when a third consumer thread, C3, is allowed to slip through even though it
+was not waiting on condition variable not_empty_ when a broadcast occurred.
+
+To illustrate this, we will use the same scenario as above: 2 threads, C1
+and
+C2, are blocked dequeuing messages from the message queue. Another thread,
+P1
+then places two messages onto the queue and calls pthread_cond_broadcast.
+C1
+returns from pthread_cond_wait, dequeues and processes the message. At this
+time, C3 acquires the external_mutex, calls pthread_cond_wait and waits on
+the events in WaitForMultipleObjects. Since C2 has not had a chance to run
+yet, the BROADCAST event is still signaled. C3 then returns from
+WaitForMultipleObjects, and dequeues and processes the message in the
+queue.
+Thus, C2 will never get a chance to dequeue a message and run.
+
+The following illustrates the sequence of events:
+
+1.   Thread C1 attempts to dequeue and waits on CV non_empty_
+2.   Thread C2 attempts to dequeue and waits on CV non_empty_
+3.   Thread P1 enqueues 2 messages and broadcasts to CV not_empty_
+4.   Thread P1 exits
+5.   Thread C1 wakes up from CV not_empty_, dequeues a message and runs
+6.   Thread C1 exits
+7.   Thread C3 waits on CV not_empty_, immediately dequeues the 2nd
+        message and runs
+8.   Thread C3 exits
+9.   Thread C2 is the only thread left and blocks forever since
+        not_empty_ will never be signaled
+
+In the above case, a thread that was not waiting on the condition variable
+when a broadcast occurred was allowed to proceed. This leads to incorrect
+semantics for a condition variable.
+
+
+COMMENTS???
+
+regards,
+alexander.
+
+-----------------------------------------------------------------------------
+
+Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_*
+     implementation questions
+Date: Wed, 21 Feb 2001 11:54:47 +0100
+From: TEREKHOV@de.ibm.com
+To: lthomas@arbitrade.com
+CC: rpj@ise.canberra.edu.au, Thomas Pfaff <tpfaff@gmx.net>,
+     Nanbor Wang <nanbor@cs.wustl.edu>
+
+Hi Louis,
+
+generation number 8..
+
+had some time to revisit timeouts/spurious wakeup problem..
+found some bugs (in 7.b/c/d) and something to improve
+(7a - using IPC semaphores but it should speedup Win32
+version as well).
+
+regards,
+alexander.
+
+---------- Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL ------
+given:
+semBlockLock - bin.semaphore
+semBlockQueue - semaphore
+mtxExternal - mutex or CS
+mtxUnblockLock - mutex or CS
+nWaitersGone - int
+nWaitersBlocked - int
+nWaitersToUnblock - int
+
+wait( timeout ) {
+
+  [auto: register int result          ]     // error checking omitted
+  [auto: register int nSignalsWasLeft ]
+  [auto: register int nWaitersWasGone ]
+
+  sem_wait( semBlockLock );
+  nWaitersBlocked++;
+  sem_post( semBlockLock );
+
+  unlock( mtxExternal );
+  bTimedOut = sem_wait( semBlockQueue,timeout );
+
+  lock( mtxUnblockLock );
+  if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+    if ( bTimeout ) {                       // timeout (or canceled)
+      if ( 0 != nWaitersBlocked ) {
+        nWaitersBlocked--;
+      }
+      else {
+        nWaitersGone++;                     // count spurious wakeups
+      }
+    }
+    if ( 0 == --nWaitersToUnblock ) {
+      if ( 0 != nWaitersBlocked ) {
+        sem_post( semBlockLock );           // open the gate
+        nSignalsWasLeft = 0;                // do not open the gate below
+again
+      }
+      else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+        nWaitersGone = 0;
+      }
+    }
+  }
+  else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
+semaphore :-)
+    sem_wait( semBlockLock );
+    nWaitersBlocked -= nWaitersGone;        // something is going on here -
+test of timeouts? :-)
+    sem_post( semBlockLock );
+    nWaitersGone = 0;
+  }
+  unlock( mtxUnblockLock );
+
+  if ( 1 == nSignalsWasLeft ) {
+    if ( 0 != nWaitersWasGone ) {
+      // sem_adjust( -nWaitersWasGone );
+      while ( nWaitersWasGone-- ) {
+        sem_wait( semBlockLock );          // better now than spurious
+later
+      }
+    }
+    sem_post( semBlockLock );              // open the gate
+  }
+
+  lock( mtxExternal );
+
+  return ( bTimedOut ) ? ETIMEOUT : 0;
+}
+
+signal(bAll) {
+
+  [auto: register int result         ]
+  [auto: register int nSignalsToIssue]
+
+  lock( mtxUnblockLock );
+
+  if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+    if ( 0 == nWaitersBlocked ) { // NO-OP
+      return unlock( mtxUnblockLock );
+    }
+    if (bAll) {
+      nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+      nWaitersBlocked = 0;
+    }
+    else {
+      nSignalsToIssue = 1;
+      nWaitersToUnblock++;
+      nWaitersBlocked--;
+    }
+  }
+  else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+    sem_wait( semBlockLock ); // close the gate
+    if ( 0 != nWaitersGone ) {
+      nWaitersBlocked -= nWaitersGone;
+      nWaitersGone = 0;
+    }
+    if (bAll) {
+      nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+      nWaitersBlocked = 0;
+    }
+    else {
+      nSignalsToIssue = nWaitersToUnblock = 1;
+      nWaitersBlocked--;
+    }
+  }
+  else { // NO-OP
+    return unlock( mtxUnblockLock );
+  }
+
+  unlock( mtxUnblockLock );
+  sem_post( semBlockQueue,nSignalsToIssue );
+  return result;
+}
+
+---------- Algorithm 8b / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ONEBYONE
+------
+given:
+semBlockLock - bin.semaphore
+semBlockQueue - bin.semaphore
+mtxExternal - mutex or CS
+mtxUnblockLock - mutex or CS
+nWaitersGone - int
+nWaitersBlocked - int
+nWaitersToUnblock - int
+
+wait( timeout ) {
+
+  [auto: register int result          ]     // error checking omitted
+  [auto: register int nWaitersWasGone ]
+  [auto: register int nSignalsWasLeft ]
+
+  sem_wait( semBlockLock );
+  nWaitersBlocked++;
+  sem_post( semBlockLock );
+
+  unlock( mtxExternal );
+  bTimedOut = sem_wait( semBlockQueue,timeout );
+
+  lock( mtxUnblockLock );
+  if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+    if ( bTimeout ) {                       // timeout (or canceled)
+      if ( 0 != nWaitersBlocked ) {
+        nWaitersBlocked--;
+        nSignalsWasLeft = 0;                // do not unblock next waiter
+below (already unblocked)
+      }
+      else {
+        nWaitersGone = 1;                   // spurious wakeup pending!!
+      }
+    }
+    if ( 0 == --nWaitersToUnblock &&
+      if ( 0 != nWaitersBlocked ) {
+        sem_post( semBlockLock );           // open the gate
+        nSignalsWasLeft = 0;                // do not open the gate below
+again
+      }
+      else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+        nWaitersGone = 0;
+      }
+    }
+  }
+  else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
+semaphore :-)
+    sem_wait( semBlockLock );
+    nWaitersBlocked -= nWaitersGone;        // something is going on here -
+test of timeouts? :-)
+    sem_post( semBlockLock );
+    nWaitersGone = 0;
+  }
+  unlock( mtxUnblockLock );
+
+  if ( 1 == nSignalsWasLeft ) {
+    if ( 0 != nWaitersWasGone ) {
+      // sem_adjust( -1 );
+      sem_wait( semBlockQueue );           // better now than spurious
+later
+    }
+    sem_post( semBlockLock );              // open the gate
+  }
+  else if ( 0 != nSignalsWasLeft ) {
+    sem_post( semBlockQueue );             // unblock next waiter
+  }
+
+  lock( mtxExternal );
+
+  return ( bTimedOut ) ? ETIMEOUT : 0;
+}
+
+signal(bAll) {
+
+  [auto: register int result ]
+
+  lock( mtxUnblockLock );
+
+  if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+    if ( 0 == nWaitersBlocked ) { // NO-OP
+      return unlock( mtxUnblockLock );
+    }
+    if (bAll) {
+      nWaitersToUnblock += nWaitersBlocked;
+      nWaitersBlocked = 0;
+    }
+    else {
+      nWaitersToUnblock++;
+      nWaitersBlocked--;
+    }
+    unlock( mtxUnblockLock );
+  }
+  else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+    sem_wait( semBlockLock ); // close the gate
+    if ( 0 != nWaitersGone ) {
+      nWaitersBlocked -= nWaitersGone;
+      nWaitersGone = 0;
+    }
+    if (bAll) {
+      nWaitersToUnblock = nWaitersBlocked;
+      nWaitersBlocked = 0;
+    }
+    else {
+      nWaitersToUnblock = 1;
+      nWaitersBlocked--;
+    }
+    unlock( mtxUnblockLock );
+    sem_post( semBlockQueue );
+  }
+  else { // NO-OP
+    unlock( mtxUnblockLock );
+  }
+
+  return result;
+}
+
+---------- Algorithm 8c / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ONEBYONE
+---------
+given:
+hevBlockLock - auto-reset event
+hevBlockQueue - auto-reset event
+mtxExternal - mutex or CS
+mtxUnblockLock - mutex or CS
+nWaitersGone - int
+nWaitersBlocked - int
+nWaitersToUnblock - int
+
+wait( timeout ) {
+
+  [auto: register int result          ]     // error checking omitted
+  [auto: register int nSignalsWasLeft ]
+  [auto: register int nWaitersWasGone ]
+
+  wait( hevBlockLock,INFINITE );
+  nWaitersBlocked++;
+  set_event( hevBlockLock );
+
+  unlock( mtxExternal );
+  bTimedOut = wait( hevBlockQueue,timeout );
+
+  lock( mtxUnblockLock );
+  if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) {
+    if ( bTimeout ) {                       // timeout (or canceled)
+      if ( 0 != nWaitersBlocked ) {
+        nWaitersBlocked--;
+        nSignalsWasLeft = 0;                // do not unblock next waiter
+below (already unblocked)
+      }
+      else {
+        nWaitersGone = 1;                   // spurious wakeup pending!!
+      }
+    }
+    if ( 0 == --nWaitersToUnblock )
+      if ( 0 != nWaitersBlocked ) {
+        set_event( hevBlockLock );          // open the gate
+        nSignalsWasLeft = 0;                // do not open the gate below
+again
+      }
+      else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+        nWaitersGone = 0;
+      }
+    }
+  }
+  else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
+event :-)
+    wait( hevBlockLock,INFINITE );
+    nWaitersBlocked -= nWaitersGone;        // something is going on here -
+test of timeouts? :-)
+    set_event( hevBlockLock );
+    nWaitersGone = 0;
+  }
+  unlock( mtxUnblockLock );
+
+  if ( 1 == nSignalsWasLeft ) {
+    if ( 0 != nWaitersWasGone ) {
+      reset_event( hevBlockQueue );         // better now than spurious
+later
+    }
+    set_event( hevBlockLock );              // open the gate
+  }
+  else if ( 0 != nSignalsWasLeft ) {
+    set_event( hevBlockQueue );             // unblock next waiter
+  }
+
+  lock( mtxExternal );
+
+  return ( bTimedOut ) ? ETIMEOUT : 0;
+}
+
+signal(bAll) {
+
+  [auto: register int result ]
+
+  lock( mtxUnblockLock );
+
+  if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+    if ( 0 == nWaitersBlocked ) { // NO-OP
+      return unlock( mtxUnblockLock );
+    }
+    if (bAll) {
+      nWaitersToUnblock += nWaitersBlocked;
+      nWaitersBlocked = 0;
+    }
+    else {
+      nWaitersToUnblock++;
+      nWaitersBlocked--;
+    }
+    unlock( mtxUnblockLock );
+  }
+  else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+    wait( hevBlockLock,INFINITE ); // close the gate
+    if ( 0 != nWaitersGone ) {
+      nWaitersBlocked -= nWaitersGone;
+      nWaitersGone = 0;
+    }
+    if (bAll) {
+      nWaitersToUnblock = nWaitersBlocked;
+      nWaitersBlocked = 0;
+    }
+    else {
+      nWaitersToUnblock = 1;
+      nWaitersBlocked--;
+    }
+    unlock( mtxUnblockLock );
+    set_event( hevBlockQueue );
+  }
+  else { // NO-OP
+    unlock( mtxUnblockLock );
+  }
+
+  return result;
+}
+
+---------- Algorithm 8d / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ALL ------
+given:
+hevBlockLock - auto-reset event
+hevBlockQueueS - auto-reset event  // for signals
+hevBlockQueueB - manual-reset even // for broadcasts
+mtxExternal - mutex or CS
+mtxUnblockLock - mutex or CS
+eBroadcast - int                   // 0: no broadcast, 1: broadcast, 2:
+broadcast after signal(s)
+nWaitersGone - int
+nWaitersBlocked - int
+nWaitersToUnblock - int
+
+wait( timeout ) {
+
+  [auto: register int result          ]     // error checking omitted
+  [auto: register int eWasBroadcast   ]
+  [auto: register int nSignalsWasLeft ]
+  [auto: register int nWaitersWasGone ]
+
+  wait( hevBlockLock,INFINITE );
+  nWaitersBlocked++;
+  set_event( hevBlockLock );
+
+  unlock( mtxExternal );
+  bTimedOut = waitformultiple( hevBlockQueueS,hevBlockQueueB,timeout,ONE );
+
+  lock( mtxUnblockLock );
+  if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) {
+    if ( bTimeout ) {                       // timeout (or canceled)
+      if ( 0 != nWaitersBlocked ) {
+        nWaitersBlocked--;
+        nSignalsWasLeft = 0;                // do not unblock next waiter
+below (already unblocked)
+      }
+      else if ( 1 != eBroadcast ) {
+        nWaitersGone = 1;
+      }
+    }
+    if ( 0 == --nWaitersToUnblock ) {
+      if ( 0 != nWaitersBlocked ) {
+        set_event( hevBlockLock );           // open the gate
+        nSignalsWasLeft = 0;                 // do not open the gate below
+again
+      }
+      else {
+        if ( 0 != (eWasBroadcast = eBroadcast) ) {
+          eBroadcast = 0;
+        }
+        if ( 0 != (nWaitersWasGone = nWaitersGone ) {
+          nWaitersGone = 0;
+        }
+      }
+    }
+    else if ( 0 != eBroadcast ) {
+      nSignalsWasLeft = 0;                  // do not unblock next waiter
+below (already unblocked)
+    }
+  }
+  else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
+event :-)
+    wait( hevBlockLock,INFINITE );
+    nWaitersBlocked -= nWaitersGone;        // something is going on here -
+test of timeouts? :-)
+    set_event( hevBlockLock );
+    nWaitersGone = 0;
+  }
+  unlock( mtxUnblockLock );
+
+  if ( 1 == nSignalsWasLeft ) {
+    if ( 0 != eWasBroadcast ) {
+      reset_event( hevBlockQueueB );
+    }
+    if ( 0 != nWaitersWasGone ) {
+      reset_event( hevBlockQueueS );        // better now than spurious
+later
+    }
+    set_event( hevBlockLock );              // open the gate
+  }
+  else if ( 0 != nSignalsWasLeft ) {
+    set_event( hevBlockQueueS );            // unblock next waiter
+  }
+
+  lock( mtxExternal );
+
+  return ( bTimedOut ) ? ETIMEOUT : 0;
+}
+
+signal(bAll) {
+
+  [auto: register int    result        ]
+  [auto: register HANDLE hevBlockQueue ]
+
+  lock( mtxUnblockLock );
+
+  if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+    if ( 0 == nWaitersBlocked ) { // NO-OP
+      return unlock( mtxUnblockLock );
+    }
+    if (bAll) {
+      nWaitersToUnblock += nWaitersBlocked;
+      nWaitersBlocked = 0;
+      eBroadcast = 2;
+      hevBlockQueue = hevBlockQueueB;
+    }
+    else {
+      nWaitersToUnblock++;
+      nWaitersBlocked--;
+      return unlock( mtxUnblockLock );
+    }
+  }
+  else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+    wait( hevBlockLock,INFINITE ); // close the gate
+    if ( 0 != nWaitersGone ) {
+      nWaitersBlocked -= nWaitersGone;
+      nWaitersGone = 0;
+    }
+    if (bAll) {
+      nWaitersToUnblock = nWaitersBlocked;
+      nWaitersBlocked = 0;
+      eBroadcast = 1;
+      hevBlockQueue = hevBlockQueueB;
+    }
+    else {
+      nWaitersToUnblock = 1;
+      nWaitersBlocked--;
+      hevBlockQueue = hevBlockQueueS;
+    }
+  }
+  else { // NO-OP
+    return unlock( mtxUnblockLock );
+  }
+
+  unlock( mtxUnblockLock );
+  set_event( hevBlockQueue );
+  return result;
+}
+---------------------- Forwarded by Alexander Terekhov/Germany/IBM on
+02/21/2001 09:13 AM ---------------------------
+
+Alexander Terekhov
+02/20/2001 04:33 PM
+
+To:   Louis Thomas <lthomas@arbitrade.com>
+cc:
+
+From: Alexander Terekhov/Germany/IBM@IBMDE
+Subject:  RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio
+      n questions
+Importance:    Normal
+
+>Sorry, gotta take a break and work on something else for a while.
+>Real work
+>calls, unfortunately. I'll get back to you in two or three days.
+
+ok. no problem. here is some more stuff for pauses you might have
+in between :)
+
+---------- Algorithm 7d / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ALL ------
+given:
+hevBlockLock - auto-reset event
+hevBlockQueueS - auto-reset event  // for signals
+hevBlockQueueB - manual-reset even // for broadcasts
+mtxExternal - mutex or CS
+mtxUnblockLock - mutex or CS
+bBroadcast - int
+nWaitersGone - int
+nWaitersBlocked - int
+nWaitersToUnblock - int
+
+wait( timeout ) {
+
+  [auto: register int result          ]     // error checking omitted
+  [auto: register int bWasBroadcast   ]
+  [auto: register int nSignalsWasLeft ]
+
+  wait( hevBlockLock,INFINITE );
+  nWaitersBlocked++;
+  set_event( hevBlockLock );
+
+  unlock( mtxExternal );
+  bTimedOut = waitformultiple( hevBlockQueueS,hevBlockQueueB,timeout,ONE );
+
+  lock( mtxUnblockLock );
+  if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) {
+    if ( bTimeout ) {                       // timeout (or canceled)
+      if ( 0 != nWaitersBlocked ) {
+        nWaitersBlocked--;
+        nSignalsWasLeft = 0;                // do not unblock next waiter
+below (already unblocked)
+      }
+      else if ( !bBroadcast ) {
+        wait( hevBlockQueueS,INFINITE );    // better now than spurious
+later
+      }
+    }
+    if ( 0 == --nWaitersToUnblock ) {
+      if ( 0 != nWaitersBlocked ) {
+        if ( bBroadcast ) {
+          reset_event( hevBlockQueueB );
+          bBroadcast = false;
+        }
+        set_event( hevBlockLock );           // open the gate
+        nSignalsWasLeft = 0;                 // do not open the gate below
+again
+      }
+      else if ( false != (bWasBroadcast = bBroadcast) ) {
+        bBroadcast = false;
+      }
+    }
+    else {
+      bWasBroadcast = bBroadcast;
+    }
+  }
+  else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
+event :-)
+    wait( hevBlockLock,INFINITE );
+    nWaitersBlocked -= nWaitersGone;        // something is going on here -
+test of timeouts? :-)
+    set_event( hevBlockLock );
+    nWaitersGone = 0;
+  }
+  unlock( mtxUnblockLock );
+
+  if ( 1 == nSignalsWasLeft ) {
+    if ( bWasBroadcast ) {
+      reset_event( hevBlockQueueB );
+    }
+    set_event( hevBlockLock );              // open the gate
+  }
+  else if ( 0 != nSignalsWasLeft && !bWasBroadcast ) {
+    set_event( hevBlockQueueS );            // unblock next waiter
+  }
+
+  lock( mtxExternal );
+
+  return ( bTimedOut ) ? ETIMEOUT : 0;
+}
+
+signal(bAll) {
+
+  [auto: register int    result        ]
+  [auto: register HANDLE hevBlockQueue ]
+
+  lock( mtxUnblockLock );
+
+  if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+    if ( 0 == nWaitersBlocked ) { // NO-OP
+      return unlock( mtxUnblockLock );
+    }
+    if (bAll) {
+      nWaitersToUnblock += nWaitersBlocked;
+      nWaitersBlocked = 0;
+      bBroadcast = true;
+      hevBlockQueue = hevBlockQueueB;
+    }
+    else {
+      nWaitersToUnblock++;
+      nWaitersBlocked--;
+      return unlock( mtxUnblockLock );
+    }
+  }
+  else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+    wait( hevBlockLock,INFINITE ); // close the gate
+    if ( 0 != nWaitersGone ) {
+      nWaitersBlocked -= nWaitersGone;
+      nWaitersGone = 0;
+    }
+    if (bAll) {
+      nWaitersToUnblock = nWaitersBlocked;
+      nWaitersBlocked = 0;
+      bBroadcast = true;
+      hevBlockQueue = hevBlockQueueB;
+    }
+    else {
+      nWaitersToUnblock = 1;
+      nWaitersBlocked--;
+      hevBlockQueue = hevBlockQueueS;
+    }
+  }
+  else { // NO-OP
+    return unlock( mtxUnblockLock );
+  }
+
+  unlock( mtxUnblockLock );
+  set_event( hevBlockQueue );
+  return result;
+}
+
+
+----------------------------------------------------------------------------
+
+Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio
+     n questions
+Date: Mon, 26 Feb 2001 22:20:12 -0600
+From: Louis Thomas <lthomas@arbitrade.com>
+To: "'TEREKHOV@de.ibm.com'" <TEREKHOV@de.ibm.com>
+CC: rpj@ise.canberra.edu.au, Thomas Pfaff <tpfaff@gmx.net>,
+     Nanbor Wang
+     <nanbor@cs.wustl.edu>
+
+Sorry all. Busy week.
+
+> this insures the fairness
+> which POSIX does not (e.g. two subsequent broadcasts - the gate does
+insure
+> that first wave waiters will start the race for the mutex before waiters
+> from the second wave - Linux pthreads process/unblock both waves
+> concurrently...)
+
+I'm not sure how we are any more fair about this than Linux. We certainly
+don't guarantee that the threads released by the first broadcast will get
+the external mutex before the threads of the second wave. In fact, it is
+possible that those threads will never get the external mutex if there is
+enough contention for it.
+
+> e.g. i was thinking about implementation with a pool of
+> N semaphores/counters [...]
+
+I considered that too. The problem is as you mentioned in a). You really
+need to assign threads to semaphores once you know how you want to wake them
+up, not when they first begin waiting which is the only time you can assign
+them.
+
+> well, i am not quite sure that i've fully understood your scenario,
+
+Hmm. Well, it think it's an important example, so I'll try again. First, we
+have thread A which we KNOW is waiting on a condition. As soon as it becomes
+unblocked for any reason, we will know because it will set a flag. Since the
+flag is not set, we are 100% confident that thread A is waiting on the
+condition. We have another thread, thread B, which has acquired the mutex
+and is about to wait on the condition. Thus it is pretty clear that at any
+point, either just A is waiting, or A and B are waiting. Now thread C comes
+along. C is about to do a broadcast on the condition. A broadcast is
+guaranteed to unblock all threads currently waiting on a condition, right?
+Again, we said that either just A is waiting, or A and B are both waiting.
+So, when C does its broadcast, depending upon whether B has started waiting
+or not, thread C will unblock A or unblock A and B. Either way, C must
+unblock A, right?
+
+Now, you said anything that happens is correct so long as a) "a signal is
+not lost between unlocking the mutex and waiting on the condition" and b) "a
+thread must not steal a signal it sent", correct? Requirement b) is easy to
+satisfy: in this scenario, thread C will never wait on the condition, so it
+won't steal any signals.  Requirement a) is not hard either. The only way we
+could fail to meet requirement a) in this scenario is if thread B was
+started waiting but didn't wake up because a signal was lost. This will not
+happen.
+
+Now, here is what happens. Assume thread C beats thread B. Thread C looks to
+see how many threads are waiting on the condition. Thread C sees just one
+thread, thread A, waiting. It does a broadcast waking up just one thread
+because just one thread is waiting. Next, before A can become unblocked,
+thread B begins waiting. Now there are two threads waiting, but only one
+will be unblocked. Suppose B wins. B will become unblocked. A will not
+become unblocked, because C only unblocked one thread (sema_post cond, 1).
+So at the end, B finishes and A remains blocked.
+
+We have met both of your requirements, so by your rules, this is an
+acceptable outcome. However, I think that the spec says this is an
+unacceptable outcome! We know for certain that A was waiting and that C did
+a broadcast, but A did not become unblocked! Yet, the spec says that a
+broadcast wakes up all waiting threads. This did not happen. Do you agree
+that this shows your rules are not strict enough?
+
+> and what about N2? :) this one does allow almost everything.
+
+Don't get me started about rule #2. I'll NEVER advocate an algorithm that
+uses rule 2 as an excuse to suck!
+
+> but it is done (decrement)under mutex protection - this is not a subject
+> of a race condition.
+
+You are correct. My mistake.
+
+> i would remove "_bTimedOut=false".. after all, it was a real timeout..
+
+I disagree. A thread that can't successfully retract its waiter status can't
+really have timed out. If a thread can't return without executing extra code
+to deal with the fact that someone tried to unblock it, I think it is a poor
+idea to pretend we
+didn't realize someone was trying to signal us. After all, a signal is more
+important than a time out.
+
+> when nSignaled != 0, it is possible to update nWaiters (--) and do not
+> touch nGone
+
+I realize this, but I was thinking that writing it the other ways saves
+another if statement.
+
+> adjust only if nGone != 0 and save one cache memory write - probably much
+slower than 'if'
+
+Hmm. You are probably right.
+
+> well, in a strange (e.g. timeout test) program you may (theoretically)
+> have an overflow of nWaiters/nGone counters (with waiters repeatedly
+timing
+> out and no signals at all).
+
+Also true. Not only that, but you also have the possibility that one could
+overflow the number of waiters as well! However, considering the limit you
+have chosen for nWaitersGone, I suppose it is unlikely that anyone would be
+able to get INT_MAX/2 threads waiting on a single condition. :)
+
+Analysis of 8a:
+
+It looks correct to me.
+
+What are IPC semaphores?
+
+In the line where you state, "else if ( nWaitersBlocked > nWaitersGone ) {
+// HARMLESS RACE CONDITION!" there is no race condition for nWaitersGone
+because nWaitersGone is never modified without holding mtxUnblockLock. You
+are correct that there is a harmless race on nWaitersBlocked, which can
+increase and make the condition become true just after we check it. If this
+happens, we interpret it as the wait starting after the signal.
+
+I like your optimization of this. You could improve Alg. 6 as follows:
+---------- Algorithm 6b ----------
+signal(bAll) {
+  _nSig=0
+  lock counters
+  // this is safe because nWaiting can only be decremented by a thread that
+  // owns counters and nGone can only be changed by a thread that owns
+counters.
+  if (nWaiting>nGone) {
+    if (0==nSignaled) {
+      sema_wait gate // close gate if not already closed
+    }
+    if (nGone>0) {
+      nWaiting-=nGone
+      nGone=0
+    }
+    _nSig=bAll?nWaiting:1
+    nSignaled+=_nSig
+    nWaiting-=_nSig
+  }
+  unlock counters
+  if (0!=_nSig) {
+    sema_post queue, _nSig
+  }
+}
+---------- ---------- ----------
+I guess this wouldn't apply to Alg 8a because nWaitersGone changes meanings
+depending upon whether the gate is open or closed.
+
+In the loop "while ( nWaitersWasGone-- ) {" you do a sema_wait on
+semBlockLock. Perhaps waiting on semBlockQueue would be a better idea.
+
+What have you gained by making the last thread to be signaled do the waits
+for all the timed out threads, besides added complexity? It took me a long
+time to figure out what your objective was with this, to realize you were
+using nWaitersGone to mean two different things, and to verify that you
+hadn't introduced any bug by doing this. Even now I'm not 100% sure.
+
+What has all this playing about with nWaitersGone really gained us besides a
+lot of complexity (it is much harder to verify that this solution is
+correct), execution overhead (we now have a lot more if statements to
+evaluate), and space overhead (more space for the extra code, and another
+integer in our data)? We did manage to save a lock/unlock pair in an
+uncommon case (when a time out occurs) at the above mentioned expenses in
+the common cases.
+
+As for 8b, c, and d, they look ok though I haven't studied them thoroughly.
+What would you use them for?
+
+    Later,
+        -Louis! :)
+
+-----------------------------------------------------------------------------
+
+Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio
+     n questions
+Date: Tue, 27 Feb 2001 15:51:28 +0100
+From: TEREKHOV@de.ibm.com
+To: Louis Thomas <lthomas@arbitrade.com>
+CC: rpj@ise.canberra.edu.au, Thomas Pfaff <tpfaff@gmx.net>,
+     Nanbor Wang <nanbor@cs.wustl.edu>
+
+Hi Louis,
+
+>> that first wave waiters will start the race for the mutex before waiters
+>> from the second wave - Linux pthreads process/unblock both waves
+>> concurrently...)
+>
+>I'm not sure how we are any more fair about this than Linux. We certainly
+>don't guarantee that the threads released by the first broadcast will get
+>the external mutex before the threads of the second wave. In fact, it is
+>possible that those threads will never get the external mutex if there is
+>enough contention for it.
+
+correct. but gate is nevertheless more fair than Linux because of the
+barrier it establishes between two races (1st and 2nd wave waiters) for
+the mutex which under 'normal' circumstances (e.g. all threads of equal
+priorities,..) will 'probably' result in fair behaviour with respect to
+mutex ownership.
+
+>> well, i am not quite sure that i've fully understood your scenario,
+>
+>Hmm. Well, it think it's an important example, so I'll try again. ...
+
+ok. now i seem to understand this example. well, now it seems to me
+that the only meaningful rule is just:
+
+a) "a signal is not lost between unlocking the mutex and waiting on the
+condition"
+
+and that the rule
+
+b) "a thread must not steal a signal it sent"
+
+is not needed at all because a thread which violates b) also violates a).
+
+i'll try to explain..
+
+i think that the most important thing is how POSIX defines waiter's
+visibility:
+
+"if another thread is able to acquire the mutex after the about-to-block
+thread
+has released it, then a subsequent call to pthread_cond_signal() or
+pthread_cond_broadcast() in that thread behaves as if it were issued after
+the about-to-block thread has blocked. "
+
+my understanding is the following:
+
+1) there is no guarantees whatsoever with respect to whether
+signal/broadcast
+will actually unblock any 'waiter' if it is done w/o acquiring the mutex
+first
+(note that a thread may release it before signal/broadcast - it does not
+matter).
+
+2) it is guaranteed that waiters become 'visible' - eligible for unblock as
+soon
+as signalling thread acquires the mutex (but not before!!)
+
+so..
+
+>So, when C does its broadcast, depending upon whether B has started
+waiting
+>or not, thread C will unblock A or unblock A and B. Either way, C must
+>unblock A, right?
+
+right. but only if C did acquire the mutex prior to broadcast (it may
+release it before broadcast as well).
+
+implementation will violate waiters visibility rule (signal will become
+lost)
+if C will not unblock A.
+
+>Now, here is what happens. Assume thread C beats thread B. Thread C looks
+to
+>see how many threads are waiting on the condition. Thread C sees just one
+>thread, thread A, waiting. It does a broadcast waking up just one thread
+>because just one thread is waiting. Next, before A can become unblocked,
+>thread B begins waiting. Now there are two threads waiting, but only one
+>will be unblocked. Suppose B wins. B will become unblocked. A will not
+>become unblocked, because C only unblocked one thread (sema_post cond, 1).
+>So at the end, B finishes and A remains blocked.
+
+thread C did acquire the mutex ("Thread C sees just one thread, thread A,
+waiting"). beginning from that moment it is guaranteed that subsequent
+broadcast will unblock A. Otherwise we will have a lost signal with respect
+to A. I do think that it does not matter whether the signal was physically
+(completely) lost or was just stolen by another thread (B) - in both cases
+it was simply lost with respect to A.
+
+>..Do you agree that this shows your rules are not strict enough?
+
+probably the opposite.. :-) i think that it shows that the only meaningful
+rule is
+
+a) "a signal is not lost between unlocking the mutex and waiting on the
+condition"
+
+with clarification of waiters visibility as defined by POSIX above.
+
+>> i would remove "_bTimedOut=false".. after all, it was a real timeout..
+>
+>I disagree. A thread that can't successfully retract its waiter status
+can't
+>really have timed out. If a thread can't return without executing extra
+code
+>to deal with the fact that someone tried to unblock it, I think it is a
+poor
+>idea to pretend we
+>didn't realize someone was trying to signal us. After all, a signal is
+more
+>important than a time out.
+
+a) POSIX does allow timed out thread to consume a signal (cancelled is
+not).
+b) ETIMEDOUT status just says that: "The time specified by abstime to
+pthread_cond_timedwait() has passed."
+c) it seem to me that hiding timeouts would violate "The
+pthread_cond_timedwait()
+function is the same as pthread_cond_wait() except that an error is
+returned if
+the absolute time specified by abstime passes (that is, system time equals
+or
+exceeds abstime) before the condition cond is signaled or broadcasted"
+because
+the abs. time did really pass before cond was signaled (waiter was
+released via semaphore). however, if it really matters, i could imaging
+that we
+can save an abs. time of signal/broadcast and compare it with timeout after
+unblock to find out whether it was a 'real' timeout or not. absent this
+check
+i do think that hiding timeouts would result in technical violation of
+specification.. but i think that this check is not important and we can
+simply
+trust timeout error code provided by wait since we are not trying to make
+'hard' realtime implementation.
+
+>What are IPC semaphores?
+
+<sys/sem.h>
+int   semctl(int, int, int, ...);
+int   semget(key_t, int, int);
+int   semop(int, struct sembuf *, size_t);
+
+they support adjustment of semaphore counter (semvalue)
+in one single call - imaging Win32 ReleaseSemaphore( hsem,-N )
+
+>In the line where you state, "else if ( nWaitersBlocked > nWaitersGone ) {
+>// HARMLESS RACE CONDITION!" there is no race condition for nWaitersGone
+>because nWaitersGone is never modified without holding mtxUnblockLock. You
+>are correct that there is a harmless race on nWaitersBlocked, which can
+>increase and make the condition become true just after we check it. If
+this
+>happens, we interpret it as the wait starting after the signal.
+
+well, the reason why i've asked on comp.programming.threads whether this
+race
+condition is harmless or not is that in order to be harmless it should not
+violate the waiters visibility rule (see above). Fortunately, we increment
+the counter under protection of external mutex.. so that any (signalling)
+thread which will acquire the mutex next, should see the updated counter
+(in signal) according to POSIX memory visibility rules and mutexes
+(memory barriers). But i am not so sure how it actually works on
+Win32/INTEL
+which does not explicitly define any memory visibility rules :(
+
+>I like your optimization of this. You could improve Alg. 6 as follows:
+>---------- Algorithm 6b ----------
+>signal(bAll) {
+>  _nSig=0
+>  lock counters
+>  // this is safe because nWaiting can only be decremented by a thread
+that
+>  // owns counters and nGone can only be changed by a thread that owns
+>counters.
+>  if (nWaiting>nGone) {
+>    if (0==nSignaled) {
+>      sema_wait gate // close gate if not already closed
+>    }
+>    if (nGone>0) {
+>      nWaiting-=nGone
+>      nGone=0
+>    }
+>    _nSig=bAll?nWaiting:1
+>    nSignaled+=_nSig
+>    nWaiting-=_nSig
+>  }
+>  unlock counters
+>  if (0!=_nSig) {
+>    sema_post queue, _nSig
+>  }
+>}
+>---------- ---------- ----------
+>I guess this wouldn't apply to Alg 8a because nWaitersGone changes
+meanings
+>depending upon whether the gate is open or closed.
+
+agree.
+
+>In the loop "while ( nWaitersWasGone-- ) {" you do a sema_wait on
+>semBlockLock. Perhaps waiting on semBlockQueue would be a better idea.
+
+you are correct. my mistake.
+
+>What have you gained by making the last thread to be signaled do the waits
+>for all the timed out threads, besides added complexity? It took me a long
+>time to figure out what your objective was with this, to realize you were
+>using nWaitersGone to mean two different things, and to verify that you
+>hadn't introduced any bug by doing this. Even now I'm not 100% sure.
+>
+>What has all this playing about with nWaitersGone really gained us besides
+a
+>lot of complexity (it is much harder to verify that this solution is
+>correct), execution overhead (we now have a lot more if statements to
+>evaluate), and space overhead (more space for the extra code, and another
+>integer in our data)? We did manage to save a lock/unlock pair in an
+>uncommon case (when a time out occurs) at the above mentioned expenses in
+>the common cases.
+
+well, please consider the following:
+
+1) with multiple waiters unblocked (but some timed out) the trick with
+counter
+seem to ensure potentially higher level of concurrency by not delaying
+most of unblocked waiters for semaphore cleanup - only the last one
+will be delayed but all others would already contend/acquire/release
+the external mutex - the critical section protected by mtxUnblockLock is
+made smaller (increment + couple of IFs is faster than system/kernel call)
+which i think is good in general. however, you are right, this is done
+at expense of 'normal' waiters..
+
+2) some semaphore APIs (e.g. POSIX IPC sems) do allow to adjust the
+semaphore counter in one call => less system/kernel calls.. imagine:
+
+if ( 1 == nSignalsWasLeft ) {
+    if ( 0 != nWaitersWasGone ) {
+      ReleaseSemaphore( semBlockQueue,-nWaitersWasGone );  // better now
+than spurious later
+    }
+    sem_post( semBlockLock );              // open the gate
+  }
+
+3) even on win32 a single thread doing multiple cleanup calls (to wait)
+will probably result in faster execution (because of processor caching)
+than multiple threads each doing a single call to wait.
+
+>As for 8b, c, and d, they look ok though I haven't studied them
+thoroughly.
+>What would you use them for?
+
+8b) for semaphores which do not allow to unblock multiple waiters
+in a single call to post/release (e.g. POSIX realtime semaphores -
+<semaphore.h>)
+
+8c/8d) for WinCE prior to 3.0 (WinCE 3.0 does have semaphores)
+
+ok. so, which one is the 'final' algorithm(s) which we should use in
+pthreads-win32??
+
+regards,
+alexander.
+
+----------------------------------------------------------------------------
+
+Louis Thomas <lthomas@arbitrade.com> on 02/27/2001 05:20:12 AM
+
+Please respond to Louis Thomas <lthomas@arbitrade.com>
+
+To:   Alexander Terekhov/Germany/IBM@IBMDE
+cc:   rpj@ise.canberra.edu.au, Thomas Pfaff <tpfaff@gmx.net>, Nanbor Wang
+      <nanbor@cs.wustl.edu>
+Subject:  RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio
+      n questions
+
+Sorry all. Busy week.
+
+> this insures the fairness
+> which POSIX does not (e.g. two subsequent broadcasts - the gate does
+insure
+> that first wave waiters will start the race for the mutex before waiters
+> from the second wave - Linux pthreads process/unblock both waves
+> concurrently...)
+
+I'm not sure how we are any more fair about this than Linux. We certainly
+don't guarantee that the threads released by the first broadcast will get
+the external mutex before the threads of the second wave. In fact, it is
+possible that those threads will never get the external mutex if there is
+enough contention for it.
+
+> e.g. i was thinking about implementation with a pool of
+> N semaphores/counters [...]
+
+I considered that too. The problem is as you mentioned in a). You really
+need to assign threads to semaphores once you know how you want to wake
+them
+up, not when they first begin waiting which is the only time you can assign
+them.
+
+> well, i am not quite sure that i've fully understood your scenario,
+
+Hmm. Well, it think it's an important example, so I'll try again. First, we
+have thread A which we KNOW is waiting on a condition. As soon as it
+becomes
+unblocked for any reason, we will know because it will set a flag. Since
+the
+flag is not set, we are 100% confident that thread A is waiting on the
+condition. We have another thread, thread B, which has acquired the mutex
+and is about to wait on the condition. Thus it is pretty clear that at any
+point, either just A is waiting, or A and B are waiting. Now thread C comes
+along. C is about to do a broadcast on the condition. A broadcast is
+guaranteed to unblock all threads currently waiting on a condition, right?
+Again, we said that either just A is waiting, or A and B are both waiting.
+So, when C does its broadcast, depending upon whether B has started waiting
+or not, thread C will unblock A or unblock A and B. Either way, C must
+unblock A, right?
+
+Now, you said anything that happens is correct so long as a) "a signal is
+not lost between unlocking the mutex and waiting on the condition" and b)
+"a
+thread must not steal a signal it sent", correct? Requirement b) is easy to
+satisfy: in this scenario, thread C will never wait on the condition, so it
+won't steal any signals.  Requirement a) is not hard either. The only way
+we
+could fail to meet requirement a) in this scenario is if thread B was
+started waiting but didn't wake up because a signal was lost. This will not
+happen.
+
+Now, here is what happens. Assume thread C beats thread B. Thread C looks
+to
+see how many threads are waiting on the condition. Thread C sees just one
+thread, thread A, waiting. It does a broadcast waking up just one thread
+because just one thread is waiting. Next, before A can become unblocked,
+thread B begins waiting. Now there are two threads waiting, but only one
+will be unblocked. Suppose B wins. B will become unblocked. A will not
+become unblocked, because C only unblocked one thread (sema_post cond, 1).
+So at the end, B finishes and A remains blocked.
+
+We have met both of your requirements, so by your rules, this is an
+acceptable outcome. However, I think that the spec says this is an
+unacceptable outcome! We know for certain that A was waiting and that C did
+a broadcast, but A did not become unblocked! Yet, the spec says that a
+broadcast wakes up all waiting threads. This did not happen. Do you agree
+that this shows your rules are not strict enough?
+
+> and what about N2? :) this one does allow almost everything.
+
+Don't get me started about rule #2. I'll NEVER advocate an algorithm that
+uses rule 2 as an excuse to suck!
+
+> but it is done (decrement)under mutex protection - this is not a subject
+> of a race condition.
+
+You are correct. My mistake.
+
+> i would remove "_bTimedOut=false".. after all, it was a real timeout..
+
+I disagree. A thread that can't successfully retract its waiter status
+can't
+really have timed out. If a thread can't return without executing extra
+code
+to deal with the fact that someone tried to unblock it, I think it is a
+poor
+idea to pretend we
+didn't realize someone was trying to signal us. After all, a signal is more
+important than a time out.
+
+> when nSignaled != 0, it is possible to update nWaiters (--) and do not
+> touch nGone
+
+I realize this, but I was thinking that writing it the other ways saves
+another if statement.
+
+> adjust only if nGone != 0 and save one cache memory write - probably much
+slower than 'if'
+
+Hmm. You are probably right.
+
+> well, in a strange (e.g. timeout test) program you may (theoretically)
+> have an overflow of nWaiters/nGone counters (with waiters repeatedly
+timing
+> out and no signals at all).
+
+Also true. Not only that, but you also have the possibility that one could
+overflow the number of waiters as well! However, considering the limit you
+have chosen for nWaitersGone, I suppose it is unlikely that anyone would be
+able to get INT_MAX/2 threads waiting on a single condition. :)
+
+Analysis of 8a:
+
+It looks correct to me.
+
+What are IPC semaphores?
+
+In the line where you state, "else if ( nWaitersBlocked > nWaitersGone ) {
+// HARMLESS RACE CONDITION!" there is no race condition for nWaitersGone
+because nWaitersGone is never modified without holding mtxUnblockLock. You
+are correct that there is a harmless race on nWaitersBlocked, which can
+increase and make the condition become true just after we check it. If this
+happens, we interpret it as the wait starting after the signal.
+
+I like your optimization of this. You could improve Alg. 6 as follows:
+---------- Algorithm 6b ----------
+signal(bAll) {
+  _nSig=0
+  lock counters
+  // this is safe because nWaiting can only be decremented by a thread that
+  // owns counters and nGone can only be changed by a thread that owns
+counters.
+  if (nWaiting>nGone) {
+    if (0==nSignaled) {
+      sema_wait gate // close gate if not already closed
+    }
+    if (nGone>0) {
+      nWaiting-=nGone
+      nGone=0
+    }
+    _nSig=bAll?nWaiting:1
+    nSignaled+=_nSig
+    nWaiting-=_nSig
+  }
+  unlock counters
+  if (0!=_nSig) {
+    sema_post queue, _nSig
+  }
+}
+---------- ---------- ----------
+I guess this wouldn't apply to Alg 8a because nWaitersGone changes meanings
+depending upon whether the gate is open or closed.
+
+In the loop "while ( nWaitersWasGone-- ) {" you do a sema_wait on
+semBlockLock. Perhaps waiting on semBlockQueue would be a better idea.
+
+What have you gained by making the last thread to be signaled do the waits
+for all the timed out threads, besides added complexity? It took me a long
+time to figure out what your objective was with this, to realize you were
+using nWaitersGone to mean two different things, and to verify that you
+hadn't introduced any bug by doing this. Even now I'm not 100% sure.
+
+What has all this playing about with nWaitersGone really gained us besides
+a
+lot of complexity (it is much harder to verify that this solution is
+correct), execution overhead (we now have a lot more if statements to
+evaluate), and space overhead (more space for the extra code, and another
+integer in our data)? We did manage to save a lock/unlock pair in an
+uncommon case (when a time out occurs) at the above mentioned expenses in
+the common cases.
+
+As for 8b, c, and d, they look ok though I haven't studied them thoroughly.
+What would you use them for?
+
+    Later,
+        -Louis! :)
+
diff --git a/README.NONPORTABLE b/README.NONPORTABLE
new file mode 100644
index 0000000..aa43297
--- /dev/null
+++ b/README.NONPORTABLE
@@ -0,0 +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.
diff --git a/README.Watcom b/README.Watcom
new file mode 100644
index 0000000..2974928
--- /dev/null
+++ b/README.Watcom
@@ -0,0 +1,62 @@
+Watcom compiler notes
+=====================
+
+Status
+------
+Not yet usable. Although the library builds under Watcom it
+substantially fails the test suite.
+
+There is a working Wmakefile for wmake for the library build.
+
+invoke as any of:
+wmake -f Wmakefile clean WC
+wmake -f Wmakefile clean WC-inlined
+wmake -f Wmakefile clean WCE
+wmake -f Wmakefile clean WCE-inlined
+
+These build pthreadWC.dll and pthreadWCE.dll.
+
+There is a working Wmakefile for wmake for the test suite.
+
+invoke as any of:
+wmake -f Wmakefile clean WC
+wmake -f Wmakefile clean WCX
+wmake -f Wmakefile clean WCE
+wmake -f Wmakefile clean WC-bench
+wmake -f Wmakefile clean WCX-bench
+wmake -f Wmakefile clean WCE-bench
+
+
+Current known problems
+----------------------
+
+Library build:
+The Watcom compiler uses a different default call convention to MS C or GNU C and so
+applications are not compatible with pthreadVC.dll etc using pre 2003-10-14 versions
+of pthread.h, sched.h, or semaphore.h. The cdecl attribute can be used on exposed
+function prototypes to force compatibility with MS C built DLLs.
+
+However, there appear to be other incompatibilities. Errno.h, for example, defines
+different values for the standard C and POSIX errors to those defined by the MS C
+errno.h. It may be that references to Watcom's threads compatible 'errno' do set
+and return translated numbers consistently, but I have not verified this.
+
+Watcom defines errno as a dereferenced pointer returned by the function
+_get_errno_ptr(). This is similar to both the MS and GNU C environments for
+multithreaded use. However, the Watcom version appears to have a number of problems:
+
+- different threads return the same pointer value. Compare with the MS and GNU C
+versions which correctly return different values (since each thread must maintain
+a thread specific errno value).
+
+- an errno value set within the DLL appears as zero in the application even though
+both share the same thread.
+
+Therefore applications built using the Watcom compiler may need to use
+a Watcom built version of the library (pthreadWC.dll). If this is the case, then
+the cdecl function attribute should not be required.
+
+Application builds:
+The test suite fails with the Watcom compiler.
+
+Test semaphore1.c fails for pthreadWC.dll because errno returns 0 instead of EAGAIN.
diff --git a/README.WinCE b/README.WinCE
new file mode 100644
index 0000000..a2cd8c2
--- /dev/null
+++ b/README.WinCE
@@ -0,0 +1,6 @@
+WinCE port
+----------
+(See the file WinCE-PORT for a detailed explanation.)
+
+Make sure you define "WINCE" amongst your compiler flags (eg. -DWINCE).
+The config.h file will define all the necessary defines for you.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..fa9efc4
--- /dev/null
+++ b/TODO
@@ -0,0 +1,7 @@
+                   Things that aren't done yet
+                   ---------------------------
+
+1. Implement PTHREAD_PROCESS_SHARED for semaphores, mutexes,
+   condition variables, read/write locks, barriers.
+
+
diff --git a/WinCE-PORT b/WinCE-PORT
new file mode 100644
index 0000000..f5981a9
--- /dev/null
+++ b/WinCE-PORT
@@ -0,0 +1,217 @@
+NOTE: The comments in this file relate to the original WinCE port
+done by Tristan Savatier. The semaphore routines have been 
+completely rewritten since (2005-04-25), having been progressively
+broken more and more by changes to the library. All of the semaphore
+routines implemented for W9x/WNT/2000 and up should now also work for
+WinCE. Also, pthread_mutex_timedlock should now work. [RPJ]
+
+----
+
+Some interesting news:
+
+I have been able to port pthread-win32 to Windows-CE,
+which uses a subset of the WIN32 API.
+
+Since we intend to keep using pthread-win32 for our
+Commercial WinCE developments, I would be very interested
+if WinCE support could be added to the main source tree
+of pthread-win32.  Also, I would like to be credited
+for this port :-)
+
+Now, here is the story...
+
+The port was performed and tested on a Casio "Cassiopeia"
+PalmSize PC, which runs a MIP processor.  The OS in the
+Casio is WinCE version 2.11, but I used VC++ 6.0 with
+the WinCE SDK for version 2.01.
+
+I used pthread-win32 to port a heavily multithreaded
+commercial application (real-time MPEG video player)
+from Linux to WinCE.  I consider the changes that
+I have done to be quite well tested.
+
+Overall the modifications that we had to do are minor.
+
+The WinCE port were based on pthread-win32-snap-1999-05-30,
+but I am certain that they can be integrated very easiely
+to more recent versions of the source.
+
+I have attached the modified source code:
+pthread-win32-snap-1999-05-30-WinCE.
+
+All the changes do not affect the code compiled on non-WinCE
+environment, provided that the macros used for WinCE compilation
+are not used, of course!
+
+Overall description of the WinCE port:
+-------------------------------------
+
+Most of the changes had to be made in areas where
+pthread-win32 was relying on some standard-C librairies
+(e.g. _ftime, calloc, errno), which are not available
+on WinCE. We have changed the code to use native Win32
+API instead (or in some cases we made wrappers).
+
+The Win32 Semaphores are not available,
+so we had to re-implement Semaphores using mutexes
+and events.
+
+Limitations / known problems of the WinCE port:
+----------------------------------------------
+
+Not all the semaphore routines have been ported
+(semaphores are defined by Posix but are not part
+pf pthread).  I have just done enough to make
+pthread routines (that rely internally on semaphores)
+work, like signal conditions.
+
+I noticed that the Win32 threads work slightly
+differently on WinCE.  This may have some impact
+on some tricky parts of pthread-win32, but I have
+not really investigated.  For example, on WinCE,
+the process is killed if the main thread falls off
+the bottom (or calls pthread_exit), regardless
+of the existence of any other detached thread.
+Microsoft manual indicates that this behavior is
+deffirent from that of Windows Threads for other
+Win32 platforms.
+
+
+Detailed descriptions of the changes and rationals:
+
+------------------------------------
+- use a new macro NEED_ERRNO.
+
+If defined, the code in errno.c that defines a reentrant errno
+is compiled, regardless of _MT and _REENTRANT.
+
+Rational: On WinCE, there is no support for <stdio.h>, <errno.h> or
+any other standard C library, i.e. even if _MT or _REENTRANT
+is defined, errno is not provided by any library.  NEED_ERRNO
+must be set to compile for WinCE.
+
+------------------------------------
+- In implement.h, change #include <semaphore.h> to #include "semaphore.h".
+
+Rational: semaphore.h is provided in pthread-win32 and should not
+be searched in the systems standard include.  would not compile.
+This change does not seem to create problems on "classic" win32
+(e.g. win95).
+
+------------------------------------
+- use a new macro NEED_CALLOC.
+
+If defined, some code in misc.c will provide a replacement
+for calloc, which is not available on Win32.
+
+
+------------------------------------
+- use a new macro NEED_CREATETHREAD.
+
+If defined, implement.h defines the macro _beginthreadex
+and _endthreadex.
+
+Rational: On WinCE, the wrappers _beginthreadex and _endthreadex
+do not exist. The native Win32 routines must be used.
+
+------------------------------------
+- in misc.c:
+
+#ifdef NEED_DUPLICATEHANDLE
+	  /* DuplicateHandle does not exist on WinCE */
+	  self->threadH = GetCurrentThread();
+#else
+	  if( !DuplicateHandle(
+			       GetCurrentProcess(),
+			       GetCurrentThread(),
+			       GetCurrentProcess(),
+			       &self->threadH,
+			       0,
+			       FALSE,
+			       DUPLICATE_SAME_ACCESS ) )
+	    {
+	      free( self );
+	      return (NULL);
+	    }
+#endif
+
+Rational: On WinCE, DuplicateHandle does not exist.  I could not understand
+why DuplicateHandle must be used.  It seems to me that getting the current
+thread handle with GetCurrentThread() is sufficient, and it seems to work
+perfectly fine, so maybe DuplicateHandle was just plain useless to begin with ?
+
+------------------------------------
+- In private.c, added some code at the beginning of ptw32_processInitialize
+to detect the case of multiple calls to ptw32_processInitialize.
+
+Rational: In order to debug pthread-win32, it is easier to compile
+it as a regular library (it is not possible to debug DLL's on winCE).
+In that case, the application must call ptw32_rocessInitialize()
+explicitely, to initialize pthread-win32.  It is safer in this circumstance
+to handle the case where ptw32_processInitialize() is called on
+an already initialized library:
+
+int
+ptw32_processInitialize (void)
+{
+	if (ptw32_processInitialized) {
+		/* 
+		 * ignore if already initialized. this is useful for 
+		 * programs that uses a non-dll pthread
+		 * library. such programs must call ptw32_processInitialize() explicitely,
+		 * since this initialization routine is automatically called only when
+		 * the dll is loaded.
+		 */
+		return TRUE;
+	}
+    ptw32_processInitialized = TRUE;
+  	[...]
+}
+
+------------------------------------
+- in private.c, if macro NEED_FTIME is defined, add routines to
+convert timespec_to_filetime and filetime_to_timespec, and modified
+code that was using _ftime() to use Win32 API instead.
+
+Rational: _ftime is not available on WinCE.  It is necessary to use
+the native Win32 time API instead.
+
+Note: the routine timespec_to_filetime is provided as a convenience and a mean
+to test that filetime_to_timespec works, but it is not used by the library.
+
+------------------------------------
+- in semaphore.c, if macro NEED_SEM is defined, add code for the routines
+_increase_semaphore and _decrease_semaphore, and modify significantly
+the implementation of the semaphores so that it does not use CreateSemaphore.
+
+Rational: CreateSemaphore is not available on WinCE.  I had to re-implement
+semaphores using mutexes and Events.
+
+Note: Only the semaphore routines that are used by pthread are implemented
+(i.e. signal conditions rely on a subset of the semaphores routines, and
+this subset works). Some other semaphore routines (e.g. sem_trywait) are
+not yet supported on my WinCE port (and since I don't need them, I am not
+planning to do anything about them).
+
+------------------------------------
+- in tsd.c, changed the code that defines TLS_OUT_OF_INDEXES
+
+/* TLS_OUT_OF_INDEXES not defined on WinCE */
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+
+Rational: TLS_OUT_OF_INDEXES is not defined in any standard include file
+on WinCE.
+
+------------------------------------
+- added file need_errno.h
+
+Rational: On WinCE, there is no errno.h file. need_errno.h is just a
+copy of windows version of errno.h, with minor modifications due to the fact
+that some of the error codes are defined by the WinCE socket library.
+In pthread.h, if NEED_ERRNO is defined, the file need_errno.h is
+included (instead of <errno.h>).
+
+
+-- eof
diff --git a/attr.c b/attr.c
new file mode 100644
index 0000000..a9d55f4
--- /dev/null
+++ b/attr.c
@@ -0,0 +1,53 @@
+/*
+ * attr.c
+ *
+ * Description:
+ * This translation unit agregates operations on thread attribute objects.
+ * It is used for inline optimisation.
+ *
+ * The included modules are used separately when static executable sizes
+ * must be minimised.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "pthread_attr_init.c"
+#include "pthread_attr_destroy.c"
+#include "pthread_attr_getdetachstate.c"
+#include "pthread_attr_setdetachstate.c"
+#include "pthread_attr_getstackaddr.c"
+#include "pthread_attr_setstackaddr.c"
+#include "pthread_attr_getstacksize.c"
+#include "pthread_attr_setstacksize.c"
+#include "pthread_attr_getscope.c"
+#include "pthread_attr_setscope.c"
diff --git a/barrier.c b/barrier.c
new file mode 100644
index 0000000..41b950c
--- /dev/null
+++ b/barrier.c
@@ -0,0 +1,47 @@
+/*
+ * barrier.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_barrier_init.c"
+#include "pthread_barrier_destroy.c"
+#include "pthread_barrier_wait.c"
+#include "pthread_barrierattr_init.c"
+#include "pthread_barrierattr_destroy.c"
+#include "pthread_barrierattr_getpshared.c"
+#include "pthread_barrierattr_setpshared.c"
diff --git a/builddmc.bat b/builddmc.bat
new file mode 100755
index 0000000..0d803d1
--- /dev/null
+++ b/builddmc.bat
@@ -0,0 +1,9 @@
+; Build the pthreads library with the Digital Mars Compiler

+;

+set DMCDIR=c:\dm

+

+;   RELEASE

+%DMCDIR%\bin\dmc -D_WIN32_WINNT -D_MT -DHAVE_CONFIG_H -I.;c:\dm\include -o+all -WD pthread.c user32.lib+kernel32.lib+wsock32.lib -L/impl -L/NODEBUG -L/SU:WINDOWS

+

+;   DEBUG

+%DMCDIR%\bin\dmc -g -D_WIN32_WINNT -D_MT -DHAVE_CONFIG_H -I.;c:\dm\include -o+all -WD pthread.c user32.lib+kernel32.lib+wsock32.lib -L/impl -L/SU:WINDOWS

diff --git a/cancel.c b/cancel.c
new file mode 100644
index 0000000..1bd14eb
--- /dev/null
+++ b/cancel.c
@@ -0,0 +1,44 @@
+/*
+ * cancel.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_setcancelstate.c"
+#include "pthread_setcanceltype.c"
+#include "pthread_testcancel.c"
+#include "pthread_cancel.c"
diff --git a/cleanup.c b/cleanup.c
new file mode 100644
index 0000000..381d1e8
--- /dev/null
+++ b/cleanup.c
@@ -0,0 +1,148 @@
+/*
+ * cleanup.c
+ *
+ * Description:
+ * This translation unit implements routines associated
+ * with cleaning up threads.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * The functions ptw32_pop_cleanup and ptw32_push_cleanup
+ * are implemented here for applications written in C with no
+ * SEH or C++ destructor support. 
+ */
+
+ptw32_cleanup_t *
+ptw32_pop_cleanup (int execute)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function pops the most recently pushed cleanup
+      *      handler. If execute is nonzero, then the cleanup handler
+      *      is executed if non-null.
+      *
+      * PARAMETERS
+      *      execute
+      *              if nonzero, execute the cleanup handler
+      *
+      *
+      * DESCRIPTION
+      *      This function pops the most recently pushed cleanup
+      *      handler. If execute is nonzero, then the cleanup handler
+      *      is executed if non-null.
+      *      NOTE: specify 'execute' as nonzero to avoid duplication
+      *                of common cleanup code.
+      *
+      * RESULTS
+      *              N/A
+      *
+      * ------------------------------------------------------
+      */
+{
+  ptw32_cleanup_t *cleanup;
+
+  cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
+
+  if (cleanup != NULL)
+    {
+      if (execute && (cleanup->routine != NULL))
+	{
+
+	  (*cleanup->routine) (cleanup->arg);
+
+	}
+
+      pthread_setspecific (ptw32_cleanupKey, (void *) cleanup->prev);
+
+    }
+
+  return (cleanup);
+
+}				/* ptw32_pop_cleanup */
+
+
+void
+ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+		    ptw32_cleanup_callback_t routine, void *arg)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function pushes a new cleanup handler onto the thread's stack
+      *      of cleanup handlers. Each cleanup handler pushed onto the stack is
+      *      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 thread calls pthread_cleanup_pop with a nonzero
+      *                 'execute' argument
+      *
+      * PARAMETERS
+      *      cleanup
+      *              a pointer to an instance of pthread_cleanup_t,
+      *
+      *      routine
+      *              pointer to a cleanup handler,
+      *
+      *      arg
+      *              parameter to be passed to the cleanup handler
+      *
+      *
+      * DESCRIPTION
+      *      This function pushes a new cleanup handler onto the thread's stack
+      *      of cleanup handlers. Each cleanup handler pushed onto the stack is
+      *      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
+      *                 'execute' argument
+      *      NOTE: pthread_push_cleanup, ptw32_pop_cleanup must be paired
+      *                in the same lexical scope.
+      *
+      * RESULTS
+      *              pthread_cleanup_t *
+      *                              pointer to the previous cleanup
+      *
+      * ------------------------------------------------------
+      */
+{
+  cleanup->routine = routine;
+  cleanup->arg = arg;
+
+  cleanup->prev = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
+
+  pthread_setspecific (ptw32_cleanupKey, (void *) cleanup);
+
+}				/* ptw32_push_cleanup */
diff --git a/condvar.c b/condvar.c
new file mode 100644
index 0000000..704f4d7
--- /dev/null
+++ b/condvar.c
@@ -0,0 +1,50 @@
+/*
+ * condvar.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "ptw32_cond_check_need_init.c"
+#include "pthread_condattr_init.c"
+#include "pthread_condattr_destroy.c"
+#include "pthread_condattr_getpshared.c"
+#include "pthread_condattr_setpshared.c"
+#include "pthread_cond_init.c"
+#include "pthread_cond_destroy.c"
+#include "pthread_cond_wait.c"
+#include "pthread_cond_signal.c"
diff --git a/config.h b/config.h
new file mode 100755
index 0000000..f56b160
--- /dev/null
+++ b/config.h
@@ -0,0 +1,134 @@
+/* config.h  */
+
+#ifndef PTW32_CONFIG_H
+#define PTW32_CONFIG_H
+
+/*********************************************************************
+ * Defaults: see target specific redefinitions below.
+ *********************************************************************/
+
+/* We're building the pthreads-win32 library */
+#define PTW32_BUILD
+
+/* Do we know about the C type sigset_t? */
+#undef HAVE_SIGSET_T
+
+/* Define if you have the <signal.h> header file.  */
+#undef HAVE_SIGNAL_H
+
+/* Define if you have the Borland TASM32 or compatible assembler.  */
+#undef HAVE_TASM32
+
+/* Define if you don't have Win32 DuplicateHandle. (eg. WinCE) */
+#undef NEED_DUPLICATEHANDLE
+
+/* Define if you don't have Win32 _beginthreadex. (eg. WinCE) */
+#undef NEED_CREATETHREAD
+
+/* Define if you don't have Win32 errno. (eg. WinCE) */
+#undef NEED_ERRNO
+
+/* Define if you don't have Win32 calloc. (eg. WinCE)  */
+#undef NEED_CALLOC
+
+/* Define if you don't have Win32 ftime. (eg. WinCE)  */
+#undef NEED_FTIME
+
+/* Define if you don't have Win32 semaphores. (eg. WinCE 2.1 or earlier)  */
+#undef NEED_SEM
+
+/* Define if you need to convert string parameters to unicode. (eg. WinCE)  */
+#undef NEED_UNICODE_CONSTS
+
+/* Define if your C (not C++) compiler supports "inline" functions. */
+#undef HAVE_C_INLINE
+
+/* Do we know about type mode_t? */
+#undef HAVE_MODE_T
+
+/* Define if you have the timespec struct */
+#undef HAVE_STRUCT_TIMESPEC
+
+/* Define if you don't have the GetProcessAffinityMask() */
+#undef NEED_PROCESS_AFFINITY_MASK
+
+/*
+# ----------------------------------------------------------------------
+# The library can be built with some alternative behaviour to better
+# facilitate development of applications on Win32 that will be ported
+# to other POSIX systems.
+#
+# Nothing described here will make the library non-compliant and strictly
+# compliant applications will not be affected in any way, but
+# applications that make assumptions that POSIX does not guarantee are
+# not strictly compliant and may fail or misbehave with some settings.
+#
+# PTW32_THREAD_ID_REUSE_INCREMENT
+# Purpose:
+# POSIX says that applications should assume that thread IDs can be
+# recycled. However, Solaris (and some other systems) use a [very large]
+# sequence number as the thread ID, which provides virtual uniqueness.
+# This provides a very high but finite level of safety for applications
+# that are not meticulous in tracking thread lifecycles e.g. applications
+# that call functions which target detached threads without some form of
+# thread exit synchronisation.
+#
+# Usage:
+# Set to any value in the range: 0 <= value < 2^wordsize.
+# Set to 0 to emulate reusable thread ID behaviour like Linux or *BSD.
+# Set to 1 for unique thread IDs like Solaris (this is the default).
+# Set to some factor of 2^wordsize to emulate smaller word size types
+# (i.e. will wrap sooner). This might be useful to emulate some embedded
+# systems.
+#
+# define PTW32_THREAD_ID_REUSE_INCREMENT 0
+#
+# ----------------------------------------------------------------------
+ */
+#undef PTW32_THREAD_ID_REUSE_INCREMENT
+
+
+/*********************************************************************
+ * Target specific groups
+ *
+ * If you find that these are incorrect or incomplete please report it
+ * to the pthreads-win32 maintainer. Thanks.
+ *********************************************************************/
+#ifdef WINCE
+//#define NEED_DUPLICATEHANDLE  // Seems to be included in Mobile6
+#define NEED_CREATETHREAD
+#define NEED_ERRNO
+//#define NEED_CALLOC           // Seems to be included in Mobile6
+#define NEED_FTIME
+//#define NEED_SEM         
+#define NEED_UNICODE_CONSTS
+#define NEED_PROCESS_AFFINITY_MASK
+#endif
+
+#ifdef _UWIN
+#define HAVE_MODE_T
+#define HAVE_STRUCT_TIMESPEC
+#endif
+
+#ifdef __GNUC__
+#define HAVE_C_INLINE
+#endif
+
+#ifdef __MINGW32__
+#define HAVE_MODE_T
+#endif
+
+#ifdef __BORLANDC__
+#endif
+
+#ifdef __WATCOMC__
+#endif
+
+#ifdef __DMC__
+#define HAVE_SIGNAL_H
+#define HAVE_C_INLINE
+#endif
+
+
+
+#endif
diff --git a/create.c b/create.c
new file mode 100644
index 0000000..0208b0e
--- /dev/null
+++ b/create.c
@@ -0,0 +1,315 @@
+/*
+ * create.c
+ *
+ * Description:
+ * This translation unit implements routines associated with spawning a new
+ * thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#if !defined(_UWIN) && !defined(WINCE)
+#include <process.h>
+#endif
+
+int
+pthread_create (pthread_t * tid,
+		const pthread_attr_t * attr,
+		void *(*start) (void *), void *arg)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function creates a thread running the start function,
+      *      passing it the parameter value, 'arg'. The 'attr'
+      *      argument specifies optional creation attributes.
+      *      The identity of the new thread is returned
+      *      via 'tid', which should not be NULL.
+      *
+      * PARAMETERS
+      *      tid
+      *              pointer to an instance of pthread_t
+      *
+      *      attr
+      *              optional pointer to an instance of pthread_attr_t
+      *
+      *      start
+      *              pointer to the starting routine for the new thread
+      *
+      *      arg
+      *              optional parameter passed to 'start'
+      *
+      *
+      * DESCRIPTION
+      *      This function creates a thread running the start function,
+      *      passing it the parameter value, 'arg'. The 'attr'
+      *      argument specifies optional creation attributes.
+      *      The identity of the new thread is returned
+      *      via 'tid', which should not be the NULL pointer.
+      *
+      * RESULTS
+      *              0               successfully created thread,
+      *              EINVAL          attr invalid,
+      *              EAGAIN          insufficient resources.
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_t thread;
+  ptw32_thread_t * tp;
+  register pthread_attr_t a;
+  HANDLE threadH = 0;
+  int result = EAGAIN;
+  int run = PTW32_TRUE;
+  ThreadParms *parms = NULL;
+  long stackSize;
+  int priority;
+  pthread_t self;
+
+  /*
+   * Before doing anything, check that tid can be stored through
+   * without invoking a memory protection error (segfault).
+   * 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->x = 0;
+
+  if (attr != NULL)
+    {
+      a = *attr;
+    }
+  else
+    {
+      a = NULL;
+    }
+
+  if ((thread = ptw32_new ()).p == NULL)
+    {
+      goto FAIL0;
+    }
+
+  tp = (ptw32_thread_t *) thread.p;
+
+  priority = tp->sched_priority;
+
+  if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL)
+    {
+      goto FAIL0;
+    }
+
+  parms->tid = thread;
+  parms->start = start;
+  parms->arg = arg;
+
+#if defined(HAVE_SIGSET_T)
+
+  /*
+   * Threads inherit their initial sigmask from their creator thread.
+   */
+  self = pthread_self();
+  tp->sigmask = ((ptw32_thread_t *)self.p)->sigmask;
+
+#endif /* HAVE_SIGSET_T */
+
+
+  if (a != NULL)
+    {
+      stackSize = a->stacksize;
+      tp->detachState = a->detachstate;
+      priority = a->param.sched_priority;
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+      /* WinCE */
+#else
+      /* Everything else */
+
+      /*
+       * Thread priority must be set to a valid system level
+       * without altering the value set by pthread_attr_setschedparam().
+       */
+
+      /*
+       * PTHREAD_EXPLICIT_SCHED is the default because Win32 threads
+       * don't inherit their creator's priority. They are started with
+       * THREAD_PRIORITY_NORMAL (win32 value). The result of not supplying
+       * an 'attr' arg to pthread_create() is equivalent to defaulting to
+       * PTHREAD_EXPLICIT_SCHED and priority THREAD_PRIORITY_NORMAL.
+       */
+      if (PTHREAD_INHERIT_SCHED == a->inheritsched)
+	{
+	  /*
+	   * If the thread that called pthread_create() is a Win32 thread
+	   * then the inherited priority could be the result of a temporary
+	   * system adjustment. This is not the case for POSIX threads.
+	   */
+#if ! defined(HAVE_SIGSET_T)
+	  self = pthread_self ();
+#endif
+	  priority = ((ptw32_thread_t *) self.p)->sched_priority;
+	}
+
+#endif
+
+    }
+  else
+    {
+      /*
+       * Default stackSize
+       */
+      stackSize = PTHREAD_STACK_MIN;
+    }
+
+  tp->state = run ? PThreadStateInitial : PThreadStateSuspended;
+
+  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.p->threadH gets NULLed later but before we've
+   * finished with it here.
+   */
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) 
+
+#if defined (WINCE)
+  tp->threadH =
+    threadH =
+    (HANDLE) _beginthreadex ((void *) NULL,	/* No security info             */
+			     (unsigned) 64 * 1024, /* default stack size   */
+			     ptw32_threadStart,
+			     parms,		     
+                 (unsigned) (CREATE_SUSPENDED| STACK_SIZE_PARAM_IS_A_RESERVATION),
+			     (unsigned *) &(tp->thread));
+#else
+  tp->threadH =
+    threadH =
+    (HANDLE) _beginthreadex ((void *) NULL,	/* No security info             */
+			     stackSize,	/* default stack size   */
+			     ptw32_threadStart,
+			     parms,		     
+                 (unsigned) CREATE_SUSPENDED,
+			     (unsigned *) &(tp->thread));
+#endif
+
+  if (threadH != 0)
+    {
+      if (a != NULL)
+	{
+	  (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority);
+	}
+
+      if (run)
+	{
+	  ResumeThread (threadH);
+	}
+    }
+
+#else /* __MINGW32__ && ! __MSVCRT__ */
+
+  /*
+   * This lock will force pthread_threadStart() to wait until we have
+   * the thread handle and have set the priority.
+   */
+  (void) pthread_mutex_lock (&tp->cancelLock);
+
+  tp->threadH =
+    threadH =
+    (HANDLE) _beginthread (ptw32_threadStart, (unsigned) stackSize,	/* default stack size   */
+			   parms);
+
+  /*
+   * Make the return code match _beginthreadex's.
+   */
+  if (threadH == (HANDLE) - 1L)
+    {
+      tp->threadH = threadH = 0;
+    }
+  else
+    {
+      if (!run)
+	{
+	  /* 
+	   * beginthread does not allow for create flags, so we do it now.
+	   * Note that beginthread itself creates the thread in SUSPENDED
+	   * mode, and then calls ResumeThread to start it.
+	   */
+	  SuspendThread (threadH);
+	}
+
+      if (a != NULL)
+	{
+	  (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority);
+	}
+    }
+
+  (void) pthread_mutex_unlock (&tp->cancelLock);
+
+#endif /* __MINGW32__ && ! __MSVCRT__ */
+
+  result = (threadH != 0) ? 0 : EAGAIN;
+
+  /*
+   * Fall Through Intentionally
+   */
+
+  /*
+   * ------------
+   * Failure Code
+   * ------------
+   */
+
+FAIL0:
+  if (result != 0)
+    {
+
+      ptw32_threadDestroy (thread);
+      tp = NULL;
+
+      if (parms != NULL)
+	{
+	  free (parms);
+	}
+    }
+  else
+    {
+      *tid = thread;
+    }
+
+#ifdef _UWIN
+  if (result == 0)
+    pthread_count++;
+#endif
+  return (result);
+
+}				/* pthread_create */
diff --git a/dll.c b/dll.c
new file mode 100644
index 0000000..c1cd4e9
--- /dev/null
+++ b/dll.c
@@ -0,0 +1,92 @@
+/*
+ * dll.c
+ *
+ * Description:
+ * This translation unit implements DLL initialisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef PTW32_STATIC_LIB
+
+#include "pthread.h"
+#include "implement.h"
+
+#ifdef _MSC_VER
+/* 
+ * lpvReserved yields an unreferenced formal parameter;
+ * ignore it
+ */
+#pragma warning( disable : 4100 )
+#endif
+
+#ifdef __cplusplus
+/*
+ * Dear c++: Please don't mangle this name. -thanks
+ */
+extern "C"
+#endif				/* __cplusplus */
+  BOOL WINAPI
+DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
+{
+  BOOL result = PTW32_TRUE;
+
+  switch (fdwReason)
+    {
+
+    case DLL_PROCESS_ATTACH:
+      result = pthread_win32_process_attach_np ();
+      break;
+
+    case DLL_THREAD_ATTACH:
+      /*
+       * A thread is being created
+       */
+      result = pthread_win32_thread_attach_np ();
+      break;
+
+    case DLL_THREAD_DETACH:
+      /*
+       * A thread is exiting cleanly
+       */
+      result = pthread_win32_thread_detach_np ();
+      break;
+
+    case DLL_PROCESS_DETACH:
+      (void) pthread_win32_thread_detach_np ();
+      result = pthread_win32_process_detach_np ();
+      break;
+    }
+
+  return (result);
+
+}				/* DllMain */
+
+#endif /* PTW32_STATIC_LIB */
diff --git a/errno.c b/errno.c
new file mode 100644
index 0000000..4e07d8c
--- /dev/null
+++ b/errno.c
@@ -0,0 +1,95 @@
+/*
+ * errno.c
+ *
+ * Description:
+ * This translation unit implements routines associated with spawning a new
+ * thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#if defined(NEED_ERRNO)
+
+#include "pthread.h"
+#include "implement.h"
+
+static int reallyBad = ENOMEM;
+
+/*
+ * Re-entrant errno.
+ *
+ * Each thread has it's own errno variable in pthread_t.
+ *
+ * The benefit of using the pthread_t structure
+ * instead of another TSD key is TSD keys are limited
+ * on Win32 to 64 per process. Secondly, to implement
+ * it properly without using pthread_t you'd need
+ * to dynamically allocate an int on starting the thread
+ * and store it manually into TLS and then ensure that you free
+ * it on thread termination. We get all that for free
+ * by simply storing the errno on the pthread_t structure.
+ *
+ * MSVC and Mingw32 already have their own thread-safe errno.
+ *
+ * #if defined( _REENTRANT ) || defined( _MT )
+ * #define errno *_errno()
+ *
+ * int *_errno( void );
+ * #else
+ * extern int errno;
+ * #endif
+ *
+ */
+
+int *
+_errno (void)
+{
+  pthread_t self;
+  int *result;
+
+  self = pthread_self ();
+  if (self.p == NULL)
+    {
+      /*
+       * Yikes! unable to allocate a thread!
+       * Throw an exception? return an error?
+       */
+      result = &reallyBad;
+    }
+  else
+    {
+      result = &(((ptw32_thread_t*)(self.p))->ptErrno);
+    }
+
+  return (result);
+
+}				/* _errno */
+
+#endif /* (NEED_ERRNO) */
diff --git a/exit.c b/exit.c
new file mode 100644
index 0000000..77adcbd
--- /dev/null
+++ b/exit.c
@@ -0,0 +1,44 @@
+/*
+ * exit.c
+ *
+ * Description:
+ * This translation unit implements routines associated with exiting from
+ * a thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#if !defined(_UWIN) && !defined(WINCE)
+#   include <process.h>
+#endif
+
+#include "pthread_exit.c"
diff --git a/fork.c b/fork.c
new file mode 100644
index 0000000..8a29550
--- /dev/null
+++ b/fork.c
@@ -0,0 +1,39 @@
+/*
+ * fork.c
+ *
+ * Description:
+ * Implementation of fork() for POSIX threads.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+
+#include "pthread.h"
+#include "implement.h"
diff --git a/global.c b/global.c
new file mode 100644
index 0000000..2b55422
--- /dev/null
+++ b/global.c
@@ -0,0 +1,115 @@
+/*
+ * global.c
+ *
+ * Description:
+ * This translation unit instantiates data associated with the implementation
+ * as a whole.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int ptw32_processInitialized = PTW32_FALSE;
+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;
+pthread_cond_t ptw32_cond_list_tail = NULL;
+
+int ptw32_concurrency = 0;
+
+/* What features have been auto-detaected */
+int ptw32_features = 0;
+
+BOOL ptw32_smp_system = PTW32_TRUE;  /* Safer if assumed true initially. */
+
+/* 
+ * Function pointer to InterlockedCompareExchange if it exists, otherwise
+ * it will be set at runtime to a substitute local version with the same
+ * functionality but may be architecture specific.
+ */
+PTW32_INTERLOCKED_LONG
+  (WINAPI * ptw32_interlocked_compare_exchange) (PTW32_INTERLOCKED_LPLONG,
+						 PTW32_INTERLOCKED_LONG,
+						 PTW32_INTERLOCKED_LONG) =
+  NULL;
+
+/* 
+ * Function pointer to QueueUserAPCEx if it exists, otherwise
+ * it will be set at runtime to a substitute routine which cannot unblock
+ * blocked threads.
+ */
+DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD) = NULL;
+
+/*
+ * Global lock for managing pthread_t struct reuse.
+ */
+CRITICAL_SECTION ptw32_thread_reuse_lock;
+
+/*
+ * Global lock for testing internal state of statically declared mutexes.
+ */
+CRITICAL_SECTION ptw32_mutex_test_init_lock;
+
+/*
+ * Global lock for testing internal state of PTHREAD_COND_INITIALIZER
+ * created condition variables.
+ */
+CRITICAL_SECTION ptw32_cond_test_init_lock;
+
+/*
+ * Global lock for testing internal state of PTHREAD_RWLOCK_INITIALIZER
+ * created read/write locks.
+ */
+CRITICAL_SECTION ptw32_rwlock_test_init_lock;
+
+/*
+ * Global lock for testing internal state of PTHREAD_SPINLOCK_INITIALIZER
+ * created spin locks.
+ */
+CRITICAL_SECTION ptw32_spinlock_test_init_lock;
+
+/*
+ * Global lock for condition variable linked list. The list exists
+ * to wake up CVs when a WM_TIMECHANGE message arrives. See
+ * w32_TimeChangeHandler.c.
+ */
+CRITICAL_SECTION ptw32_cond_list_lock;
+
+#ifdef _UWIN
+/*
+ * Keep a count of the number of threads.
+ */
+int pthread_count = 0;
+#endif
diff --git a/implement.h b/implement.h
new file mode 100644
index 0000000..a04b0ee
--- /dev/null
+++ b/implement.h
@@ -0,0 +1,714 @@
+/*
+ * implement.h
+ *
+ * Definitions that don't need to be public.
+ *
+ * Keeps all the internals out of pthread.h
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef _IMPLEMENT_H
+#define _IMPLEMENT_H
+
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x400
+
+#include <windows.h>
+
+/*
+ * In case windows.h doesn't define it (e.g. WinCE perhaps)
+ */
+#ifdef WINCE
+typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
+#endif
+
+/*
+ * note: ETIMEDOUT is correctly defined in winsock.h
+ */
+#include <winsock.h>
+
+/*
+ * In case ETIMEDOUT hasn't been defined above somehow.
+ */
+#ifndef ETIMEDOUT
+#  define ETIMEDOUT 10060	/* This is the value in winsock.h. */
+#endif
+
+#if !defined(malloc)
+#include <malloc.h>
+#endif
+
+#if !defined(INT_MAX)
+#include <limits.h>
+#endif
+
+/* use local include files during development */
+#include "semaphore.h"
+#include "sched.h"
+
+#if defined(HAVE_C_INLINE) || defined(__cplusplus)
+#define INLINE inline
+#else
+#define INLINE
+#endif
+
+#if defined (__MINGW32__) || (_MSC_VER >= 1300)
+#define PTW32_INTERLOCKED_LONG long
+#define PTW32_INTERLOCKED_LPLONG long*
+#else
+#define PTW32_INTERLOCKED_LONG PVOID
+#define PTW32_INTERLOCKED_LPLONG PVOID*
+#endif
+
+#if defined(__MINGW32__)
+#include <stdint.h>
+#elif defined(__BORLANDC__)
+#define int64_t ULONGLONG
+#else
+#define int64_t _int64
+#endif
+
+typedef enum
+{
+  /*
+   * This enumeration represents the state of the thread;
+   * The thread is still "alive" if the numeric value of the
+   * state is greater or equal "PThreadStateRunning".
+   */
+  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        */
+  PThreadStateException,	/* Thread alive but exiting             */
+  /* due to an exception                  */
+  PThreadStateLast
+}
+PThreadState;
+
+
+typedef struct ptw32_thread_t_ ptw32_thread_t;
+
+struct ptw32_thread_t_
+{
+#ifdef _UWIN
+  DWORD dummy[5];
+#endif
+  DWORD thread;
+  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;
+  int detachState;
+  pthread_mutex_t threadLock;	/* Used for serialised access to public thread state */
+  int sched_priority;		/* As set, not as currently is */
+  pthread_mutex_t cancelLock;	/* Used for async-cancel safety */
+  int cancelState;
+  int cancelType;
+  HANDLE cancelEvent;
+#ifdef __CLEANUP_C
+  jmp_buf start_mark;
+#endif				/* __CLEANUP_C */
+#if HAVE_SIGSET_T
+  sigset_t sigmask;
+#endif				/* HAVE_SIGSET_T */
+  int implicit:1;
+  void *keys;
+  void *nextAssoc;
+};
+
+
+/* 
+ * Special value to mark attribute objects as valid.
+ */
+#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
+
+struct pthread_attr_t_
+{
+  unsigned long valid;
+  void *stackaddr;
+  size_t stacksize;
+  int detachstate;
+  struct sched_param param;
+  int inheritsched;
+  int contentionscope;
+#if HAVE_SIGSET_T
+  sigset_t sigmask;
+#endif				/* HAVE_SIGSET_T */
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Semaphores, Mutexes and Condition Variables
+ * ====================
+ * ====================
+ */
+
+struct sem_t_
+{
+  int value;
+  pthread_mutex_t lock;
+  HANDLE sem;
+#ifdef NEED_SEM
+  int leftToUnblock;
+#endif
+};
+
+#define PTW32_OBJECT_AUTO_INIT ((void *) -1)
+#define PTW32_OBJECT_INVALID   NULL
+
+struct pthread_mutex_t_
+{
+  LONG lock_idx;		/* Provides exclusive access to mutex state
+				   via the Interlocked* mechanism.
+				    0: unlocked/free.
+				    1: locked - no other waiters.
+				   -1: locked - with possible other waiters.
+				*/
+  int recursive_count;		/* Number of unlocks a thread needs to perform
+				   before the lock is released (recursive
+				   mutexes only). */
+  int kind;			/* Mutex type. */
+  pthread_t ownerThread;
+  HANDLE event;			/* Mutex release notification to waiting
+				   threads. */
+};
+
+struct pthread_mutexattr_t_
+{
+  int pshared;
+  int kind;
+};
+
+/*
+ * Possible values, other than PTW32_OBJECT_INVALID,
+ * for the "interlock" element in a spinlock.
+ *
+ * In this implementation, when a spinlock is initialised,
+ * the number of cpus available to the process is checked.
+ * If there is only one cpu then "interlock" is set equal to
+ * PTW32_SPIN_USE_MUTEX and u.mutex is a initialised mutex.
+ * If the number of cpus is greater than 1 then "interlock"
+ * is set equal to PTW32_SPIN_UNLOCKED and the number is
+ * stored in u.cpus. This arrangement allows the spinlock
+ * routines to attempt an InterlockedCompareExchange on "interlock"
+ * immediately and, if that fails, to try the inferior mutex.
+ *
+ * "u.cpus" isn't used for anything yet, but could be used at
+ * some point to optimise spinlock behaviour.
+ */
+#define PTW32_SPIN_UNLOCKED    (1)
+#define PTW32_SPIN_LOCKED      (2)
+#define PTW32_SPIN_USE_MUTEX   (3)
+
+struct pthread_spinlock_t_
+{
+  long interlock;		/* Locking element for multi-cpus. */
+  union
+  {
+    int cpus;			/* No. of cpus if multi cpus, or   */
+    pthread_mutex_t mutex;	/* mutex if single cpu.            */
+  } u;
+};
+
+struct pthread_barrier_t_
+{
+  unsigned int nCurrentBarrierHeight;
+  unsigned int nInitialBarrierHeight;
+  int iStep;
+  int pshared;
+  sem_t semBarrierBreeched[2];
+};
+
+struct pthread_barrierattr_t_
+{
+  int pshared;
+};
+
+struct pthread_key_t_
+{
+  DWORD key;
+  void (*destructor) (void *);
+  pthread_mutex_t keyLock;
+  void *threads;
+};
+
+
+typedef struct ThreadParms ThreadParms;
+typedef struct ThreadKeyAssoc ThreadKeyAssoc;
+
+struct ThreadParms
+{
+  pthread_t tid;
+  void *(*start) (void *);
+  void *arg;
+};
+
+
+struct pthread_cond_t_
+{
+  long nWaitersBlocked;		/* Number of threads blocked            */
+  long nWaitersGone;		/* Number of threads timed out          */
+  long nWaitersToUnblock;	/* Number of threads to unblock         */
+  sem_t semBlockQueue;		/* Queue up threads waiting for the     */
+  /*   condition to become signalled      */
+  sem_t semBlockLock;		/* Semaphore that guards access to      */
+  /* | waiters blocked count/block queue  */
+  /* +-> Mandatory Sync.LEVEL-1           */
+  pthread_mutex_t mtxUnblockLock;	/* Mutex that guards access to          */
+  /* | waiters (to)unblock(ed) counts     */
+  /* +-> Optional* Sync.LEVEL-2           */
+  pthread_cond_t next;		/* Doubly linked list                   */
+  pthread_cond_t prev;
+};
+
+
+struct pthread_condattr_t_
+{
+  int pshared;
+};
+
+#define PTW32_RWLOCK_MAGIC 0xfacade2
+
+struct pthread_rwlock_t_
+{
+  pthread_mutex_t mtxExclusiveAccess;
+  pthread_mutex_t mtxSharedAccessCompleted;
+  pthread_cond_t cndSharedAccessCompleted;
+  int nSharedAccessCount;
+  int nExclusiveAccessCount;
+  int nCompletedSharedAccessCount;
+  int nMagic;
+};
+
+struct pthread_rwlockattr_t_
+{
+  int pshared;
+};
+
+/*
+ * MCS lock queue node - see ptw32_MCS_lock.c
+ */
+struct ptw32_mcs_node_t_
+{
+  struct ptw32_mcs_node_t_ **lock;        /* ptr to tail of queue */
+  struct ptw32_mcs_node_t_  *next;        /* ptr to successor in queue */
+  LONG                       readyFlag;   /* set after lock is released by
+                                             predecessor */
+  LONG                       nextFlag;    /* set after 'next' ptr is set by
+                                             successor */
+};
+
+typedef struct ptw32_mcs_node_t_   ptw32_mcs_local_node_t;
+typedef struct ptw32_mcs_node_t_  *ptw32_mcs_lock_t;
+
+
+struct ThreadKeyAssoc
+{
+  /*
+   * Purpose:
+   *      This structure creates an association between a thread and a key.
+   *      It is used to implement the implicit invocation of a user defined
+   *      destroy routine for thread specific data registered by a user upon
+   *      exiting a thread.
+   *
+   *      Graphically, the arrangement is as follows, where:
+   *
+   *         K - Key with destructor
+   *            (head of chain is key->threads)
+   *         T - Thread that has called pthread_setspecific(Kn)
+   *            (head of chain is thread->keys)
+   *         A - Association. Each association is a node at the
+   *             intersection of two doubly-linked lists.
+   *
+   *                 T1    T2    T3
+   *                 |     |     |
+   *                 |     |     |
+   *         K1 -----+-----A-----A----->
+   *                 |     |     |
+   *                 |     |     |
+   *         K2 -----A-----A-----+----->
+   *                 |     |     |
+   *                 |     |     |
+   *         K3 -----A-----+-----A----->
+   *                 |     |     |
+   *                 |     |     |
+   *                 V     V     V
+   *
+   *      Access to the association is guarded by two locks: the key's
+   *      general lock (guarding the row) and the thread's general
+   *      lock (guarding the column). This avoids the need for a
+   *      dedicated lock for each association, which not only consumes
+   *      more handles but requires that: before the lock handle can
+   *      be released - both the key must be deleted and the thread
+   *      must have called the destructor. The two-lock arrangement
+   *      allows the resources to be freed as soon as either thread or
+   *      key is concluded.
+   *
+   *      To avoid deadlock: whenever both locks are required, the key
+   *      and thread locks are always acquired in the order: key lock
+   *      then thread lock. An exception to this exists when a thread
+   *      calls the destructors, however this is done carefully to
+   *      avoid deadlock.
+   *
+   *      An association is created when a thread first calls
+   *      pthread_setspecific() on a key that has a specified
+   *      destructor.
+   *
+   *      An association is destroyed either immediately after the
+   *      thread calls the key destructor function on thread exit, or
+   *      when the key is deleted.
+   *
+   * Attributes:
+   *      thread
+   *              reference to the thread that owns the
+   *              association. This is actually the pointer to the
+   *              thread struct itself. Since the association is
+   *              destroyed before the thread exits, this can never
+   *              point to a different logical thread to the one that
+   *              created the assoc, i.e. after thread struct reuse.
+   *
+   *      key
+   *              reference to the key that owns the association.
+   *
+   *      nextKey
+   *              The pthread_t->keys attribute is the head of a
+   *              chain of associations that runs through the nextKey
+   *              link. This chain provides the 1 to many relationship
+   *              between a pthread_t and all pthread_key_t on which
+   *              it called pthread_setspecific.
+   *
+   *      prevKey
+   *              Similarly.
+   *
+   *      nextThread
+   *              The pthread_key_t->threads attribute is the head of
+   *              a chain of assoctiations that runs through the
+   *              nextThreads link. This chain provides the 1 to many
+   *              relationship between a pthread_key_t and all the 
+   *              PThreads that have called pthread_setspecific for
+   *              this pthread_key_t.
+   *
+   *      prevThread
+   *              Similarly.
+   *
+   * Notes:
+   *      1)      As soon as either the key or the thread is no longer
+   *              referencing the association, it can be destroyed. The
+   *              association will be removed from both chains.
+   *
+   *      2)      Under WIN32, an association is only created by
+   *              pthread_setspecific if the user provided a
+   *              destroyRoutine when they created the key.
+   *
+   *
+   */
+  ptw32_thread_t * thread;
+  pthread_key_t key;
+  ThreadKeyAssoc *nextKey;
+  ThreadKeyAssoc *nextThread;
+  ThreadKeyAssoc *prevKey;
+  ThreadKeyAssoc *prevThread;
+};
+
+
+#ifdef __CLEANUP_SEH
+/*
+ * --------------------------------------------------------------
+ * MAKE_SOFTWARE_EXCEPTION
+ *      This macro constructs a software exception code following
+ *      the same format as the standard Win32 error codes as defined
+ *      in WINERROR.H
+ *  Values are 32 bit values layed out as follows:
+ *
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *  +---+-+-+-----------------------+-------------------------------+
+ *  |Sev|C|R|     Facility          |               Code            |
+ *  +---+-+-+-----------------------+-------------------------------+
+ *
+ * Severity Values:
+ */
+#define SE_SUCCESS              0x00
+#define SE_INFORMATION          0x01
+#define SE_WARNING              0x02
+#define SE_ERROR                0x03
+
+#define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
+( (DWORD) ( ( (_severity) << 30 ) |     /* Severity code        */ \
+            ( 1 << 29 ) |               /* MS=0, User=1         */ \
+            ( 0 << 28 ) |               /* Reserved             */ \
+            ( (_facility) << 16 ) |     /* Facility Code        */ \
+            ( (_exception) <<  0 )      /* Exception Code       */ \
+            ) )
+
+/*
+ * We choose one specific Facility/Error code combination to
+ * identify our software exceptions vs. WIN32 exceptions.
+ * We store our actual component and error code within
+ * the optional information array.
+ */
+#define EXCEPTION_PTW32_SERVICES        \
+     MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
+                              PTW32_SERVICES_FACILITY, \
+                              PTW32_SERVICES_ERROR )
+
+#define PTW32_SERVICES_FACILITY         0xBAD
+#define PTW32_SERVICES_ERROR            0xDEED
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * Services available through EXCEPTION_PTW32_SERVICES
+ * and also used [as parameters to ptw32_throw()] as
+ * generic exception selectors.
+ */
+
+#define PTW32_EPS_EXIT                  (1)
+#define PTW32_EPS_CANCEL                (2)
+
+
+/* Useful macros */
+#define PTW32_MAX(a,b)  ((a)<(b)?(b):(a))
+#define PTW32_MIN(a,b)  ((a)>(b)?(b):(a))
+
+
+/* Declared in global.c */
+extern PTW32_INTERLOCKED_LONG (WINAPI *
+			       ptw32_interlocked_compare_exchange)
+  (PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG, PTW32_INTERLOCKED_LONG);
+
+/* Declared in pthread_cancel.c */
+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_EMPTY ((ptw32_thread_t *) 1)
+
+extern int ptw32_processInitialized;
+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;
+extern pthread_cond_t ptw32_cond_list_tail;
+
+extern int ptw32_mutex_default_kind;
+
+extern int ptw32_concurrency;
+
+extern int ptw32_features;
+
+extern BOOL ptw32_smp_system;  /* True: SMP system, False: Uni-processor system */
+
+extern CRITICAL_SECTION ptw32_thread_reuse_lock;
+extern CRITICAL_SECTION ptw32_mutex_test_init_lock;
+extern CRITICAL_SECTION ptw32_cond_list_lock;
+extern CRITICAL_SECTION ptw32_cond_test_init_lock;
+extern CRITICAL_SECTION ptw32_rwlock_test_init_lock;
+extern CRITICAL_SECTION ptw32_spinlock_test_init_lock;
+
+#ifdef _UWIN
+extern int pthread_count;
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif				/* __cplusplus */
+
+/*
+ * =====================
+ * =====================
+ * Forward Declarations
+ * =====================
+ * =====================
+ */
+
+  int ptw32_is_attr (const pthread_attr_t * attr);
+
+  int ptw32_cond_check_need_init (pthread_cond_t * cond);
+  int ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
+  int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
+
+  PTW32_INTERLOCKED_LONG WINAPI
+    ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
+				      PTW32_INTERLOCKED_LONG value,
+				      PTW32_INTERLOCKED_LONG comparand);
+
+  LONG WINAPI
+    ptw32_InterlockedExchange (LPLONG location,
+			       LONG value);
+
+  DWORD
+    ptw32_RegisterCancelation (PAPCFUNC callback,
+			       HANDLE threadH, DWORD callback_arg);
+
+  int ptw32_processInitialize (void);
+
+  void ptw32_processTerminate (void);
+
+  void ptw32_threadDestroy (pthread_t tid);
+
+  void ptw32_pop_cleanup_all (int execute);
+
+  pthread_t ptw32_new (void);
+
+  pthread_t ptw32_threadReusePop (void);
+
+  void ptw32_threadReusePush (pthread_t thread);
+
+  int ptw32_getprocessors (int *count);
+
+  int ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
+
+  void ptw32_rwlock_cancelwrwait (void *arg);
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+  unsigned __stdcall
+#else
+  void
+#endif
+    ptw32_threadStart (void *vthreadParms);
+
+  void ptw32_callUserDestroyRoutines (pthread_t thread);
+
+  int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key);
+
+  void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
+
+  int ptw32_semwait (sem_t * sem);
+
+  DWORD ptw32_relmillisecs (const struct timespec * abstime);
+
+  void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
+
+  void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node);
+
+#ifdef NEED_FTIME
+  void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
+  void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
+#endif
+
+/* Declared in misc.c */
+#ifdef NEED_CALLOC
+#define calloc(n, s) ptw32_calloc(n, s)
+  void *ptw32_calloc (size_t n, size_t s);
+#endif
+
+/* Declared in private.c */
+  void ptw32_throw (DWORD exception);
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+
+
+#ifdef _UWIN_
+#   ifdef       _MT
+#       ifdef __cplusplus
+extern "C"
+{
+#       endif
+  _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
+					      unsigned, void *);
+  _CRTIMP void __cdecl _endthread (void);
+  _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
+						unsigned (__stdcall *) (void *),
+						void *, unsigned, unsigned *);
+  _CRTIMP void __cdecl _endthreadex (unsigned);
+#       ifdef __cplusplus
+}
+#       endif
+#   endif
+#elif !defined(WINCE)
+#   include <process.h>
+#endif
+
+
+/*
+ * Defaults. Could be overridden when building the inlined version of the dll.
+ * See ptw32_InterlockedCompareExchange.c
+ */
+#ifndef PTW32_INTERLOCKED_COMPARE_EXCHANGE
+#if defined(WINCE) && defined(_ARM_)
+#define PTW32_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange 
+#else 
+#define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_interlocked_compare_exchange
+#endif
+#endif
+
+#ifndef PTW32_INTERLOCKED_EXCHANGE
+#define PTW32_INTERLOCKED_EXCHANGE InterlockedExchange
+#endif
+
+
+/*
+ * Check for old and new versions of cygwin. See the FAQ file:
+ *
+ * Question 1 - How do I get pthreads-win32 to link under Cygwin or Mingw32?
+ *
+ * Patch by Anders Norlander <anorland@hem2.passagen.se>
+ */
+#if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(NEED_CREATETHREAD)
+
+/* 
+ * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
+ * in order to avoid warnings because of return type
+ */
+
+#define _beginthreadex(security, \
+                       stack_size, \
+                       start_proc, \
+                       arg, \
+                       flags, \
+                       pid) \
+        CreateThread(security, \
+                     stack_size, \
+                     (LPTHREAD_START_ROUTINE) start_proc, \
+                     arg, \
+                     flags, \
+                     pid)
+
+#define _endthreadex ExitThread
+
+#endif				/* __CYGWIN32__ || __CYGWIN__ || NEED_CREATETHREAD */
+
+
+#endif				/* _IMPLEMENT_H */
diff --git a/manual/ChangeLog b/manual/ChangeLog
new file mode 100644
index 0000000..c07cdd7
--- /dev/null
+++ b/manual/ChangeLog
@@ -0,0 +1,62 @@
+2005-05-06  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* PortabilityIssues.html: Was nonPortableIssues.html.
+	* index.html: Updated; add table of contents at top.
+	* *.html: Add Pthreads-win32 header info; add link back to the
+	index page 'index.html'.
+
+2005-05-06  Ross Johnson  <ross at callisto.canberra.edu.au>
+
+	* index.html: New.
+	* nonPortableIssues.html: New.
+	* pthread_attr_init.html: New.
+	* pthread_attr_setstackaddr.html: New.
+	* pthread_attr_setstacksize.html: New.
+	* pthread_barrierattr_init.html: New.
+	* pthread_barrierattr_setpshared.html: New.
+	* pthread_barrier_init.html: New.
+	* pthread_barrier_wait.html: New.
+	* pthreadCancelableWait.html: New.
+	* pthread_cancel.html: New.
+	* pthread_cleanup_push.html: New.
+	* pthread_condattr_init.html: New.
+	* pthread_condattr_setpshared.html: New.
+	* pthread_cond_init.html: New.
+	* pthread_create.html: New.
+	* pthread_delay_np.html: New.
+	* pthread_detach.html: New.
+	* pthread_equal.html: New.
+	* pthread_exit.html: New.
+	* pthread_getw32threadhandle_np.html: New.
+	* pthread_join.html: New.
+	* pthread_key_create.html: New.
+	* pthread_kill.html: New.
+	* pthread_mutexattr_init.html: New.
+	* pthread_mutexattr_setpshared.html: New.
+	* pthread_mutex_init.html: New.
+	* pthread_num_processors_np.html: New.
+	* pthread_once.html: New.
+	* pthread_rwlockattr_init.html: New.
+	* pthread_rwlockattr_setpshared.html: New.
+	* pthread_rwlock_init.html: New.
+	* pthread_rwlock_rdlock.html: New.
+	* pthread_rwlock_timedrdlock.html: New.
+	* pthread_rwlock_timedwrlock.html: New.
+	* pthread_rwlock_unlock.html: New.
+	* pthread_rwlock_wrlock.html: New.
+	* pthread_self.html: New.
+	* pthread_setcancelstate.html: New.
+	* pthread_setcanceltype.html: New.
+	* pthread_setconcurrency.html: New.
+	* pthread_setschedparam.html: New.
+	* pthread_spin_init.html: New.
+	* pthread_spin_lock.html: New.
+	* pthread_spin_unlock.html: New.
+	* pthread_timechange_handler_np.html: New.
+	* pthread_win32_attach_detach_np.html: New.
+	* pthread_win32_test_features_np.html: New.
+	* sched_get_priority_max.html: New.
+	* sched_getscheduler.html: New.
+	* sched_setscheduler.html: New.
+	* sched_yield.html: New.
+	* sem_init.html: New.
diff --git a/manual/PortabilityIssues.html b/manual/PortabilityIssues.html
new file mode 100644
index 0000000..d97d0bd
--- /dev/null
+++ b/manual/PortabilityIssues.html
@@ -0,0 +1,718 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PORTABILITYISSUES manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050506;11580000">

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<H4><A HREF="#toc">Table of Contents</A></H4>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">Portability issues</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>Thread priority</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<H3>Thread priority</H3>

+<P STYLE="margin-left: 2cm">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.</P>

+<P STYLE="margin-left: 2cm">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.</P>

+<P STYLE="margin-left: 2cm">The following table shows the base

+priority levels for combinations of priority class and priority value

+in Win32.</P>

+<DL>

+	<DL>

+		<DD>

+		<TABLE WIDTH=742 BORDER=0 CELLPADDING=0 CELLSPACING=0 STYLE="page-break-inside: avoid">

+			<COL WIDTH=50>

+			<COL WIDTH=356>

+			<COL WIDTH=336>

+			<THEAD>

+				<TR VALIGN=TOP>

+					<TD WIDTH=50>

+						<P ALIGN=CENTER><BR>

+						</P>

+					</TD>

+					<TD WIDTH=356>

+						<P ALIGN=LEFT><B>Process Priority Class</B></P>

+					</TD>

+					<TD WIDTH=336>

+						<P ALIGN=LEFT><B>Thread Priority Level</B></P>

+					</TD>

+				</TR>

+			</THEAD>

+			<TBODY>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="1" SDNUM="3081;">

+						<P ALIGN=CENTER>1</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_IDLE</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="1" SDNUM="3081;">

+						<P ALIGN=CENTER>1</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_IDLE</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="1" SDNUM="3081;">

+						<P ALIGN=CENTER>1</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_IDLE</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="1" SDNUM="3081;">

+						<P ALIGN=CENTER>1</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_IDLE</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="1" SDNUM="3081;">

+						<P ALIGN=CENTER>1</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_IDLE</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="2" SDNUM="3081;">

+						<P ALIGN=CENTER>2</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="3" SDNUM="3081;">

+						<P ALIGN=CENTER>3</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="4" SDNUM="3081;">

+						<P ALIGN=CENTER>4</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="4" SDNUM="3081;">

+						<P ALIGN=CENTER>4</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="5" SDNUM="3081;">

+						<P ALIGN=CENTER>5</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="5" SDNUM="3081;">

+						<P ALIGN=CENTER>5</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="5" SDNUM="3081;">

+						<P ALIGN=CENTER>5</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Background NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="6" SDNUM="3081;">

+						<P ALIGN=CENTER>6</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="6" SDNUM="3081;">

+						<P ALIGN=CENTER>6</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="6" SDNUM="3081;">

+						<P ALIGN=CENTER>6</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Background NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="7" SDNUM="3081;">

+						<P ALIGN=CENTER>7</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="7" SDNUM="3081;">

+						<P ALIGN=CENTER>7</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Background NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="7" SDNUM="3081;">

+						<P ALIGN=CENTER>7</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Foreground NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="8" SDNUM="3081;">

+						<P ALIGN=CENTER>8</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="8" SDNUM="3081;">

+						<P ALIGN=CENTER>8</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="8" SDNUM="3081;">

+						<P ALIGN=CENTER>8</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Foreground NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="8" SDNUM="3081;">

+						<P ALIGN=CENTER>8</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="9" SDNUM="3081;">

+						<P ALIGN=CENTER>9</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="9" SDNUM="3081;">

+						<P ALIGN=CENTER>9</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Foreground NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="9" SDNUM="3081;">

+						<P ALIGN=CENTER>9</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="10" SDNUM="3081;">

+						<P ALIGN=CENTER>10</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Foreground NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="10" SDNUM="3081;">

+						<P ALIGN=CENTER>10</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="11" SDNUM="3081;">

+						<P ALIGN=CENTER>11</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>Foreground NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="11" SDNUM="3081;">

+						<P ALIGN=CENTER>11</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="11" SDNUM="3081;">

+						<P ALIGN=CENTER>11</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="12" SDNUM="3081;">

+						<P ALIGN=CENTER>12</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="12" SDNUM="3081;">

+						<P ALIGN=CENTER>12</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="13" SDNUM="3081;">

+						<P ALIGN=CENTER>13</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="14" SDNUM="3081;">

+						<P ALIGN=CENTER>14</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="15" SDNUM="3081;">

+						<P ALIGN=CENTER>15</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="15" SDNUM="3081;">

+						<P ALIGN=CENTER>15</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>HIGH_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_TIME_CRITICAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="15" SDNUM="3081;">

+						<P ALIGN=CENTER>15</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>IDLE_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_TIME_CRITICAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="15" SDNUM="3081;">

+						<P ALIGN=CENTER>15</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>BELOW_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_TIME_CRITICAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="15" SDNUM="3081;">

+						<P ALIGN=CENTER>15</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_TIME_CRITICAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="15" SDNUM="3081;">

+						<P ALIGN=CENTER>15</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>ABOVE_NORMAL_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_TIME_CRITICAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="16" SDNUM="3081;">

+						<P ALIGN=CENTER>16</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_IDLE</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="17" SDNUM="3081;">

+						<P ALIGN=CENTER>17</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="-7" SDNUM="3081;">

+						<P ALIGN=LEFT>-7</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="18" SDNUM="3081;">

+						<P ALIGN=CENTER>18</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="-6" SDNUM="3081;">

+						<P ALIGN=LEFT>-6</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="19" SDNUM="3081;">

+						<P ALIGN=CENTER>19</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="-5" SDNUM="3081;">

+						<P ALIGN=LEFT>-5</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="20" SDNUM="3081;">

+						<P ALIGN=CENTER>20</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="-4" SDNUM="3081;">

+						<P ALIGN=LEFT>-4</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="21" SDNUM="3081;">

+						<P ALIGN=CENTER>21</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="-3" SDNUM="3081;">

+						<P ALIGN=LEFT>-3</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="22" SDNUM="3081;">

+						<P ALIGN=CENTER>22</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_LOWEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="23" SDNUM="3081;">

+						<P ALIGN=CENTER>23</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_BELOW_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="24" SDNUM="3081;">

+						<P ALIGN=CENTER>24</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="25" SDNUM="3081;">

+						<P ALIGN=CENTER>25</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_ABOVE_NORMAL</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="26" SDNUM="3081;">

+						<P ALIGN=CENTER>26</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_HIGHEST</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="27" SDNUM="3081;">

+						<P ALIGN=CENTER>27</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="3" SDNUM="3081;">

+						<P ALIGN=LEFT>3</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="28" SDNUM="3081;">

+						<P ALIGN=CENTER>28</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="4" SDNUM="3081;">

+						<P ALIGN=LEFT>4</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="29" SDNUM="3081;">

+						<P ALIGN=CENTER>29</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="5" SDNUM="3081;">

+						<P ALIGN=LEFT>5</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="30" SDNUM="3081;">

+						<P ALIGN=CENTER>30</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=BOTTOM SDVAL="6" SDNUM="3081;">

+						<P ALIGN=LEFT>6</P>

+					</TD>

+				</TR>

+				<TR>

+					<TD WIDTH=50 VALIGN=BOTTOM SDVAL="31" SDNUM="3081;">

+						<P ALIGN=CENTER>31</P>

+					</TD>

+					<TD WIDTH=356 VALIGN=TOP>

+						<P ALIGN=LEFT>REALTIME_PRIORITY_CLASS</P>

+					</TD>

+					<TD WIDTH=336 VALIGN=TOP>

+						<P ALIGN=LEFT>THREAD_PRIORITY_TIME_CRITICAL</P>

+					</TD>

+				</TR>

+			</TBODY>

+		</TABLE>

+	</DL>

+</DL>

+<P STYLE="margin-left: 2cm">Windows NT: Values -7, -6, -5, -4, -3, 3,

+4, 5, and 6 are not supported.</P>

+<P STYLE="margin-left: 2cm">As you can see, the real priority levels

+available to any individual Win32 thread are non-contiguous.</P>

+<P STYLE="margin-left: 2cm">An application using Pthreads-w32 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.</P>

+<P STYLE="margin-left: 2cm">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_CLASS even if levels -7, -6, -5, -4, -3, 3, 4, 5,

+and 6 are supported.</P>

+<P STYLE="margin-left: 2cm">If it wishes, a Win32 application using

+pthreads-w32 can use the Win32 defined priority macros

+THREAD_PRIORITY_IDLE through THREAD_PRIORITY_TIME_CRITICAL.</P>

+<H2><A HREF="#toc3" NAME="sect3">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc4" NAME="sect4">See also</A></H2>

+<P><BR><BR>

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Author</A>

+		</P>

+	<LI><P><A HREF="#sect4" NAME="toc4">See also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/index.html b/manual/index.html
new file mode 100644
index 0000000..2fa01d2
--- /dev/null
+++ b/manual/index.html
@@ -0,0 +1,146 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE></TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;17350500">

+	<META NAME="CHANGED" CONTENT="20050506;12240700">

+</HEAD>

+<BODY LANG="en-GB" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<H3>Table of Contents</H3>

+<P STYLE="margin-left: 2cm"><A HREF="#sect1" NAME="toc1">POSIX

+threads API reference</A><BR><A HREF="#sect2" NAME="toc2">Miscellaneous

+POSIX thread safe routines provided by Pthreads-w32</A><BR><A HREF="#sect3" NAME="toc3">Non-portable

+Pthreads-w32 routines</A><BR><A HREF="#sect4" NAME="toc4">Other</A></P>

+<H2><A HREF="#toc1" NAME="sect1">POSIX threads API reference</A></H2>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_getdetachstate</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_getinheritsched</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_getschedparam</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_getschedpolicy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_getscope</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_setstackaddr.html"><B>pthread_attr_getstackaddr</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_setstacksize.html"><B>pthread_attr_getstacksize</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_setdetachstate</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_setinheritsched</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_setschedparam</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_setschedpolicy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_init.html"><B>pthread_attr_setscope</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_setstackaddr.html"><B>pthread_attr_setstackaddr</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_attr_setstacksize.html"><B>pthread_attr_setstacksize</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrierattr_init.html"><B>pthread_barrierattr_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrierattr_setpshared.html"><B>pthread_barrierattr_getpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrierattr_init.html"><B>pthread_barrierattr_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrierattr_setpshared.html"><B>pthread_barrierattr_setpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrier_init.html"><B>pthread_barrier_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrier_init.html"><B>pthread_barrier_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cancel.html"><B>pthread_cancel</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cleanup_push.html"><B>pthread_cleanup_pop</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cleanup_push.html"><B>pthread_cleanup_push</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_condattr_init.html"><B>pthread_condattr_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_condattr_setpshared.html"><B>pthread_condattr_getpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_condattr_init.html"><B>pthread_condattr_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_condattr_setpshared.html"><B>pthread_condattr_setpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cond_init.html"><B>pthread_cond_broadcast</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cond_init.html"><B>pthread_cond_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cond_init.html"><B>pthread_cond_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cond_init.html"><B>pthread_cond_signal</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cond_init.html"><B>pthread_cond_timedwait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cond_init.html"><B>pthread_cond_wait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_create.html"><B>pthread_create</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_detach.html"><B>pthread_detach</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_equal.html"><B>pthread_equal</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_exit.html"><B>pthread_exit</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_setconcurrency.html"><B>pthread_getconcurrency</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_setschedparam.html"><B>pthread_getschedparam</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_key_create.html"><B>pthread_getspecific</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_join.html"><B>pthread_join</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_key_create.html"><B>pthread_key_create</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_key_create.html"><B>pthread_key_delete</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_kill.html"><B>pthread_kill</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_getkind_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_setpshared.html"><B>pthread_mutexattr_getpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_gettype</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_setkind_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_setpshared.html"><B>pthread_mutexattr_setpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_settype</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutex_init.html"><B>pthread_mutex_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutex_init.html"><B>pthread_mutex_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutex_init.html"><B>pthread_mutex_lock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutex_init.html"><B>pthread_mutex_timedlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutex_init.html"><B>pthread_mutex_trylock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_mutex_init.html"><B>pthread_mutex_unlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_once.html"><B>pthread_once</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlockattr_init.html"><B>pthread_rwlockattr_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlockattr_setpshared.html"><B>pthread_rwlockattr_getpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlockattr_init.html"><B>pthread_rwlockattr_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlockattr_setpshared.html"><B>pthread_rwlockattr_setpshared</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_timedrdlock.html"><B>pthread_rwlock_timedrdlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_timedwrlock.html"><B>pthread_rwlock_timedwrlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_tryrdlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_trywrlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_self.html"><B>pthread_self</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cancel.html"><B>pthread_setcancelstate</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cancel.html"><B>pthread_setcanceltype</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_setconcurrency.html"><B>pthread_setconcurrency</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_setschedparam.html"><B>pthread_setschedparam</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_key_create.html"><B>pthread_setspecific</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_kill.html"><B>pthread_sigmask</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_spin_init.html"><B>pthread_spin_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_spin_init.html"><B>pthread_spin_init</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_spin_lock.html"><B>pthread_spin_lock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_spin_lock.html"><B>pthread_spin_trylock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_spin_unlock.html"><B>pthread_spin_unlock</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_cancel.html"><B>pthread_testcancel</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sched_get_priority_max.html"><B>sched_get_priority_max</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sched_get_priority_max.html"><B>sched_get_priority_min</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sched_getscheduler.html"><B>sched_getscheduler</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sched_setscheduler.html"><B>sched_setscheduler</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sched_yield.html"><B>sched_yield</B></A></P>

+<P STYLE="margin-left: 2cm"><B>sem_close</B></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_destroy</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_getvalue</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_init</B></A></P>

+<P STYLE="margin-left: 2cm"><B>sem_open</B></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_post</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_post_multiple</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_timedwait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_trywait</B></A></P>

+<P STYLE="margin-left: 2cm"><B>sem_unlink</B></P>

+<P STYLE="margin-left: 2cm"><A HREF="sem_init.html"><B>sem_wait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_kill.html"><B>sigwait</B></A></P>

+<H2><A HREF="#toc2" NAME="sect2">Miscellaneous POSIX thread safe

+routines provided by Pthreads-w32</A></H2>

+<P STYLE="margin-left: 2cm"><B>asctime_r</B></P>

+<P STYLE="margin-left: 2cm"><B>ctime_r</B></P>

+<P STYLE="margin-left: 2cm"><B>gmtime_r</B></P>

+<P STYLE="margin-left: 2cm"><B>localtime_r</B></P>

+<P STYLE="margin-left: 2cm"><B>rand_r</B></P>

+<H2><A HREF="#toc3" NAME="sect3">Non-portable Pthreads-w32 routines</A></H2>

+<P STYLE="margin-left: 2cm"><A HREF="pthreadCancelableWait.html"><B>pthreadCancelableTimedWait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthreadCancelableWait.html"><B>pthreadCancelableWait</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_delay_np.html"><B>pthread_delay_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_getw32threadhandle_np.html"><B>pthread_getw32threadhandle_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_num_processors_np.html"><B>pthread_num_processors_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_win32_test_features_np.html"><B>pthread_win32_test_features_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_timechange_handler_np.html"><B>pthread_timechange_handler_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_win32_attach_detach_np.html"><B>pthread_win32_process_attach_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_win32_attach_detach_np.html"><B>pthread_win32_process_detach_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_win32_attach_detach_np.html"><B>pthread_win32_thread_attach_np</B></A></P>

+<P STYLE="margin-left: 2cm"><A HREF="pthread_win32_attach_detach_np.html"><B>pthread_win32_thread_detach_np</B></A></P>

+<H2><A HREF="#toc4" NAME="sect4">Other</A></H2>

+<P STYLE="margin-left: 2cm"><A HREF="PortabilityIssues.html"><B>Portability

+issues</B></A></P>

+</BODY>

+</HTML>

diff --git a/manual/pthreadCancelableWait.html b/manual/pthreadCancelableWait.html
new file mode 100644
index 0000000..ae5e80d
--- /dev/null
+++ b/manual/pthreadCancelableWait.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREADCANCELLABLEWAIT manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050505;23242300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthreadCancelableTimedWait,

+pthreadCancelableWait – provide cancellation hooks for user Win32

+routines</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthreadCancelableTimedWait (HANDLE </B><I>waitHandle</I><B>,

+DWORD </B><I>timeout</I><B>);</B></P>

+<P><B>int pthreadCancelableWait (HANDLE </B><I>waitHandle</I><B>);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>These two functions provide hooks into the <A HREF="pthread_cancel.html"><B>pthread_cancel</B></A>()

+mechanism that will allow you to wait on a Windows handle and make it

+a cancellation point. Both functions block until either the given

+Win32 <B>HANDLE</B> is signalled, or <A HREF="pthread_cancel.html"><B>pthread_cancel</B></A>()

+has been called. They are implemented using <B>WaitForMultipleObjects</B>

+on <I>waitHandle</I> and the manually reset Win32 event handle that

+is the target of <A HREF="pthread_cancel.html"><B>pthread_cancel</B></A>().

+These routines may be called from Win32 native threads but

+<A HREF="pthread_cancel.html"><B>pthread_cancel</B></A>() will

+require that thread's POSIX thread ID that the thread must retrieve

+using <A HREF="pthread_self.html"><B>pthread_self</B></A>().</P>

+<P><B>pthreadCancelableTimedWait</B> is the timed version that will

+return with the code <B>ETIMEDOUT</B> if the interval <I>timeout</I>

+milliseconds elapses before <I>waitHandle</I> is signalled.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>These routines allow routines that block on Win32 HANDLEs to be

+cancellable via <A HREF="pthread_cancel.html"><B>pthread_cancel</B></A>().</P>

+<H2><A HREF="#toc4" NAME="sect4">Return Value</A></H2>

+<P><BR><BR>

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>The <B>pthreadCancelableTimedWait</B> function returns the

+following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ETIMEDOUT</B>

+				</DT></DL>

+</DL>

+<P STYLE="margin-left: 2cm">

+The interval <I>timeout</I> milliseconds elapsed before <I>waitHandle</I>

+was signalled.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc7" NAME="sect7">See also</A></H2>

+<P><A HREF="pthread_cancel.html"><B>pthread_cancel()</B></A>,

+<A HREF="pthread_self.html"><B>pthread_self()</B></A></P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4"></A><A HREF="#sect4" NAME="toc4">Return

+	Value</A><A HREF="#sect4" NAME="toc4"></A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Author</A>

+		</P>

+	<LI><P><A HREF="#sect7" NAME="toc7">See also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_attr_init.html b/manual/pthread_attr_init.html
new file mode 100644
index 0000000..7da0248
--- /dev/null
+++ b/manual/pthread_attr_init.html
@@ -0,0 +1,280 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_ATTR_INIT(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;10092900">

+	<META NAME="CHANGED" CONTENT="20050505;16540200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_attr_init, pthread_attr_destroy,

+pthread_attr_setdetachstate, pthread_attr_getdetachstate,

+pthread_attr_setschedparam, pthread_attr_getschedparam,

+pthread_attr_setschedpolicy, pthread_attr_getschedpolicy,

+pthread_attr_setinheritsched, pthread_attr_getinheritsched,

+pthread_attr_setscope, pthread_attr_getscope - thread creation

+attributes 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_attr_init(pthread_attr_t *</B><I>attr</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_destroy(pthread_attr_t *</B><I>attr</I><B>);</B>

+</P>

+<P><B>int pthread_attr_setdetachstate(pthread_attr_t *</B><I>attr</I><B>,

+int </B><I>detachstate</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_getdetachstate(const pthread_attr_t *</B><I>attr</I><B>,

+int *</B><I>detachstate</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_setschedpolicy(pthread_attr_t *</B><I>attr</I><B>,

+int </B><I>policy</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_getschedpolicy(const pthread_attr_t *</B><I>attr</I><B>,

+int *</B><I>policy</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_setschedparam(pthread_attr_t *</B><I>attr</I><B>,

+const struct sched_param *</B><I>param</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_getschedparam(const pthread_attr_t *</B><I>attr</I><B>,

+struct sched_param *</B><I>param</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_setinheritsched(pthread_attr_t *</B><I>attr</I><B>,

+int </B><I>inherit</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_getinheritsched(const pthread_attr_t *</B><I>attr</I><B>,

+int *</B><I>inherit</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_setscope(pthread_attr_t *</B><I>attr</I><B>,

+int </B><I>scope</I><B>);</B> 

+</P>

+<P><B>int pthread_attr_getscope(const pthread_attr_t *</B><I>attr</I><B>,

+int *</B><I>scope</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Setting attributes for threads is achieved by filling a thread

+attribute object <I>attr</I> of type <B>pthread_attr_t</B>, then

+passing it as second argument to <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A>

+. Passing <B>NULL</B> is equivalent to passing a thread attribute

+object with all attributes set to their default values. 

+</P>

+<P><B>pthread_attr_init</B> initializes the thread attribute object

+<I>attr</I> and fills it with default values for the attributes. (The

+default values are listed below for each attribute.) 

+</P>

+<P>Each attribute <I>attrname</I> (see below for a list of all

+attributes) can be individually set using the function

+<B>pthread_attr_set</B><I>attrname</I> and retrieved using the

+function <B>pthread_attr_get</B><I>attrname.</I> 

+</P>

+<P><B>pthread_attr_destroy</B> destroys a thread attribute object,

+which must not then be reused until it is reinitialized. 

+</P>

+<P>Attribute objects are consulted only when creating a new thread.

+The same attribute object can be used for creating several threads.

+Modifying an attribute object after a call to <B>pthread_create</B>

+does not change the attributes of the thread previously created. 

+</P>

+<P>The following thread attributes are supported: 

+</P>

+<H3><A HREF="#toc3" NAME="sect3">detachstate</A></H3>

+<P>Control whether the thread is created in the joinable state (value

+<B>PTHREAD_CREATE_JOINABLE</B>) or in the detached state (

+<B>PTHREAD_CREATE_DETACHED</B>). 

+</P>

+<P>Default value: <B>PTHREAD_CREATE_JOINABLE</B>. 

+</P>

+<P>In the joinable state, another thread can synchronize on the

+thread termination and recover its termination code using

+<A HREF="pthread_join.html"><B>pthread_join</B>(3)</A> . When a

+joinable thread terminates, some of the thread resources are kept

+allocated, and released only when another thread performs

+<A HREF="pthread_join.html"><B>pthread_join</B>(3)</A> on that

+thread. 

+</P>

+<P>In the detached state, the thread's resources are released

+immediately when it terminates. <A HREF="pthread_join.html"><B>pthread_join</B>(3)</A>

+cannot be used to synchronize on the thread termination. 

+</P>

+<P>A thread created in the joinable state can later be put in the

+detached thread using <A HREF="pthread_detach.html"><B>pthread_detach</B>(3)</A>

+. 

+</P>

+<H3><A HREF="#toc4" NAME="sect4">schedpolicy</A></H3>

+<P>Select the scheduling policy for the thread: one of <B>SCHED_OTHER</B>

+(regular, non-real-time scheduling), <B>SCHED_RR</B> (real-time,

+round-robin) or <B>SCHED_FIFO</B> (real-time, first-in first-out). 

+</P>

+<P><B>Pthreads-w32</B> only supports <B>SCHED_OTHER</B> - attempting

+to set one of the other policies will return an error ENOTSUP.</P>

+<P>Default value: <B>SCHED_OTHER</B>. 

+</P>

+<P><B>Pthreads-w32</B> only supports <B>SCHED_OTHER</B> - attempting

+to set one of the other policies will return an error ENOTSUP.</P>

+<P>The scheduling policy of a thread can be changed after creation

+with <A HREF="pthread_setschedparam.html"><B>pthread_setschedparam</B>(3)</A>

+. 

+</P>

+<H3><A HREF="#toc5" NAME="sect5">schedparam</A></H3>

+<P>Contain the scheduling parameters (essentially, the scheduling

+priority) for the thread.</P>

+<P><B>Pthreads-w32</B> supports the priority levels defined by the

+Windows system it is running on. Under Windows, thread priorities are

+relative to the process priority class, which must be set via the

+Windows W32 API.</P>

+<P>Default value: priority is 0 (Win32 level <B>THREAD_PRIORITY_NORMAL</B>).

+</P>

+<P>The scheduling priority of a thread can be changed after creation

+with <A HREF="pthread_setschedparam.html"><B>pthread_setschedparam</B>(3)</A>

+. 

+</P>

+<H3><A HREF="#toc6" NAME="sect6">inheritsched</A></H3>

+<P>Indicate whether the scheduling policy and scheduling parameters

+for the newly created thread are determined by the values of the

+<I>schedpolicy</I> and <I>schedparam</I> attributes (value

+<B>PTHREAD_EXPLICIT_SCHED</B>) or are inherited from the parent

+thread (value <B>PTHREAD_INHERIT_SCHED</B>). 

+</P>

+<P>Default value: <B>PTHREAD_EXPLICIT_SCHED</B>. 

+</P>

+<H3><A HREF="#toc7" NAME="sect7">scope</A></H3>

+<P>Define the scheduling contention scope for the created thread. The

+only value supported in the <B>Pthreads-w32</B> implementation is

+<B>PTHREAD_SCOPE_SYSTEM</B>, meaning that the threads contend for CPU

+time with all processes running on the machine. The other value

+specified by the standard, <B>PTHREAD_SCOPE_PROCESS</B>, means that

+scheduling contention occurs only between the threads of the running

+process.</P>

+<P><B>Pthreads-w32</B> only supports <B>PTHREAD_SCOPE_SYSTEM</B>.</P>

+<P>Default value: <B>PTHREAD_SCOPE_SYSTEM</B>. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Return Value</A></H2>

+<P>All functions return 0 on success and a non-zero error code on

+error. On success, the <B>pthread_attr_get</B><I>attrname</I>

+functions also store the current value of the attribute <I>attrname</I>

+in the location pointed to by their second argument. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">Errors</A></H2>

+<P>The <B>pthread_attr_setdetachstate</B> function returns the

+following error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the specified <I>detachstate</I> is not one of

+		<B>PTHREAD_CREATE_JOINABLE</B> or <B>PTHREAD_CREATE_DETACHED</B>. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_attr_setschedparam</B> function returns the following

+error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the priority specified in <I>param</I> is outside the range of

+		allowed priorities for the scheduling policy currently in <I>attr</I>

+		(1 to 99 for <B>SCHED_FIFO</B> and <B>SCHED_RR</B>; 0 for

+		<B>SCHED_OTHER</B>). 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_attr_setschedpolicy</B> function returns the following

+error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the specified <I>policy</I> is not one of <B>SCHED_OTHER</B>,

+		<B>SCHED_FIFO</B>, or <B>SCHED_RR</B>. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ENOTSUP</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<I>policy</I> is not <B>SCHED_OTHER</B>, the only value supported

+		by <B>Pthreads-w32</B>.</DD></DL>

+</DL>

+<P>

+The <B>pthread_attr_setinheritsched</B> function returns the

+following error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the specified <I>inherit</I> is not one of <B>PTHREAD_INHERIT_SCHED</B>

+		or <B>PTHREAD_EXPLICIT_SCHED</B>. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_attr_setscope</B> function returns the following error

+codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the specified <I>scope</I> is not one of <B>PTHREAD_SCOPE_SYSTEM</B>

+		or <B>PTHREAD_SCOPE_PROCESS</B>. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ENOTSUP</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the specified <I>scope</I> is <B>PTHREAD_SCOPE_PROCESS</B> (not

+		supported by <B>Pthreads-w32</B>). 

+		</DD></DL>

+</DL>

+<H2>

+<A HREF="#toc10" NAME="sect10">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc11" NAME="sect11">See Also</A></H2>

+<P><A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> ,

+<A HREF="pthread_join.html"><B>pthread_join</B>(3)</A> ,

+<A HREF="pthread_detach.html"><B>pthread_detach</B>(3)</A> ,

+<A HREF="pthread_setschedparam.html"><B>pthread_setschedparam</B>(3)</A>

+. 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<UL>

+		<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">detachstate</A>

+				</P>

+		<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">schedpolicy</A>

+				</P>

+		<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">schedparam</A>

+				</P>

+		<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">inheritsched</A>

+				</P>

+		<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">scope</A>

+				</P>

+	</UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect10" NAME="toc10">Author</A>

+		</P>

+	<LI><P><A HREF="#sect11" NAME="toc11">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_attr_setstackaddr.html b/manual/pthread_attr_setstackaddr.html
new file mode 100644
index 0000000..38a4355
--- /dev/null
+++ b/manual/pthread_attr_setstackaddr.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_ATTR_GETSTACKADDR&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;11025500">

+	<META NAME="CHANGED" CONTENT="20050505;17571400">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_attr_getstackaddr, pthread_attr_setstackaddr - get and set

+the stackaddr attribute 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_attr_getstackaddr(const pthread_attr_t *restrict</B>

+<I>attr</I><B>, void **restrict</B> <I>stackaddr</I><B>); <BR>int

+pthread_attr_setstackaddr(pthread_attr_t *</B><I>attr</I><B>, void

+*</B><I>stackaddr</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_attr_getstackaddr</B> and <B>pthread_attr_setstackaddr</B>

+functions, respectively, shall get and set the thread creation

+<I>stackaddr</I> attribute in the <I>attr</I> object. 

+</P>

+<P>The <I>stackaddr</I> attribute specifies the location of storage

+to be used for the created thread’s stack. The size of the storage

+shall be at least {PTHREAD_STACK_MIN}. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_THREAD_ATTR_STACKADDR</B> in

+pthread.h as -1 to indicate that these routines are implemented but

+cannot used to set or get the stack address. These routines always

+return the error ENOSYS when called.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, <B>pthread_attr_getstackaddr</B> and

+<B>pthread_attr_setstackaddr</B> shall return a value of 0;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<P>The <B>pthread_attr_getstackaddr</B> function stores the <I>stackaddr</I>

+attribute value in <I>stackaddr</I> if successful. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_attr_setstackaddr</B> function always returns the

+following error code: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ENOSYS</B></DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The function is not supported. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_attr_getstackaddr</B> function always returns the

+following error code: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ENOSYS</B></DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The function is not supported. 

+		</DD></DL>

+</DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>The specification of the <I>stackaddr</I> attribute presents

+several ambiguities that make portable use of these interfaces

+impossible. The description of the single address parameter as a

+&quot;stack&quot; does not specify a particular relationship between

+the address and the &quot;stack&quot; implied by that address. For

+example, the address may be taken as the low memory address of a

+buffer intended for use as a stack, or it may be taken as the address

+to be used as the initial stack pointer register value for the new

+thread. These two are not the same except for a machine on which the

+stack grows &quot;up&quot; from low memory to high, and on which a

+&quot;push&quot; operation first stores the value in memory and then

+increments the stack pointer register. Further, on a machine where

+the stack grows &quot;down&quot; from high memory to low,

+interpretation of the address as the &quot;low memory&quot; address

+requires a determination of the intended size of the stack.

+IEEE&nbsp;Std&nbsp;1003.1-2001 has introduced the new interfaces

+<A HREF="pthread_attr_setstack.html"><B>pthread_attr_setstack</B>(3)</A>

+and <A HREF="pthread_attr_getstack.html"><B>pthread_attr_getstack</B>(3)</A>

+to resolve these ambiguities. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_attr_init.html"><B>pthread_attr_destroy</B>(3)</A>

+, <A HREF="pthread_attr_init.html"><B>pthread_attr_getdetachstate</B>(3)</A>

+, <A HREF="pthread_attr_getstack.html"><B>pthread_attr_getstack</B>(3)</A>

+, <A HREF="pthread_attr_getstacksize.html"><B>pthread_attr_getstacksize</B>(3)</A>

+, <A HREF="pthread_attr_setstack.html"><B>pthread_attr_setstack</B>(3)</A>

+, <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> , the

+Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;limits.h&gt;</I>, <I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_attr_setstacksize.html b/manual/pthread_attr_setstacksize.html
new file mode 100644
index 0000000..0d9672b
--- /dev/null
+++ b/manual/pthread_attr_setstacksize.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_ATTR_GETSTACKSIZE&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;11224900">

+	<META NAME="CHANGED" CONTENT="20050505;18003200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_attr_getstacksize, pthread_attr_setstacksize - get and set

+the stacksize attribute 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_attr_getstacksize(const pthread_attr_t *restrict</B>

+<I>attr</I><B>, size_t *restrict</B> <I>stacksize</I><B>); <BR>int

+pthread_attr_setstacksize(pthread_attr_t *</B><I>attr</I><B>, size_t</B>

+<I>stacksize</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_attr_getstacksize</B> and <B>pthread_attr_setstacksize</B>

+functions, respectively, shall get and set the thread creation

+<I>stacksize</I> attribute in the <I>attr</I> object. 

+</P>

+<P>The <I>stacksize</I> attribute shall define the minimum stack size

+(in bytes) allocated for the created threads stack. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_THREAD_ATTR_STACKSIZE</B> in

+pthread.h to indicate that these routines are implemented and may be

+used to set or get the stack size.</P>

+<P>Default value: 0 (in Pthreads-w32 a value of 0 means the stack

+will grow as required)</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, <B>pthread_attr_getstacksize</B> and

+<B>pthread_attr_setstacksize</B> shall return a value of 0;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<P>The <B>pthread_attr_getstacksize</B> function stores the <I>stacksize</I>

+attribute value in <I>stacksize</I> if successful. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_attr_setstacksize</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value of <I>stacksize</I> is less than {PTHREAD_STACK_MIN} or

+	exceeds a system-imposed limit. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_attr_init.html"><B>pthread_attr_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_attr_setstackaddr.html"><B>pthread_attr_getstackaddr</B>(3)</A>

+<B>,</B> <A HREF="pthread_attr_init.html"><B>pthread_attr_getdetachstate</B>(3)</A>

+<B>,</B> <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> <B>,</B>

+the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;limits.h&gt;</I>, <I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_barrier_init.html b/manual/pthread_barrier_init.html
new file mode 100644
index 0000000..bc3324c
--- /dev/null
+++ b/manual/pthread_barrier_init.html
@@ -0,0 +1,200 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_BARRIER_DESTROY&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 2.0  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;11372800">

+	<META NAME="CHANGEDBY" CONTENT="Ross Johnson">

+	<META NAME="CHANGED" CONTENT="20060408;9450100">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_barrier_destroy, pthread_barrier_init - destroy and

+initialize a barrier object (<B>ADVANCED REALTIME THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_barrier_destroy(pthread_barrier_t *</B><I>barrier</I><B>);

+<BR>int pthread_barrier_init(pthread_barrier_t *restrict</B> <I>barrier</I><B>,

+const pthread_barrierattr_t *restrict</B> <I>attr</I><B>, unsigned</B>

+<I>count</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_barrier_destroy</B> function shall destroy the

+barrier referenced by <I>barrier</I> and release any resources used

+by the barrier. The effect of subsequent use of the barrier is

+undefined until the barrier is reinitialized by another call to

+<B>pthread_barrier_init</B> . An implementation may use this function

+to set <I>barrier</I> to an invalid value. The results are undefined

+if <B>pthread_barrier_destroy</B> is called when any thread is

+blocked on the barrier, or if this function is called with an

+uninitialized barrier. 

+</P>

+<P>The <B>pthread_barrier_init</B> function shall allocate any

+resources required to use the barrier referenced by <I>barrier</I>

+and shall initialize the barrier with attributes referenced by <I>attr</I>.

+If <I>attr</I> is NULL, the default barrier attributes shall be used;

+the effect is the same as passing the address of a default barrier

+attributes object. The results are undefined if <B>pthread_barrier_init</B>

+is called when any thread is blocked on the barrier (that is, has not

+returned from the <A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A>

+call). The results are undefined if a barrier is used without first

+being initialized. The results are undefined if <B>pthread_barrier_init</B>

+is called specifying an already initialized barrier. 

+</P>

+<P>The <I>count</I> argument specifies the number of threads that

+must call <A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A>

+before any of them successfully return from the call. The value

+specified by <I>count</I> must be greater than zero. 

+</P>

+<P>If the <B>pthread_barrier_init</B> function fails, the barrier

+shall not be initialized and the contents of <I>barrier</I> are

+undefined. 

+</P>

+<P>Only the object referenced by <I>barrier</I> may be used for

+performing synchronization. The result of referring to copies of that

+object in calls to <B>pthread_barrier_destroy</B> <B>or</B>

+<A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A>

+is undefined.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, these functions shall return zero;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_barrier_destroy</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD>

+	The implementation has detected an attempt to destroy a barrier

+	while it is in use (for example, while being used in a

+	<A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A>

+	call) by another thread. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>barrier</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_barrier_init</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EAGAIN</B> 

+	</DT><DD>

+	The system lacks the necessary resources to initialize another

+	barrier. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD>

+	The value specified by <I>count</I> is equal to zero. 

+	</DD><DT>

+	<B>ENOMEM</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	Insufficient memory exists to initialize the barrier. 

+	</DD></DL>

+<P>

+The <B>pthread_barrier_init</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD>

+	The implementation has detected an attempt to reinitialize a barrier

+	while it is in use (for example, while being used in a

+	<A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A>

+	call) by another thread. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>The <B>pthread_barrier_destroy</B> and <B>pthread_barrier_init</B>

+functions are part of the Barriers option and need not be provided on

+all implementations. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_BARRIERS</B> to indicate

+that these routines are implemented and may be used.</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc11" NAME="sect11">Known Bugs</A></H2>

+<DL>

+	<DD STYLE="margin-left: 0cm; margin-bottom: 0.5cm">In

+	<B><SPAN LANG="en-GB"><SPAN LANG="en-GB">pthreads-win32</SPAN></SPAN></B>,

+	<A HREF="pthread_barrier_wait.html"></A><A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A><A HREF="pthread_barrier_wait.html"></A>

+	may deadlock if the number of running threads able to wait on the

+	barrier object exceeds the value given as the <I><SPAN LANG="en-GB"><SPAN LANG="en-GB">count</SPAN></SPAN></I>

+	parameter in <B>pthread_barrier_init</B>. 

+	</DD></DL>

+<H2>

+<A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_barrier_wait.html"><B>pthread_barrier_wait</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect11" NAME="toc11">Known

+	Bugs</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/pthread_barrier_wait.html b/manual/pthread_barrier_wait.html
new file mode 100644
index 0000000..4db0594
--- /dev/null
+++ b/manual/pthread_barrier_wait.html
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_BARRIER_WAIT&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 2.0  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;11484200">

+	<META NAME="CHANGEDBY" CONTENT="Ross Johnson">

+	<META NAME="CHANGED" CONTENT="20060408;9504600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_barrier_wait - synchronize at a barrier (<B>ADVANCED

+REALTIME THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_barrier_wait(pthread_barrier_t *</B><I>barrier</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_barrier_wait</B> function shall synchronize

+participating threads at the barrier referenced by <I>barrier</I>.

+The calling thread shall block until the required number of threads

+have called <B>pthread_barrier_wait</B> specifying the barrier. 

+</P>

+<P>When the required number of threads have called

+<B>pthread_barrier_wait</B> specifying the barrier, the constant

+<B>PTHREAD_BARRIER_SERIAL_THREAD</B> shall be returned to one

+unspecified thread and zero shall be returned to each of the

+remaining threads. At this point, the barrier shall be reset to the

+state it had as a result of the most recent <A HREF="pthread_barrier_init.html"><B>pthread_barrier_init</B>(3)</A>

+function that referenced it. 

+</P>

+<P>The constant <B>PTHREAD_BARRIER_SERIAL_THREAD</B> is defined in

+<I>&lt;pthread.h&gt;</I> and its value shall be distinct from any

+other value returned by <B>pthread_barrier_wait</B> . 

+</P>

+<P>The results are undefined if this function is called with an

+uninitialized barrier. 

+</P>

+<P>If a signal is delivered to a thread blocked on a barrier, upon

+return from the signal handler the thread shall resume waiting at the

+barrier if the barrier wait has not completed (that is, if the

+required number of threads have not arrived at the barrier during the

+execution of the signal handler); otherwise, the thread shall

+continue as normal from the completed barrier wait. Until the thread

+in the signal handler returns from it, it is unspecified whether

+other threads may proceed past the barrier once they have all reached

+it. 

+</P>

+<P>A thread that has blocked on a barrier shall not prevent any

+unblocked thread that is eligible to use the same processing

+resources from eventually making forward progress in its execution.

+Eligibility for processing resources shall be determined by the

+scheduling policy. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, the <B>pthread_barrier_wait</B>

+function shall return <B>PTHREAD_BARRIER_SERIAL_THREAD</B> for a

+single (arbitrary) thread synchronized at the barrier and zero for

+each of the other threads. Otherwise, an error number shall be

+returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_barrier_wait</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>barrier</I> does not refer to an

+	initialized barrier object. 

+	</DD></DL>

+<P>

+This function shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using this function may be subject to priority

+inversion, as discussed in the Base Definitions volume of

+IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285, Priority Inversion. 

+</P>

+<P>The <B>pthread_barrier_wait</B> function is part of the Barriers

+option and need not be provided on all implementations. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_BARRIERS</B> to indicate

+that this routine is implemented and may be used.</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc11" NAME="sect11">Known Bugs</A></H2>

+<DL>

+	<DD STYLE="margin-left: 0cm; margin-bottom: 0.5cm">In

+	<B><SPAN LANG="en-GB">pthreads-win32</SPAN></B>,

+	<B>pthread_barrier_wait</B> may deadlock if the number of running

+	threads able to wait on the barrier object exceeds the value given

+	as the <I><SPAN LANG="en-GB">count</SPAN></I> parameter in

+	<A HREF="pthread_barrier_init.html"><B>pthread_barrier_init(3)</B></A>.

+		</DD></DL>

+<H2>

+<A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_barrier_init.html"><B>pthread_barrier_destroy</B>(3)</A>,

+<A HREF="pthread_barrier_init.html"><B>pthread_barrier_init(3)</B></A>,

+the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect11" NAME="toc11">Known

+	Bugs</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/pthread_barrierattr_init.html b/manual/pthread_barrierattr_init.html
new file mode 100644
index 0000000..87f846f
--- /dev/null
+++ b/manual/pthread_barrierattr_init.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_BARRIERATTR_DESTROY&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;11502600">

+	<META NAME="CHANGED" CONTENT="20050505;18032300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_barrierattr_destroy, pthread_barrierattr_init - destroy

+and initialize the barrier attributes object (<B>ADVANCED REALTIME

+THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P>i<B>nt pthread_barrierattr_destroy(pthread_barrierattr_t *</B><I>attr</I><B>);

+<BR>int pthread_barrierattr_init(pthread_barrierattr_t *</B><I>attr</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_barrierattr_destroy</B> function shall destroy a

+barrier attributes object. A destroyed <I>attr</I> attributes object

+can be reinitialized using <B>pthread_barrierattr_init</B> ; the

+results of otherwise referencing the object after it has been

+destroyed are undefined. An implementation may cause

+<B>pthread_barrierattr_destroy</B> to set the object referenced by

+<I>attr</I> to an invalid value. 

+</P>

+<P>The <B>pthread_barrierattr_init</B> function shall initialize a

+barrier attributes object <I>attr</I> with the default value for all

+of the attributes defined by the implementation. 

+</P>

+<P>Results are undefined if <B>pthread_barrierattr_init</B> is called

+specifying an already initialized <I>attr</I> attributes object. 

+</P>

+<P>After a barrier attributes object has been used to initialize one

+or more barriers, any function affecting the attributes object

+(including destruction) shall not affect any previously initialized

+barrier. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_barrierattr_destroy</B> and

+<B>pthread_barrierattr_init</B> functions shall return zero;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_barrierattr_destroy</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_barrierattr_init</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>ENOMEM</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	Insufficient memory exists to initialize the barrier attributes

+	object. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>The <B>pthread_barrierattr_destroy</B> and

+<B>pthread_barrierattr_init</B> functions are part of the Barriers

+option and need not be provided on all implementations. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_BARRIERS</B> to indicate

+that these routines are implemented and may be used.</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_barrierattr_setpshared.html"><B>pthread_barrierattr_getpshared</B>(3)</A>

+<B>,</B> <A HREF="pthread_barrierattr_setpshared.html"><B>pthread_barrierattr_setpshared</B>(3)</A>

+, the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I>. 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_barrierattr_setpshared.html b/manual/pthread_barrierattr_setpshared.html
new file mode 100644
index 0000000..dc96543
--- /dev/null
+++ b/manual/pthread_barrierattr_setpshared.html
@@ -0,0 +1,159 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_BARRIERATTR_GETPSHARED&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;11552100">

+	<META NAME="CHANGED" CONTENT="20050505;18080400">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_barrierattr_getpshared, pthread_barrierattr_setpshared -

+get and set the process-shared attribute of the barrier attributes

+object (<B>ADVANCED REALTIME THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_barrierattr_getpshared(const pthread_barrierattr_t

+* restrict</B> <I>attr</I><B>, int *restrict</B> <I>pshared</I><B>);

+<BR>int pthread_barrierattr_setpshared(pthread_barrierattr_t *</B><I>attr</I><B>,

+int</B> <I>pshared</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_barrierattr_getpshared</B> function shall obtain

+the value of the <I>process-shared</I> attribute from the attributes

+object referenced by <I>attr</I>. The <B>pthread_barrierattr_setpshared</B>

+function shall set the <I>process-shared</I> attribute in an

+initialized attributes object referenced by <I>attr</I>. 

+</P>

+<P>The <I>process-shared</I> attribute is set to

+PTHREAD_PROCESS_SHARED to permit a barrier to be operated upon by any

+thread that has access to the memory where the barrier is allocated.

+If the <I>process-shared</I> attribute is PTHREAD_PROCESS_PRIVATE,

+the barrier shall only be operated upon by threads created within the

+same process as the thread that initialized the barrier; if threads

+of different processes attempt to operate on such a barrier, the

+behavior is undefined. The default value of the attribute shall be

+PTHREAD_PROCESS_PRIVATE. Both constants PTHREAD_PROCESS_SHARED and

+PTHREAD_PROCESS_PRIVATE are defined in <I>&lt;pthread.h&gt;</I>. 

+</P>

+<P><B>Pthreads-w32</B> defines _<B>POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that these routines are implemented but

+that the process shared attribute is not supported.</P>

+<P>Additional attributes, their default values, and the names of the

+associated functions to get and set those attribute values are

+implementation-defined. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_barrierattr_getpshared</B> function

+shall return zero and store the value of the <I>process-shared</I>

+attribute of <I>attr</I> into the object referenced by the <I>pshared</I>

+parameter. Otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<P>If successful, the <B>pthread_barrierattr_setpshared</B> function

+shall return zero; otherwise, an error number shall be returned to

+indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>These functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD><DT>

+	The <B>pthread_barrierattr_setpshared</B> function may fail if: 

+	</DT><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The new value specified for the <I>process-shared</I> attribute is

+	not one of the legal values <B>PTHREAD_PROCESS_SHARED</B> or

+	<B>PTHREAD_PROCESS_PRIVATE</B>. 

+	</DD><DT>

+	<B>ENOSYS</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> was <B>PTHREAD_PROCESS_SHARED</B>

+	(Pthreads-w32).</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>The <B>pthread_barrierattr_getpshared</B> and

+<B>pthread_barrierattr_setpshared</B> functions are part of the

+Barriers option and need not be provided on all implementations. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_BARRIERS</B> and

+<B>_POSIX_THREAD_PROCESS_SHARED</B> in pthread.h as -1 to indicate

+that these routines are implemented and may be used, but do not

+support the process shared option.</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_barrier_init.html"><B>pthread_barrier_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_barrierattr_init.html"><B>pthread_barrierattr_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_barrierattr_init.html"><B>pthread_barrierattr_init</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_cancel.html b/manual/pthread_cancel.html
new file mode 100644
index 0000000..99b5553
--- /dev/null
+++ b/manual/pthread_cancel.html
@@ -0,0 +1,205 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_CANCEL(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;12090500">

+	<META NAME="CHANGED" CONTENT="20050505;18220000">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_cancel, pthread_setcancelstate, pthread_setcanceltype,

+pthread_testcancel - thread cancellation 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_cancel(pthread_t </B><I>thread</I><B>);</B> 

+</P>

+<P><B>int pthread_setcancelstate(int </B><I>state</I><B>, int

+*</B><I>oldstate</I><B>);</B> 

+</P>

+<P><B>int pthread_setcanceltype(int </B><I>type</I><B>, int

+*</B><I>oldtype</I><B>);</B> 

+</P>

+<P><B>void pthread_testcancel(void);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Cancellation is the mechanism by which a thread can terminate the

+execution of another thread. More precisely, a thread can send a

+cancellation request to another thread. Depending on its settings,

+the target thread can then either ignore the request, honor it

+immediately, or defer it until it reaches a cancellation point. 

+</P>

+<P>When a thread eventually honors a cancellation request, it

+performs as if <B>pthread_exit(PTHREAD_CANCELED)</B> has been called

+at that point: all cleanup handlers are executed in reverse order,

+destructor functions for thread-specific data are called, and finally

+the thread stops executing with the return value <B>PTHREAD_CANCELED</B>.

+See <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> for more

+information. 

+</P>

+<P><B>pthread_cancel</B> sends a cancellation request to the thread

+denoted by the <I>thread</I> argument. 

+</P>

+<P><B>pthread_setcancelstate</B> changes the cancellation state for

+the calling thread -- that is, whether cancellation requests are

+ignored or not. The <I>state</I> argument is the new cancellation

+state: either <B>PTHREAD_CANCEL_ENABLE</B> to enable cancellation, or

+<B>PTHREAD_CANCEL_DISABLE</B> to disable cancellation (cancellation

+requests are ignored). If <I>oldstate</I> is not <B>NULL</B>, the

+previous cancellation state is stored in the location pointed to by

+<I>oldstate</I>, and can thus be restored later by another call to

+<B>pthread_setcancelstate</B>. 

+</P>

+<P><B>pthread_setcanceltype</B> changes the type of responses to

+cancellation requests for the calling thread: asynchronous

+(immediate) or deferred. The <I>type</I> argument is the new

+cancellation type: either <B>PTHREAD_CANCEL_ASYNCHRONOUS</B> to

+cancel the calling thread as soon as the cancellation request is

+received, or <B>PTHREAD_CANCEL_DEFERRED</B> to keep the cancellation

+request pending until the next cancellation point. If <I>oldtype</I>

+is not <B>NULL</B>, the previous cancellation state is stored in the

+location pointed to by <I>oldtype</I>, and can thus be restored later

+by another call to <B>pthread_setcanceltype</B>. 

+</P>

+<P><B>Pthreads-w32</B> provides two levels of support for

+<B>PTHREAD_CANCEL_ASYNCHRONOUS</B>: full and partial. Full support

+requires an additional DLL and driver be installed on the Windows

+system (see the See Also section below) that allows blocked threads

+to be cancelled immediately. Partial support means that the target

+thread will not cancel until it resumes execution naturally. Partial

+support is provided if either the DLL or the driver are not

+automatically detected by the pthreads-w32 library at run-time.</P>

+<P>Threads are always created by <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A>

+with cancellation enabled and deferred. That is, the initial

+cancellation state is <B>PTHREAD_CANCEL_ENABLE</B> and the initial

+type is <B>PTHREAD_CANCEL_DEFERRED</B>. 

+</P>

+<P>Cancellation points are those points in the program execution

+where a test for pending cancellation requests is performed and

+cancellation is executed if positive. The following POSIX threads

+functions are cancellation points: 

+</P>

+<P><A HREF="pthread_join.html"><B>pthread_join</B>(3)</A>

+<BR><A HREF="pthread_cond_init.html"><B>pthread_cond_wait</B>(3)</A>

+<BR><A HREF="pthread_cond_init.html"><B>pthread_cond_timedwait</B>(3)</A>

+<BR><A HREF=""><B>pthread_testcancel</B>(3)</A> <BR><A HREF="sem_init.html"><B>sem_wait</B>(3)</A>

+<BR><A HREF="sem_init.html"><B>sem_timedwait</B>(3)</A> <BR><A HREF="pthread_kill.html"><B>sigwait</B>(3)</A></P>

+<P><B>Pthreads-w32</B> provides two functions to enable additional

+cancellation points to be created in user functions that block on

+Win32 HANDLEs:</P>

+<P><A HREF="pthreadCancelableWait.html">pthreadCancelableWait()</A>

+<BR><A HREF="pthreadCancelableTimedWait.html">pthreadCancelableTimedWait()</A></P>

+<P>All other POSIX threads functions are guaranteed not to be

+cancellation points. That is, they never perform cancellation in

+deferred cancellation mode. 

+</P>

+<P><B>pthread_testcancel</B> does nothing except testing for pending

+cancellation and executing it. Its purpose is to introduce explicit

+checks for cancellation in long sequences of code that do not call

+cancellation point functions otherwise. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P><B>pthread_cancel</B>, <B>pthread_setcancelstate</B> and

+<B>pthread_setcanceltype</B> return 0 on success and a non-zero error

+code on error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P><B>pthread_cancel</B> returns the following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ESRCH</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		no thread could be found corresponding to that specified by the

+		<I>thread</I> ID. 

+		</DD></DL>

+</DL>

+<P>

+<B>pthread_setcancelstate</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>state</I> argument is not 

+		</DD></DL>

+</DL>

+<BLOCKQUOTE>

+<B>PTHREAD_CANCEL_ENABLE</B> nor <B>PTHREAD_CANCEL_DISABLE</B> 

+</BLOCKQUOTE>

+<P><B>pthread_setcanceltype</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>type</I> argument is not 

+		</DD></DL>

+</DL>

+<BLOCKQUOTE>

+<B>PTHREAD_CANCEL_DEFERRED</B> nor <B>PTHREAD_CANCEL_ASYNCHRONOUS</B>

+</BLOCKQUOTE>

+<H2><A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> ,

+<A HREF="pthread_cleanup_push.html"><B>pthread_cleanup_push</B>(3)</A>

+, <A HREF="pthread_cleanup_pop.html"><B>pthread_cleanup_pop</B>(3)</A>

+, Pthreads-w32 package README file 'Prerequisites' section. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Bugs</A></H2>

+<P>POSIX specifies that a number of system calls (basically, all

+system calls that may block, such as <A HREF="read.html"><B>read</B>(2)</A>

+, <A HREF="write.html"><B>write</B>(2)</A> , <A HREF="wait.html"><B>wait</B>(2)</A>

+, etc.) and library functions that may call these system calls (e.g.

+<A HREF="fprintf.html"><B>fprintf</B>(3)</A> ) are cancellation

+points. <B>Pthreads-win32</B> is not integrated enough with the C

+library to implement this, and thus none of the C library functions

+is a cancellation point. 

+</P>

+<P>A workaround for these calls is to temporarily switch to

+asynchronous cancellation (assuming full asynchronous cancellation

+support is installed). So, checking for cancellation during a <B>read</B>

+system call, for instance, can be achieved as follows: 

+</P>

+<BLOCKQUOTE><BR><BR>

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1cm; margin-right: 1cm">pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &amp;oldCancelType);

+read(fd, buffer, length);

+pthread_setcanceltype(oldCancelType, NULL);</PRE>

+<HR>

+<BLOCKQUOTE><A NAME="toc"></A><B>Table of Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE><A HREF="#sect7" NAME="toc7">Bugs</A> 

+	</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_cleanup_push.html b/manual/pthread_cleanup_push.html
new file mode 100644
index 0000000..052ea6e
--- /dev/null
+++ b/manual/pthread_cleanup_push.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_CLEANUP(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;20152200">

+	<META NAME="CHANGED" CONTENT="20050505;18252600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_cleanup_push, pthread_cleanup_pop - install and remove

+cleanup handlers 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>void pthread_cleanup_push(void (*</B><I>routine</I><B>) (void

+*), void *</B><I>arg</I><B>);</B> 

+</P>

+<P><B>void pthread_cleanup_pop(int </B><I>execute</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Cleanup handlers are functions that get called when a thread

+terminates, either by calling <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>

+or because of cancellation. Cleanup handlers are installed and

+removed following a stack-like discipline. 

+</P>

+<P>The purpose of cleanup handlers is to free the resources that a

+thread may hold at the time it terminates. In particular, if a thread

+exits or is cancelled while it owns a locked mutex, the mutex will

+remain locked forever and prevent other threads from executing

+normally. The best way to avoid this is, just before locking the

+mutex, to install a cleanup handler whose effect is to unlock the

+mutex. Cleanup handlers can be used similarly to free blocks

+allocated with <A HREF="malloc.html"><B>malloc</B>(3)</A> or close

+file descriptors on thread termination. 

+</P>

+<P><B>pthread_cleanup_push</B> installs the <I>routine</I> function

+with argument <I>arg</I> as a cleanup handler. From this point on to

+the matching <B>pthread_cleanup_pop</B>, the function <I>routine</I>

+will be called with arguments <I>arg</I> when the thread terminates,

+either through <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>

+or by cancellation. If several cleanup handlers are active at that

+point, they are called in LIFO order: the most recently installed

+handler is called first. 

+</P>

+<P><B>pthread_cleanup_pop</B> removes the most recently installed

+cleanup handler. If the <I>execute</I> argument is not 0, it also

+executes the handler, by calling the <I>routine</I> function with

+arguments <I>arg</I>. If the <I>execute</I> argument is 0, the

+handler is only removed but not executed. 

+</P>

+<P>Matching pairs of <B>pthread_cleanup_push</B> and

+<B>pthread_cleanup_pop</B> must occur in the same function, at the

+same level of block nesting. Actually, <B>pthread_cleanup_push</B>

+and <B>pthread_cleanup_pop</B> are macros, and the expansion of

+<B>pthread_cleanup_push</B> introduces an open brace <B>{</B> with

+the matching closing brace <B>}</B> being introduced by the expansion

+of the matching <B>pthread_cleanup_pop</B>. 

+</P>

+<H2 STYLE="margin-top: 0cm"><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">None. 

+</BLOCKQUOTE>

+<H2 STYLE="margin-top: 0cm"><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">None. 

+</BLOCKQUOTE>

+<H2 STYLE="margin-top: 0cm"><A HREF="#toc5" NAME="sect5">Author</A></H2>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">Xavier Leroy

+&lt;Xavier.Leroy@inria.fr&gt; 

+</BLOCKQUOTE>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">Modified by

+Ross Johnson for use with Pthreads-w32.</BLOCKQUOTE>

+<H2 STYLE="margin-top: 0cm"><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm"><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>

+, <A HREF="pthread_cancel.html"><B>pthread_cancel</B>(3)</A> ,

+<A HREF="pthread_cancel.html"><B>pthread_setcanceltype</B>(3)</A> . 

+</BLOCKQUOTE>

+<H2 STYLE="margin-top: 0cm"><A HREF="#toc7" NAME="sect7">Example</A></H2>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">Here is how

+to lock a mutex <I>mut</I> in such a way that it will be unlocked if

+the thread is canceled while <I>mut</I> is locked: 

+</BLOCKQUOTE>

+<PRE>pthread_cleanup_push(pthread_mutex_unlock, (void *) &amp;mut);

+pthread_mutex_lock(&amp;mut);

+/* do some work */

+pthread_mutex_unlock(&amp;mut);

+pthread_cleanup_pop(0);</PRE><BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">

+Equivalently, the last two lines can be replaced by 

+</BLOCKQUOTE>

+<PRE STYLE="margin-bottom: 0.5cm">pthread_cleanup_pop(1);</PRE><BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">

+Notice that the code above is safe only in deferred cancellation mode

+(see <A HREF="pthread_cancel.html"><B>pthread_setcanceltype</B>(3)</A>

+). In asynchronous cancellation mode, a cancellation can occur

+between <B>pthread_cleanup_push</B> and <B>pthread_mutex_lock</B>, or

+between <B>pthread_mutex_unlock</B> and <B>pthread_cleanup_pop</B>,

+resulting in both cases in the thread trying to unlock a mutex not

+locked by the current thread. This is the main reason why

+asynchronous cancellation is difficult to use. 

+</BLOCKQUOTE>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">If the code

+above must also work in asynchronous cancellation mode, then it must

+switch to deferred mode for locking and unlocking the mutex: 

+</BLOCKQUOTE>

+<PRE>pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &amp;oldtype);

+pthread_cleanup_push(pthread_mutex_unlock, (void *) &amp;mut);

+pthread_mutex_lock(&amp;mut);

+/* do some work */

+pthread_cleanup_pop(1);

+pthread_setcanceltype(oldtype, NULL);</PRE>

+<HR>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm"><A NAME="toc"></A>

+<B>Table of Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm"><A HREF="#sect7" NAME="toc7">Example</A>

+		</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_cond_init.html b/manual/pthread_cond_init.html
new file mode 100644
index 0000000..ecbf6ae
--- /dev/null
+++ b/manual/pthread_cond_init.html
@@ -0,0 +1,313 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_COND(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;16454400">

+	<META NAME="CHANGED" CONTENT="20050505;19004700">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_cond_init, pthread_cond_destroy, pthread_cond_signal,

+pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait -

+operations on conditions 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>pthread_cond_t </B><I>cond</I> <B>= PTHREAD_COND_INITIALIZER;</B>

+</P>

+<P><B>int pthread_cond_init(pthread_cond_t *</B><I>cond</I><B>,

+pthread_condattr_t *</B><I>cond_attr</I><B>);</B> 

+</P>

+<P><B>int pthread_cond_signal(pthread_cond_t *</B><I>cond</I><B>);</B>

+</P>

+<P><B>int pthread_cond_broadcast(pthread_cond_t *</B><I>cond</I><B>);</B>

+</P>

+<P><B>int pthread_cond_wait(pthread_cond_t *</B><I>cond</I><B>,

+pthread_mutex_t *</B><I>mutex</I><B>);</B> 

+</P>

+<P><B>int pthread_cond_timedwait(pthread_cond_t *</B><I>cond</I><B>,

+pthread_mutex_t *</B><I>mutex</I><B>, const struct timespec

+*</B><I>abstime</I><B>);</B> 

+</P>

+<P><B>int pthread_cond_destroy(pthread_cond_t *</B><I>cond</I><B>);</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>A condition (short for ‘‘condition variable’’) is a

+synchronization device that allows threads to suspend execution and

+relinquish the processors until some predicate on shared data is

+satisfied. The basic operations on conditions are: signal the

+condition (when the predicate becomes true), and wait for the

+condition, suspending the thread execution until another thread

+signals the condition. 

+</P>

+<P>A condition variable must always be associated with a mutex, to

+avoid the race condition where a thread prepares to wait on a

+condition variable and another thread signals the condition just

+before the first thread actually waits on it. 

+</P>

+<P><B>pthread_cond_init</B> initializes the condition variable <I>cond</I>,

+using the condition attributes specified in <I>cond_attr</I>, or

+default attributes if <I>cond_attr</I> is <B>NULL</B>. 

+</P>

+<P>Variables of type <B>pthread_cond_t</B> can also be initialized

+statically, using the constant <B>PTHREAD_COND_INITIALIZER</B>. In

+the <B>Pthreads-w32</B> implementation, an application should still

+call <B>pthread_cond_destroy</B> at some point to ensure that any

+resources consumed by the condition variable are released.</P>

+<P><B>pthread_cond_signal</B> restarts one of the threads that are

+waiting on the condition variable <I>cond</I>. If no threads are

+waiting on <I>cond</I>, nothing happens. If several threads are

+waiting on <I>cond</I>, exactly one is restarted, but it is not

+specified which. 

+</P>

+<P><B>pthread_cond_broadcast</B> restarts all the threads that are

+waiting on the condition variable <I>cond</I>. Nothing happens if no

+threads are waiting on <I>cond</I>. 

+</P>

+<P><B>pthread_cond_wait</B> atomically unlocks the <I>mutex</I> (as

+per <B>pthread_unlock_mutex</B>) and waits for the condition variable

+<I>cond</I> to be signalled. The thread execution is suspended and

+does not consume any CPU time until the condition variable is

+signalled. The <I>mutex</I> must be locked by the calling thread on

+entrance to <B>pthread_cond_wait</B>. Before returning to the calling

+thread, <B>pthread_cond_wait</B> re-acquires <I>mutex</I> (as per

+<B>pthread_lock_mutex</B>). 

+</P>

+<P>Unlocking the mutex and suspending on the condition variable is

+done atomically. Thus, if all threads always acquire the mutex before

+signalling the condition, this guarantees that the condition cannot

+be signalled (and thus ignored) between the time a thread locks the

+mutex and the time it waits on the condition variable. 

+</P>

+<P><B>pthread_cond_timedwait</B> atomically unlocks <I>mutex</I> and

+waits on <I>cond</I>, as <B>pthread_cond_wait</B> does, but it also

+bounds the duration of the wait. If <I>cond</I> has not been

+signalled within the amount of time specified by <I>abstime</I>, the

+mutex <I>mutex</I> is re-acquired and <B>pthread_cond_timedwait</B>

+returns the error <B>ETIMEDOUT</B>. The <I>abstime</I> parameter

+specifies an absolute time, with the same origin as <A HREF="time.html"><B>time</B>(2)</A>

+and <A HREF="gettimeofday.html"><B>gettimeofday</B>(2)</A>. 

+</P>

+<P><B>pthread_cond_destroy</B> destroys a condition variable, freeing

+the resources it might hold. No threads must be waiting on the

+condition variable on entrance to <B>pthread_cond_destroy</B>.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P><B>pthread_cond_wait</B> and <B>pthread_cond_timedwait</B> are

+cancellation points. If a thread is cancelled while suspended in one

+of these functions, the thread immediately resumes execution, then

+locks again the <I>mutex</I> argument to <B>pthread_cond_wait</B> and

+<B>pthread_cond_timedwait</B>, and finally executes the cancellation.

+Consequently, cleanup handlers are assured that <I>mutex</I> is

+locked when they are called. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Async-signal Safety</A></H2>

+<P>The condition functions are not async-signal safe, and should not

+be called from a signal handler. In particular, calling

+<B>pthread_cond_signal</B> or <B>pthread_cond_broadcast</B> from a

+signal handler may deadlock the calling thread. 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Return Value</A></H2>

+<P>All condition variable functions return 0 on success and a

+non-zero error code on error. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Errors</A></H2>

+<P><B>pthread_cond_init</B>, <B>pthread_cond_signal</B>,

+<B>pthread_cond_broadcast</B>, and <B>pthread_cond_wait</B> never

+return an error code. 

+</P>

+<P>The <B>pthread_cond_init</B> function returns the following error

+codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The <I>cond</I> argument is invalid. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ENOMEM</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 4cm">

+There was not enough memory to allocate the condition variable. 

+</BLOCKQUOTE>

+<P>The <B>pthread_cond_signal</B> function returns the following

+error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The <I>cond</I> argument is invalid. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_cond_broadcast</B> function returns the following

+error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The <I>cond</I> argument is invalid. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_cond_wait</B> function returns the following error

+codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The <I>cond</I> argument is invalid. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ENOMEM</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 4cm">

+There was not enough memory to allocate the statically initialised

+condition variable. Statically initialised condition variables are

+dynamically allocated by the first thread to wait on them.</BLOCKQUOTE>

+<P>The <B>pthread_cond_timedwait</B> function returns the following

+error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT></DL>

+</DL>

+<P STYLE="margin-left: 2cm">

+The <I>cond</I> argument is invalid. 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ETIMEDOUT</B>

+				</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The condition variable was not signalled before the timeout

+		specified by <I>abstime</I> 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ENOMEM</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 4cm">

+There was not enough memory to allocate the statically initialised

+condition variable. Statically initialised condition variables are

+dynamically allocated by the first thread to wait on them. 

+</BLOCKQUOTE>

+<P>The <B>pthread_cond_destroy</B> function returns the following

+error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT></DL>

+</DL>

+<P STYLE="margin-left: 2cm; margin-right: 1cm">

+The <I>cond</I> argument is invalid. 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EBUSY</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		Some threads are currently waiting on <I>cond</I>. 

+		</DD></DL>

+</DL>

+<H2>

+<A HREF="#toc7" NAME="sect7">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc8" NAME="sect8">See Also</A></H2>

+<P><A HREF="pthread_condattr_init.html"><B>pthread_condattr_init</B>(3)</A>

+, <A HREF="pthread_mutex_lock.html"><B>pthread_mutex_lock</B>(3)</A>

+, <A HREF="pthread_mutex_unlock.html"><B>pthread_mutex_unlock</B>(3)</A>

+, <A HREF="pthread_cancel.html"><B>pthread_cancel(3)</B></A>. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">Example</A></H2>

+<P>Consider two shared variables <I>x</I> and <I>y</I>, protected by

+the mutex <I>mut</I>, and a condition variable <I>cond</I> that is to

+be signaled whenever <I>x</I> becomes greater than <I>y</I>. 

+</P>

+<PRE STYLE="margin-left: 1cm; margin-right: 1cm">int x,y;

+pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;</PRE><BLOCKQUOTE>

+Waiting until <I>x</I> is greater than <I>y</I> is performed as

+follows: 

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1.01cm">pthread_mutex_lock(&amp;mut);

+while (x &lt;= y) {

+        pthread_cond_wait(&amp;cond, &amp;mut);

+}

+/* operate on x and y */

+pthread_mutex_unlock(&amp;mut);</PRE><BLOCKQUOTE STYLE="margin-left: 3.01cm">

+Modifications on <I>x</I> and <I>y</I> that may cause <I>x</I> to

+become greater than <I>y</I> should signal the condition if needed: 

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1.01cm">pthread_mutex_lock(&amp;mut);

+/* modify x and y */

+if (x &gt; y) pthread_cond_broadcast(&amp;cond);

+pthread_mutex_unlock(&amp;mut);</PRE><BLOCKQUOTE STYLE="margin-left: 3.01cm">

+If it can be proved that at most one waiting thread needs to be waken

+up (for instance, if there are only two threads communicating through

+<I>x</I> and <I>y</I>), <B>pthread_cond_signal</B> can be used as a

+slightly more efficient alternative to <B>pthread_cond_broadcast</B>.

+If in doubt, use <B>pthread_cond_broadcast</B>. 

+</BLOCKQUOTE>

+<BLOCKQUOTE STYLE="margin-left: 3.01cm">To wait for <I>x</I> to

+become greater than <I>y</I> with a timeout of 5 seconds, do: 

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1.01cm">struct timeval now;

+struct timespec timeout;

+int retcode;

+pthread_mutex_lock(&amp;mut);

+gettimeofday(&amp;now);

+timeout.tv_sec = now.tv_sec + 5;

+timeout.tv_nsec = now.tv_usec * 1000;

+retcode = 0;

+while (x &lt;= y &amp;&amp; retcode != ETIMEDOUT) {

+        retcode = pthread_cond_timedwait(&amp;cond, &amp;mut, &amp;timeout);

+}

+if (retcode == ETIMEDOUT) {

+        /* timeout occurred */

+} else {

+        /* operate on x and y */

+}

+pthread_mutex_unlock(&amp;mut);</PRE>

+<HR>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm"><A NAME="toc"></A>

+<B>Table of Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Async-signal

+	Safety</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 0cm"><A HREF="#sect9" NAME="toc9">Example</A>

+		</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_condattr_init.html b/manual/pthread_condattr_init.html
new file mode 100644
index 0000000..b799e18
--- /dev/null
+++ b/manual/pthread_condattr_init.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_CONDATTR(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;16375600">

+	<META NAME="CHANGED" CONTENT="20050504;16570300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_condattr_init, pthread_condattr_destroy - condition

+creation 

+</P>

+<P>attributes 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_condattr_init(pthread_condattr_t *</B><I>attr</I><B>);</B>

+</P>

+<P><B>int pthread_condattr_destroy(pthread_condattr_t *</B><I>attr</I><B>);</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Condition attributes can be specified at condition creation time,

+by passing a condition attribute object as second argument to

+<A HREF="pthread_cond_init.html"><B>pthread_cond_init</B>(3)</A> .

+Passing <B>NULL</B> is equivalent to passing a condition attribute

+object with all attributes set to their default values. 

+</P>

+<P><B>pthread_condattr_init</B> initializes the condition attribute

+object <I>attr</I> and fills it with default values for the

+attributes. <B>pthread_condattr_destroy</B> destroys a condition

+attribute object, which must not be reused until it is reinitialized.</P>

+<P><B>Pthreads-w32</B> defines _<B>POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that the attribute routines are

+implemented but that the process shared attribute is not supported.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>All condition variable functions return 0 on success and a

+non-zero error code on error.</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_condattr_init</B> function returns the following

+error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ENOMEM</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The was insufficient memory to create the attribute.<SPAN STYLE="font-weight: medium">

+		</SPAN>

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_condattr_destroy</B> function returns the following

+error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The <I>attr</I> argument is not valid.<SPAN STYLE="font-weight: medium">

+		</SPAN>

+		</DD></DL>

+</DL>

+<H2>

+<A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_cond_init.html"><B>pthread_cond_init</B>(3)</A> .

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_condattr_setpshared.html b/manual/pthread_condattr_setpshared.html
new file mode 100644
index 0000000..ff4fe22
--- /dev/null
+++ b/manual/pthread_condattr_setpshared.html
@@ -0,0 +1,153 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_CONDATTR_GETPSHARED&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;17542300">

+	<META NAME="CHANGED" CONTENT="20050505;18293100">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_condattr_getpshared, pthread_condattr_setpshared - get and

+set the process-shared condition variable attributes 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_condattr_getpshared(const pthread_condattr_t

+*restrict</B> <I>attr</I><B>, int *restrict</B> <I>pshared</I><B>);

+<BR>int pthread_condattr_setpshared(pthread_condattr_t *</B><I>attr</I><B>,

+int</B> <I>pshared</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_condattr_getpshared</B> function shall obtain the

+value of the <I>process-shared</I> attribute from the attributes

+object referenced by <I>attr</I>. The <B>pthread_condattr_setpshared</B>

+function shall set the <I>process-shared</I> attribute in an

+initialized attributes object referenced by <I>attr</I>. 

+</P>

+<P>The <I>process-shared</I> attribute is set to

+<B>PTHREAD_PROCESS_SHARED</B> to permit a condition variable to be

+operated upon by any thread that has access to the memory where the

+condition variable is allocated, even if the condition variable is

+allocated in memory that is shared by multiple processes. If the

+<I>process-shared</I> attribute is <B>PTHREAD_PROCESS_PRIVATE</B>,

+the condition variable shall only be operated upon by threads created

+within the same process as the thread that initialized the condition

+variable; if threads of differing processes attempt to operate on

+such a condition variable, the behavior is undefined. The default

+value of the attribute is <B>PTHREAD_PROCESS_PRIVATE</B>. 

+</P>

+<P><B>Pthreads-w32</B> defines _<B>POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that these routines are implemented but

+that the process shared attribute is not supported.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_condattr_setpshared</B> function

+shall return zero; otherwise, an error number shall be returned to

+indicate the error. 

+</P>

+<P>If successful, the <B>pthread_condattr_getpshared</B> function

+shall return zero and store the value of the <I>process-shared</I>

+attribute of <I>attr</I> into the object referenced by the <I>pshared</I>

+parameter. Otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_condattr_getpshared</B> and

+<B>pthread_condattr_setpshared</B> functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_condattr_setpshared</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The new value specified for the attribute is outside the range of

+	legal values for that attribute. 

+	</DD><DT>

+	<B>ENOSYS</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> was <B>PTHREAD_PROCESS_SHARED</B>

+	(Pthreads-w32).</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that these routines are implemented and

+may be used, but do not support the process shared option.</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> <B>,</B>

+<A HREF="pthread_cond_init.html"><B>pthread_cond_destroy</B>(3)</A> <B>,</B>

+<A HREF="pthread_condattr_init.html"><B>pthread_condattr_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_mutex_init.html"><B>pthread_mutex_destroy</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_create.html b/manual/pthread_create.html
new file mode 100644
index 0000000..c5d80ba
--- /dev/null
+++ b/manual/pthread_create.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_CREATE(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;19394700">

+	<META NAME="CHANGED" CONTENT="20050504;20140200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_create - create a new thread 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_create(pthread_t * </B><I>thread</I><B>,

+pthread_attr_t * </B><I>attr</I><B>, void * (*</B><I>start_routine</I><B>)(void

+*), void * </B><I>arg</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_create</B> creates a new thread of control that

+executes concurrently with the calling thread. The new thread applies

+the function <I>start_routine</I> passing it <I>arg</I> as first

+argument. The new thread terminates either explicitly, by calling

+<A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> , or

+implicitly, by returning from the <I>start_routine</I> function. The

+latter case is equivalent to calling <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>

+with the result returned by <I>start_routine</I> as exit code. 

+</P>

+<P>The initial signal state of the new thread is inherited from it's

+creating thread and there are no pending signals. <B>Pthreads-w32</B>

+does not yet implement signals.</P>

+<P>The <I>attr</I> argument specifies thread attributes to be applied

+to the new thread. See <A HREF="pthread_attr_init.html"><B>pthread_attr_init</B>(3)</A>

+for a complete list of thread attributes. The <I>attr</I> argument

+can also be <B>NULL</B>, in which case default attributes are used:

+the created thread is joinable (not detached) and has default (non

+real-time) scheduling policy. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>On success, the identifier of the newly created thread is stored

+in the location pointed by the <I>thread</I> argument, and a 0 is

+returned. On error, a non-zero error code is returned. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<DL>

+	<DT><B>EAGAIN</B> 

+	</DT><DL>

+		<DL>

+			<DT>

+			Not enough system resources to create a process for the new

+			thread, or<BR>more than <B>PTHREAD_THREADS_MAX</B> threads are

+			already active. 

+			</DT></DL>

+	</DL>

+</DL>

+<H2>

+<A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> ,

+<A HREF="pthread_join.html"><B>pthread_join</B>(3)</A> ,

+<A HREF="pthread_detach.html"><B>pthread_detach</B>(3)</A> ,

+<A HREF="pthread_attr_init.html"><B>pthread_attr_init</B>(3)</A> . 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_delay_np.html b/manual/pthread_delay_np.html
new file mode 100644
index 0000000..99d5f39
--- /dev/null
+++ b/manual/pthread_delay_np.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_DELAY_NP manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050505;21371500">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthread_delay_np – suspend the

+thread for a specified period</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_delay_np (const struct timespec *</B>interval<B>);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_delay_np</B> 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.</P>

+<P>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 cancellation request.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P><B>pthread_delay_np </B>is a cancellation point.</P>

+<H2><A HREF="#toc4" NAME="sect4">Return Value</A></H2>

+<P>If an error condition occurs, <B>pthread_delay_np</B> returns an

+integer value indicating the type of error.</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>The <B>pthread_delay_np</B> function returns the following error

+code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT></DL>

+</DL>

+<P STYLE="margin-left: 2cm">

+The value specified by interval is invalid.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_detach.html b/manual/pthread_detach.html
new file mode 100644
index 0000000..4a588b4
--- /dev/null
+++ b/manual/pthread_detach.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_DETACH(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 2.0  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;18010700">

+	<META NAME="CHANGEDBY" CONTENT="Ross Johnson">

+	<META NAME="CHANGED" CONTENT="20060408;9255600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_detach - put a running thread in the detached state 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_detach(pthread_t </B><I>th</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_detach</B> puts the thread <I>th</I> in the detached

+state. This guarantees that the resources consumed by <I>th</I> will

+be freed immediately when <I>th</I> terminates. However, this

+prevents other threads from synchronizing on the termination of <I>th</I>

+using <B>pthread_join</B>. If, when <B>pthread_detach</B> is called,

+<I>th</I> has already terminated, all of <I>th</I>'s remaining

+resources will be freed.</P>

+<P>A thread can be created initially in the detached state, using the

+<B>detachstate</B> attribute to <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A>

+. In contrast, <B>pthread_detach</B> applies to threads created in

+the joinable state, and which need to be put in the detached state

+later. 

+</P>

+<P>After <B>pthread_detach</B> completes, subsequent attempts to

+perform <B>pthread_join</B> on <I>th</I> will fail. If another thread

+is already joining the thread <I>th</I> at the time <B>pthread_detach</B>

+is called, <I>th</I> will be detached and <B>pthread_join</B> will

+eventually return when <I>th</I> terminates but may not return with

+<I>th</I>'s correct return code. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>On success, 0 is returned. On error, a non-zero error code is

+returned. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<DL>

+	<DT><B>ESRCH</B> 

+	</DT><DD>

+	No thread could be found corresponding to that specified by <I>th</I>

+		</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	the thread <I>th</I> is already in the detached state 

+	</DD></DL>

+<H2>

+<A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with Pthreads-w32.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> ,

+<A HREF="pthread_join.html"><B>pthread_join</B>(3)</A> ,

+<A HREF="pthread_attr_init.html"><B>pthread_attr_setdetachstate</B>(3)</A>

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/pthread_equal.html b/manual/pthread_equal.html
new file mode 100644
index 0000000..0817909
--- /dev/null
+++ b/manual/pthread_equal.html
@@ -0,0 +1,48 @@
+<!-- manual page source format generated by PolyglotMan v3.2, -->

+<!-- available at http://polyglotman.sourceforge.net/ -->

+

+<html>

+<head>

+<title>PTHREAD_EQUAL(3) manual page</title>

+</head>

+<body bgcolor='white'>

+<a href='#toc'>Table of Contents</a><p>

+

+<p> 

+<h2><a name='sect0' href='#toc0'>Name</a></h2>

+pthread_equal - compare two thread identifiers 

+<p> 

+<h2><a name='sect1' href='#toc1'>Synopsis</a></h2>

+<b>#include &lt;pthread.h&gt;</b>

+

+<p> <b>int pthread_equal(pthread_t </b><i>thread1</i><b>, pthread_t </b><i>thread2</i><b>);</b> 

+<p> 

+<h2><a name='sect2' href='#toc2'>Description</a></h2>

+<b>pthread_equal</b>

+determines if two thread identifiers refer to the same thread. 

+<p> 

+<h2><a name='sect3' href='#toc3'>Return Value</a></h2>

+A

+non-zero value is returned if  <i>thread1</i> and  <i>thread2</i> refer to the same thread.

+Otherwise, 0 is returned. 

+<p> 

+<h2><a name='sect4' href='#toc4'>Author</a></h2>

+Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+<p> 

+<h2><a name='sect5' href='#toc5'>See Also</a></h2>

+<a href='file:pthread_self.html'><b>pthread_self</b>(3)</a>

+.

+<p>

+

+<hr><p>

+<a name='toc'><b>Table of Contents</b></a><p>

+<ul>

+<li><a name='toc0' href='#sect0'>Name</a></li>

+<li><a name='toc1' href='#sect1'>Synopsis</a></li>

+<li><a name='toc2' href='#sect2'>Description</a></li>

+<li><a name='toc3' href='#sect3'>Return Value</a></li>

+<li><a name='toc4' href='#sect4'>Author</a></li>

+<li><a name='toc5' href='#sect5'>See Also</a></li>

+</ul>

+</body>

+</html>

diff --git a/manual/pthread_exit.html b/manual/pthread_exit.html
new file mode 100644
index 0000000..f5aac31
--- /dev/null
+++ b/manual/pthread_exit.html
@@ -0,0 +1,59 @@
+<!-- manual page source format generated by PolyglotMan v3.2, -->

+<!-- available at http://polyglotman.sourceforge.net/ -->

+

+<html>

+<head>

+<title>PTHREAD_EXIT(3) manual page</title>

+</head>

+<body bgcolor='white'>

+<a href='#toc'>Table of Contents</a><p>

+

+<p> 

+<h2><a name='sect0' href='#toc0'>Name</a></h2>

+pthread_exit - terminate the calling thread 

+<p> 

+<h2><a name='sect1' href='#toc1'>Synopsis</a></h2>

+<b>#include &lt;pthread.h&gt;</b>

+

+<p> <b>void pthread_exit(void *</b><i>retval</i><b>);</b> 

+<p> 

+<h2><a name='sect2' href='#toc2'>Description</a></h2>

+<b>pthread_exit</b> terminates the

+execution of the calling thread. All cleanup handlers that have been set

+for the calling thread with <a href='file:pthread_cleanup_push.html'><b>pthread_cleanup_push</b>(3)</a>

+ are executed in reverse

+order (the most recently pushed handler is executed first). Finalization

+functions for thread-specific data are then called for all keys that have

+non- <b>NULL</b> values associated with them in the calling thread (see <a href='file:pthread_key_create.html'><b>pthread_key_create</b>(3)</a>

+).

+Finally, execution of the calling thread is stopped. 

+<p> The  <i>retval</i> argument

+is the return value of the thread. It can be consulted from another thread

+using  <a href='file:pthread_join.html'><b>pthread_join</b>(3)</a>

+. 

+<p> 

+<h2><a name='sect3' href='#toc3'>Return Value</a></h2>

+The  <b>pthread_exit</b> function never returns.

+

+<p> 

+<h2><a name='sect4' href='#toc4'>Author</a></h2>

+Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+<p> 

+<h2><a name='sect5' href='#toc5'>See Also</a></h2>

+<a href='file:pthread_create.html'><b>pthread_create</b>(3)</a>

+, <a href='file:pthread_join.html'><b>pthread_join</b>(3)</a>

+.

+<p>

+

+<hr><p>

+<a name='toc'><b>Table of Contents</b></a><p>

+<ul>

+<li><a name='toc0' href='#sect0'>Name</a></li>

+<li><a name='toc1' href='#sect1'>Synopsis</a></li>

+<li><a name='toc2' href='#sect2'>Description</a></li>

+<li><a name='toc3' href='#sect3'>Return Value</a></li>

+<li><a name='toc4' href='#sect4'>Author</a></li>

+<li><a name='toc5' href='#sect5'>See Also</a></li>

+</ul>

+</body>

+</html>

diff --git a/manual/pthread_getw32threadhandle_np.html b/manual/pthread_getw32threadhandle_np.html
new file mode 100644
index 0000000..bc7b87a
--- /dev/null
+++ b/manual/pthread_getw32threadhandle_np.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_GETW32THREADHANDLE_NP manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050505;21523500">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthread_getw32threadhandle_np – get

+the Win32 thread handle associated with a thread</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>HANDLE pthread_getw32threadhandle_np(pthread_t</B> <I>thread</I><B>);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Returns the Win32 native thread <B>HANDLE</B> that the POSIX

+thread <I>thread</I> is running as.</P>

+<P>Applications can use the Win32 handle to set Win32 specific

+attributes of the thread.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc4" NAME="sect4">Return Value</A></H2>

+<P><B>pthread_getw32threadhandle_np</B> returns the Win32 native

+thread <B>HANDLE</B> for the specified POSIX thread <I>thread</I>.</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_join.html b/manual/pthread_join.html
new file mode 100644
index 0000000..a66d4d4
--- /dev/null
+++ b/manual/pthread_join.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_JOIN(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;18232700">

+	<META NAME="CHANGED" CONTENT="20050504;18421400">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_join - wait for termination of another thread 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_join(pthread_t </B><I>th</I><B>, void

+**</B><I>thread_return</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_join</B> suspends the execution of the calling thread

+until the thread identified by <I>th</I> terminates, either by

+calling <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> or by

+being cancelled. 

+</P>

+<P>If <I>thread_return</I> is not <B>NULL</B>, the return value of <I>th</I>

+is stored in the location pointed to by <I>thread_return</I>. The

+return value of <I>th</I> is either the argument it gave to

+<A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> , or

+<B>PTHREAD_CANCELED</B> if <I>th</I> was cancelled. 

+</P>

+<P>The joined thread <B>th</B> must be in the joinable state: it must

+not have been detached using <A HREF="pthread_detach.html"><B>pthread_detach</B>(3)</A>

+or the <B>PTHREAD_CREATE_DETACHED</B> attribute to <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A>

+. 

+</P>

+<P>When a joinable thread terminates, its memory resources (thread

+descriptor and stack) are not deallocated until another thread

+performs <B>pthread_join</B> on it. Therefore, <B>pthread_join</B>

+must be called once for each joinable thread created to avoid memory

+leaks. 

+</P>

+<P>At most one thread can wait for the termination of a given thread.

+Calling <B>pthread_join</B> on a thread <I>th</I> on which another

+thread is already waiting for termination returns an error. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P><B>pthread_join</B> is a cancellation point. If a thread is

+cancelled while suspended in <B>pthread_join</B>, the thread

+execution resumes immediately and the cancellation is executed

+without waiting for the <I>th</I> thread to terminate. If

+cancellation occurs during <B>pthread_join</B>, the <I>th</I> thread

+remains not joined. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Return Value</A></H2>

+<P>On success, the return value of <I>th</I> is stored in the

+location pointed to by <I>thread_return</I>, and 0 is returned. On

+error, a non-zero error code is returned. 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<DL>

+	<DT><B>ESRCH</B> 

+	</DT><DD>

+	No thread could be found corresponding to that specified by <I>th</I>.

+		</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD>

+	The <I>th</I> thread has been detached. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD>

+	Another thread is already waiting on termination of <I>th</I>. 

+	</DD><DT>

+	<B>EDEADLK</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The <I>th</I> argument refers to the calling thread. 

+	</DD></DL>

+<H2>

+<A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">See Also</A></H2>

+<P><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> ,

+<A HREF="pthread_detach.html"><B>pthread_detach</B>(3)</A> ,

+<A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> ,

+<A HREF="pthread_attr_setdetachstate.html"><B>pthread_attr_setdetachstate</B>(3)</A>

+, <A HREF="pthread_cleanup_push.html"><B>pthread_cleanup_push</B>(3)</A>

+, <A HREF="pthread_key_create.html"><B>pthread_key_create</B>(3)</A>

+. 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Author</A>

+		</P>

+	<LI><P><A HREF="#sect7" NAME="toc7">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_key_create.html b/manual/pthread_key_create.html
new file mode 100644
index 0000000..a94d6e6
--- /dev/null
+++ b/manual/pthread_key_create.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_SPECIFIC(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;18425400">

+	<META NAME="CHANGED" CONTENT="20050509;18220200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_key_create, pthread_key_delete, pthread_setspecific,

+pthread_getspecific - management of thread-specific data 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_key_create(pthread_key_t *</B><I>key</I><B>, void

+(*</B><I>destr_function</I><B>) (void *));</B> 

+</P>

+<P><B>int pthread_key_delete(pthread_key_t </B><I>key</I><B>);</B> 

+</P>

+<P><B>int pthread_setspecific(pthread_key_t </B><I>key</I><B>, const

+void *</B><I>pointer</I><B>);</B> 

+</P>

+<P><B>void * pthread_getspecific(pthread_key_t </B><I>key</I><B>);</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Programs often need global or static variables that have different

+values in different threads. Since threads share one memory space,

+this cannot be achieved with regular variables. Thread-specific data

+is the POSIX threads answer to this need. 

+</P>

+<P>Each thread possesses a private memory block, the thread-specific

+data area, or TSD area for short. This area is indexed by TSD keys.

+The TSD area associates values of type <B>void *</B> to TSD keys. TSD

+keys are common to all threads, but the value associated with a given

+TSD key can be different in each thread. 

+</P>

+<P>For concreteness, the TSD areas can be viewed as arrays of <B>void

+*</B> pointers, TSD keys as integer indices into these arrays, and

+the value of a TSD key as the value of the corresponding array

+element in the calling thread. 

+</P>

+<P>When a thread is created, its TSD area initially associates <B>NULL</B>

+with all keys. 

+</P>

+<P><B>pthread_key_create</B> allocates a new TSD key. The key is

+stored in the location pointed to by <I>key</I>. There is a limit of

+<B>PTHREAD_KEYS_MAX</B> on the number of keys allocated at a given

+time. The value initially associated with the returned key is <B>NULL</B>

+in all currently executing threads. 

+</P>

+<P>The <I>destr_function</I> argument, if not <B>NULL</B>, specifies

+a destructor function associated with the key. When a thread

+terminates via <B>pthread_exit</B> or by cancellation, <I>destr_function</I>

+is called with arguments the value associated with the key in that

+thread. The <I>destr_function</I> is not called if that value is <B>NULL</B><SPAN STYLE="font-weight: medium">

+or the key has been deleted</SPAN>. The order in which destructor

+functions are called at thread termination time is unspecified. 

+</P>

+<P>Before the destructor function is called, the <B>NULL</B> value is

+associated with the key in the current thread. A destructor function

+might, however, re-associate non- <B>NULL</B> values to that key or

+some other key. To deal with this, if after all the destructors have

+been called for all non- <B>NULL</B> values, there are still some

+non- <B>NULL</B> values with associated destructors, then the process

+is repeated.</P>

+<P><B>pthread_key_delete</B> deallocates a TSD key. It does not check

+whether non- <B>NULL</B> values are associated with that key in the

+currently executing threads, nor call the destructor function

+associated with the key. 

+</P>

+<P><B>pthread_setspecific</B> changes the value associated with <I>key</I>

+in the calling thread, storing the given <I>pointer</I> instead. 

+</P>

+<P><B>pthread_getspecific</B> returns the value currently associated

+with <I>key</I> in the calling thread. 

+</P>

+<P>The routines <B>pthread_setspecific</B>, <B>pthread_getspecific</B>,

+and <B>pthread_key_delete</B> can be called from <I>destr_function</I>

+targeting any valid key including the key on which <I>destr_function</I>

+is currently operating. If <B>pthread_getspecific</B> is called on

+the key whose thread specific data is being destroyed, the value NULL

+is returned, unless <B>pthread_setspecific</B> was called previously

+on that key from within <I>destr_function</I> to set the value to

+non-NULL. For some implementations the effect of calling

+<B>pthread_setspecific</B> from within <I>destr_function</I> can be

+either memory leakage or infinite loops if <I>destr_function</I> has

+already been called at least <B>PTHREAD_DESTRUCTOR_ITERATIONS</B>

+times.</P>

+<P STYLE="font-weight: medium"><B>Pthreads-w32</B> stops running key

+<I>destr_function</I> routines after <B>PTHREAD_DESTRUCTOR_ITERATIONS</B>

+iterations, even if some non- <B>NULL</B> values with associated

+descriptors remain. If memory is allocated and associated with a key

+from within <I>destr_function</I>, that memory may not be reclaimed

+because that key's <I>destr_function</I>, may not run again.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P><B>pthread_key_create</B>, <B>pthread_key_delete</B>, and

+<B>pthread_setspecific</B> return 0 on success and a non-zero error

+code on failure. If successful, <B>pthread_key_create</B> stores the

+newly allocated key in the location pointed to by its <I>key</I>

+argument. 

+</P>

+<P><B>pthread_getspecific</B> returns the value associated with <I>key</I>

+on success, and <B>NULL</B> on error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P><B>pthread_key_create</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EAGAIN</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 5cm">

+<B>PTHREAD_KEYS_MAX</B> keys are already allocated 

+</BLOCKQUOTE>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ENOMEM</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 5cm">

+Insufficient memory to allocate the key. 

+</BLOCKQUOTE>

+<P><B>pthread_key_delete</B> and <B>pthread_setspecific</B> return

+the following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<I>key</I> is not a valid, allocated TSD key 

+		</DD></DL>

+</DL>

+<P>

+<B>pthread_getspecific</B> returns <B>NULL</B> if <I>key</I> is not a

+valid, allocated TSD key. 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_create.html">pthread_create(3)</A> ,

+<A HREF="pthread_exit.html">pthread_exit(3)</A> ,

+<A HREF="pthread_cancel.html">pthread_testcancel(3)</A> . 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Example</A></H2>

+<P>The following code fragment allocates a thread-specific array of

+100 characters, with automatic reclamation at thread exit: 

+</P>

+<BLOCKQUOTE><BR><BR>

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1cm; margin-right: 1cm">/* Key for the thread-specific buffer */

+static pthread_key_t buffer_key;

+/* Once-only initialisation of the key */

+static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;

+/* Allocate the thread-specific buffer */

+void buffer_alloc(void)

+{

+  pthread_once(&amp;buffer_key_once, buffer_key_alloc);

+  pthread_setspecific(buffer_key, malloc(100));

+}

+/* Return the thread-specific buffer */

+char * get_buffer(void)

+{

+  return (char *) pthread_getspecific(buffer_key);

+}

+/* Allocate the key */

+static void buffer_key_alloc()

+{

+  pthread_key_create(&amp;buffer_key, buffer_destroy);

+}

+/* Free the thread-specific buffer */

+static void buffer_destroy(void * buf)

+{

+  free(buf);

+}</PRE>

+<HR>

+<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm"><A NAME="toc"></A>

+<B>Table of Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE><A HREF="#sect7" NAME="toc7">Example</A> 

+	</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/pthread_kill.html b/manual/pthread_kill.html
new file mode 100644
index 0000000..4a66e0e
--- /dev/null
+++ b/manual/pthread_kill.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_SIGNAL(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;18500100">

+	<META NAME="CHANGED" CONTENT="20050504;23005800">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_sigmask, pthread_kill, sigwait - handling of signals in

+threads 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> <BR><B>#include &lt;signal.h&gt;</B>

+</P>

+<P><B>int pthread_sigmask(int </B><I>how</I><B>, const sigset_t

+*</B><I>newmask</I><B>, sigset_t *</B><I>oldmask</I><B>);</B> 

+</P>

+<P><B>int pthread_kill(pthread_t </B><I>thread</I><B>, int </B><I>signo</I><B>);</B>

+</P>

+<P><B>int sigwait(const sigset_t *</B>set, <B>int</B> *sig);</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_sigmask</B> changes the signal mask for the calling

+thread as described by the <I>how</I> and <I>newmask</I> arguments.

+If <I>oldmask</I> is not <B>NULL</B>, the previous signal mask is

+stored in the location pointed to by <I>oldmask</I>. <B>Pthreads-w32</B>

+implements this function but no other function uses the signal mask

+yet.</P>

+<P>The meaning of the <I>how</I> and <I>newmask</I> arguments is the

+same as for <B><SPAN STYLE="font-style: normal">sigprocmask</SPAN></B>(2).

+If <I>how</I> is <B>SIG_SETMASK</B>, the signal mask is set to

+<I>newmask</I>. If <I>how</I> is <B>SIG_BLOCK</B>, the signals

+specified to <I>newmask</I> are added to the current signal mask. If

+<I>how</I> is <B>SIG_UNBLOCK</B>, the signals specified to <I>newmask</I>

+are removed from the current signal mask. 

+</P>

+<P>Recall that signal masks are set on a per-thread basis, but signal

+actions and signal handlers, as set with <B>sigaction</B>(2), are

+shared between all threads. 

+</P>

+<P><B>pthread_kill</B> send signal number <I>signo</I> to the thread

+<I>thread</I>. <B>Pthreads-w32</B> only supports signal number 0,

+which does not send any signal but causes <B>pthread_kill</B> to

+return an error if <I>thread</I> is not valid.</P>

+<P><B>sigwait</B> suspends the calling thread until one of the

+signals in <I>set</I> is delivered to the calling thread. It then

+stores the number of the signal received in the location pointed to

+by <I>sig</I> and returns. The signals in <I>set</I> must be blocked

+and not ignored on entrance to <B>sigwait</B>. If the delivered

+signal has a signal handler function attached, that function is <I>not</I>

+called. <B>Pthreads-w32</B> implements this function as a

+cancellation point only - it does not wait for any signals and does

+not change the location pointed to by <I>sig</I>.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P><B>sigwait</B> is a cancellation point. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Return Value</A></H2>

+<P>On success, 0 is returned. On failure, a non-zero error code is

+returned. 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>The <B>pthread_sigmask</B> function returns the following error

+codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<I>how</I> is not one of <B>SIG_SETMASK</B>, <B>SIG_BLOCK</B>, or

+		<B>SIG_UNBLOCK</B> 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_kill</B> function returns the following error codes on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<I>signo</I> is not a valid signal number or is unsupported.</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ESRCH</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the thread <I>thread</I> does not exist (e.g. it has already

+		terminated) 

+		</DD></DL>

+</DL>

+<P>

+The <B>sigwait</B> function never returns an error. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc7" NAME="sect7">See Also</A></H2>

+<P> 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Notes</A></H2>

+<P>In any implementation, for <B>sigwait</B> to work reliably, the

+signals being waited for must be blocked in all threads, not only in

+the calling thread, since otherwise the POSIX semantics for signal

+delivery do not guarantee that it’s the thread doing the <B>sigwait</B>

+that will receive the signal. The best way to achieve this is to

+block those signals before any threads are created, and never unblock

+them in the program other than by calling <B>sigwait</B>. This works

+because all threads inherit their initial sigmask from their creating

+thread.</P>

+<H2><A HREF="#toc9" NAME="sect9">Bugs</A></H2>

+<P><B>Pthreads-w32</B> does not implement signals yet and so these

+routines have almost no use except to prevent the compiler or linker

+from complaining. <B>pthread_kill</B> is useful in determining if the

+thread is a valid thread, but since many threads implementations

+reuse thread IDs, the valid thread may no longer be the thread you

+think it is, and so this method of determining thread validity is not

+portable, and very risky. <B>Pthreads-w32</B> from version 1.0.0

+onwards implements pseudo-unique thread IDs, so applications that use

+this technique (but really shouldn't) have some protection.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Author</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">See

+	Also</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Notes</A>

+		</P>

+	<LI><P><A HREF="#sect9" NAME="toc9">Bugs</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_mutex_init.html b/manual/pthread_mutex_init.html
new file mode 100644
index 0000000..cf0db6c
--- /dev/null
+++ b/manual/pthread_mutex_init.html
@@ -0,0 +1,277 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_MUTEX(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;5000">

+	<META NAME="CHANGED" CONTENT="20050505;19000600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock,

+pthread_mutex_timedlock, pthread_mutex_unlock, pthread_mutex_destroy

+- operations on mutexes 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>#include &lt;time.h&gt;</B></P>

+<P><B>pthread_mutex_t </B><I>fastmutex</I> <B>=

+PTHREAD_MUTEX_INITIALIZER;</B> 

+</P>

+<P><B>pthread_mutex_t </B><I>recmutex</I> <B>=

+PTHREAD_RECURSIVE_MUTEX_INITIALIZER;</B> 

+</P>

+<P><B>pthread_mutex_t </B><I>errchkmutex</I> <B>=

+PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;</B> 

+</P>

+<P><B>pthread_mutex_t </B><I>recmutex</I> <B>=

+PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;</B> 

+</P>

+<P><B>pthread_mutex_t </B><I>errchkmutex</I> <B>=

+PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;</B> 

+</P>

+<P><B>int pthread_mutex_init(pthread_mutex_t *</B><I>mutex</I><B>,

+const pthread_mutexattr_t *</B><I>mutexattr</I><B>);</B> 

+</P>

+<P><B>int pthread_mutex_lock(pthread_mutex_t *</B><I>mutex</I><B>);</B>

+</P>

+<P><B>int pthread_mutex_trylock(pthread_mutex_t *</B><I>mutex</I><B>);</B>

+</P>

+<P><B>int pthread_mutex_timedlock(pthread_mutex_t *</B><I>mutex,

+</I><B>const struct timespec *</B><I>abs_timeout</I><B>);</B> 

+</P>

+<P><B>int pthread_mutex_unlock(pthread_mutex_t *</B><I>mutex</I><B>);</B>

+</P>

+<P><B>int pthread_mutex_destroy(pthread_mutex_t *</B><I>mutex</I><B>);</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>A mutex is a MUTual EXclusion device, and is useful for protecting

+shared data structures from concurrent modifications, and

+implementing critical sections and monitors. 

+</P>

+<P>A mutex has two possible states: unlocked (not owned by any

+thread), and locked (owned by one thread). A mutex can never be owned

+by two different threads simultaneously. A thread attempting to lock

+a mutex that is already locked by another thread is suspended until

+the owning thread unlocks the mutex first. 

+</P>

+<P><B>pthread_mutex_init</B> initializes the mutex object pointed to

+by <I>mutex</I> according to the mutex attributes specified in

+<I>mutexattr</I>. If <I>mutexattr</I> is <B>NULL</B>, default

+attributes are used instead. 

+</P>

+<P>The type of a mutex determines whether it can be locked again by a

+thread that already owns it. The default type is “normal”. See

+<A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_init</B>(3)</A>

+for more information on mutex attributes. 

+</P>

+<P>Variables of type <B>pthread_mutex_t</B> can also be initialized

+statically, using the constants <B>PTHREAD_MUTEX_INITIALIZER</B> (for

+normal “fast” mutexes), <B>PTHREAD_RECURSIVE_MUTEX_INITIALIZER</B>

+(for recursive mutexes), and <B>PTHREAD_ERRORCHECK_MUTEX_INITIALIZER</B>

+(for error checking mutexes).  <SPAN STYLE="font-weight: medium"> In

+the <B>Pthreads-w32</B> implementation, an application should still

+call <B>pthread_mutex_destroy</B> at some point to ensure that any

+resources consumed by the mutex are released.</SPAN></P>

+<P><B>pthread_mutex_lock</B> locks the given mutex. If the mutex is

+currently unlocked, it becomes locked and owned by the calling

+thread, and <B>pthread_mutex_lock</B> returns immediately. If the

+mutex is already locked by another thread, <B>pthread_mutex_lock</B>

+suspends the calling thread until the mutex is unlocked. 

+</P>

+<P>If the mutex is already locked by the calling thread, the behavior

+of <B>pthread_mutex_lock</B> depends on the type of the mutex. If the

+mutex is of the “normal” type, the calling thread is suspended

+until the mutex is unlocked, thus effectively causing the calling

+thread to deadlock. If the mutex is of the ‘‘error checking’’

+type, <B>pthread_mutex_lock</B> returns immediately with the error

+code <B>EDEADLK</B>. If the mutex is of the ‘‘recursive’’

+type, <B>pthread_mutex_lock</B> succeeds and returns immediately,

+recording the number of times the calling thread has locked the

+mutex. An equal number of <B>pthread_mutex_unlock</B> operations must

+be performed before the mutex returns to the unlocked state. 

+</P>

+<P><B>pthread_mutex_trylock</B> behaves identically to

+<B>pthread_mutex_lock</B>, except that it does not block the calling

+thread if the mutex is already locked by another thread (or by the

+calling thread in the case of a “normal” mutex). Instead,

+<B>pthread_mutex_trylock</B> returns immediately with the error code

+<B>EBUSY</B>. 

+</P>

+<P><B>pthread_mutex_timedlock</B> behaves identically to

+<B>pthread_mutex_lock</B>, except that if it cannot acquire the lock

+before the <I>abs_timeout</I> time, the call returns with the error

+code <B>ETIMEDOUT</B>. If the mutex can be locked immediately it is,

+and the <B>abs_timeout</B> parameter is ignored.</P>

+<P><B>pthread_mutex_unlock</B> unlocks the given mutex. The mutex is

+assumed to be locked and owned by the calling thread on entrance to

+<B>pthread_mutex_unlock</B>. If the mutex is of the “normal”

+type, <B>pthread_mutex_unlock</B> always returns it to the unlocked

+state. If it is of the ‘‘recursive’’ type, it decrements the

+locking count of the mutex (number of <B>pthread_mutex_lock</B>

+operations performed on it by the calling thread), and only when this

+count reaches zero is the mutex actually unlocked. 

+</P>

+<P>On ‘‘error checking’’ mutexes, <B>pthread_mutex_unlock</B>

+actually checks at run-time that the mutex is locked on entrance, and

+that it was locked by the same thread that is now calling

+<B>pthread_mutex_unlock</B>. If these conditions are not met, an

+error code is returned and the mutex remains unchanged. ‘‘Normal’’

+mutexes perform no such checks, thus allowing a locked mutex to be

+unlocked by a thread other than its owner. This is non-portable

+behavior and is not meant to be used as a feature.</P>

+<P><B>pthread_mutex_destroy</B> destroys a mutex object, freeing the

+resources it might hold. The mutex must be unlocked on entrance.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>None of the mutex functions is a cancellation point, not even

+<B>pthread_mutex_lock</B>, in spite of the fact that it can suspend a

+thread for arbitrary durations. This way, the status of mutexes at

+cancellation points is predictable, allowing cancellation handlers to

+unlock precisely those mutexes that need to be unlocked before the

+thread stops executing. Consequently, threads using deferred

+cancellation should never hold a mutex for extended periods of time. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Async-signal Safety</A></H2>

+<P>The mutex functions are not async-signal safe. What this means is

+that they should not be called from a signal handler. In particular,

+calling <B>pthread_mutex_lock</B> or <B>pthread_mutex_unlock</B> from

+a signal handler may deadlock the calling thread. 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Return Value</A></H2>

+<P><B>pthread_mutex_init</B> always returns 0. The other mutex

+functions return 0 on success and a non-zero error code on error. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Errors</A></H2>

+<P>The <B>pthread_mutex_lock</B> function returns the following error

+code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex has not been properly initialized. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>EDEADLK</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex is already locked by the calling thread (‘‘error

+		checking’’ mutexes only). 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_mutex_trylock</B> function returns the following error

+codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EBUSY</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex could not be acquired because it was currently locked. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex has not been properly initialized. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_mutex_timedlock</B> function returns the following

+error codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ETIMEDOUT</B>

+				</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex could not be acquired before the <I>abs_timeout</I> time

+		arrived. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex has not been properly initialized. 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_mutex_unlock</B> function returns the following error

+code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex has not been properly initialized. 

+		</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>EPERM</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the calling thread does not own the mutex (‘‘error checking’’

+		mutexes only). 

+		</DD></DL>

+</DL>

+<P>

+The <B>pthread_mutex_destroy</B> function returns the following error

+code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EBUSY</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the mutex is currently locked. 

+		</DD></DL>

+</DL>

+<H2>

+<A HREF="#toc7" NAME="sect7">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc8" NAME="sect8">See Also</A></H2>

+<P><A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_init</B>(3)</A>

+, <A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_settype</B>(3)</A>

+, <A HREF="pthread_cancel.html"><B>pthread_cancel</B>(3)</A> . 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">Example</A></H2>

+<P>A shared global variable <I>x</I> can be protected by a mutex as

+follows: 

+</P>

+<PRE STYLE="margin-left: 1cm; margin-right: 1cm">int x;

+pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;</PRE><BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">

+All accesses and modifications to <I>x</I> should be bracketed by

+calls to <B>pthread_mutex_lock</B> and <B>pthread_mutex_unlock</B> as

+follows: 

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1.03cm; margin-right: 2cm">pthread_mutex_lock(&amp;mut);

+/* operate on x */

+pthread_mutex_unlock(&amp;mut);</PRE>

+<HR>

+<BLOCKQUOTE STYLE="margin-right: 4cm"><A NAME="toc"></A><B>Table of

+Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Async-signal

+	Safety</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm; margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-right: 4cm"><A HREF="#sect9" NAME="toc9">Example</A>

+		</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_mutexattr_init.html b/manual/pthread_mutexattr_init.html
new file mode 100644
index 0000000..4839832
--- /dev/null
+++ b/manual/pthread_mutexattr_init.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_MUTEXATTR(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;23040500">

+	<META NAME="CHANGED" CONTENT="20050505;18370400">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_mutexattr_init, pthread_mutexattr_destroy,

+pthread_mutexattr_settype, pthread_mutexattr_gettype - mutex creation

+attributes 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_mutexattr_init(pthread_mutexattr_t *</B><I>attr</I><B>);</B>

+</P>

+<P><B>int pthread_mutexattr_destroy(pthread_mutexattr_t *</B><I>attr</I><B>);</B>

+</P>

+<P><B>int pthread_mutexattr_settype(pthread_mutexattr_t *</B><I>attr</I><B>,

+int </B><I>type</I><B>);</B> 

+</P>

+<P><B>int pthread_mutexattr_gettype(const pthread_mutexattr_t *</B><I>attr</I><B>,

+int *</B><I>type</I><B>);</B> 

+</P>

+<P><B>int pthread_mutexattr_setkind_np(pthread_mutexattr_t *</B><I>attr</I><B>,

+int </B><I>type</I><B>);</B> 

+</P>

+<P><B>int pthread_mutexattr_getkind_np(const pthread_mutexattr_t

+*</B><I>attr</I><B>, int *</B><I>type</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Mutex attributes can be specified at mutex creation time, by

+passing a mutex attribute object as second argument to

+<A HREF="pthread_mutex_init.html"><B>pthread_mutex_init</B>(3)</A> .

+Passing <B>NULL</B> is equivalent to passing a mutex attribute object

+with all attributes set to their default values. 

+</P>

+<P><B>pthread_mutexattr_init</B> initializes the mutex attribute

+object <I>attr</I> and fills it with default values for the

+attributes. 

+</P>

+<P><B>pthread_mutexattr_destroy</B> destroys a mutex attribute

+object, which must not be reused until it is reinitialized.</P>

+<P>The following mutex types are supported:</P>

+<P STYLE="margin-left: 2cm"><B>PTHREAD_MUTEX_NORMAL</B> - for

+‘‘fast’’ mutexes.</P>

+<P STYLE="margin-left: 2cm"><B>PTHREAD_MUTEX_RECURSIVE</B> - for

+‘‘recursive’’ mutexes.</P>

+<P STYLE="margin-left: 2cm"><B>PTHREAD_MUTEX_ERRORCHECK</B> - for

+‘‘error checking’’ mutexes.</P>

+<P>The mutex type determines what happens if a thread attempts to

+lock a mutex it already owns with <A HREF="pthread_mutex_lock.html"><B>pthread_mutex_lock</B>(3)</A>

+. If the mutex is of the “normal” or “fast” type,

+<A HREF="pthread_mutex_lock.html"><B>pthread_mutex_lock</B>(3)</A>

+simply suspends the calling thread forever. If the mutex is of the

+‘‘error checking’’ type, <A HREF="pthread_mutex_lock.html"><B>pthread_mutex_lock</B>(3)</A>

+returns immediately with the error code <B>EDEADLK</B>. If the mutex

+is of the ‘‘recursive’’ type, the call to

+<A HREF="pthread_mutex_lock.html"><B>pthread_mutex_lock</B>(3)</A>

+returns immediately with a success return code. The number of times

+the thread owning the mutex has locked it is recorded in the mutex.

+The owning thread must call <A HREF="pthread_mutex_unlock.html"><B>pthread_mutex_unlock</B>(3)</A>

+the same number of times before the mutex returns to the unlocked

+state. 

+</P>

+<P>The default mutex type is <B>PTHREAD_MUTEX_NORMAL</B></P>

+<P><B>Pthreads-w32</B> also recognises the following equivalent types

+that are used by Linux:</P>

+<P STYLE="margin-left: 2cm; font-weight: medium"><B>PTHREAD_MUTEX_FAST_NP</B>

+– equivalent to <B>PTHREAD_MUTEX_NORMAL</B></P>

+<P STYLE="margin-left: 2cm"><B>PTHREAD_MUTEX_RECURSIVE_NP</B></P>

+<P STYLE="margin-left: 2cm"><B>PTHREAD_MUTEX_ERRORCHECK_NP</B></P>

+<P><B>pthread_mutexattr_settype</B> sets the mutex type attribute in

+<I>attr</I> to the value specified by <I>type</I>. 

+</P>

+<P><B>pthread_mutexattr_gettype</B> retrieves the current value of

+the mutex kind attribute in <I>attr</I> and stores it in the location

+pointed to by <I>type</I>. 

+</P>

+<P><B>Pthreads-w32</B> also recognises the following equivalent

+functions that are used in Linux:</P>

+<P><B>pthread_mutexattr_setkind_np</B> is an alias for

+<B>pthread_mutexattr_settype</B>. 

+</P>

+<P STYLE="font-weight: medium"><B>pthread_mutexattr_getkind_np</B> is

+an alias for <B>pthread_mutexattr_gettype</B>. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P><B>pthread_mutexattr_init</B>, <B>pthread_mutexattr_destroy</B>

+and <B>pthread_mutexattr_gettype</B> always return 0. 

+</P>

+<P><B>pthread_mutexattr_settype</B> returns 0 on success and a

+non-zero error code on error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>On error, <B>pthread_mutexattr_settype</B> returns the following

+error code: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	<I>type</I> is none of:<BR><B>PTHREAD_MUTEX_NORMAL</B>,

+	<B>PTHREAD_MUTEX_FAST_NP</B>,<BR><B>PTHREAD_MUTEX_RECURSIVE</B>,

+	<B>PTHREAD_MUTEX_RECURSIVE_NP,<BR>PTHREAD_MUTEX_ERRORCHECK</B>,

+	<B>PTHREAD_MUTEX_ERRORCHECK_NP</B> 

+	</DD></DL>

+<H2>

+<A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_mutex_init.html"><B>pthread_mutex_init</B>(3)</A>

+, <A HREF="pthread_mutex_lock.html"><B>pthread_mutex_lock</B>(3)</A>

+, <A HREF="pthread_mutex_unlock.html"><B>pthread_mutex_unlock</B>(3)</A>

+. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7"><U><FONT COLOR="#000080">Notes</FONT></U></A></H2>

+<P>For speed, <B>Pthreads-w32</B> never checks the thread ownership

+of mutexes of type <B>PTHREAD_MUTEX_NORMAL</B> (or

+<B>PTHREAD_MUTEX_FAST_NP</B>) when performing operations on the

+mutex. It is therefore possible for one thread to lock such a mutex

+and another to unlock it.</P>

+<P><SPAN STYLE="font-weight: medium">When developing code, it is a

+common precaution to substitute the error checking type, and drop in

+the normal type for release if the extra performance is required.</SPAN></P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See

+	Also</A></P>

+	<LI><P><A HREF="#sect7" NAME="toc7">Notes</A></P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_mutexattr_setpshared.html b/manual/pthread_mutexattr_setpshared.html
new file mode 100644
index 0000000..78b36b4
--- /dev/null
+++ b/manual/pthread_mutexattr_setpshared.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_MUTEXATTR_GETPSHARED&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;23480600">

+	<META NAME="CHANGED" CONTENT="20050505;18381800">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_mutexattr_getpshared, pthread_mutexattr_setpshared - get

+and set the process-shared attribute 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_mutexattr_getpshared(const pthread_mutexattr_t *

+restrict</B> <I>attr</I><B>, int *restrict</B> <I>pshared</I><B>);

+<BR>int pthread_mutexattr_setpshared(pthread_mutexattr_t *</B><I>attr</I><B>,

+int</B> <I>pshared</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_mutexattr_getpshared</B> function shall obtain the

+value of the <I>process-shared</I> attribute from the attributes

+object referenced by <I>attr</I>. The <B>pthread_mutexattr_setpshared</B>

+function shall set the <I>process-shared</I> attribute in an

+initialized attributes object referenced by <I>attr</I>. 

+</P>

+<P>The <I>process-shared</I> attribute is set to

+<B>PTHREAD_PROCESS_SHARED</B> to permit a mutex to be operated upon

+by any thread that has access to the memory where the mutex is

+allocated, even if the mutex is allocated in memory that is shared by

+multiple processes. If the <I>process-shared</I> attribute is

+<B>PTHREAD_PROCESS_PRIVATE</B>, the mutex shall only be operated upon

+by threads created within the same process as the thread that

+initialized the mutex; if threads of differing processes attempt to

+operate on such a mutex, the behavior is undefined. The default value

+of the attribute shall be <B>PTHREAD_PROCESS_PRIVATE</B>. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that these routines are implemented but

+the process shared option is not supported.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, <B>pthread_mutexattr_setpshared</B>

+shall return zero; otherwise, an error number shall be returned to

+indicate the error. 

+</P>

+<P>Upon successful completion, <B>pthread_mutexattr_getpshared</B>

+shall return zero and store the value of the <I>process-shared</I>

+attribute of <I>attr</I> into the object referenced by the <I>pshared</I>

+parameter. Otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_mutexattr_getpshared</B> and

+<B>pthread_mutexattr_setpshared</B> functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_mutexattr_setpshared</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The new value specified for the attribute is outside the range of

+	legal values for that attribute. 

+	</DD><DT>

+	<B>ENOTSUP</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The new value specified for the attribute is PTHREAD_PROCESS_SHARED.

+		</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_cond_init.html"><B>pthread_cond_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A> <B>,</B>

+<A HREF="pthread_mutex_init.html"><B>pthread_mutex_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_mutexattr_init.html"><B>pthread_mutexattr_destroy</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_num_processors_np.html b/manual/pthread_num_processors_np.html
new file mode 100644
index 0000000..20d3b83
--- /dev/null
+++ b/manual/pthread_num_processors_np.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_NUM_PROCESSORS_NP manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050505;21514100">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthread_num_processors_np – get the

+number of processors (CPUs) in use by the process</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_num_processors_np(void);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_num_processors_np </B>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.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc4" NAME="sect4"><FONT COLOR="#000080">Return Value</FONT></A></H2>

+<P><B>pthread_num_processors_np</B> returns the number of processors

+currently available to the process.</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_once.html b/manual/pthread_once.html
new file mode 100644
index 0000000..67b25e7
--- /dev/null
+++ b/manual/pthread_once.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_ONCE(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050603;463100">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_once - once-only initialization 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>pthread_once_t </B><I>once_control</I> <B>= PTHREAD_ONCE_INIT;</B>

+</P>

+<P><B>int pthread_once(pthread_once_t *</B><I>once_control</I><B>,

+void (*</B><I>init_routine</I><B>) (void));</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The purpose of <B>pthread_once</B> is to ensure that a piece of

+initialization code is executed at most once. The <I>once_control</I>

+argument points to a static or extern variable statically initialized

+to <B>PTHREAD_ONCE_INIT</B>. 

+</P>

+<P>The first time <B>pthread_once</B> is called with a given

+<I>once_control</I> argument, it calls <I>init_routine</I> with no

+argument and changes the value of the <I>once_control</I> variable to

+record that initialization has been performed. Subsequent calls to

+<B>pthread_once</B> with the same <B>once_control</B> argument do

+nothing. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>While <B>pthread_once</B> is not a cancellation point,

+<I>init_routine</I> can be. The effect on <I>once_control</I> of a

+cancellation inside the <I>init_routine</I> is to leave it as if

+<B>pthread_once</B> had not been called by the cancelled thread.</P>

+<H2><A HREF="#toc4" NAME="sect4">Return Value</A></H2>

+<P STYLE="text-decoration: none"><FONT COLOR="#000000"><B>pthread_once</B>

+returns 0 on success, or an error code on failure.</FONT></P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>The <B>pthread_once</B> function returns the following error code

+on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT></DL>

+</DL>

+<P STYLE="margin-left: 2cm">

+The once_control or init_routine parameter is NULL.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/pthread_rwlock_init.html b/manual/pthread_rwlock_init.html
new file mode 100644
index 0000000..ef83b44
--- /dev/null
+++ b/manual/pthread_rwlock_init.html
@@ -0,0 +1,193 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCK_DESTROY&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;10211800">

+	<META NAME="CHANGED" CONTENT="20050505;18563400">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlock_destroy, pthread_rwlock_init - destroy and

+initialize a read-write lock object 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>pthread_wrlock_t </B><I>rwlock</I> <B>=

+PTHREAD_RWLOCK_INITIALIZER;</B></P>

+<P><B>int pthread_rwlock_destroy(pthread_rwlock_t *</B><I>rwlock</I><B>);

+<BR>int pthread_rwlock_init(pthread_rwlock_t *restrict</B> <I>rwlock</I><B>,

+const pthread_rwlockattr_t *restrict</B> <I>attr</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlock_destroy</B> function shall destroy the

+read-write lock object referenced by <I>rwlock</I> and release any

+resources used by the lock. The effect of subsequent use of the lock

+is undefined until the lock is reinitialized by another call to

+<B>pthread_rwlock_init</B>. An implementation may cause

+<B>pthread_rwlock_destroy</B> to set the object referenced by <I>rwlock</I>

+to an invalid value. Results are undefined if <B>pthread_rwlock_destroy</B>

+is called when any thread holds <I>rwlock</I>. Attempting to destroy

+an uninitialized read-write lock results in undefined behavior. 

+</P>

+<P>The <B>pthread_rwlock_init</B> function shall allocate any

+resources required to use the read-write lock referenced by <I>rwlock</I>

+and initializes the lock to an unlocked state with attributes

+referenced by <I>attr</I>. If <I>attr</I> is NULL, the default

+read-write lock attributes shall be used; the effect is the same as

+passing the address of a default read-write lock attributes object.

+Once initialized, the lock can be used any number of times without

+being reinitialized. Results are undefined if <B>pthread_rwlock_init</B>

+is called specifying an already initialized read-write lock. Results

+are undefined if a read-write lock is used without first being

+initialized. 

+</P>

+<P>If the <B>pthread_rwlock_init</B> function fails, <I>rwlock</I>

+shall not be initialized and the contents of <I>rwlock</I> are

+undefined. 

+</P>

+<P><B>Pthreads-w32</B> supports statically initialized <I>rwlock</I>

+objects using <B>PTHREAD_RWLOCK_INITIALIZER</B>. <SPAN STYLE="font-weight: medium">

+An application should still call <B>pthread_rwlock_destroy</B> at

+some point to ensure that any resources consumed by the read/write

+lock are released.</SPAN></P>

+<P>Only the object referenced by <I>rwlock</I> may be used for

+performing synchronization. The result of referring to copies of that

+object in calls to <B>pthread_rwlock_destroy</B> ,

+<B>pthread_rwlock_rdlock</B> , <B>pthread_rwlock_timedrdlock</B> ,

+<B>pthread_rwlock_timedwrlock</B> , <B>pthread_rwlock_tryrdlock</B> ,

+<B>pthread_rwlock_trywrlock</B> , <B>pthread_rwlock_unlock</B> , or

+<B>pthread_rwlock_wrlock</B> is undefined. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as 200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_rwlock_destroy</B> and

+<B>pthread_rwlock_init</B> functions shall return zero; otherwise, an

+error number shall be returned to indicate the error. 

+</P>

+<P>The [EBUSY] and [EINVAL] error checks, if implemented, act as if

+they were performed immediately at the beginning of processing for

+the function and caused an error return prior to modifying the state

+of the read-write lock specified by <I>rwlock</I>. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlock_destroy</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD>

+	The implementation has detected an attempt to destroy the object

+	referenced by <I>rwlock</I> while it is locked. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>rwlock</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_rwlock_init</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EAGAIN</B> 

+	</DT><DD>

+	The system lacked the necessary resources (other than memory) to

+	initialize another read-write lock. 

+	</DD><DT>

+	<B>ENOMEM</B> 

+	</DT><DD>

+	Insufficient memory exists to initialize the read-write lock. 

+	</DD><DD STYLE="margin-left: 0cm; margin-bottom: 0.5cm">

+	<BR><BR>

+	</DD></DL>

+<P>

+The <B>pthread_rwlock_init</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using these and related read-write lock functions may

+be subject to priority inversion, as discussed in the Base

+Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285,

+Priority Inversion. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedrdlock.html"><B>pthread_rwlock_timedrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedwrlock.html"><B>pthread_rwlock_timedwrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_tryrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_trywrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlock_rdlock.html b/manual/pthread_rwlock_rdlock.html
new file mode 100644
index 0000000..b6e79a8
--- /dev/null
+++ b/manual/pthread_rwlock_rdlock.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCK_RDLOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;10352600">

+	<META NAME="CHANGED" CONTENT="20050505;12554200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlock_rdlock, pthread_rwlock_tryrdlock - lock a

+read-write lock object for reading 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_rwlock_rdlock(pthread_rwlock_t <I>*</I></B><I>rwlock</I><B>);

+<BR></B>i<B>nt pthread_rwlock_tryrdlock(pthread_rwlock_t <I>*</I></B><I>rwlock</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlock_rdlock</B> function shall apply a read lock

+to the read-write lock referenced by <I>rwlock</I>. The calling

+thread acquires the read lock if a writer does not hold the lock and

+there are no writers blocked on the lock. 

+</P>

+<P><B>Pthreads-win32</B> does not prefer either writers or readers in

+acquiring the lock – all threads enter a single prioritised FIFO

+queue. While this may not be optimally efficient for some

+applications, it does ensure that one type does not starve the other.</P>

+<P>A thread may hold multiple concurrent read locks on <I>rwlock</I>

+(that is, successfully call the <B>pthread_rwlock_rdlock</B> function

+<I>n</I> times). If so, the application shall ensure that the thread

+performs matching unlocks (that is, it calls the

+<A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B>(3)</A>

+function <I>n</I> times). 

+</P>

+<P>The <B>pthread_rwlock_tryrdlock</B> function shall apply a read

+lock as in the <B>pthread_rwlock_rdlock</B> function, with the

+exception that the function shall fail if the equivalent

+<B>pthread_rwlock_rdlock</B> call would have blocked the calling

+thread. In no case shall the <B>pthread_rwlock_tryrdlock</B> function

+ever block; it always either acquires the lock or fails and returns

+immediately. 

+</P>

+<P>Results are undefined if any of these functions are called with an

+uninitialized read-write lock. 

+</P>

+<P><B>Pthreads-w32</B> does not detect deadlock if the thread already

+owns the lock for writing.</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as  200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_rwlock_rdlock</B> function shall

+return zero; otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<P>The <B>pthread_rwlock_tryrdlock</B> function shall return zero if

+the lock for reading on the read-write lock object referenced by

+<I>rwlock</I> is acquired. Otherwise, an error number shall be

+returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlock_tryrdlock</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The read-write lock could not be acquired for reading because a

+	writer holds the lock or a writer with the appropriate priority was

+	blocked on it. 

+	</DD></DL>

+<P>

+The <B>pthread_rwlock_rdlock</B> and <B>pthread_rwlock_tryrdlock</B>

+functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD>

+	The value specified by <I>rwlock</I> does not refer to an

+	initialized read-write lock object. 

+	</DD><DT>

+	<B>EAGAIN</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The read lock could not be acquired because the maximum number of

+	read locks for <I>rwlock</I> has been exceeded. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using these functions may be subject to priority

+inversion, as discussed in the Base Definitions volume of

+IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285, Priority Inversion. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedrdlock.html"><B>pthread_rwlock_timedrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedwrlock.html"><B>pthread_rwlock_timedwrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_trywrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlock_timedrdlock.html b/manual/pthread_rwlock_timedrdlock.html
new file mode 100644
index 0000000..88bf8f8
--- /dev/null
+++ b/manual/pthread_rwlock_timedrdlock.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCK_TIMEDRDLOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;11101700">

+	<META NAME="CHANGED" CONTENT="20050505;12560000">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlock_timedrdlock - lock a read-write lock for reading 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; <BR></B>#include &lt;time.h&gt; 

+</P>

+<P><B>int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict</B>

+<I>rwlock</I><B>, const struct timespec *restrict</B> <I>abs_timeout</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlock_timedrdlock</B> function shall apply a read

+lock to the read-write lock referenced by <I>rwlock</I> as in the

+<A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B>(3)</A>

+function. However, if the lock cannot be acquired without waiting for

+other threads to unlock the lock, this wait shall be terminated when

+the specified timeout expires. The timeout shall expire when the

+absolute time specified by <I>abs_timeout</I> passes, as measured by

+the clock on which timeouts are based (that is, when the value of

+that clock equals or exceeds <I>abs_timeout</I>), or if the absolute

+time specified by <I>abs_timeout</I> has already been passed at the

+time of the call. 

+</P>

+<P>The <B>timespec</B> data type is defined in the <I>&lt;time.h&gt;</I>

+header. Under no circumstances shall the function fail with a timeout

+if the lock can be acquired immediately. The validity of the

+<I>abs_timeout</I> parameter need not be checked if the lock can be

+immediately acquired. 

+</P>

+<P>The calling thread may deadlock if at the time the call is made it

+holds a write lock on <I>rwlock</I>. The results are undefined if

+this function is called with an uninitialized read-write lock. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as  200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>The <B>pthread_rwlock_timedrdlock</B> function shall return zero

+if the lock for reading on the read-write lock object referenced by

+<I>rwlock</I> is acquired. Otherwise, an error number shall be

+returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlock_timedrdlock</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>ETIMEDOUT</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The lock could not be acquired before the specified timeout expired.

+		</DD></DL>

+<P>

+The <B>pthread_rwlock_timedrdlock</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EAGAIN</B> 

+	</DT><DD>

+	The read lock could not be acquired because the maximum number of

+	read locks for lock would be exceeded. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>rwlock</I> does not refer to an

+	initialized read-write lock object, or the <I>abs_timeout</I>

+	nanosecond value is less than zero or greater than or equal to 1000

+	million. 

+	</DD></DL>

+<P>

+This function shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using this function may be subject to priority

+inversion, as discussed in the Base Definitions volume of

+IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285, Priority Inversion. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedwrlock.html"><B>pthread_rwlock_timedwrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_tryrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_trywrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I>, <I>&lt;time.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlock_timedwrlock.html b/manual/pthread_rwlock_timedwrlock.html
new file mode 100644
index 0000000..2f72c55
--- /dev/null
+++ b/manual/pthread_rwlock_timedwrlock.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCK_TIMEDWRLOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;11172800">

+	<META NAME="CHANGED" CONTENT="20050505;12561600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlock_timedwrlock - lock a read-write lock for writing 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; <BR></B>#include &lt;time.h&gt; 

+</P>

+<P><B>int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict</B>

+<I>rwlock</I><B>, const struct timespec *restrict</B> <I>abs_timeout</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlock_timedwrlock</B> function shall apply a write

+lock to the read-write lock referenced by <I>rwlock</I> as in the

+<A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B>(3)</A>

+function. However, if the lock cannot be acquired without waiting for

+other threads to unlock the lock, this wait shall be terminated when

+the specified timeout expires. The timeout shall expire when the

+absolute time specified by <I>abs_timeout</I> passes, as measured by

+the clock on which timeouts are based (that is, when the value of

+that clock equals or exceeds <I>abs_timeout</I>), or if the absolute

+time specified by <I>abs_timeout</I> has already been passed at the

+time of the call. 

+</P>

+<P>The <B>timespec</B> data type is defined in the <I>&lt;time.h&gt;</I>

+header. Under no circumstances shall the function fail with a timeout

+if the lock can be acquired immediately. The validity of the

+<I>abs_timeout</I> parameter need not be checked if the lock can be

+immediately acquired. 

+</P>

+<P>The calling thread may deadlock if at the time the call is made it

+holds the read-write lock. The results are undefined if this function

+is called with an uninitialized read-write lock. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as  200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>The <B>pthread_rwlock_timedwrlock</B> function shall return zero

+if the lock for writing on the read-write lock object referenced by

+<I>rwlock</I> is acquired. Otherwise, an error number shall be

+returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlock_timedwrlock</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>ETIMEDOUT</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The lock could not be acquired before the specified timeout expired.

+		</DD></DL>

+<P>

+The <B>pthread_rwlock_timedwrlock</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by rwlock does not refer to an initialized

+	read-write lock object, or the <I>abs_timeout</I> nanosecond value

+	is less than zero or greater than or equal to 1000 million. 

+	</DD></DL>

+<P>

+This function shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using this function may be subject to priority

+inversion, as discussed in the Base Definitions volume of

+IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285, Priority Inversion. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedrdlock.html"><B>pthread_rwlock_timedrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_tryrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_trywrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I>, <I>&lt;time.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlock_unlock.html b/manual/pthread_rwlock_unlock.html
new file mode 100644
index 0000000..6c8d25a
--- /dev/null
+++ b/manual/pthread_rwlock_unlock.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCK_UNLOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;11291100">

+	<META NAME="CHANGED" CONTENT="20050505;12562700">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlock_unlock - unlock a read-write lock object 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P>in<B>t pthread_rwlock_unlock(pthread_rwlock_t <I>*</I></B><I>rwlock</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlock_unlock</B> function shall release a lock

+held on the read-write lock object referenced by <I>rwlock</I>.

+Results are undefined if the read-write lock <I>rwlock</I> is not

+held by the calling thread. 

+</P>

+<P>If this function is called to release a read lock from the

+read-write lock object and there are other read locks currently held

+on this read-write lock object, the read-write lock object remains in

+the read locked state. If this function releases the last read lock

+for this read-write lock object, the read-write lock object shall be

+put in the unlocked state with no owners. 

+</P>

+<P>If this function is called to release a write lock for this

+read-write lock object, the read-write lock object shall be put in

+the unlocked state. 

+</P>

+<P><B>Pthreads-win32</B> does not prefer either writers or readers in

+acquiring the lock – all threads enter a single prioritised FIFO

+queue. While this may not be optimally efficient for some

+applications, it does ensure that one type does not starve the other.</P>

+<P>Results are undefined if any of these functions are called with an

+uninitialized read-write lock. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as  200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_rwlock_unlock</B> function shall

+return zero; otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlock_unlock</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD>

+	The value specified by <I>rwlock</I> does not refer to an

+	initialized read-write lock object. 

+	</DD><DD STYLE="margin-left: 0cm; margin-bottom: 0.5cm">

+	<BR><BR>

+	</DD></DL>

+<P>

+The <B>pthread_rwlock_unlock</B> function shall not return an error

+code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedrdlock.html"><B>pthread_rwlock_timedrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedwrlock.html"><B>pthread_rwlock_timedwrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_tryrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_trywrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_wrlock.html"><B>pthread_rwlock_wrlock</B>(3)</A>

+, the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlock_wrlock.html b/manual/pthread_rwlock_wrlock.html
new file mode 100644
index 0000000..f4ef782
--- /dev/null
+++ b/manual/pthread_rwlock_wrlock.html
@@ -0,0 +1,153 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCK_TRYWRLOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;11221900">

+	<META NAME="CHANGED" CONTENT="20050505;12563800">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlock_trywrlock, pthread_rwlock_wrlock - lock a

+read-write lock object for writing 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_rwlock_trywrlock(pthread_rwlock_t <I>*</I></B><I>rwlock</I><B>);

+<BR>int pthread_rwlock_wrlock(pthread_rwlock_t <I>*</I></B><I>rwlock</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlock_trywrlock</B> function shall apply a write

+lock like the <B>pthread_rwlock_wrlock</B> function, with the

+exception that the function shall fail if any thread currently holds

+<I>rwlock</I> (for reading or writing). 

+</P>

+<P>The <B>pthread_rwlock_wrlock</B> function shall apply a write lock

+to the read-write lock referenced by <I>rwlock</I>. The calling

+thread acquires the write lock if no other thread (reader or writer)

+holds the read-write lock <I>rwlock</I>. Otherwise, the thread shall

+block until it can acquire the lock. The calling thread may deadlock

+if at the time the call is made it holds the read-write lock (whether

+a read or write lock). 

+</P>

+<P><B>Pthreads-win32</B> does not prefer either writers or readers in

+acquiring the lock – all threads enter a single prioritised FIFO

+queue. While this may not be optimally efficient for some

+applications, it does ensure that one type does not starve the other.</P>

+<P>Results are undefined if any of these functions are called with an

+uninitialized read-write lock. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as  200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>The <B>pthread_rwlock_trywrlock</B> function shall return zero if

+the lock for writing on the read-write lock object referenced by

+<I>rwlock</I> is acquired. Otherwise, an error number shall be

+returned to indicate the error. 

+</P>

+<P>If successful, the <B>pthread_rwlock_wrlock</B> function shall

+return zero; otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlock_trywrlock</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The read-write lock could not be acquired for writing because it was

+	already locked for reading or writing. 

+	</DD></DL>

+<P>

+The <B>pthread_rwlock_trywrlock</B> and <B>pthread_rwlock_wrlock</B>

+functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>rwlock</I> does not refer to an

+	initialized read-write lock object. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using these functions may be subject to priority

+inversion, as discussed in the Base Definitions volume of

+IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285, Priority Inversion. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_rdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedrdlock.html"><B>pthread_rwlock_timedrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_timedwrlock.html"><B>pthread_rwlock_timedwrlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_rdlock.html"><B>pthread_rwlock_tryrdlock</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlock_unlock.html"><B>pthread_rwlock_unlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlockattr_init.html b/manual/pthread_rwlockattr_init.html
new file mode 100644
index 0000000..4a24f7b
--- /dev/null
+++ b/manual/pthread_rwlockattr_init.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCKATTR_DESTROY&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;504000">

+	<META NAME="CHANGED" CONTENT="20050505;18474200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlockattr_destroy, pthread_rwlockattr_init - destroy and

+initialize the read-write lock attributes object 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_rwlockattr_destroy(pthread_rwlockattr_t <I>*</I></B><I>attr</I><B>);

+<BR>int pthread_rwlockattr_init(pthread_rwlockattr_t <I>*</I></B><I>attr</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlockattr_destroy</B> function shall destroy a

+read-write lock attributes object. A destroyed <I>attr</I> attributes

+object can be reinitialized using <B>pthread_rwlockattr_init</B> ;

+the results of otherwise referencing the object after it has been

+destroyed are undefined. An implementation may cause

+<B>pthread_rwlockattr_destroy</B> to set the object referenced by

+<I>attr</I> to an invalid value. 

+</P>

+<P>The <B>pthread_rwlockattr_init</B> function shall initialize a

+read-write lock attributes object <I>attr</I> with the default value

+for all of the attributes defined by the implementation. 

+</P>

+<P>Results are undefined if <B>pthread_rwlockattr_init</B> is called

+specifying an already initialized <I>attr</I> attributes object. 

+</P>

+<P>After a read-write lock attributes object has been used to

+initialize one or more read-write locks, any function affecting the

+attributes object (including destruction) shall not affect any

+previously initialized read-write locks. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as 200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_rwlockattr_destroy</B> and

+<B>pthread_rwlockattr_init</B> functions shall return zero;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlockattr_destroy</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_rwlockattr_init</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>ENOMEM</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	Insufficient memory exists to initialize the read-write lock

+	attributes object. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlockattr_setpshared.html"><B>pthread_rwlockattr_getpshared</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlockattr_setpshared.html"><B>pthread_rwlockattr_setpshared</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_rwlockattr_setpshared.html b/manual/pthread_rwlockattr_setpshared.html
new file mode 100644
index 0000000..2a427fe
--- /dev/null
+++ b/manual/pthread_rwlockattr_setpshared.html
@@ -0,0 +1,160 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_RWLOCKATTR_GETPSHARED&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;10124400">

+	<META NAME="CHANGED" CONTENT="20050505;12572100">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_rwlockattr_getpshared, pthread_rwlockattr_setpshared - get

+and set the process-shared attribute of the read-write lock

+attributes object 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *

+restrict </B><I>attr</I><B>, int *restrict</B> <I>pshared</I><B>);

+<BR>int pthread_rwlockattr_setpshared(pthread_rwlockattr_t <I>*</I></B><I>attr</I><B>,

+int</B> <I>pshared</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_rwlockattr_getpshared</B> function shall obtain the

+value of the <I>process-shared</I> attribute from the initialized

+attributes object referenced by <I>attr</I>. The

+<B>pthread_rwlockattr_setpshared</B> function shall set the

+<I>process-shared</I> attribute in an initialized attributes object

+referenced by <I>attr</I>. 

+</P>

+<P>The <I>process-shared</I> attribute shall be set to

+<B>PTHREAD_PROCESS_SHARED</B> to permit a read-write lock to be

+operated upon by any thread that has access to the memory where the

+read-write lock is allocated, even if the read-write lock is

+allocated in memory that is shared by multiple processes. If the

+<I>process-shared</I> attribute is <B>PTHREAD_PROCESS_PRIVATE</B>,

+the read-write lock shall only be operated upon by threads created

+within the same process as the thread that initialized the read-write

+lock; if threads of differing processes attempt to operate on such a

+read-write lock, the behavior is undefined. The default value of the

+<I>process-shared</I> attribute shall be <B>PTHREAD_PROCESS_PRIVATE</B>.

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that these routines are implemented but

+they do not support the process shared option.</P>

+<P>Additional attributes, their default values, and the names of the

+associated functions to get and set those attribute values are

+implementation-defined. 

+</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_READER_WRITER_LOCKS</B> in

+pthread.h as  200112L to indicate that the reader/writer routines are

+implemented and may be used.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, the <B>pthread_rwlockattr_getpshared</B>

+function shall return zero and store the value of the <I>process-shared</I>

+attribute of <I>attr</I> into the object referenced by the <I>pshared</I>

+parameter. Otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<P>If successful, the <B>pthread_rwlockattr_setpshared</B> function

+shall return zero; otherwise, an error number shall be returned to

+indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_rwlockattr_getpshared</B> and

+<B>pthread_rwlockattr_setpshared</B> functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>attr</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_rwlockattr_setpshared</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The new value specified for the attribute is outside the range of

+	legal values for that attribute. 

+	</DD><DT>

+	<B>ENOTSUP</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The new value specified for the attribute is <B>PTHREAD_PROCESS_SHARED</B>.

+		</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_rwlock_init.html"><B>pthread_rwlock_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlockattr_init.html"><B>pthread_rwlockattr_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_rwlockattr_init.html"><B>pthread_rwlockattr_init</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_self.html b/manual/pthread_self.html
new file mode 100644
index 0000000..5af3cd5
--- /dev/null
+++ b/manual/pthread_self.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_SELF(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;11361600">

+	<META NAME="CHANGED" CONTENT="20050505;11575700">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_self - return identifier of current thread 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>pthread_t pthread_self(void);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_self</B> return the thread identifier for the calling

+thread. 

+</P>

+<P><B>Pthreads-w32</B> also provides support for <B>Win32</B> native

+threads to interact with POSIX threads through the pthreads API.

+Whereas all threads created via a call to pthread_create have a POSIX

+thread ID and thread state, the library ensures that any Win32 native

+threads that interact through the Pthreads API also generate a POSIX

+thread ID and thread state when and if necessary. This provides full

+<SPAN LANG="en-GB">reciprocity</SPAN> between Win32 and POSIX

+threads. Win32 native threads that generate a POSIX thread ID and

+state are treated by the library as having been created with the

+<B>PTHREAD_CREATE_DETACHED</B> attribute.</P>

+<P>Any Win32 native thread may call <B>pthread_self</B> directly to

+return it's POSIX thread identifier. The ID and state will be

+generated if it does not already exist. Win32 native threads do not

+need to call <B>pthread_self</B> before calling Pthreads-w32 routines

+unless that routine requires a pthread_t parameter.</P>

+<H2><A HREF="#toc3" NAME="sect3">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc4" NAME="sect4">See Also</A></H2>

+<P><A HREF="pthread_equal.html"><B>pthread_equal</B>(3)</A> ,

+<A HREF="pthread_join.html"><B>pthread_join</B>(3)</A> ,

+<A HREF="pthread_detach.html"><B>pthread_detach</B>(3)</A> ,

+<A HREF="pthread_setschedparam.html"><B>pthread_setschedparam</B>(3)</A>

+, <A HREF="pthread_setschedparam.html"><B>pthread_getschedparam</B>(3)</A>

+. 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Author</A>

+		</P>

+	<LI><P><A HREF="#sect4" NAME="toc4">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_setcancelstate.html b/manual/pthread_setcancelstate.html
new file mode 100644
index 0000000..1dd9ec3
--- /dev/null
+++ b/manual/pthread_setcancelstate.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_CANCEL(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;12090500">

+	<META NAME="CHANGED" CONTENT="20050504;16361300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_cancel, pthread_setcancelstate, pthread_setcanceltype,

+pthread_testcancel - thread cancellation 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_cancel(pthread_t </B><I>thread</I><B>);</B> 

+</P>

+<P><B>int pthread_setcancelstate(int </B><I>state</I><B>, int

+*</B><I>oldstate</I><B>);</B> 

+</P>

+<P><B>int pthread_setcanceltype(int </B><I>type</I><B>, int

+*</B><I>oldtype</I><B>);</B> 

+</P>

+<P><B>void pthread_testcancel(void);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Cancellation is the mechanism by which a thread can terminate the

+execution of another thread. More precisely, a thread can send a

+cancellation request to another thread. Depending on its settings,

+the target thread can then either ignore the request, honor it

+immediately, or defer it until it reaches a cancellation point. 

+</P>

+<P>When a thread eventually honors a cancellation request, it

+performs as if <B>pthread_exit(PTHREAD_CANCELED)</B> has been called

+at that point: all cleanup handlers are executed in reverse order,

+destructor functions for thread-specific data are called, and finally

+the thread stops executing with the return value <B>PTHREAD_CANCELED</B>.

+See <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> for more

+information. 

+</P>

+<P><B>pthread_cancel</B> sends a cancellation request to the thread

+denoted by the <I>thread</I> argument. 

+</P>

+<P><B>pthread_setcancelstate</B> changes the cancellation state for

+the calling thread -- that is, whether cancellation requests are

+ignored or not. The <I>state</I> argument is the new cancellation

+state: either <B>PTHREAD_CANCEL_ENABLE</B> to enable cancellation, or

+<B>PTHREAD_CANCEL_DISABLE</B> to disable cancellation (cancellation

+requests are ignored). If <I>oldstate</I> is not <B>NULL</B>, the

+previous cancellation state is stored in the location pointed to by

+<I>oldstate</I>, and can thus be restored later by another call to

+<B>pthread_setcancelstate</B>. 

+</P>

+<P><B>pthread_setcanceltype</B> changes the type of responses to

+cancellation requests for the calling thread: asynchronous

+(immediate) or deferred. The <I>type</I> argument is the new

+cancellation type: either <B>PTHREAD_CANCEL_ASYNCHRONOUS</B> to

+cancel the calling thread as soon as the cancellation request is

+received, or <B>PTHREAD_CANCEL_DEFERRED</B> to keep the cancellation

+request pending until the next cancellation point. If <I>oldtype</I>

+is not <B>NULL</B>, the previous cancellation state is stored in the

+location pointed to by <I>oldtype</I>, and can thus be restored later

+by another call to <B>pthread_setcanceltype</B>. 

+</P>

+<P><B>Pthreads-w32</B> provides two levels of support for

+<B>PTHREAD_CANCEL_ASYNCHRONOUS</B>: full and partial. Full support

+requires an additional DLL and driver be installed on the Windows

+system (see the See Also section below) that allows blocked threads

+to be cancelled immediately. Partial support means that the target

+thread will not cancel until it resumes execution naturally. Partial

+support is provided if either the DLL or the driver are not

+automatically detected by the pthreads-w32 library at run-time.</P>

+<P>Threads are always created by <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A>

+with cancellation enabled and deferred. That is, the initial

+cancellation state is <B>PTHREAD_CANCEL_ENABLE</B> and the initial

+type is <B>PTHREAD_CANCEL_DEFERRED</B>. 

+</P>

+<P>Cancellation points are those points in the program execution

+where a test for pending cancellation requests is performed and

+cancellation is executed if positive. The following POSIX threads

+functions are cancellation points: 

+</P>

+<P><A HREF="pthread_join.html"><B>pthread_join</B>(3)</A>

+<BR><A HREF="pthread_cond_wait.html"><B>pthread_cond_wait</B>(3)</A>

+<BR><A HREF="pthread_cond_timedwait.html"><B>pthread_cond_timedwait</B>(3)</A>

+<BR><A HREF="pthread_testcancel.html"><B>pthread_testcancel</B>(3)</A>

+<BR><A HREF="sem_wait.html"><B>sem_wait</B>(3)</A> <BR><A HREF="sem_timedwait.html"><B>sem_timedwait</B>(3)</A>

+<BR><A HREF="sigwait.html"><B>sigwait</B>(3)</A> (not supported under

+<B>Pthreads-w32</B>)</P>

+<P><B>Pthreads-w32</B> provides two functions to enable additional

+cancellation points to be created in user functions that block on

+Win32 HANDLEs:</P>

+<P><A HREF="pthreadCancelableWait.html">pthreadCancelableWait()</A>

+<BR><A HREF="pthreadCancelableTimedWait.html">pthreadCancelableTimedWait()</A></P>

+<P>All other POSIX threads functions are guaranteed not to be

+cancellation points. That is, they never perform cancellation in

+deferred cancellation mode. 

+</P>

+<P><B>pthread_testcancel</B> does nothing except testing for pending

+cancellation and executing it. Its purpose is to introduce explicit

+checks for cancellation in long sequences of code that do not call

+cancellation point functions otherwise. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P><B>pthread_cancel</B>, <B>pthread_setcancelstate</B> and

+<B>pthread_setcanceltype</B> return 0 on success and a non-zero error

+code on error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P><B>pthread_cancel</B> returns the following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ESRCH</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		no thread could be found corresponding to that specified by the

+		<I>thread</I> ID. 

+		</DD></DL>

+</DL>

+<P>

+<B>pthread_setcancelstate</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>state</I> argument is not 

+		</DD></DL>

+</DL>

+<BLOCKQUOTE>

+<B>PTHREAD_CANCEL_ENABLE</B> nor <B>PTHREAD_CANCEL_DISABLE</B> 

+</BLOCKQUOTE>

+<P><B>pthread_setcanceltype</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>type</I> argument is not 

+		</DD></DL>

+</DL>

+<BLOCKQUOTE>

+<B>PTHREAD_CANCEL_DEFERRED</B> nor <B>PTHREAD_CANCEL_ASYNCHRONOUS</B>

+</BLOCKQUOTE>

+<H2><A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> ,

+<A HREF="pthread_cleanup_push.html"><B>pthread_cleanup_push</B>(3)</A>

+, <A HREF="pthread_cleanup_pop.html"><B>pthread_cleanup_pop</B>(3)</A>

+, Pthreads-w32 package README file 'Prerequisites' section. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Bugs</A></H2>

+<P>POSIX specifies that a number of system calls (basically, all

+system calls that may block, such as <A HREF="read.html"><B>read</B>(2)</A>

+, <A HREF="write.html"><B>write</B>(2)</A> , <A HREF="wait.html"><B>wait</B>(2)</A>

+, etc.) and library functions that may call these system calls (e.g.

+<A HREF="fprintf.html"><B>fprintf</B>(3)</A> ) are cancellation

+points. <B>Pthreads-win32</B> is not integrated enough with the C

+library to implement this, and thus none of the C library functions

+is a cancellation point. 

+</P>

+<P>A workaround for these calls is to temporarily switch to

+asynchronous cancellation (assuming full asynchronous cancellation

+support is installed). So, checking for cancellation during a <B>read</B>

+system call, for instance, can be achieved as follows: 

+</P>

+<BLOCKQUOTE><BR><BR>

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1cm; margin-right: 1cm">pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &amp;oldCancelType);

+read(fd, buffer, length);

+pthread_setcanceltype(oldCancelType, NULL);</PRE>

+<HR>

+<BLOCKQUOTE><A NAME="toc"></A><B>Table of Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE><A HREF="#sect7" NAME="toc7">Bugs</A> 

+	</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_setcanceltype.html b/manual/pthread_setcanceltype.html
new file mode 100644
index 0000000..27bb1e3
--- /dev/null
+++ b/manual/pthread_setcanceltype.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_CANCEL(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;12090500">

+	<META NAME="CHANGED" CONTENT="20050504;16362800">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_cancel, pthread_setcancelstate, pthread_setcanceltype,

+pthread_testcancel - thread cancellation 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_cancel(pthread_t </B><I>thread</I><B>);</B> 

+</P>

+<P><B>int pthread_setcancelstate(int </B><I>state</I><B>, int

+*</B><I>oldstate</I><B>);</B> 

+</P>

+<P><B>int pthread_setcanceltype(int </B><I>type</I><B>, int

+*</B><I>oldtype</I><B>);</B> 

+</P>

+<P><B>void pthread_testcancel(void);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Cancellation is the mechanism by which a thread can terminate the

+execution of another thread. More precisely, a thread can send a

+cancellation request to another thread. Depending on its settings,

+the target thread can then either ignore the request, honor it

+immediately, or defer it until it reaches a cancellation point. 

+</P>

+<P>When a thread eventually honors a cancellation request, it

+performs as if <B>pthread_exit(PTHREAD_CANCELED)</B> has been called

+at that point: all cleanup handlers are executed in reverse order,

+destructor functions for thread-specific data are called, and finally

+the thread stops executing with the return value <B>PTHREAD_CANCELED</B>.

+See <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> for more

+information. 

+</P>

+<P><B>pthread_cancel</B> sends a cancellation request to the thread

+denoted by the <I>thread</I> argument. 

+</P>

+<P><B>pthread_setcancelstate</B> changes the cancellation state for

+the calling thread -- that is, whether cancellation requests are

+ignored or not. The <I>state</I> argument is the new cancellation

+state: either <B>PTHREAD_CANCEL_ENABLE</B> to enable cancellation, or

+<B>PTHREAD_CANCEL_DISABLE</B> to disable cancellation (cancellation

+requests are ignored). If <I>oldstate</I> is not <B>NULL</B>, the

+previous cancellation state is stored in the location pointed to by

+<I>oldstate</I>, and can thus be restored later by another call to

+<B>pthread_setcancelstate</B>. 

+</P>

+<P><B>pthread_setcanceltype</B> changes the type of responses to

+cancellation requests for the calling thread: asynchronous

+(immediate) or deferred. The <I>type</I> argument is the new

+cancellation type: either <B>PTHREAD_CANCEL_ASYNCHRONOUS</B> to

+cancel the calling thread as soon as the cancellation request is

+received, or <B>PTHREAD_CANCEL_DEFERRED</B> to keep the cancellation

+request pending until the next cancellation point. If <I>oldtype</I>

+is not <B>NULL</B>, the previous cancellation state is stored in the

+location pointed to by <I>oldtype</I>, and can thus be restored later

+by another call to <B>pthread_setcanceltype</B>. 

+</P>

+<P><B>Pthreads-w32</B> provides two levels of support for

+<B>PTHREAD_CANCEL_ASYNCHRONOUS</B>: full and partial. Full support

+requires an additional DLL and driver be installed on the Windows

+system (see the See Also section below) that allows blocked threads

+to be cancelled immediately. Partial support means that the target

+thread will not cancel until it resumes execution naturally. Partial

+support is provided if either the DLL or the driver are not

+automatically detected by the pthreads-w32 library at run-time.</P>

+<P>Threads are always created by <A HREF="pthread_create.html"><B>pthread_create</B>(3)</A>

+with cancellation enabled and deferred. That is, the initial

+cancellation state is <B>PTHREAD_CANCEL_ENABLE</B> and the initial

+type is <B>PTHREAD_CANCEL_DEFERRED</B>. 

+</P>

+<P>Cancellation points are those points in the program execution

+where a test for pending cancellation requests is performed and

+cancellation is executed if positive. The following POSIX threads

+functions are cancellation points: 

+</P>

+<P><A HREF="pthread_join.html"><B>pthread_join</B>(3)</A>

+<BR><A HREF="pthread_cond_wait.html"><B>pthread_cond_wait</B>(3)</A>

+<BR><A HREF="pthread_cond_timedwait.html"><B>pthread_cond_timedwait</B>(3)</A>

+<BR><A HREF="pthread_testcancel.html"><B>pthread_testcancel</B>(3)</A>

+<BR><A HREF="sem_wait.html"><B>sem_wait</B>(3)</A> <BR><A HREF="sem_timedwait.html"><B>sem_timedwait</B>(3)</A>

+<BR><A HREF="sigwait.html"><B>sigwait</B>(3)</A> (not supported under

+<B>Pthreads-w32</B>)</P>

+<P><B>Pthreads-w32</B> provides two functions to enable additional

+cancellation points to be created in user functions that block on

+Win32 HANDLEs:</P>

+<P><A HREF="pthreadCancelableWait.html">pthreadCancelableWait()</A>

+<BR><A HREF="pthreadCancelableTimedWait.html">pthreadCancelableTimedWait()</A></P>

+<P>All other POSIX threads functions are guaranteed not to be

+cancellation points. That is, they never perform cancellation in

+deferred cancellation mode. 

+</P>

+<P><B>pthread_testcancel</B> does nothing except testing for pending

+cancellation and executing it. Its purpose is to introduce explicit

+checks for cancellation in long sequences of code that do not call

+cancellation point functions otherwise. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P><B>pthread_cancel</B>, <B>pthread_setcancelstate</B> and

+<B>pthread_setcanceltype</B> return 0 on success and a non-zero error

+code on error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P><B>pthread_cancel</B> returns the following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ESRCH</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		no thread could be found corresponding to that specified by the

+		<I>thread</I> ID. 

+		</DD></DL>

+</DL>

+<P>

+<B>pthread_setcancelstate</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>state</I> argument is not 

+		</DD></DL>

+</DL>

+<BLOCKQUOTE>

+<B>PTHREAD_CANCEL_ENABLE</B> nor <B>PTHREAD_CANCEL_DISABLE</B> 

+</BLOCKQUOTE>

+<P><B>pthread_setcanceltype</B> returns the following error code on

+error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>type</I> argument is not 

+		</DD></DL>

+</DL>

+<BLOCKQUOTE>

+<B>PTHREAD_CANCEL_DEFERRED</B> nor <B>PTHREAD_CANCEL_ASYNCHRONOUS</B>

+</BLOCKQUOTE>

+<H2><A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A> ,

+<A HREF="pthread_cleanup_push.html"><B>pthread_cleanup_push</B>(3)</A>

+, <A HREF="pthread_cleanup_pop.html"><B>pthread_cleanup_pop</B>(3)</A>

+, Pthreads-w32 package README file 'Prerequisites' section. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Bugs</A></H2>

+<P>POSIX specifies that a number of system calls (basically, all

+system calls that may block, such as <A HREF="read.html"><B>read</B>(2)</A>

+, <A HREF="write.html"><B>write</B>(2)</A> , <A HREF="wait.html"><B>wait</B>(2)</A>

+, etc.) and library functions that may call these system calls (e.g.

+<A HREF="fprintf.html"><B>fprintf</B>(3)</A> ) are cancellation

+points. <B>Pthreads-win32</B> is not integrated enough with the C

+library to implement this, and thus none of the C library functions

+is a cancellation point. 

+</P>

+<P>A workaround for these calls is to temporarily switch to

+asynchronous cancellation (assuming full asynchronous cancellation

+support is installed). So, checking for cancellation during a <B>read</B>

+system call, for instance, can be achieved as follows: 

+</P>

+<BLOCKQUOTE><BR><BR>

+</BLOCKQUOTE>

+<PRE STYLE="margin-left: 1cm; margin-right: 1cm">pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &amp;oldCancelType);

+read(fd, buffer, length);

+pthread_setcanceltype(oldCancelType, NULL);</PRE>

+<HR>

+<BLOCKQUOTE><A NAME="toc"></A><B>Table of Contents</B></BLOCKQUOTE>

+<UL>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</BLOCKQUOTE>

+	<LI><BLOCKQUOTE STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See

+	Also</A> 

+	</BLOCKQUOTE>

+	<LI><BLOCKQUOTE><A HREF="#sect7" NAME="toc7">Bugs</A> 

+	</BLOCKQUOTE>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_setconcurrency.html b/manual/pthread_setconcurrency.html
new file mode 100644
index 0000000..f3f598f
--- /dev/null
+++ b/manual/pthread_setconcurrency.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_GETCONCURRENCY&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;19162600">

+	<META NAME="CHANGED" CONTENT="20050505;19223800">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_getconcurrency, pthread_setconcurrency - get and set the

+level of concurrency 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_getconcurrency(void);</B> <BR><B>int

+pthread_setconcurrency(int</B> <I>new_level</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Unbound threads in a process may or may not be required to be

+simultaneously active. By default, the threads implementation ensures

+that a sufficient number of threads are active so that the process

+can continue to make progress. While this conserves system resources,

+it may not produce the most effective level of concurrency. 

+</P>

+<P>The <B>pthread_setconcurrency</B> function allows an application

+to inform the threads implementation of its desired concurrency

+level, <I>new_level</I>. The actual level of concurrency provided by

+the implementation as a result of this function call is unspecified. 

+</P>

+<P>If <I>new_level</I> is zero, it causes the implementation to

+maintain the concurrency level at its discretion as if

+<B>pthread_setconcurrency</B> had never been called. 

+</P>

+<P>The <B>pthread_getconcurrency</B> function shall return the value

+set by a previous call to the <B>pthread_setconcurrency</B> function.

+If the <B>pthread_setconcurrency</B> function was not previously

+called, this function shall return zero to indicate that the

+implementation is maintaining the concurrency level. 

+</P>

+<P>A call to <B>pthread_setconcurrency</B> shall inform the

+implementation of its desired concurrency level. The implementation

+shall use this as a hint, not a requirement. 

+</P>

+<P>If an implementation does not support multiplexing of user threads

+on top of several kernel-scheduled entities, the

+<B>pthread_setconcurrency</B> and <B>pthread_getconcurrency</B>

+functions are provided for source code compatibility but they shall

+have no effect when called. To maintain the function semantics, the

+<I>new_level</I> parameter is saved when <B>pthread_setconcurrency</B>

+is called so that a subsequent call to <B>pthread_getconcurrency</B>

+shall return the same value. 

+</P>

+<P><B>Pthreads-w32</B> provides these routines for source code

+compatibility only, as described in the previous paragraph.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>pthread_setconcurrency</B> function shall

+return zero; otherwise, an error number shall be returned to indicate

+the error. 

+</P>

+<P>The <B>pthread_getconcurrency</B> function shall always return the

+concurrency level set by a previous call to <B>pthread_setconcurrency</B>

+. If the <B>pthread_setconcurrency</B> function has never been

+called, <B>pthread_getconcurrency</B> shall return zero. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_setconcurrency</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD>

+	The value specified by <I>new_level</I> is negative. 

+	</DD><DT>

+	<B>EAGAIN</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specific by <I>new_level</I> would cause a system resource

+	to be exceeded. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Use of these functions changes the state of the underlying

+concurrency upon which the application depends. Library developers

+are advised to not use the <B>pthread_getconcurrency</B> and

+<B>pthread_setconcurrency</B> functions since their use may conflict

+with an applications use of these functions. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P>The Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_setschedparam.html b/manual/pthread_setschedparam.html
new file mode 100644
index 0000000..8337ce2
--- /dev/null
+++ b/manual/pthread_setschedparam.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_SETSCHEDPARAM(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050504;18110100">

+	<META NAME="CHANGED" CONTENT="20050614;14012300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_setschedparam, pthread_getschedparam - control thread

+scheduling 

+</P>

+<P>parameters 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>int pthread_setschedparam(pthread_t </B><I>target_thread</I><B>,

+int </B><I>policy</I><B>, const struct sched_param *</B><I>param</I><B>);</B>

+</P>

+<P><B>int pthread_getschedparam(pthread_t </B><I>target_thread</I><B>,

+int *</B><I>policy</I><B>, struct sched_param *</B><I>param</I><B>);</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_setschedparam</B> sets the scheduling parameters for

+the thread <I>target_thread</I> as indicated by <I>policy</I> and

+<I>param</I>. <I>policy</I> can be either <B>SCHED_OTHER</B>

+(regular, non-real-time scheduling), <B>SCHED_RR</B> (real-time,

+round-robin) or <B>SCHED_FIFO</B> (real-time, first-in first-out).

+<I>param</I> specifies the scheduling priority for the two real-time

+policies.</P>

+<P><B>Pthreads-w32</B> only supports SCHED_OTHER and does not support

+the real-time scheduling policies <B>SCHED_RR</B> and <B>SCHED_FIFO.</B>

+</P>

+<P><B>pthread_getschedparam</B> retrieves the scheduling policy and

+scheduling parameters for the thread <I>target_thread</I> and stores

+them in the locations pointed to by <I>policy</I> and <I>param</I>,

+respectively. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P><B>pthread_setschedparam</B> and <B>pthread_getschedparam</B>

+return 0 on success and a non-zero error code on error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>On error, <B>pthread_setschedparam</B> returns the following error

+codes: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ENOTSUP</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<I>policy</I> is not <B>SCHED_OTHER.</B></DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		One of the arguments is invalid, or the priority value specified by

+		<I>param</I> is not valid for the specified policy.</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ESRCH</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		The <I>target_thread</I> is invalid or has already terminated 

+		</DD></DL>

+</DL>

+<P>

+On error, <B>pthread_getschedparam</B> returns the following error

+codes: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ESRCH</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		the <I>target_thread</I> is invalid or has already terminated 

+		</DD></DL>

+</DL>

+<H2>

+<A HREF="#toc5" NAME="sect5">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc6" NAME="sect6">See Also</A></H2>

+<P><A HREF="sched_setscheduler.html"><B>sched_setscheduler</B>(2)</A>

+, <A HREF="sched_getscheduler.html"><B>sched_getscheduler</B>(2)</A>

+, <A HREF="sched_getparam.html"><B>sched_getparam</B>(2)</A> ,

+<A HREF="pthread_attr_setschedpolicy.html"><B>pthread_attr_setschedpolicy</B>(3)</A>

+, <A HREF="pthread_attr_setschedparam.html"><B>pthread_attr_setschedparam</B>(3)</A>

+. 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/pthread_spin_init.html b/manual/pthread_spin_init.html
new file mode 100644
index 0000000..dbf21d5
--- /dev/null
+++ b/manual/pthread_spin_init.html
@@ -0,0 +1,176 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_SPIN_DESTROY&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;12074100">

+	<META NAME="CHANGED" CONTENT="20050505;19014200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_spin_destroy, pthread_spin_init - destroy or initialize a

+spin lock object (<B>ADVANCED REALTIME THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>pthread_spinlock_t</B> <I>lock</I> <B>=

+PTHREAD_SPINLOCK_INITIALIZER;</B></P>

+<P><B>int pthread_spin_destroy(pthread_spinlock_t *</B><I>lock</I><B>);

+<BR>int pthread_spin_init(pthread_spinlock_t *</B><I>lock</I><B>, int</B>

+<I>pshared</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_spin_destroy</B> function shall destroy the spin

+lock referenced by <I>lock</I> and release any resources used by the

+lock. The effect of subsequent use of the lock is undefined until the

+lock is reinitialized by another call to <B>pthread_spin_init</B> .

+The results are undefined if <B>pthread_spin_destroy</B> is called

+when a thread holds the lock, or if this function is called with an

+uninitialized thread spin lock. 

+</P>

+<P>The <B>pthread_spin_init</B> function shall allocate any resources

+required to use the spin lock referenced by <I>lock</I> and

+initialize the lock to an unlocked state. 

+</P>

+<P><B>Pthreads-w32</B> supports single and multiple processor systems

+as well as process CPU affinity masking by checking the mask when the

+spin lock is initialized. If the process is using only a single

+processor at the time <B>pthread_spin_init</B> is called then the

+spin lock is initialized as a PTHREAD_MUTEX_NORMAL mutex object. A

+thread that calls <A HREF="pthread_spin_lock.html"><B>pthread_spin_lock(3)</B></A>

+will block rather than spin in this case. If the process CPU affinity

+mask is altered after the spin lock has been initialised, the spin

+lock is not modified, and may no longer be optimal for the number of

+CPUs available.</P>

+<P><B>Pthreads-w32</B> defines <B>_POSIX_THREAD_PROCESS_SHARED</B> in

+pthread.h as -1 to indicate that these routines do not support the

+<B>PTHREAD_PROCESS_SHARED</B> attribute. <B>pthread_spin_init</B>

+will return the error <B>ENOTSUP</B> if the value of <I>pshared</I>

+is not <B>PTHREAD_PROCESS_PRIVATE</B>.</P>

+<P>The results are undefined if <B>pthread_spin_init</B> is called

+specifying an already initialized spin lock. The results are

+undefined if a spin lock is used without first being initialized. 

+</P>

+<P>If the <B>pthread_spin_init</B> function fails, the lock is not

+initialized and the contents of <I>lock</I> are undefined. 

+</P>

+<P>Only the object referenced by <I>lock</I> may be used for

+performing synchronization. 

+</P>

+<P>The result of referring to copies of that object in calls to

+<B>pthread_spin_destroy</B> , <A HREF="pthread_spin_lock.html"><B>pthread_spin_lock</B>(3)</A>

+, <A HREF="pthread_spin_lock.html"><B>pthread_spin_trylock</B>(3)</A>,

+or <A HREF="pthread_spin_unlock.html"><B>pthread_spin_unlock</B>(3)</A>

+is undefined. 

+</P>

+<P><B>Pthreads-w32</B> supports statically initialized spin locks

+using <B>PTHREAD_SPINLOCK_INITIALIZER</B>. An application should

+still call <B>pthread_spin_destroy</B> at some point to ensure that

+any resources consumed by the spin lock are released.</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, these functions shall return zero;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>These functions may fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD>

+	The implementation has detected an attempt to initialize or destroy

+	a spin lock while it is in use (for example, while being used in a

+	<A HREF="pthread_spin_lock.html"><B>pthread_spin_lock</B>(3)</A>

+	call) by another thread. 

+	</DD><DT>

+	<B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>lock</I> is invalid. 

+	</DD></DL>

+<P>

+The <B>pthread_spin_init</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>ENOTSUP</B> 

+	</DT><DD>

+	The value of <I>pshared</I> is not <B>PTHREAD_PROCESS_PRIVATE</B>.</DD><DT>

+	<B>ENOMEM</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	Insufficient memory exists to initialize the lock. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>The <B>pthread_spin_destroy</B> and <B>pthread_spin_init</B>

+functions are part of the Spin Locks option and need not be provided

+on all implementations. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_spin_lock.html"><B>pthread_spin_lock</B>(3)</A> <B>,</B>

+<A HREF="pthread_spin_unlock.html"><B>pthread_spin_unlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_spin_lock.html b/manual/pthread_spin_lock.html
new file mode 100644
index 0000000..398d2e4
--- /dev/null
+++ b/manual/pthread_spin_lock.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_SPIN_LOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;12202300">

+	<META NAME="CHANGED" CONTENT="20050505;19302300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_spin_lock, pthread_spin_trylock - lock a spin lock object

+(<B>ADVANCED REALTIME THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_spin_lock(pthread_spinlock_t *</B><I>lock</I><B>);

+<BR>int pthread_spin_trylock(pthread_spinlock_t *</B><I>lock</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_spin_lock</B> function shall lock the spin lock

+referenced by <I>lock</I>. The calling thread shall acquire the lock

+if it is not held by another thread. Otherwise, the thread shall spin

+(that is, shall not return from the <B>pthread_spin_lock</B> call)

+until the lock becomes available. The results are undefined if the

+calling thread holds the lock at the time the call is made.</P>

+<P><B>Pthreads-w32</B> supports single and multiple processor systems

+as well as process CPU affinity masking by checking the mask when the

+spin lock is initialized. If the process is using only a single

+processor at the time <A HREF="pthread_spin_init.html"><B>pthread_spin_init</B>(3)</A>

+is called then the spin lock is initialized as a PTHREAD_MUTEX_NORMAL

+mutex object. A thread that calls <B>pthread_spin_lock</B> will block

+rather than spin in this case. If the process CPU affinity mask is

+altered after the spin lock has been initialised, the spin lock is

+not modified, and may no longer be optimal for the number of CPUs

+available.</P>

+<P>The <B>pthread_spin_trylock</B> function shall lock the spin lock

+referenced by <I>lock</I> if it is not held by any thread. Otherwise,

+the function shall fail. 

+</P>

+<P>The results are undefined if any of these functions is called with

+an uninitialized spin lock. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, these functions shall return zero;

+otherwise, an error number shall be returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>These functions may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value specified by <I>lock</I> does not refer to an initialized

+	spin lock object. 

+	</DD></DL>

+<P>

+The <B>pthread_spin_trylock</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EBUSY</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	A thread currently holds the lock. 

+	</DD></DL>

+<P>

+These functions shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>Applications using this function may be subject to priority

+inversion, as discussed in the Base Definitions volume of

+IEEE&nbsp;Std&nbsp;1003.1-2001, Section 3.285, Priority Inversion. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_spin_init.html"><B>pthread_spin_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_spin_unlock.html"><B>pthread_spin_unlock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_spin_unlock.html b/manual/pthread_spin_unlock.html
new file mode 100644
index 0000000..cf8c4b1
--- /dev/null
+++ b/manual/pthread_spin_unlock.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;PTHREAD_SPIN_UNLOCK&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;12401400">

+	<META NAME="CHANGED" CONTENT="20050505;12462400">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>pthread_spin_unlock - unlock a spin lock object (<B>ADVANCED

+REALTIME THREADS</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt; </B>

+</P>

+<P><B>int pthread_spin_unlock(pthread_spinlock_t *</B><I>lock</I><B>);

+</B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>pthread_spin_unlock</B> function shall release the spin

+lock referenced by <I>lock</I> which was locked via the

+<A HREF="pthread_spin_lock.html"><B>pthread_spin_lock</B>(3)</A> or

+<A HREF="pthread_spin_lock.html"><B>pthread_spin_trylock</B>(3)</A>

+functions. If there are threads spinning on the lock when

+<B>pthread_spin_unlock</B> is called, the lock becomes available and

+an unspecified spinning thread shall acquire the lock. 

+</P>

+<P><B>Pthreads-w32</B> does not check ownership of the lock and it is

+therefore possible for a thread other than the locker to unlock the

+spin lock. This is not a feature that should be exploited.</P>

+<P>The results are undefined if this function is called with an

+uninitialized thread spin lock. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, the <B>pthread_spin_unlock</B>

+function shall return zero; otherwise, an error number shall be

+returned to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>pthread_spin_unlock</B> function may fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD>

+	An invalid argument was specified. 

+	</DD><DD STYLE="margin-left: -2cm">

+	<BR>

+	</DD></DL>

+<P>

+This function shall not return an error code of [EINTR]. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P><B>Pthreads-w32</B> does not check ownership of the lock and it is

+therefore possible for a thread other than the locker to unlock the

+spin lock. This is not a feature that should be exploited.</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="pthread_spin_init.html"><B>pthread_spin_destroy</B>(3)</A>

+<B>,</B> <A HREF="pthread_spin_lock.html"><B>pthread_spin_lock</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;pthread.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_timechange_handler_np.html b/manual/pthread_timechange_handler_np.html
new file mode 100644
index 0000000..2f9fc5d
--- /dev/null
+++ b/manual/pthread_timechange_handler_np.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_TIMECHANGE_HANDLER_NP manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050505;22110600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthread_timechange_handler_np –

+alert timed waiting condition variables to system time changes.</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>void * pthread_timechange_handler_np(void * </B><I>dummy</I><B>);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>To improve tolerance against operator or time service initiated

+system clock changes.</P>

+<P><B>pthread_timechange_handler_np </B>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.</P>

+<P><B>pthread_timechange_handler_np </B>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. If run as a

+thread, the return code must be retrieved through <A HREF="pthread_join.html"><B>pthread_join</B>()</A>.</P>

+<P>Although the <I>dummy</I> parameter is required it is not used and

+any value including NULL can be given.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc4" NAME="sect4"><FONT COLOR="#000080">Return Value</FONT></A></H2>

+<P><B>pthread_timechange_handler_np</B> returns 0 on success, or an

+error code.</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>The <B>pthread_timechange_handler_np</B> function returns the

+following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EAGAIN</B> 

+		</DT></DL>

+</DL>

+<P STYLE="margin-left: 2cm; margin-bottom: 0cm">

+To indicate that not all condition variables were signalled for some

+reason.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_win32_attach_detach_np.html b/manual/pthread_win32_attach_detach_np.html
new file mode 100644
index 0000000..1fb4a50
--- /dev/null
+++ b/manual/pthread_win32_attach_detach_np.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_WIN32_ATTACH_DETACH_NP manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050505;22415600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthread_win32_process_attach_np,

+pthread_win32_process_detach_np, pthread_win32_thread_attach_np,

+pthread_win32_thread_detach_np – exposed versions of the

+pthreads-w32 DLL dllMain() switch functionality for use when

+statically linking the library.</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>BOOL pthread_win32_process_attach_np (void);</B></P>

+<P><B>BOOL pthread_win32_process_detach_np (void);</B></P>

+<P><B>BOOL pthread_win32_thread_attach_np (void);</B></P>

+<P><B>BOOL pthread_win32_thread_detach_np (void);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>These functions contain the code normally run via <B>dllMain</B>

+when the library is used as a dll but which need to be called

+explicitly by an application when the library is statically linked.</P>

+<P>You will need to call <B>pthread_win32_process_attach_np</B>

+before you can call any pthread routines when statically linking. You

+should call <B>pthread_win32_process_detach_np</B> before exiting

+your application to clean up.</P>

+<P><B>pthread_win32_thread_attach_np</B> is currently a no-op, but

+<B>pthread_win32_thread_detach_np</B> 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.</P>

+<P>These functions invariably return TRUE except for

+<B>pthread_win32_process_attach_np</B> which will return FALSE if

+pthreads-w32 initialisation fails.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc4" NAME="sect4"><FONT COLOR="#000080">Return Value</FONT></A></H2>

+<P>These routines return TRUE (non-zero) on success, or FALSE (0) if

+they fail.</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/pthread_win32_test_features_np.html b/manual/pthread_win32_test_features_np.html
new file mode 100644
index 0000000..7e6c665
--- /dev/null
+++ b/manual/pthread_win32_test_features_np.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>PTHREAD_WIN32_TEST_FEATURES_NP manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;322600">

+	<META NAME="CHANGED" CONTENT="20050510;17405600">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P STYLE="font-weight: medium">pthread_win32_test_features_np –

+find out what features were detected at process attach time.</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;pthread.h&gt;</B> 

+</P>

+<P><B>BOOL pthread_win32_test_features_np(int</B> <I>mask</I><B>);</B></P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P><B>pthread_win32_test_features_np</B> allows an application to

+check which run-time auto-detected features are available within the

+library.</P>

+<P>The possible features are:</P>

+<P><B>PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE</B></P>

+<P STYLE="margin-left: 2cm">Return TRUE if the Win32 version of

+InterlockedCompareExchange() is being used. On IA32 systems the

+library can use optimised and inlinable assembler versions of

+InterlockedExchange() and InterlockedCompareExchange().</P>

+<P><B>PTW32_ALERTABLE_ASYNC_CANCEL</B></P>

+<P STYLE="margin-left: 2cm">Return TRUE if the QueueUserAPCEx package

+QUSEREX.DLL and the AlertDrv.sys driver was detected. This package

+provides alertable (pre-emptive) asynchronous threads cancellation.

+If this feature returns FALSE then the default async cancel scheme is

+in use, which cannot cancel blocked threads.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc4" NAME="sect4"><FONT COLOR="#000080">Return Value</FONT></A></H2>

+<P><B>pthread_win32_test_features_np</B> returns TRUE (non-zero) if

+the specified feature is present, and FALSE (0) otherwise.</P>

+<H2><A HREF="#toc5" NAME="sect5">Errors</A></H2>

+<P>None.</P>

+<H2><A HREF="#toc6" NAME="sect6">Author</A></H2>

+<P>Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Errors</A>

+		</P>

+	<LI><P><A HREF="#sect6" NAME="toc6">Author</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/sched_get_priority_max.html b/manual/sched_get_priority_max.html
new file mode 100644
index 0000000..f79f59b
--- /dev/null
+++ b/manual/sched_get_priority_max.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;SCHED_GET_PRIORITY_MAX&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;12575100">

+	<META NAME="CHANGED" CONTENT="20050510;12533300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>sched_get_priority_max, sched_get_priority_min - get priority

+limits (<B>REALTIME</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;sched.h&gt; </B>

+</P>

+<P><B>int sched_get_priority_max(int</B> <I>policy</I><B>); <BR>int

+sched_get_priority_min(int</B> <I>policy</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>sched_get_priority_max</B> and <B>sched_get_priority_min</B>

+functions shall return the appropriate maximum or minimum,

+respectively, for the scheduling policy specified by <I>policy</I>. 

+</P>

+<P>The value of <I>policy</I> shall be one of the scheduling policy

+values defined in <I>&lt;sched.h&gt;</I>. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>If successful, the <B>sched_get_priority_max</B> and

+<B>sched_get_priority_min</B> functions shall return the appropriate

+maximum or minimum values, respectively. If unsuccessful, they shall

+return a value of -1 and set <I>errno</I> to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>sched_get_priority_max</B> and <B>sched_get_priority_min</B>

+functions shall fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	The value of the <I>policy</I> parameter does not represent a

+	defined scheduling policy. 

+	</DD></DL>

+<P>

+<I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="sched_getscheduler.html"><B>sched_getscheduler</B>(3)</A>

+<B>,</B> <A HREF="sched_setscheduler.html"><B>sched_setscheduler</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;sched.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/manual/sched_getscheduler.html b/manual/sched_getscheduler.html
new file mode 100644
index 0000000..dd1d964
--- /dev/null
+++ b/manual/sched_getscheduler.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;SCHED_GETSCHEDULER&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;13153500">

+	<META NAME="CHANGED" CONTENT="20050505;13202000">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>sched_getscheduler - get scheduling policy (<B>REALTIME</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;sched.h&gt; </B>

+</P>

+<P><B>int sched_getscheduler(pid_t</B> <I>pid</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>sched_getscheduler</B> function shall return the scheduling

+policy of the process specified by <I>pid</I>. If the value of <I>pid</I>

+is negative, the behavior of the <B>sched_getscheduler</B> function

+is unspecified. 

+</P>

+<P>The values that can be returned by <B>sched_getscheduler</B> are

+defined in the <I>&lt;sched.h&gt;</I> header. 

+</P>

+<P><B>Pthreads-w32</B> only supports the <B>SCHED_OTHER</B> policy,

+which is the only value that can be returned. However, checks on <I>pid</I>

+and permissions are performed first so that the other useful side

+effects of this routine are retained.</P>

+<P>If a process specified by <I>pid</I> exists, and if the calling

+process has permission, the scheduling policy shall be returned for

+the process whose process ID is equal to <I>pid</I>. 

+</P>

+<P>If <I>pid</I> is zero, the scheduling policy shall be returned for

+the calling process. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, the <B>sched_getscheduler</B> function

+shall return the scheduling policy of the specified process. If

+unsuccessful, the function shall return -1 and set <I>errno</I> to

+indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>sched_getscheduler</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EPERM</B> 

+	</DT><DD>

+	The requesting process does not have permission to determine the

+	scheduling policy of the specified process. 

+	</DD><DT>

+	<B>ESRCH</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	No process can be found corresponding to that specified by <I>pid</I>.

+		</DD></DL>

+<P>

+<I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="sched_setscheduler.html"><B>sched_setscheduler</B>(3)</A>

+, the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;sched.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/sched_setscheduler.html b/manual/sched_setscheduler.html
new file mode 100644
index 0000000..206508d
--- /dev/null
+++ b/manual/sched_setscheduler.html
@@ -0,0 +1,181 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;SCHED_SETSCHEDULER&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;13012200">

+	<META NAME="CHANGED" CONTENT="20050505;13193700">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>sched_setscheduler - set scheduling policy and parameters

+(<B>REALTIME</B>) 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;sched.h&gt; </B>

+</P>

+<P><B>int sched_setscheduler(pid_t</B> <I>pid</I><B>, int</B> <I>policy</I><B>,

+const struct sched_param *</B><I>param</I><B>); </B>

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>sched_setscheduler</B> function shall set the scheduling

+policy and scheduling parameters of the process specified by <I>pid</I>

+to <I>policy</I> and the parameters specified in the <B>sched_param</B>

+structure pointed to by <I>param</I>, respectively. The value of the

+<I>sched_priority</I> member in the <B>sched_param</B> structure

+shall be any integer within the inclusive priority range for the

+scheduling policy specified by <I>policy</I>. If the value of <I>pid</I>

+is negative, the behavior of the <B>sched_setscheduler</B> function

+is unspecified. 

+</P>

+<P>The possible values for the <I>policy</I> parameter are defined in

+the <I>&lt;sched.h&gt;</I> header. 

+</P>

+<P><B>Pthreads-w32</B> only supports the <B>SCHED_OTHER</B> policy.

+Any other value for <I>policy</I> will return failure with errno set

+to <B>ENOSYS</B>. However, checks on <I>pid</I> and permissions are

+performed first so that the other useful side effects of this routine

+are retained.</P>

+<P>If a process specified by <I>pid</I> exists, and if the calling

+process has permission, the scheduling policy and scheduling

+parameters shall be set for the process whose process ID is equal to

+<I>pid</I>. 

+</P>

+<P>If <I>pid</I> is zero, the scheduling policy and scheduling

+parameters shall be set for the calling process. 

+</P>

+<P>Implementations may require that the requesting process have

+permission to set its own scheduling parameters or those of another

+process. Additionally, implementation-defined restrictions may apply

+as to the appropriate privileges required to set a process’ own

+scheduling policy, or another process’ scheduling policy, to a

+particular value. 

+</P>

+<P>The <B>sched_setscheduler</B> function shall be considered

+successful if it succeeds in setting the scheduling policy and

+scheduling parameters of the process specified by <I>pid</I> to the

+values specified by <I>policy</I> and the structure pointed to by

+<I>param</I>, respectively. 

+</P>

+<P>The effect of this function on individual threads is dependent on

+the scheduling contention scope of the threads: 

+</P>

+<DL>

+	<DT>* 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	For threads with system scheduling contention scope, these functions

+	shall have no effect on their scheduling. 

+	</DD><DT>

+	* 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	For threads with process scheduling contention scope, the threads’

+	scheduling policy and associated parameters shall not be affected.

+	However, the scheduling of these threads with respect to threads in

+	other processes may be dependent on the scheduling parameters of

+	their process, which are governed using these functions. 

+	</DD></DL>

+<P>

+This function is not atomic with respect to other threads in the

+process. Threads may continue to execute while this function call is

+in the process of changing the scheduling policy and associated

+scheduling parameters for the underlying kernel-scheduled entities

+used by the process contention scope threads. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>Upon successful completion, the function shall return the former

+scheduling policy of the specified process. If the <B>sched_setscheduler</B>

+function fails to complete successfully, the policy and scheduling

+parameters shall remain unchanged, and the function shall return a

+value of -1 and set <I>errno</I> to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>The <B>sched_setscheduler</B> function shall fail if: 

+</P>

+<DL>

+	<DT><B>EINVAL</B> 

+	</DT><DD>

+	The value of the <I>policy</I> parameter is invalid, or one or more

+	of the parameters contained in <I>param</I> is outside the valid

+	range for the specified scheduling policy. 

+	</DD><DT>

+	<B>EPERM</B> 

+	</DT><DD>

+	The requesting process does not have permission to set either or

+	both of the scheduling parameters or the scheduling policy of the

+	specified process. 

+	</DD><DT>

+	<B>ESRCH</B> 

+	</DT><DD STYLE="margin-bottom: 0.5cm">

+	No process can be found corresponding to that specified by <I>pid</I>.

+		</DD></DL>

+<P>

+<I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P><A HREF="sched_getscheduler.html"><B>sched_getscheduler</B>(3)</A>

+<B>,</B> the Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;sched.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/sched_yield.html b/manual/sched_yield.html
new file mode 100644
index 0000000..1691afb
--- /dev/null
+++ b/manual/sched_yield.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>&quot;SCHED_YIELD&quot;(P) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;14034600">

+	<META NAME="CHANGED" CONTENT="20050505;14050300">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>sched_yield - yield the processor 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;sched.h&gt; </B>

+</P>

+<P><B>int sched_yield(void);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>The <B>sched_yield</B> function shall force the running thread to

+relinquish the processor until it again becomes the head of its

+thread list. It takes no arguments. 

+</P>

+<H2><A HREF="#toc3" NAME="sect3">Return Value</A></H2>

+<P>The <B>sched_yield</B> function shall return 0 if it completes

+successfully; otherwise, it shall return a value of -1 and set <I>errno</I>

+to indicate the error. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Errors</A></H2>

+<P>No errors are defined. 

+</P>

+<P><I>The following sections are informative.</I> 

+</P>

+<H2><A HREF="#toc5" NAME="sect5">Examples</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Application Usage</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc7" NAME="sect7">Rationale</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc8" NAME="sect8">Future Directions</A></H2>

+<P>None. 

+</P>

+<H2><A HREF="#toc9" NAME="sect9">See Also</A></H2>

+<P>The Base Definitions volume of IEEE&nbsp;Std&nbsp;1003.1-2001,

+<I>&lt;sched.h&gt;</I> 

+</P>

+<H2><A HREF="#toc10" NAME="sect10">Copyright</A></H2>

+<P>Portions of this text are reprinted and reproduced in electronic

+form from IEEE Std 1003.1, 2003 Edition, Standard for Information

+Technology -- Portable Operating System Interface (POSIX), The Open

+Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the

+Institute of Electrical and Electronics Engineers, Inc and The Open

+Group. In the event of any discrepancy between this version and the

+original IEEE and The Open Group Standard, the original IEEE and The

+Open Group Standard is the referee document. The original Standard

+can be obtained online at <A HREF="http://www.opengroup.org/unix/online.html">http://www.opengroup.org/unix/online.html</A>

+. 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Examples</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Application

+	Usage</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Rationale</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect8" NAME="toc8">Future

+	Directions</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect9" NAME="toc9">See

+	Also</A> 

+	</P>

+	<LI><P><A HREF="#sect10" NAME="toc10">Copyright</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>

diff --git a/manual/sem_init.html b/manual/sem_init.html
new file mode 100644
index 0000000..338867e
--- /dev/null
+++ b/manual/sem_init.html
@@ -0,0 +1,200 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML>

+<HEAD>

+	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">

+	<TITLE>SEMAPHORES(3) manual page</TITLE>

+	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3  (Linux)">

+	<META NAME="CREATED" CONTENT="20050505;14061900">

+	<META NAME="CHANGED" CONTENT="20050514;195200">

+	<!-- manual page source format generated by PolyglotMan v3.2, -->

+	<!-- available at http://polyglotman.sourceforge.net/ -->

+</HEAD>

+<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">

+<H4>POSIX Threads for Windows – REFERENCE - <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A></H4>

+<P><A HREF="index.html">Reference Index</A></P>

+<P><A HREF="#toc">Table of Contents</A></P>

+<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>

+<P>sem_init, sem_wait, sem_trywait, sem_post, sem_getvalue,

+sem_destroy - operations on semaphores 

+</P>

+<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>

+<P><B>#include &lt;semaphore.h&gt;</B> 

+</P>

+<P><B>int sem_init(sem_t *</B><I>sem</I><B>, int </B><I>pshared</I><B>,

+unsigned int </B><I>value</I><B>);</B> 

+</P>

+<P><B>int sem_wait(sem_t * </B><I>sem</I><B>);</B> 

+</P>

+<P><B>int sem_timedwait(sem_t * </B><I>sem</I>, <B>const struct

+timespec *</B><I>abstime</I><B>);</B> 

+</P>

+<P><B>int sem_trywait(sem_t * </B><I>sem</I><B>);</B> 

+</P>

+<P><B>int sem_post(sem_t * </B><I>sem</I><B>);</B> 

+</P>

+<P><B>int sem_post_multiple(sem_t * </B><I>sem, </I><B>int</B>

+<I>number</I><B>);</B> 

+</P>

+<P><B>int sem_getvalue(sem_t * </B><I>sem</I><B>, int * </B><I>sval</I><B>);</B>

+</P>

+<P><B>int sem_destroy(sem_t * </B><I>sem</I><B>);</B> 

+</P>

+<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>

+<P>Semaphores are counters for resources shared between threads. The

+basic operations on semaphores are: increment the counter atomically,

+and wait until the counter is non-null and decrement it atomically. 

+</P>

+<P><B>sem_init</B> initializes the semaphore object pointed to by

+<I>sem</I>. The count associated with the semaphore is set initially

+to <I>value</I>. The <I>pshared</I> argument indicates whether the

+semaphore is local to the current process ( <I>pshared</I> is zero)

+or is to be shared between several processes ( <I>pshared</I> is not

+zero).</P>

+<P><B>Pthreads-w32</B> currently does not support process-shared

+semaphores, thus <B>sem_init</B> always returns with error <B>EPERM</B>

+if <I>pshared</I> is not zero. 

+</P>

+<P><B>sem_wait</B> atomically decrements <I>sem</I>'s count if it is

+greater than 0 and returns immediately or it suspends the calling

+thread until it can resume following a call to <B>sem_post</B> or

+<B>sem_post_multiple</B>.</P>

+<P><B>sem_timedwait</B> atomically decrements <I>sem</I>'s count if

+it is greater than 0 and returns immediately, or it suspends the

+calling thread. If <I>abstime</I> time arrives before the thread can

+resume following a call to <B>sem_post</B> or <B>sem_post_multiple</B>,

+then <B>sem_timedwait</B> returns with a return code of -1 after

+having set <B>errno</B> to <B>ETIMEDOUT</B>. If the call can return

+without suspending then <I>abstime</I> is not checked.</P>

+<P><B>sem_trywait</B> atomically decrements <I>sem</I>'s count if it

+is greater than 0 and returns immediately, or it returns immediately

+with a return code of -1 after having set <B>errno</B> to <B>EAGAIN</B>.

+<B>sem_trywait</B> never blocks.</P>

+<P><B>sem_post</B> either releases one thread if there are any

+waiting on <I>sem</I>, or it atomically increments <I>sem</I>'s

+count.</P>

+<P><B>sem_post_multiple</B> either releases multiple threads if there

+are any waiting on <I>sem</I> and/or it atomically increases <I>sem</I>'s

+count. If there are currently <I>n</I> waiters, where <I>n</I> the

+largest number less than or equal to <I>number</I>, then <I>n</I>

+waiters are released and <I>sem</I>'s count is incremented by <I>number</I>

+minus <I>n</I>.</P>

+<P><B>sem_getvalue</B> stores in the location pointed to by <I>sval</I>

+the current count of the semaphore <I>sem</I>. In the <B>Pthreads-w32</B>

+implementation: if the value returned in <I>sval</I> is greater than

+or equal to 0 it was the <I>sem</I>'s count at some point during the

+call to <B>sem_getvalue</B>. If the value returned in <I>sval</I> is

+less than 0 then it's absolute value represents the number of threads

+waiting on <I>sem</I> at some point during the call to <B>sem_getvalue.

+</B>POSIX does not require an implementation of <B>sem_getvalue</B>

+to return a value in <I>sval</I> that is less than 0, but if it does

+then it's absolute value must represent the number of waiters.</P>

+<P><B>sem_destroy</B> destroys a semaphore object, freeing the

+resources it might hold. No threads should be waiting on the

+semaphore at the time <B>sem_destroy</B> is called.</P>

+<H2><A HREF="#toc3" NAME="sect3">Cancellation</A></H2>

+<P><B>sem_wait</B> and <B>sem_timedwait</B> are cancellation points. 

+</P>

+<H2><A HREF="#toc4" NAME="sect4">Async-signal Safety</A></H2>

+<P>These routines are not async-cancel safe.</P>

+<H2><A HREF="#toc5" NAME="sect5">Return Value</A></H2>

+<P>All semaphore functions return 0 on success, or -1 on error in

+which case they write an error code in <B>errno</B>. 

+</P>

+<H2><A HREF="#toc6" NAME="sect6">Errors</A></H2>

+<P>The <B>sem_init</B> function sets <B>errno</B> to the following

+codes on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EINVAL</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<I>value</I> exceeds the maximal counter value <B>SEM_VALUE_MAX</B>

+				</DD><DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		<B>ENOSYS</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 3cm">

+<I>pshared</I> is not zero 

+</BLOCKQUOTE>

+<P>The <B>sem_timedwait</B> function sets <B>errno</B> to the

+following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ETIMEDOUT</B>

+				</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 3cm">

+if <I>abstime</I> arrives before the waiting thread can resume

+following a call to <B>sem_post</B> or <B>sem_post_multiple</B>. 

+</BLOCKQUOTE>

+<P>The <B>sem_trywait</B> function sets <B>errno</B> to the following

+error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EAGAIN</B> 

+		</DT></DL>

+</DL>

+<BLOCKQUOTE STYLE="margin-left: 3cm">

+if the semaphore count is currently 0 

+</BLOCKQUOTE>

+<P>The <B>sem_post</B> and <B>sem_post_multiple</B> functions set

+<B>errno</B> to the following error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>ERANGE</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		if after incrementing, the semaphore count would exceed

+		<B>SEM_VALUE_MAX</B> (the semaphore count is left unchanged in this

+		case) 

+		</DD></DL>

+</DL>

+<P>

+The <B>sem_destroy</B> function sets <B>errno</B> to the following

+error code on error: 

+</P>

+<DL>

+	<DL>

+		<DT STYLE="margin-right: 1cm; margin-bottom: 0.5cm"><B>EBUSY</B> 

+		</DT><DD STYLE="margin-right: 1cm; margin-bottom: 0.5cm">

+		if some threads are currently blocked waiting on the semaphore. 

+		</DD></DL>

+</DL>

+<H2>

+<A HREF="#toc7" NAME="sect7">Author</A></H2>

+<P>Xavier Leroy &lt;Xavier.Leroy@inria.fr&gt; 

+</P>

+<P>Modified by Ross Johnson for use with <A HREF="http://sources.redhat.com/pthreads-win32">Pthreads-w32</A>.</P>

+<H2><A HREF="#toc8" NAME="sect8">See Also</A></H2>

+<P><A HREF="pthread_mutex_init.html"><B>pthread_mutex_init</B>(3)</A>

+, <A HREF="pthread_cond_init.html"><B>pthread_cond_init</B>(3)</A> ,

+<A HREF="pthread_cancel.html"><B>pthread_cancel</B>(3)</A> . 

+</P>

+<HR>

+<P><A NAME="toc"></A><B>Table of Contents</B></P>

+<UL>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Cancellation</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Async-signal

+	Safety</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Return

+	Value</A> 

+	</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">Errors</A>

+		</P>

+	<LI><P STYLE="margin-bottom: 0cm"><A HREF="#sect7" NAME="toc7">Author</A>

+		</P>

+	<LI><P><A HREF="#sect8" NAME="toc8">See Also</A> 

+	</P>

+</UL>

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/misc.c b/misc.c
new file mode 100644
index 0000000..06d1d21
--- /dev/null
+++ b/misc.c
@@ -0,0 +1,50 @@
+/*
+ * misc.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_kill.c"
+#include "pthread_once.c"
+#include "pthread_self.c"
+#include "pthread_equal.c"
+#include "pthread_setconcurrency.c"
+#include "pthread_getconcurrency.c"
+#include "ptw32_new.c"
+#include "ptw32_calloc.c"
+#include "ptw32_reuse.c"
+#include "w32_CancelableWait.c"
diff --git a/mutex.c b/mutex.c
new file mode 100644
index 0000000..81825a3
--- /dev/null
+++ b/mutex.c
@@ -0,0 +1,59 @@
+/*
+ * mutex.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#if !defined(_UWIN) && !defined(WINCE)
+#   include <process.h>
+#endif
+#ifndef NEED_FTIME
+#include <sys/timeb.h>
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "ptw32_mutex_check_need_init.c"
+#include "pthread_mutex_init.c"
+#include "pthread_mutex_destroy.c"
+#include "pthread_mutexattr_init.c"
+#include "pthread_mutexattr_destroy.c"
+#include "pthread_mutexattr_getpshared.c"
+#include "pthread_mutexattr_setpshared.c"
+#include "pthread_mutexattr_settype.c"
+#include "pthread_mutexattr_gettype.c"
+#include "pthread_mutex_lock.c"
+#include "pthread_mutex_timedlock.c"
+#include "pthread_mutex_unlock.c"
+#include "pthread_mutex_trylock.c"
diff --git a/need_errno.h b/need_errno.h
new file mode 100644
index 0000000..2609f8d
--- /dev/null
+++ b/need_errno.h
@@ -0,0 +1,132 @@
+/***
+* errno.h - system wide error numbers (set by system calls)
+*
+*       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
+*
+* Purpose:
+*       This file defines the system-wide error numbers (set by
+*       system calls).  Conforms to the XENIX standard.  Extended
+*       for compatibility with Uniforum standard.
+*       [System V]
+*
+*       [Public]
+*
+****/
+
+#if     _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifndef _INC_ERRNO
+#define _INC_ERRNO
+
+#if     !defined(_WIN32) && !defined(_MAC)
+#error ERROR: Only Mac or Win32 targets supported!
+#endif
+
+#include <winsock.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+
+
+/* Define _CRTIMP */
+
+#ifndef _CRTIMP
+#ifdef  _DLL
+#define _CRTIMP __declspec(dllimport)
+#else   /* ndef _DLL */
+#define _CRTIMP
+#endif  /* _DLL */
+#endif  /* _CRTIMP */
+
+
+/* Define __cdecl for non-Microsoft compilers */
+
+#if     ( !defined(_MSC_VER) && !defined(__cdecl) )
+#define __cdecl
+#endif
+
+/* Define _CRTAPI1 (for compatibility with the NT SDK) */
+
+#ifndef _CRTAPI1
+#if	_MSC_VER >= 800 && _M_IX86 >= 300
+#define _CRTAPI1 __cdecl
+#else
+#define _CRTAPI1
+#endif
+#endif
+
+
+/* declare reference to errno */
+
+#if     (defined(_MT) || defined(_MD) || defined(_DLL)) && !defined(_MAC)
+_CRTIMP extern int * __cdecl _errno(void);
+#define errno   (*_errno())
+#else   /* ndef _MT && ndef _MD && ndef _DLL */
+_CRTIMP extern int errno;
+#endif  /* _MT || _MD || _DLL */
+
+/* Error Codes */
+
+#define EPERM           1
+#define ENOENT          2
+#define ESRCH           3
+#define EINTR           4
+#define EIO             5
+#define ENXIO           6
+#define E2BIG           7
+#define ENOEXEC         8
+#define EBADF           9
+#define ECHILD          10
+#define EAGAIN          11
+#define ENOMEM          12
+#define EACCES          13
+#define EFAULT          14
+#define EBUSY           16
+#define EEXIST          17
+#define EXDEV           18
+#define ENODEV          19
+#define ENOTDIR         20
+#define EISDIR          21
+#define EINVAL          22
+#define ENFILE          23
+#define EMFILE          24
+#define ENOTTY          25
+#define EFBIG           27
+#define ENOSPC          28
+#define ESPIPE          29
+#define EROFS           30
+#define EMLINK          31
+#define EPIPE           32
+#define EDOM            33
+#define ERANGE          34
+#define EDEADLK         36
+
+/* defined differently in winsock.h on WinCE */
+#ifndef ENAMETOOLONG
+#define ENAMETOOLONG    38
+#endif
+
+#define ENOLCK          39
+#define ENOSYS          40
+
+/* defined differently in winsock.h on WinCE */
+#ifndef ENOTEMPTY
+#define ENOTEMPTY       41
+#endif
+
+#define EILSEQ          42
+
+/*
+ * Support EDEADLOCK for compatibiity with older MS-C versions.
+ */
+#define EDEADLOCK       EDEADLK
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* _INC_ERRNO */
diff --git a/nonportable.c b/nonportable.c
new file mode 100644
index 0000000..6c2a990
--- /dev/null
+++ b/nonportable.c
@@ -0,0 +1,46 @@
+/*
+ * nonportable.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "pthread_mutexattr_setkind_np.c"
+#include "pthread_mutexattr_getkind_np.c"
+#include "pthread_getw32threadhandle_np.c"
+#include "pthread_delay_np.c"
+#include "pthread_num_processors_np.c"
+#include "pthread_win32_attach_detach_np.c"
+#include "pthread_timechange_handler_np.c"
diff --git a/private.c b/private.c
new file mode 100644
index 0000000..7e311b1
--- /dev/null
+++ b/private.c
@@ -0,0 +1,57 @@
+/*
+ * private.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* Must be first to define HAVE_INLINABLE_INTERLOCKED_CMPXCHG */
+#include "ptw32_InterlockedCompareExchange.c"
+
+#include "ptw32_MCS_lock.c"
+#include "ptw32_is_attr.c"
+#include "ptw32_processInitialize.c"
+#include "ptw32_processTerminate.c"
+#include "ptw32_threadStart.c"
+#include "ptw32_threadDestroy.c"
+#include "ptw32_tkAssocCreate.c"
+#include "ptw32_tkAssocDestroy.c"
+#include "ptw32_callUserDestroyRoutines.c"
+#include "ptw32_semwait.c"
+#include "ptw32_timespec.c"
+#include "ptw32_relmillisecs.c"
+#include "ptw32_throw.c"
+#include "ptw32_getprocessors.c"
diff --git a/pthread.c b/pthread.c
new file mode 100644
index 0000000..660c254
--- /dev/null
+++ b/pthread.c
@@ -0,0 +1,65 @@
+/*
+ * pthread.c
+ *
+ * Description:
+ * This translation unit agregates pthreads-win32 translation units.
+ * It is used for inline optimisation of the library,
+ * maximising for speed at the expense of size.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* The following are ordered for inlining */
+
+#include "private.c"
+#include "attr.c"
+#include "barrier.c"
+#include "cancel.c"
+#include "cleanup.c"
+#include "condvar.c"
+#include "create.c"
+#include "dll.c"
+#include "errno.c"
+#include "exit.c"
+#include "fork.c"
+#include "global.c"
+#include "misc.c"
+#include "mutex.c"
+#include "nonportable.c"
+#include "rwlock.c"
+#include "sched.c"
+#include "semaphore.c"
+#include "signal.c"
+#include "spin.c"
+#include "sync.c"
+#include "tsd.c"
diff --git a/pthread.h b/pthread.h
new file mode 100644
index 0000000..11a3895
--- /dev/null
+++ b/pthread.h
@@ -0,0 +1,1378 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+// Next 6 lines added by ESL for consitency accross all projects
+#ifndef __CLEANUP_C
+#define __CLEANUP_C
+#endif
+#ifdef PTW32_STATIC_LIB
+#error Using this library as static lib is problematic because of the initialization routines, especially when exiting a Win32 thread. Use only as DLL
+#endif
+
+/*
+ * See the README file for an explanation of the pthreads-win32 version
+ * numbering scheme and how the DLL is named etc.
+ */
+#define PTW32_VERSION 2,8,0,0
+#define PTW32_VERSION_STRING "2, 8, 0, 0\0"
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ *   WIN32 SEH
+ *   C
+ *   C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard 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.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
+#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
+#endif
+
+/*
+ * Stop here if we are being included by the resource compiler.
+ */
+#ifndef RC_INVOKED
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#ifdef _UWIN
+#   define HAVE_STRUCT_TIMESPEC 1
+#   define HAVE_SIGNAL_H        1
+#   undef HAVE_CONFIG_H
+#   pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ *      Provides an implementation of PThreads based upon the
+ *      standard:
+ *
+ *              POSIX 1003.1-2001
+ *  and
+ *    The Single Unix Specification version 3
+ *
+ *    (these two are equivalent)
+ *
+ *      in order to enhance code portability between Windows,
+ *  various commercial Unix implementations, and Linux.
+ *
+ *      See the ANNOUNCE file for a full list of conforming
+ *      routines and defined constants, and a list of missing
+ *      routines and constants not defined in this implementation.
+ *
+ * Authors:
+ *      There have been many contributors to this library.
+ *      The initial implementation was contributed by
+ *      John Bossom, and several others have provided major
+ *      sections or revisions of parts of the implementation.
+ *      Often significant effort has been contributed to
+ *      find and fix important bugs and other problems to
+ *      improve the reliability of the library, which sometimes
+ *      is not reflected in the amount of code which changed as
+ *      result.
+ *      As much as possible, the contributors are acknowledged
+ *      in the ChangeLog file in the source code distribution
+ *      where their changes are noted in detail.
+ *
+ *      Contributors are listed in the CONTRIBUTORS file.
+ *
+ *      As usual, all bouquets go to the contributors, and all
+ *      brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ *      The code base for this project is coordinated and
+ *      eventually pre-tested, packaged, and made available by
+ *
+ *              Ross Johnson <rpj@callisto.canberra.edu.au>
+ *
+ * QA Testers:
+ *      Ultimately, the library is tested in the real world by
+ *      a host of competent and demanding scientists and
+ *      engineers who report bugs and/or provide solutions
+ *      which are then fixed or incorporated into subsequent
+ *      versions of the library. Each time a bug is fixed, a
+ *      test case is written to prove the fix and ensure
+ *      that later changes to the code don't reintroduce the
+ *      same error. The number of test cases is slowly growing
+ *      and therefore so is the code reliability.
+ *
+ * Compliance:
+ *      See the file ANNOUNCE for the list of implemented
+ *      and not-implemented routines and defined options.
+ *      Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ *      The source code and other information about this library
+ *      are available from
+ *
+ *              http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
+/*
+ * VC++6.0 or early compiler's header has no DWORD_PTR type.
+ */
+typedef unsigned long DWORD_PTR;
+#endif
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifndef NEED_FTIME
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <setjmp.h>
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+  PTW32_FALSE = 0,
+  PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+#  if defined(WINCE)
+#    define NEED_ERRNO
+#    define NEED_SEM
+#  endif
+#  if defined(_UWIN) || defined(__MINGW32__)
+#    define HAVE_MODE_T
+#  endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define some error numbers.
+ */
+#ifndef ENOTSUP
+#  define ENOTSUP 48   /* This is the value in Solaris. */
+#endif
+
+#ifndef ETIMEDOUT
+#  define ETIMEDOUT 10060     /* This is the value in winsock.h. */
+#endif
+
+#ifndef ENOSYS
+#  define ENOSYS 140     /* Semi-arbitrary value */
+#endif
+
+#ifndef EDEADLK
+#  ifdef EDEADLOCK
+#    define EDEADLK EDEADLOCK
+#  else
+#    define EDEADLK 36     /* This is the value in MSVC. */
+#  endif
+#endif
+
+#include <sched.h>
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it.
+ */
+#ifndef PTW32_INCLUDE_WINDOWS_H
+#ifndef HANDLE
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#ifndef DWORD
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#ifndef HAVE_STRUCT_TIMESPEC
+#define HAVE_STRUCT_TIMESPEC 1
+struct timespec {
+        long tv_sec;
+        long tv_nsec;
+};
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#ifndef SIG_UNBLOCK 
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif                          /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * Options are normally set in <unistd.h>, which is not provided
+ * with pthreads-win32.
+ *
+ * For conformance with the Single Unix Specification (version 3), all of the
+ * options below are defined, and have a value of either -1 (not supported)
+ * or 200112L (supported).
+ *
+ * These options can neither be left undefined nor have a value of 0, because
+ * either indicates that sysconf(), which is not implemented, may be used at
+ * runtime to check the status of the option.
+ *
+ * _POSIX_THREADS (== 200112L)
+ *                      If == 200112L, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
+ *                      If == 200112L, you can control the size of a thread's
+ *                      stack
+ *                              pthread_attr_getstacksize
+ *                              pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (== -1)
+ *                      If == 200112L, you can allocate and control a thread's
+ *                      stack. If not supported, the following functions
+ *                      will return ENOSYS, indicating they are not
+ *                      supported:
+ *                              pthread_attr_getstackaddr
+ *                              pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
+ *                      If == 200112L, you can use realtime scheduling.
+ *                      This option indicates that the behaviour of some
+ *                      implemented functions conforms to the additional TPS
+ *                      requirements in the standard. E.g. rwlocks favour
+ *                      writers over readers when threads have equal priority.
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (== -1)
+ *                      If == 200112L, you can create priority inheritance
+ *                      mutexes.
+ *                              pthread_mutexattr_getprotocol +
+ *                              pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (== -1)
+ *                      If == 200112L, you can create priority ceiling mutexes
+ *                      Indicates the availability of:
+ *                              pthread_mutex_getprioceiling
+ *                              pthread_mutex_setprioceiling
+ *                              pthread_mutexattr_getprioceiling
+ *                              pthread_mutexattr_getprotocol     +
+ *                              pthread_mutexattr_setprioceiling
+ *                              pthread_mutexattr_setprotocol     +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (== -1)
+ *                      If set, you can create mutexes and condition
+ *                      variables that can be shared with another
+ *                      process.If set, indicates the availability
+ *                      of:
+ *                              pthread_mutexattr_getpshared
+ *                              pthread_mutexattr_setpshared
+ *                              pthread_condattr_getpshared
+ *                              pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
+ *                      If == 200112L you can use the special *_r library
+ *                      functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (== 200112L)
+ *                      If == 200112L, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (== 200112L)
+ *                      If == 200112L, you can use spin locks
+ *
+ * _POSIX_BARRIERS (== 200112L)
+ *                      If == 200112L, you can use barriers
+ *
+ *      + These functions provide both 'inherit' and/or
+ *        'protect' protocol, based upon these macro
+ *        settings.
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#undef _POSIX_THREADS
+#define _POSIX_THREADS 200112L
+
+#undef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS 200112L
+
+#undef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS 200112L
+
+#undef _POSIX_BARRIERS
+#define _POSIX_BARRIERS 200112L
+
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
+
+#undef _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
+
+/*
+ * The following options are not supported
+ */
+#undef _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+#undef _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_INHERIT -1
+
+#undef _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PRIO_PROTECT -1
+
+/* TPS is not fully supported.  */
+#undef _POSIX_THREAD_PRIORITY_SCHEDULING
+#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
+
+#undef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+
+
+/*
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * These limits are normally set in <limits.h>, which is not provided with
+ * pthreads-win32.
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ *                      Maximum number of attempts to destroy
+ *                      a thread's thread-specific data on
+ *                      termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ *                      Maximum number of thread-specific data keys
+ *                      available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ *                      Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ *                      Maximum number of threads supported per
+ *                      process (must be at least 64).
+ *
+ * SEM_NSEMS_MAX
+ *                      The maximum number of semaphores a process can have.
+ *                      (must be at least 256)
+ *
+ * SEM_VALUE_MAX
+ *                      The maximum value a semaphore can have.
+ *                      (must be at least 32767)
+ *
+ */
+#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS     4
+
+#undef PTHREAD_DESTRUCTOR_ITERATIONS
+#define PTHREAD_DESTRUCTOR_ITERATIONS           _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+#undef _POSIX_THREAD_KEYS_MAX
+#define _POSIX_THREAD_KEYS_MAX                  128
+
+#undef PTHREAD_KEYS_MAX
+#define PTHREAD_KEYS_MAX                        _POSIX_THREAD_KEYS_MAX
+
+#undef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN                       0
+
+#undef _POSIX_THREAD_THREADS_MAX
+#define _POSIX_THREAD_THREADS_MAX               64
+
+  /* Arbitrary value */
+#undef PTHREAD_THREADS_MAX
+#define PTHREAD_THREADS_MAX                     2019
+
+#undef _POSIX_SEM_NSEMS_MAX
+#define _POSIX_SEM_NSEMS_MAX                    256
+
+  /* Arbitrary value */
+#undef SEM_NSEMS_MAX
+#define SEM_NSEMS_MAX                           1024
+
+#undef _POSIX_SEM_VALUE_MAX
+#define _POSIX_SEM_VALUE_MAX                    32767
+
+#undef SEM_VALUE_MAX
+#define SEM_VALUE_MAX                           INT_MAX
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+#  ifdef PTW32_BUILD
+#    define PTW32_DLLPORT __declspec (dllexport)
+#  else
+#    define PTW32_DLLPORT __declspec (dllimport)
+#  endif
+#else
+#  define PTW32_DLLPORT
+#endif
+
+/*
+ * The Open Watcom C/C++ compiler uses a non-standard calling convention
+ * that passes function args in registers unless __cdecl is explicitly specified
+ * in exposed function prototypes.
+ *
+ * We force all calls to cdecl even though this could slow Watcom code down
+ * slightly. If you know that the Watcom compiler will be used to build both
+ * the DLL and application, then you can probably define this as a null string.
+ * Remember that pthread.h (this file) is used for both the DLL and application builds.
+ */
+#define PTW32_CDECL __cdecl
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+#   include     <sys/types.h>
+#else
+/*
+ * 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_ * 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_ * 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;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+  PTHREAD_CREATE_JOINABLE       = 0,  /* Default */
+  PTHREAD_CREATE_DETACHED       = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+  PTHREAD_INHERIT_SCHED         = 0,
+  PTHREAD_EXPLICIT_SCHED        = 1,  /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+  PTHREAD_SCOPE_PROCESS         = 0,
+  PTHREAD_SCOPE_SYSTEM          = 1,  /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+  PTHREAD_CANCEL_ENABLE         = 0,  /* Default */
+  PTHREAD_CANCEL_DISABLE        = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+  PTHREAD_CANCEL_ASYNCHRONOUS   = 0,
+  PTHREAD_CANCEL_DEFERRED       = 1,  /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+  PTHREAD_PROCESS_PRIVATE       = 0,
+  PTHREAD_PROCESS_SHARED        = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+  PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED       ((void *) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT       { PTW32_FALSE, 0, 0, 0}
+
+struct pthread_once_t_
+{
+  int          done;        /* indicates if user function has been executed */
+  void *       lock;
+  int          reserved1;
+  int          reserved2;
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
+
+/*
+ * Compatibility with LinuxThreads
+ */
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+  /* Compatibility with LinuxThreads */
+  PTHREAD_MUTEX_FAST_NP,
+  PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+  PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+  /* For compatibility with POSIX */
+  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+
+#if defined(_MSC_VER)
+/* Disable MSVC 'anachronism used' warning */
+#pragma warning( disable : 4229 )
+#endif
+
+typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
+
+#if defined(_MSC_VER)
+#pragma warning( default : 4229 )
+#endif
+
+struct ptw32_cleanup_t
+{
+  ptw32_cleanup_callback_t routine;
+  void *arg;
+  struct ptw32_cleanup_t *prev;
+};
+
+#ifdef __CLEANUP_SEH
+        /*
+         * WIN32 SEH version of cancel cleanup.
+         */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+        { \
+            ptw32_cleanup_t     _cleanup; \
+            \
+        _cleanup.routine        = (ptw32_cleanup_callback_t)(_rout); \
+            _cleanup.arg        = (_arg); \
+            __try \
+              { \
+
+#define pthread_cleanup_pop( _execute ) \
+              } \
+            __finally \
+                { \
+                    if( _execute || AbnormalTermination()) \
+                      { \
+                          (*(_cleanup.routine))( _cleanup.arg ); \
+                      } \
+                } \
+        }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+        /*
+         * C implementation of PThreads cancel cleanup
+         */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+        { \
+            ptw32_cleanup_t     _cleanup; \
+            \
+            ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+            (void) ptw32_pop_cleanup( _execute ); \
+        }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+        /*
+         * C++ version of cancel cleanup.
+         * - John E. Bossom.
+         */
+
+        class PThreadCleanup {
+          /*
+           * PThreadCleanup
+           *
+           * Purpose
+           *      This class is a C++ helper class that is
+           *      used to implement pthread_cleanup_push/
+           *      pthread_cleanup_pop.
+           *      The destructor of this class automatically
+           *      pops the pushed cleanup routine regardless
+           *      of how the code exits the scope
+           *      (i.e. such as by an exception)
+           */
+      ptw32_cleanup_callback_t cleanUpRout;
+          void    *       obj;
+          int             executeIt;
+
+        public:
+          PThreadCleanup() :
+            cleanUpRout( 0 ),
+            obj( 0 ),
+            executeIt( 0 )
+            /*
+             * No cleanup performed
+             */
+            {
+            }
+
+          PThreadCleanup(
+             ptw32_cleanup_callback_t routine,
+                         void    *       arg ) :
+            cleanUpRout( routine ),
+            obj( arg ),
+            executeIt( 1 )
+            /*
+             * Registers a cleanup routine for 'arg'
+             */
+            {
+            }
+
+          ~PThreadCleanup()
+            {
+              if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+                {
+                  (void) (*cleanUpRout)( obj );
+                }
+            }
+
+          void execute( int exec )
+            {
+              executeIt = exec;
+            }
+        };
+
+        /*
+         * C++ implementation of PThreads cancel cleanup;
+         * This implementation takes advantage of a helper
+         * class who's destructor automatically calls the
+         * cleanup routine if we exit our scope weirdly
+         */
+#define pthread_cleanup_push( _rout, _arg ) \
+        { \
+            PThreadCleanup  cleanup((ptw32_cleanup_callback_t)(_rout), \
+                                    (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+            cleanup.execute( _execute ); \
+        }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
+                                         int *detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
+                                       void **stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
+                                       size_t * stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
+                                         int detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
+                                       void *stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
+                                       size_t stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
+                                        struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
+                                        const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
+                                         int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *,
+                                         int *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
+                                         int inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr,
+                                         int * inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
+                                   int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
+                                   int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
+                            const pthread_attr_t * attr,
+                            void *(*start) (void *),
+                            void *arg);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
+                           pthread_t t2);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
+                          void **value_ptr);
+
+PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
+                                    int *oldstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
+                                   int *oldtype);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
+                          void (*init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+                                 void (*routine) (void *),
+                                 void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
+                                void (*destructor) (void *));
+
+PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
+                                 const void *value);
+
+PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
+                                          * attr,
+                                          int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+                                          int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
+                                            * attr,
+                                            int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+                                            int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
+                                const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex,
+                                    const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
+                                  const pthread_barrierattr_t * attr,
+                                  unsigned int count);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
+                                         int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
+                                         int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
+                               const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
+                               pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
+                                    pthread_mutex_t * mutex,
+                                    const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
+                                   int policy,
+                                   const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
+                                   int *policy,
+                                   struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
+ 
+PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
+                                const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+                                       const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+                                       const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+                                           int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+                                           int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+                                         int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+                                         int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
+
+/*
+ * Features that are auto-detected at load/run time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
+enum ptw32_features {
+  PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
+  PTW32_ALERTABLE_ASYNC_CANCEL              = 0x0002  /* Can cancel blocked threads. */
+};
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ *              WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
+                                        DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#ifndef _UWIN
+#  if defined(NEED_ERRNO)
+#    ifndef errno
+        PTW32_DLLPORT int * PTW32_CDECL _errno( void );
+#    endif
+#  else
+#    ifndef errno
+#      if (defined(_MT) || defined(_DLL))
+         __declspec(dllimport) extern int * __cdecl _errno(void);
+#        define errno   (*_errno())
+#      endif
+#    endif
+#  endif
+#endif
+
+/*
+ * WIN32 C runtime library had been made thread-safe
+ * without affecting the user interface. Provide
+ * mappings from the UNIX thread-safe versions to
+ * the standard C runtime library calls.
+ * Only provide function mappings for functions that
+ * actually exist on WIN32.
+ */
+
+#if !defined(__MINGW32__)
+#define strtok_r( _s, _sep, _lasts ) \
+        ( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+#define asctime_r( _tm, _buf ) \
+        ( strcpy( (_buf), asctime( (_tm) ) ), \
+          (_buf) )
+
+#define ctime_r( _clock, _buf ) \
+        ( strcpy( (_buf), ctime( (_clock) ) ),  \
+          (_buf) )
+
+#define gmtime_r( _clock, _result ) \
+        ( *(_result) = *gmtime( (_clock) ), \
+          (_result) )
+
+#define localtime_r( _clock, _result ) \
+        ( *(_result) = *localtime( (_clock) ), \
+          (_result) )
+
+#define rand_r( _seed ) \
+        ( _seed == _seed? rand() : rand() )
+
+
+/*
+ * Some compiler environments don't define some things.
+ */
+#if defined(__BORLANDC__)
+#  define _ftime ftime
+#  define _timeb timeb
+#endif
+
+#ifdef __cplusplus
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit   : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef PTW32_BUILD
+
+#ifdef __CLEANUP_SEH
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+        __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+                 ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_CXX
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#ifdef _MSC_VER
+        /*
+         * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+         * if you want Pthread-Win32 cancelation and pthread_exit to work.
+         */
+
+#ifndef PtW32NoCatchWarn
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message("  Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message("  with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message("  cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message("    #ifdef PtW32CatchAll")
+#pragma message("      PtW32CatchAll")
+#pragma message("    #else")
+#pragma message("      catch(...)")
+#pragma message("    #endif")
+#pragma message("        {")
+#pragma message("          /* Catchall block processing */")
+#pragma message("        }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+        catch( ptw32_exception & ) { throw; } \
+        catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+        catch( ptw32_exception & ) { throw; } \
+        catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#ifdef __cplusplus
+}                               /* End of extern "C" */
+#endif                          /* __cplusplus */
+
+#ifdef PTW32__HANDLE_DEF
+# undef HANDLE
+#endif
+#ifdef PTW32__DWORD_DEF
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* ! RC_INVOKED */
+
+#endif /* PTHREAD_H */
diff --git a/pthread.sln b/pthread.sln
new file mode 100644
index 0000000..df03d05
--- /dev/null
+++ b/pthread.sln
@@ -0,0 +1,36 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pthread", "pthread.vcproj", "{420D8ADF-C6AC-461A-824A-BC0CA4857F17}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|Windows Mobile 6 Professional SDK (ARMV4I) = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+		Debug|Windows Mobile 6 Standard SDK (ARMV4I) = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+		Release|Win32 = Release|Win32
+		Release|Windows Mobile 6 Professional SDK (ARMV4I) = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+		Release|Windows Mobile 6 Standard SDK (ARMV4I) = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Win32.ActiveCfg = Debug|Win32
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Win32.Build.0 = Debug|Win32
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Windows Mobile 6 Standard SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Windows Mobile 6 Standard SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Debug|Windows Mobile 6 Standard SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Standard SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Win32.ActiveCfg = Release|Win32
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Win32.Build.0 = Release|Win32
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Windows Mobile 6 Standard SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Windows Mobile 6 Standard SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+		{420D8ADF-C6AC-461A-824A-BC0CA4857F17}.Release|Windows Mobile 6 Standard SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Standard SDK (ARMV4I)
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/pthread.vcproj b/pthread.vcproj
new file mode 100644
index 0000000..e7b592a
--- /dev/null
+++ b/pthread.vcproj
@@ -0,0 +1,615 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="9.00"

+	Name="pthread"

+	ProjectGUID="{420D8ADF-C6AC-461A-824A-BC0CA4857F17}"

+	RootNamespace="pthread"

+	TargetFrameworkVersion="0"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+		<Platform

+			Name="Windows Mobile 6 Professional SDK (ARMV4I)"

+		/>

+		<Platform

+			Name="Windows Mobile 6 Standard SDK (ARMV4I)"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="false"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="true"

+				SuppressStartupBanner="true"

+				TargetEnvironment="1"

+				TypeLibraryName=".\./pthread.tlb"

+				HeaderFileName=""

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="2"

+				InlineFunctionExpansion="0"

+				AdditionalIncludeDirectories="."

+				PreprocessorDefinitions="__CLEANUP_C;WIN32;NDEBUG;_WINDOWS;_USRDLL;HAVE_CONFIG_H=1"

+				StringPooling="true"

+				RuntimeLibrary="2"

+				FloatingPointModel="0"

+				PrecompiledHeaderFile=".\./pthread.pch"

+				AssemblerListingLocation=".\./"

+				ObjectFile=".\./"

+				ProgramDataBaseFileName=".\./"

+				SuppressStartupBanner="true"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG,PTW32_RC_MSC"

+				Culture="1033"

+				AdditionalIncludeDirectories="."

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="ws2_32.lib"

+				OutputFile="$(SolutionDir)..\..\build\products\$(ConfigurationName)\$(ProjectName).dll"

+				SuppressStartupBanner="true"

+				GenerateDebugInformation="true"

+				ImportLibrary=".\./pthreadVC2.lib"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+				SuppressStartupBanner="true"

+				OutputFile=".\./pthread.bsc"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="false"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_DEBUG"

+				MkTypLibCompatible="true"

+				SuppressStartupBanner="true"

+				TargetEnvironment="1"

+				TypeLibraryName=".\./pthread.tlb"

+				HeaderFileName=""

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="."

+				PreprocessorDefinitions="__CLEANUP_C;WIN32;_DEBUG;_WINDOWS;_USRDLL;HAVE_CONFIG_H=1"

+				StringPooling="false"

+				RuntimeLibrary="3"

+				PrecompiledHeaderFile=".\./pthread.pch"

+				AssemblerListingLocation=".\./"

+				ObjectFile=".\./"

+				ProgramDataBaseFileName=".\./"

+				SuppressStartupBanner="true"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_DEBUG,PTW32_RC_MSC"

+				Culture="1033"

+				AdditionalIncludeDirectories="."

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="ws2_32.lib"

+				OutputFile="$(SolutionDir)..\..\build\products\$(ConfigurationName)\$(ProjectName).dll"

+				SuppressStartupBanner="true"

+				ProgramDatabaseFile=".\./pthreadVC2.pdb"

+				GenerateMapFile="true"

+				MapFileName=".\./pthreadVC2.map"

+				ImportLibrary=".\./pthreadVC2.lib"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+				SuppressStartupBanner="true"

+				OutputFile=".\./pthread.bsc"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"

+			OutputDirectory="$(SolutionDir)Windows Mobile 6 Professional SDK (ARMV4I)\$(ConfigurationName)"

+			IntermediateDirectory="Windows Mobile 6 Professional SDK (ARMV4I)\$(ConfigurationName)"

+			ConfigurationType="2"

+			InheritedPropertySheets="$(SolutionDir)..\WinMobileConfig$(ConfigurationName).vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODELNDEBUG"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				ExecutionBucket="7"

+				FavorSizeOrSpeed="1"

+				WholeProgramOptimization="true"

+				AdditionalIncludeDirectories="."

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;NDEBUG;$(ARCHFAM);$(_ARCHFAM_);_CONSOLE;HAVE_CONFIG_H=1"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODELNDEBUG"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions=" /subsystem:windowsce,5.02"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCCodeSignTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+			<DeploymentTool

+				ForceDirty="-1"

+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\Desktop"

+				RegisterOutput="0"

+				AdditionalFiles=""

+			/>

+			<DebuggerTool

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"

+			OutputDirectory="$(SolutionDir)Windows Mobile 6 Standard SDK (ARMV4I)\$(ConfigurationName)"

+			IntermediateDirectory="Windows Mobile 6 Standard SDK (ARMV4I)\$(ConfigurationName)"

+			ConfigurationType="2"

+			InheritedPropertySheets="$(SolutionDir)..\WinMobileConfig$(ConfigurationName).vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODELNDEBUG"

+				TargetEnvironment="1"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				ExecutionBucket="7"

+				FavorSizeOrSpeed="1"

+				WholeProgramOptimization="true"

+				AdditionalIncludeDirectories="."

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;NDEBUG;$(ARCHFAM);$(_ARCHFAM_);_CONSOLE;HAVE_CONFIG_H=1"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODELNDEBUG"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions=" /subsystem:windowsce,5.02"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCCodeSignTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+			<DeploymentTool

+				ForceDirty="-1"

+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\Desktop"

+				RegisterOutput="0"

+				AdditionalFiles=""

+			/>

+			<DebuggerTool

+			/>

+		</Configuration>

+		<Configuration

+			Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"

+			OutputDirectory="$(SolutionDir)Windows Mobile 6 Professional SDK (ARMV4I)\$(ConfigurationName)"

+			IntermediateDirectory="Windows Mobile 6 Professional SDK (ARMV4I)\$(ConfigurationName)"

+			ConfigurationType="2"

+			InheritedPropertySheets="$(SolutionDir)..\WinMobileConfig$(ConfigurationName).vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODEL;_DEBUG;DEBUG"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				ExecutionBucket="7"

+				AdditionalIncludeDirectories="."

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);_CONSOLE;_DEBUG;HAVE_CONFIG_H=1"

+				DisableSpecificWarnings="4005"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODEL;_DEBUG;DEBUG"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions=" /subsystem:windowsce,5.02"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCCodeSignTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+			<DeploymentTool

+				ForceDirty="-1"

+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\Desktop"

+				RegisterOutput="0"

+				AdditionalFiles=""

+			/>

+			<DebuggerTool

+			/>

+		</Configuration>

+		<Configuration

+			Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"

+			OutputDirectory="$(SolutionDir)Windows Mobile 6 Standard SDK (ARMV4I)\$(ConfigurationName)"

+			IntermediateDirectory="Windows Mobile 6 Standard SDK (ARMV4I)\$(ConfigurationName)"

+			ConfigurationType="2"

+			InheritedPropertySheets="$(SolutionDir)..\WinMobileConfig$(ConfigurationName).vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODEL;_DEBUG;DEBUG"

+				TargetEnvironment="1"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				ExecutionBucket="7"

+				AdditionalIncludeDirectories="."

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);_CONSOLE;_DEBUG;HAVE_CONFIG_H=1"

+				DisableSpecificWarnings="4005"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODEL;_DEBUG;DEBUG"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions=" /subsystem:windowsce,5.02"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCCodeSignTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+			<DeploymentTool

+				ForceDirty="-1"

+				RemoteDirectory="%CSIDL_PROGRAM_FILES%\Desktop"

+				RegisterOutput="0"

+				AdditionalFiles=""

+			/>

+			<DebuggerTool

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

+			>

+			<File

+				RelativePath="pthread.c"

+				>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories=""

+						PreprocessorDefinitions=""

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories=""

+						PreprocessorDefinitions=""

+					/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl"

+			>

+			<File

+				RelativePath=".\config.h"

+				>

+			</File>

+			<File

+				RelativePath="implement.h"

+				>

+			</File>

+			<File

+				RelativePath="pthread.h"

+				>

+			</File>

+			<File

+				RelativePath="sched.h"

+				>

+			</File>

+			<File

+				RelativePath="semaphore.h"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"

+			>

+			<File

+				RelativePath="version.rc"

+				>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCResourceCompilerTool"

+						PreprocessorDefinitions=""

+						AdditionalIncludeDirectories=""

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCResourceCompilerTool"

+						PreprocessorDefinitions=""

+						AdditionalIncludeDirectories=""

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"

+					>

+					<Tool

+						Name="VCResourceCompilerTool"

+						PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;NDEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODELNDEBUG;PTW32_RC_MSC"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"

+					>

+					<Tool

+						Name="VCResourceCompilerTool"

+						PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;NDEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODELNDEBUG;PTW32_RC_MSC"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"

+					>

+					<Tool

+						Name="VCResourceCompilerTool"

+						PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODEL;_DEBUG;PTW32_RC_MSC"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"

+					>

+					<Tool

+						Name="VCResourceCompilerTool"

+						PreprocessorDefinitions="_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);STANDARDSHELL_UI_MODEL;_DEBUG;PTW32_RC_MSC"

+					/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/pthread_attr_destroy.c b/pthread_attr_destroy.c
new file mode 100644
index 0000000..8b3e04c
--- /dev/null
+++ b/pthread_attr_destroy.c
@@ -0,0 +1,79 @@
+/*
+ * pthread_attr_destroy.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_destroy (pthread_attr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Destroys a thread attributes object.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *
+      * DESCRIPTION
+      *      Destroys a thread attributes object.
+      *
+      *      NOTES:
+      *              1)      Does not affect threads created with 'attr'.
+      *
+      * RESULTS
+      *              0               successfully destroyed attr,
+      *              EINVAL          'attr' is invalid.
+      *
+      * ------------------------------------------------------
+      */
+{
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * Set the attribute object to a specific invalid value.
+   */
+  (*attr)->valid = 0;
+  free (*attr);
+  *attr = NULL;
+
+  return 0;
+}
diff --git a/pthread_attr_getdetachstate.c b/pthread_attr_getdetachstate.c
new file mode 100644
index 0000000..978f288
--- /dev/null
+++ b/pthread_attr_getdetachstate.c
@@ -0,0 +1,87 @@
+/*
+ * pthread_attr_getdetachstate.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function determines whether threads created with
+      *      'attr' will run detached.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *      detachstate
+      *              pointer to an integer into which is returned one
+      *              of:
+      *
+      *              PTHREAD_CREATE_JOINABLE
+      *                              Thread ID is valid, must be joined
+      *
+      *              PTHREAD_CREATE_DETACHED
+      *                              Thread ID is invalid, cannot be joined,
+      *                              canceled, or modified
+      *
+      *
+      * DESCRIPTION
+      *      This function determines whether threads created with
+      *      'attr' will run detached.
+      *
+      *      NOTES:
+      *              1)      You cannot join or cancel detached threads.
+      *
+      * RESULTS
+      *              0               successfully retrieved detach state,
+      *              EINVAL          'attr' is invalid
+      *
+      * ------------------------------------------------------
+      */
+{
+  if (ptw32_is_attr (attr) != 0 || detachstate == NULL)
+    {
+      *detachstate = PTHREAD_CREATE_DETACHED;
+      return EINVAL;
+    }
+
+  *detachstate = (*attr)->detachstate;
+  return 0;
+}
diff --git a/pthread_attr_getinheritsched.c b/pthread_attr_getinheritsched.c
new file mode 100644
index 0000000..5085077
--- /dev/null
+++ b/pthread_attr_getinheritsched.c
@@ -0,0 +1,51 @@
+/*
+ * pthread_attr_getinheritsched.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getinheritsched (pthread_attr_t * attr, int *inheritsched)
+{
+  if (ptw32_is_attr (attr) != 0 || inheritsched == NULL)
+    {
+      return EINVAL;
+    }
+
+  *inheritsched = (*attr)->inheritsched;
+  return 0;
+}
diff --git a/pthread_attr_getschedparam.c b/pthread_attr_getschedparam.c
new file mode 100644
index 0000000..ab89b22
--- /dev/null
+++ b/pthread_attr_getschedparam.c
@@ -0,0 +1,52 @@
+/*
+ * pthread_attr_getschedparam.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getschedparam (const pthread_attr_t * attr,
+			    struct sched_param *param)
+{
+  if (ptw32_is_attr (attr) != 0 || param == NULL)
+    {
+      return EINVAL;
+    }
+
+  memcpy (param, &(*attr)->param, sizeof (*param));
+  return 0;
+}
diff --git a/pthread_attr_getschedpolicy.c b/pthread_attr_getschedpolicy.c
new file mode 100644
index 0000000..04adbd5
--- /dev/null
+++ b/pthread_attr_getschedpolicy.c
@@ -0,0 +1,61 @@
+/*
+ * pthread_attr_getschedpolicy.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getschedpolicy (pthread_attr_t * attr, int *policy)
+{
+  if (ptw32_is_attr (attr) != 0 || policy == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * Validate the policy arg.
+   * Check that a policy constant wasn't passed rather than &policy.
+   */
+  if (policy <= (int *) SCHED_MAX)
+    {
+      return EINVAL;
+    }
+
+  *policy = SCHED_OTHER;
+
+  return 0;
+}
diff --git a/pthread_attr_getscope.c b/pthread_attr_getscope.c
new file mode 100644
index 0000000..3c86382
--- /dev/null
+++ b/pthread_attr_getscope.c
@@ -0,0 +1,54 @@
+/*
+ * pthread_attr_getscope.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope)
+{
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+  *contentionscope = (*attr)->contentionscope;
+  return 0;
+#else
+  return ENOSYS;
+#endif
+}
diff --git a/pthread_attr_getstackaddr.c b/pthread_attr_getstackaddr.c
new file mode 100644
index 0000000..9b55959
--- /dev/null
+++ b/pthread_attr_getstackaddr.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_attr_getstackaddr.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function determines the address of the stack
+      *      on which threads created with 'attr' will run.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *      stackaddr
+      *              pointer into which is returned the stack address.
+      *
+      *
+      * DESCRIPTION
+      *      This function determines the address of the stack
+      *      on which threads created with 'attr' will run.
+      *
+      *      NOTES:
+      *              1)      Function supported only if this macro is
+      *                      defined:
+      *
+      *                              _POSIX_THREAD_ATTR_STACKADDR
+      *
+      *              2)      Create only one thread for each stack
+      *                      address..
+      *
+      * RESULTS
+      *              0               successfully retreived stack address,
+      *              EINVAL          'attr' is invalid
+      *              ENOSYS          function not supported
+      *
+      * ------------------------------------------------------
+      */
+{
+#if defined( _POSIX_THREAD_ATTR_STACKADDR )
+
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  *stackaddr = (*attr)->stackaddr;
+  return 0;
+
+#else
+
+  return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKADDR */
+}
diff --git a/pthread_attr_getstacksize.c b/pthread_attr_getstacksize.c
new file mode 100644
index 0000000..da8db63
--- /dev/null
+++ b/pthread_attr_getstacksize.c
@@ -0,0 +1,100 @@
+/*
+ * pthread_attr_getstacksize.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function determines the size of the stack on
+      *      which threads created with 'attr' will run.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *      stacksize
+      *              pointer to size_t into which is returned the
+      *              stack size, in bytes.
+      *
+      *
+      * DESCRIPTION
+      *      This function determines the size of the stack on
+      *      which threads created with 'attr' will run.
+      *
+      *      NOTES:
+      *              1)      Function supported only if this macro is
+      *                      defined:
+      *
+      *                              _POSIX_THREAD_ATTR_STACKSIZE
+      *
+      *              2)      Use on newly created attributes object to
+      *                      find the default stack size.
+      *
+      * RESULTS
+      *              0               successfully retrieved stack size,
+      *              EINVAL          'attr' is invalid
+      *              ENOSYS          function not supported
+      *
+      * ------------------------------------------------------
+      */
+{
+#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  /* Everything is okay. */
+  *stacksize = (*attr)->stacksize;
+  return 0;
+
+#else
+
+  return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
+
+}
diff --git a/pthread_attr_init.c b/pthread_attr_init.c
new file mode 100644
index 0000000..6c10bd3
--- /dev/null
+++ b/pthread_attr_init.c
@@ -0,0 +1,117 @@
+/*
+ * pthread_attr_init.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_init (pthread_attr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Initializes a thread attributes object with default
+      *      attributes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *
+      * DESCRIPTION
+      *      Initializes a thread attributes object with default
+      *      attributes.
+      *
+      *      NOTES:
+      *              1)      Used to define thread attributes
+      *
+      * RESULTS
+      *              0               successfully initialized attr,
+      *              ENOMEM          insufficient memory for attr.
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_attr_t attr_result;
+
+  if (attr == NULL)
+    {
+      /* This is disallowed. */
+      return EINVAL;
+    }
+
+  attr_result = (pthread_attr_t) malloc (sizeof (*attr_result));
+
+  if (attr_result == NULL)
+    {
+      return ENOMEM;
+    }
+
+#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+  /*
+   * Default to zero size. Unless changed explicitly this
+   * will allow Win32 to set the size to that of the
+   * main thread.
+   */
+  attr_result->stacksize = 0;
+#endif
+
+#ifdef _POSIX_THREAD_ATTR_STACKADDR
+  /* FIXME: Set this to something sensible when we support it. */
+  attr_result->stackaddr = NULL;
+#endif
+
+  attr_result->detachstate = PTHREAD_CREATE_JOINABLE;
+
+#if HAVE_SIGSET_T
+  memset (&(attr_result->sigmask), 0, sizeof (sigset_t));
+#endif /* HAVE_SIGSET_T */
+
+  /*
+   * Win32 sets new threads to THREAD_PRIORITY_NORMAL and
+   * not to that of the parent thread. We choose to default to
+   * this arrangement.
+   */
+  attr_result->param.sched_priority = THREAD_PRIORITY_NORMAL;
+  attr_result->inheritsched = PTHREAD_EXPLICIT_SCHED;
+  attr_result->contentionscope = PTHREAD_SCOPE_SYSTEM;
+
+  attr_result->valid = PTW32_ATTR_VALID;
+
+  *attr = attr_result;
+
+  return 0;
+}
diff --git a/pthread_attr_setdetachstate.c b/pthread_attr_setdetachstate.c
new file mode 100644
index 0000000..784642a
--- /dev/null
+++ b/pthread_attr_setdetachstate.c
@@ -0,0 +1,91 @@
+/*
+ * pthread_attr_setdetachstate.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function specifies whether threads created with
+      *      'attr' will run detached.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *      detachstate
+      *              an integer containing one of:
+      *
+      *              PTHREAD_CREATE_JOINABLE
+      *                              Thread ID is valid, must be joined
+      *
+      *              PTHREAD_CREATE_DETACHED
+      *                              Thread ID is invalid, cannot be joined,
+      *                              canceled, or modified
+      *
+      *
+      * DESCRIPTION
+      *      This function specifies whether threads created with
+      *      'attr' will run detached.
+      *
+      *      NOTES:
+      *              1)      You cannot join or cancel detached threads.
+      *
+      * RESULTS
+      *              0               successfully set detach state,
+      *              EINVAL          'attr' or 'detachstate' is invalid
+      *
+      * ------------------------------------------------------
+      */
+{
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  if (detachstate != PTHREAD_CREATE_JOINABLE &&
+      detachstate != PTHREAD_CREATE_DETACHED)
+    {
+      return EINVAL;
+    }
+
+  (*attr)->detachstate = detachstate;
+  return 0;
+}
diff --git a/pthread_attr_setinheritsched.c b/pthread_attr_setinheritsched.c
new file mode 100644
index 0000000..e0a407a
--- /dev/null
+++ b/pthread_attr_setinheritsched.c
@@ -0,0 +1,57 @@
+/*
+ * pthread_attr_setinheritsched.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched)
+{
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  if (PTHREAD_INHERIT_SCHED != inheritsched
+      && PTHREAD_EXPLICIT_SCHED != inheritsched)
+    {
+      return EINVAL;
+    }
+
+  (*attr)->inheritsched = inheritsched;
+  return 0;
+}
diff --git a/pthread_attr_setschedparam.c b/pthread_attr_setschedparam.c
new file mode 100644
index 0000000..f246bfa
--- /dev/null
+++ b/pthread_attr_setschedparam.c
@@ -0,0 +1,63 @@
+/*
+ * pthread_attr_setschedparam.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setschedparam (pthread_attr_t * attr,
+			    const struct sched_param *param)
+{
+  int priority;
+
+  if (ptw32_is_attr (attr) != 0 || param == NULL)
+    {
+      return EINVAL;
+    }
+
+  priority = param->sched_priority;
+
+  /* Validate priority level. */
+  if (priority < sched_get_priority_min (SCHED_OTHER) ||
+      priority > sched_get_priority_max (SCHED_OTHER))
+    {
+      return EINVAL;
+    }
+
+  memcpy (&(*attr)->param, param, sizeof (*param));
+  return 0;
+}
diff --git a/pthread_attr_setschedpolicy.c b/pthread_attr_setschedpolicy.c
new file mode 100644
index 0000000..45ff165
--- /dev/null
+++ b/pthread_attr_setschedpolicy.c
@@ -0,0 +1,55 @@
+/*
+ * pthread_attr_setschedpolicy.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy)
+{
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  if (policy != SCHED_OTHER)
+    {
+      return ENOTSUP;
+    }
+
+  return 0;
+}
diff --git a/pthread_attr_setscope.c b/pthread_attr_setscope.c
new file mode 100644
index 0000000..9cef423
--- /dev/null
+++ b/pthread_attr_setscope.c
@@ -0,0 +1,62 @@
+/*
+ * pthread_attr_setscope.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_setscope (pthread_attr_t * attr, int contentionscope)
+{
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+  switch (contentionscope)
+    {
+    case PTHREAD_SCOPE_SYSTEM:
+      (*attr)->contentionscope = contentionscope;
+      return 0;
+    case PTHREAD_SCOPE_PROCESS:
+      return ENOTSUP;
+    default:
+      return EINVAL;
+    }
+#else
+  return ENOSYS;
+#endif
+}
diff --git a/pthread_attr_setstackaddr.c b/pthread_attr_setstackaddr.c
new file mode 100644
index 0000000..96a8320
--- /dev/null
+++ b/pthread_attr_setstackaddr.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_attr_setstackaddr.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Threads created with 'attr' will run on the stack
+      *      starting at 'stackaddr'.
+      *      Stack must be at least PTHREAD_STACK_MIN bytes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *      stacksize
+      *              stack size, in bytes.
+      *
+      *
+      * DESCRIPTION
+      *      Threads created with 'attr' will run on the stack
+      *      starting at 'stackaddr'.
+      *      Stack must be at least PTHREAD_STACK_MIN bytes.
+      *
+      *      NOTES:
+      *              1)      Function supported only if this macro is
+      *                      defined:
+      *
+      *                              _POSIX_THREAD_ATTR_STACKADDR
+      *
+      *              2)      Create only one thread for each stack
+      *                      address..
+      *
+      *              3)      Ensure that stackaddr is aligned.
+      *
+      * RESULTS
+      *              0               successfully set stack address,
+      *              EINVAL          'attr' is invalid
+      *              ENOSYS          function not supported
+      *
+      * ------------------------------------------------------
+      */
+{
+#if defined( _POSIX_THREAD_ATTR_STACKADDR )
+
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  (*attr)->stackaddr = stackaddr;
+  return 0;
+
+#else
+
+  return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKADDR */
+}
diff --git a/pthread_attr_setstacksize.c b/pthread_attr_setstacksize.c
new file mode 100644
index 0000000..9df46af
--- /dev/null
+++ b/pthread_attr_setstacksize.c
@@ -0,0 +1,110 @@
+/*
+ * pthread_attr_setstacksize.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function specifies the size of the stack on
+      *      which threads created with 'attr' will run.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_attr_t
+      *
+      *      stacksize
+      *              stack size, in bytes.
+      *
+      *
+      * DESCRIPTION
+      *      This function specifies the size of the stack on
+      *      which threads created with 'attr' will run.
+      *
+      *      NOTES:
+      *              1)      Function supported only if this macro is
+      *                      defined:
+      *
+      *                              _POSIX_THREAD_ATTR_STACKSIZE
+      *
+      *              2)      Find the default first (using
+      *                      pthread_attr_getstacksize), then increase
+      *                      by multiplying.
+      *
+      *              3)      Only use if thread needs more than the
+      *                      default.
+      *
+      * RESULTS
+      *              0               successfully set stack size,
+      *              EINVAL          'attr' is invalid or stacksize too
+      *                              small or too big.
+      *              ENOSYS          function not supported
+      *
+      * ------------------------------------------------------
+      */
+{
+#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+
+#if PTHREAD_STACK_MIN > 0
+
+  /*  Verify that the stack size is within range. */
+  if (stacksize < PTHREAD_STACK_MIN)
+    {
+      return EINVAL;
+    }
+
+#endif
+
+  if (ptw32_is_attr (attr) != 0)
+    {
+      return EINVAL;
+    }
+
+  /* Everything is okay. */
+  (*attr)->stacksize = stacksize;
+  return 0;
+
+#else
+
+  return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
+
+}
diff --git a/pthread_barrier_destroy.c b/pthread_barrier_destroy.c
new file mode 100644
index 0000000..9302ba7
--- /dev/null
+++ b/pthread_barrier_destroy.c
@@ -0,0 +1,67 @@
+/*
+ * pthread_barrier_destroy.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrier_destroy (pthread_barrier_t * barrier)
+{
+  int result = 0;
+  pthread_barrier_t b;
+
+  if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
+    {
+      return EINVAL;
+    }
+
+  b = *barrier;
+  *barrier = NULL;
+
+  if (0 == (result = sem_destroy (&(b->semBarrierBreeched[0]))))
+    {
+      if (0 == (result = sem_destroy (&(b->semBarrierBreeched[1]))))
+	{
+	  (void) free (b);
+	  return 0;
+	}
+      (void) sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0);
+    }
+
+  *barrier = b;
+  return (result);
+}
diff --git a/pthread_barrier_init.c b/pthread_barrier_init.c
new file mode 100644
index 0000000..dc1b50c
--- /dev/null
+++ b/pthread_barrier_init.c
@@ -0,0 +1,81 @@
+/*
+ * pthread_barrier_init.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrier_init (pthread_barrier_t * barrier,
+		      const pthread_barrierattr_t * attr, unsigned int count)
+{
+  pthread_barrier_t b;
+
+  if (barrier == NULL || count == 0)
+    {
+      return EINVAL;
+    }
+
+  if (NULL != (b = (pthread_barrier_t) calloc (1, sizeof (*b))))
+    {
+      b->pshared = (attr != NULL && *attr != NULL
+		    ? (*attr)->pshared : PTHREAD_PROCESS_PRIVATE);
+
+      b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count;
+      b->iStep = 0;
+
+      /*
+       * Two semaphores are used in the same way as two stepping
+       * stones might be used in crossing a stream. Once all
+       * threads are safely on one stone, the other stone can
+       * be moved ahead, and the threads can start moving to it.
+       * If some threads decide to eat their lunch before moving
+       * then the other threads have to wait.
+       */
+      if (0 == sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0))
+	{
+	  if (0 == sem_init (&(b->semBarrierBreeched[1]), b->pshared, 0))
+	    {
+	      *barrier = b;
+	      return 0;
+	    }
+	  (void) sem_destroy (&(b->semBarrierBreeched[0]));
+	}
+      (void) free (b);
+    }
+
+  return ENOMEM;
+}
diff --git a/pthread_barrier_wait.c b/pthread_barrier_wait.c
new file mode 100644
index 0000000..01ae297
--- /dev/null
+++ b/pthread_barrier_wait.c
@@ -0,0 +1,99 @@
+/*
+ * pthread_barrier_wait.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrier_wait (pthread_barrier_t * barrier)
+{
+  int result;
+  int step;
+  pthread_barrier_t b;
+
+  if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
+    {
+      return EINVAL;
+    }
+
+  b = *barrier;
+  step = b->iStep;
+
+  if (0 == InterlockedDecrement ((long *) &(b->nCurrentBarrierHeight)))
+    {
+      /* Must be done before posting the semaphore. */
+      b->nCurrentBarrierHeight = b->nInitialBarrierHeight;
+
+      /*
+       * There is no race condition between the semaphore wait and post
+       * because we are using two alternating semas and all threads have
+       * entered barrier_wait and checked nCurrentBarrierHeight before this
+       * barrier's sema can be posted. Any threads that have not quite
+       * entered sem_wait below when the multiple_post has completed
+       * will nevertheless continue through the semaphore (barrier)
+       * and will not be left stranded.
+       */
+      result = (b->nInitialBarrierHeight > 1
+		? sem_post_multiple (&(b->semBarrierBreeched[step]),
+				     b->nInitialBarrierHeight - 1) : 0);
+    }
+  else
+    {
+      /*
+       * Use the non-cancelable version of sem_wait().
+       */
+      result = ptw32_semwait (&(b->semBarrierBreeched[step]));
+    }
+
+  /*
+   * The first thread across will be the PTHREAD_BARRIER_SERIAL_THREAD.
+   * This also sets up the alternate semaphore as the next barrier.
+   */
+  if (0 == result)
+    {
+      result = ((PTW32_INTERLOCKED_LONG) step ==
+		PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG)
+						    & (b->iStep),
+						    (PTW32_INTERLOCKED_LONG)
+						    (1L - step),
+						    (PTW32_INTERLOCKED_LONG)
+						    step) ?
+		PTHREAD_BARRIER_SERIAL_THREAD : 0);
+    }
+
+  return (result);
+}
diff --git a/pthread_barrierattr_destroy.c b/pthread_barrierattr_destroy.c
new file mode 100644
index 0000000..5ab662e
--- /dev/null
+++ b/pthread_barrierattr_destroy.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_barrier_attr_destroy.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_destroy (pthread_barrierattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Destroys a barrier attributes object. The object can
+      *      no longer be used.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_barrierattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Destroys a barrier attributes object. The object can
+      *      no longer be used.
+      *
+      *      NOTES:
+      *              1)      Does not affect barrieres created using 'attr'
+      *
+      * RESULTS
+      *              0               successfully released attr,
+      *              EINVAL          'attr' is invalid.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+
+  if (attr == NULL || *attr == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      pthread_barrierattr_t ba = *attr;
+
+      *attr = NULL;
+      free (ba);
+    }
+
+  return (result);
+}				/* pthread_barrierattr_destroy */
diff --git a/pthread_barrierattr_getpshared.c b/pthread_barrierattr_getpshared.c
new file mode 100644
index 0000000..44c467e
--- /dev/null
+++ b/pthread_barrierattr_getpshared.c
@@ -0,0 +1,95 @@
+/*
+ * pthread_barrier_attr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr,
+				int *pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Determine whether barriers created with 'attr' can be
+      *      shared between processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_barrierattr_t
+      *
+      *      pshared
+      *              will be set to one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      *
+      * DESCRIPTION
+      *      Mutexes creatd with 'attr' can be shared between
+      *      processes if pthread_barrier_t variable is allocated
+      *      in memory shared by these processes.
+      *      NOTES:
+      *              1)      pshared barriers MUST be allocated in shared
+      *                      memory.
+      *              2)      The following macro is defined if shared barriers
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully retrieved attribute,
+      *              EINVAL          'attr' is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+    {
+      *pshared = (*attr)->pshared;
+      result = 0;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+}				/* pthread_barrierattr_getpshared */
diff --git a/pthread_barrierattr_init.c b/pthread_barrierattr_init.c
new file mode 100644
index 0000000..342f8b0
--- /dev/null
+++ b/pthread_barrierattr_init.c
@@ -0,0 +1,85 @@
+/*
+ * pthread_barrier_attr_init.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_init (pthread_barrierattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Initializes a barrier attributes object with default
+      *      attributes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_barrierattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Initializes a barrier attributes object with default
+      *      attributes.
+      *
+      *      NOTES:
+      *              1)      Used to define barrier types
+      *
+      * RESULTS
+      *              0               successfully initialized attr,
+      *              ENOMEM          insufficient memory for attr.
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_barrierattr_t ba;
+  int result = 0;
+
+  ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba));
+
+  if (ba == NULL)
+    {
+      result = ENOMEM;
+    }
+  else
+    {
+      ba->pshared = PTHREAD_PROCESS_PRIVATE;
+    }
+
+  *attr = ba;
+
+  return (result);
+}				/* pthread_barrierattr_init */
diff --git a/pthread_barrierattr_setpshared.c b/pthread_barrierattr_setpshared.c
new file mode 100644
index 0000000..08c6fde
--- /dev/null
+++ b/pthread_barrierattr_setpshared.c
@@ -0,0 +1,119 @@
+/*
+ * pthread_barrier_attr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Barriers created with 'attr' can be shared between
+      *      processes if pthread_barrier_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_barrierattr_t
+      *
+      *      pshared
+      *              must be one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      * DESCRIPTION
+      *      Mutexes creatd with 'attr' can be shared between
+      *      processes if pthread_barrier_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      *      NOTES:
+      *              1)      pshared barriers MUST be allocated in shared
+      *                      memory.
+      *
+      *              2)      The following macro is defined if shared barriers
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully set attribute,
+      *              EINVAL          'attr' or pshared is invalid,
+      *              ENOSYS          PTHREAD_PROCESS_SHARED not supported,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) &&
+      ((pshared == PTHREAD_PROCESS_SHARED) ||
+       (pshared == PTHREAD_PROCESS_PRIVATE)))
+    {
+      if (pshared == PTHREAD_PROCESS_SHARED)
+	{
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+	  result = ENOSYS;
+	  pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+	  result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+	}
+      else
+	{
+	  result = 0;
+	}
+
+      (*attr)->pshared = pshared;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+
+}				/* pthread_barrierattr_setpshared */
diff --git a/pthread_cancel.c b/pthread_cancel.c
new file mode 100644
index 0000000..42ab3f6
--- /dev/null
+++ b/pthread_cancel.c
@@ -0,0 +1,232 @@
+/*
+ * pthread_cancel.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#if defined(_M_IX86) || defined(_X86_)
+#define PTW32_PROGCTR(Context)  ((Context).Eip)
+#endif
+
+#if defined (_M_IA64)
+#define PTW32_PROGCTR(Context)  ((Context).StIIP)
+#endif
+
+#if defined(_MIPS_)
+#define PTW32_PROGCTR(Context)  ((Context).Fir)
+#endif
+
+#if defined(_ALPHA_)
+#define PTW32_PROGCTR(Context)  ((Context).Fir)
+#endif
+
+#if defined(_PPC_)
+#define PTW32_PROGCTR(Context)  ((Context).Iar)
+#endif
+
+#if defined(_AMD64_)
+#define PTW32_PROGCTR(Context)  ((Context).Rip)
+#endif
+
+#if defined(WINCE) && defined(_ARM_)
+/* This is a hack as i don't know what to use (Marcel Ruff 2006-11-29) */
+static ULONG val;
+#define PTW32_PROGCTR(Context) (val)
+/* TODO: What to use from
+/* typedef struct _CONTEXT in C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\Smartphone2003\Include\winnt.h */
+/*#define PTW32_PROGCTR(Context) ((Context).FpExc)*/
+#endif
+
+#if !defined(PTW32_PROGCTR)
+#error Module contains CPU-specific code; modify and recompile.
+#endif
+
+static void
+ptw32_cancel_self (void)
+{
+  ptw32_throw (PTW32_EPS_CANCEL);
+
+  /* Never reached */
+}
+
+static void CALLBACK
+ptw32_cancel_callback (DWORD unused)
+{
+  ptw32_throw (PTW32_EPS_CANCEL);
+
+  /* Never reached */
+}
+
+/*
+ * ptw32_RegisterCancelation() -
+ * Must have args of same type as QueueUserAPCEx because this function
+ * is a substitute for QueueUserAPCEx if it's not available.
+ */
+DWORD
+ptw32_RegisterCancelation (PAPCFUNC unused1, HANDLE threadH, DWORD unused2)
+{
+  CONTEXT context;
+
+  context.ContextFlags = CONTEXT_CONTROL;
+  GetThreadContext (threadH, &context);
+  PTW32_PROGCTR (context) = (DWORD_PTR) ptw32_cancel_self;
+  SetThreadContext (threadH, &context);
+  return 0;
+}
+
+int
+pthread_cancel (pthread_t thread)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function requests cancellation of 'thread'.
+      *
+      * PARAMETERS
+      *      thread
+      *              reference to an instance of pthread_t
+      *
+      *
+      * DESCRIPTION
+      *      This function requests cancellation of 'thread'.
+      *      NOTE: cancellation is asynchronous; use pthread_join to
+      *                wait for termination of 'thread' if necessary.
+      *
+      * RESULTS
+      *              0               successfully requested cancellation,
+      *              ESRCH           no thread found corresponding to 'thread',
+      *              ENOMEM          implicit self thread create failed.
+      * ------------------------------------------------------
+      */
+{
+  int result;
+  int cancel_self;
+  pthread_t self;
+  ptw32_thread_t * tp;
+
+  result = pthread_kill (thread, 0);
+
+  if (0 != result)
+    {
+      return result;
+    }
+
+  if ((self = pthread_self ()).p == NULL)
+    {
+      return ENOMEM;
+    };
+
+  /*
+   * FIXME!!
+   *
+   * Can a thread cancel itself?
+   *
+   * The standard doesn't
+   * specify an error to be returned if the target
+   * thread is itself.
+   *
+   * If it may, then we need to ensure that a thread can't
+   * deadlock itself trying to cancel itself asyncronously
+   * (pthread_cancel is required to be an async-cancel
+   * safe function).
+   */
+  cancel_self = pthread_equal (thread, self);
+
+  tp = (ptw32_thread_t *) thread.p;
+
+  /*
+   * Lock for async-cancel safety.
+   */
+  (void) pthread_mutex_lock (&tp->cancelLock);
+
+  if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
+      && tp->cancelState == PTHREAD_CANCEL_ENABLE
+      && tp->state < PThreadStateCanceling)
+    {
+      if (cancel_self)
+	{
+	  tp->state = PThreadStateCanceling;
+	  tp->cancelState = PTHREAD_CANCEL_DISABLE;
+
+	  (void) pthread_mutex_unlock (&tp->cancelLock);
+	  ptw32_throw (PTW32_EPS_CANCEL);
+
+	  /* Never reached */
+	}
+      else
+	{
+	  HANDLE threadH = tp->threadH;
+
+	  SuspendThread (threadH);
+
+	  if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT)
+	    {
+	      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
+	       * this will result in a call to ptw32_RegisterCancelation and only
+	       * the threadH arg will be used.
+	       */
+	      ptw32_register_cancelation (ptw32_cancel_callback, threadH, 0);
+	      (void) pthread_mutex_unlock (&tp->cancelLock);
+	      ResumeThread (threadH);
+	    }
+	}
+    }
+  else
+    {
+      /*
+       * Set for deferred cancellation.
+       */
+      if (tp->state < PThreadStateCancelPending)
+	{
+	  tp->state = PThreadStateCancelPending;
+	  if (!SetEvent (tp->cancelEvent))
+	    {
+	      result = ESRCH;
+	    }
+	}
+      else if (tp->state >= PThreadStateCanceling)
+	{
+	  result = ESRCH;
+	}
+
+      (void) pthread_mutex_unlock (&tp->cancelLock);
+    }
+
+  return (result);
+}
diff --git a/pthread_cond_destroy.c b/pthread_cond_destroy.c
new file mode 100644
index 0000000..3d29ffc
--- /dev/null
+++ b/pthread_cond_destroy.c
@@ -0,0 +1,244 @@
+/*
+ * pthread_cond_destroy.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_cond_destroy (pthread_cond_t * cond)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function destroys a condition variable
+      *
+      *
+      * PARAMETERS
+      *      cond
+      *              pointer to an instance of pthread_cond_t
+      *
+      *
+      * DESCRIPTION
+      *      This function destroys a condition variable.
+      *
+      *      NOTES:
+      *              1)      A condition variable can be destroyed
+      *                      immediately after all the threads that
+      *                      are blocked on it are awakened. e.g.
+      *
+      *                      struct list {
+      *                        pthread_mutex_t lm;
+      *                        ...
+      *                      }
+      *
+      *                      struct elt {
+      *                        key k;
+      *                        int busy;
+      *                        pthread_cond_t notbusy;
+      *                        ...
+      *                      }
+      *
+      *                      
+      *                      struct elt *
+      *                      list_find(struct list *lp, key k)
+      *                      {
+      *                        struct elt *ep;
+      *
+      *                        pthread_mutex_lock(&lp->lm);
+      *                        while ((ep = find_elt(l,k) != NULL) && ep->busy)
+      *                          pthread_cond_wait(&ep->notbusy, &lp->lm);
+      *                        if (ep != NULL)
+      *                          ep->busy = 1;
+      *                        pthread_mutex_unlock(&lp->lm);
+      *                        return(ep);
+      *                      }
+      *
+      *                      delete_elt(struct list *lp, struct elt *ep)
+      *                      {
+      *                        pthread_mutex_lock(&lp->lm);
+      *                        assert(ep->busy);
+      *                        ... remove ep from list ...
+      *                        ep->busy = 0;
+      *                    (A) pthread_cond_broadcast(&ep->notbusy);
+      *                        pthread_mutex_unlock(&lp->lm);
+      *                    (B) pthread_cond_destroy(&rp->notbusy);
+      *                        free(ep);
+      *                      }
+      *
+      *                      In this example, the condition variable
+      *                      and its list element may be freed (line B)
+      *                      immediately after all threads waiting for
+      *                      it are awakened (line A), since the mutex
+      *                      and the code ensure that no other thread
+      *                      can touch the element to be deleted.
+      *
+      * RESULTS
+      *              0               successfully released condition variable,
+      *              EINVAL          'cond' is invalid,
+      *              EBUSY           'cond' is in use,
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_cond_t cv;
+  int result = 0, result1 = 0, result2 = 0;
+
+  /*
+   * Assuming any race condition here is harmless.
+   */
+  if (cond == NULL || *cond == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*cond != PTHREAD_COND_INITIALIZER)
+    {
+      EnterCriticalSection (&ptw32_cond_list_lock);
+
+      cv = *cond;
+
+      /*
+       * Close the gate; this will synchronize this thread with
+       * all already signaled waiters to let them retract their
+       * waiter status - SEE NOTE 1 ABOVE!!!
+       */
+      if (sem_wait (&(cv->semBlockLock)) != 0)
+	{
+	  return errno;
+	}
+
+      /*
+       * !TRY! lock mtxUnblockLock; try will detect busy condition
+       * and will not cause a deadlock with respect to concurrent
+       * signal/broadcast.
+       */
+      if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0)
+	{
+	  (void) sem_post (&(cv->semBlockLock));
+	  return result;
+	}
+
+      /*
+       * Check whether cv is still busy (still has waiters)
+       */
+      if (cv->nWaitersBlocked > cv->nWaitersGone)
+	{
+	  if (sem_post (&(cv->semBlockLock)) != 0)
+	    {
+	      result = errno;
+	    }
+	  result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock));
+	  result2 = EBUSY;
+	}
+      else
+	{
+	  /*
+	   * Now it is safe to destroy
+	   */
+	  *cond = NULL;
+
+	  if (sem_destroy (&(cv->semBlockLock)) != 0)
+	    {
+	      result = errno;
+	    }
+	  if (sem_destroy (&(cv->semBlockQueue)) != 0)
+	    {
+	      result1 = errno;
+	    }
+	  if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
+	    {
+	      result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock));
+	    }
+
+	  /* Unlink the CV from the list */
+
+	  if (ptw32_cond_list_head == cv)
+	    {
+	      ptw32_cond_list_head = cv->next;
+	    }
+	  else
+	    {
+	      cv->prev->next = cv->next;
+	    }
+
+	  if (ptw32_cond_list_tail == cv)
+	    {
+	      ptw32_cond_list_tail = cv->prev;
+	    }
+	  else
+	    {
+	      cv->next->prev = cv->prev;
+	    }
+
+	  (void) free (cv);
+	}
+
+      LeaveCriticalSection (&ptw32_cond_list_lock);
+    }
+  else
+    {
+      /*
+       * See notes in ptw32_cond_check_need_init() above also.
+       */
+      EnterCriticalSection (&ptw32_cond_test_init_lock);
+
+      /*
+       * Check again.
+       */
+      if (*cond == PTHREAD_COND_INITIALIZER)
+	{
+	  /*
+	   * This is all we need to do to destroy a statically
+	   * initialised cond that has not yet been used (initialised).
+	   * If we get to here, another thread waiting to initialise
+	   * this cond will get an EINVAL. That's OK.
+	   */
+	  *cond = NULL;
+	}
+      else
+	{
+	  /*
+	   * The cv has been initialised while we were waiting
+	   * so assume it's in use.
+	   */
+	  result = EBUSY;
+	}
+
+      LeaveCriticalSection (&ptw32_cond_test_init_lock);
+    }
+
+  return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
+}
diff --git a/pthread_cond_init.c b/pthread_cond_init.c
new file mode 100644
index 0000000..d2de232
--- /dev/null
+++ b/pthread_cond_init.c
@@ -0,0 +1,165 @@
+/*
+ * pthread_cond_init.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function initializes a condition variable.
+      *
+      * PARAMETERS
+      *      cond
+      *              pointer to an instance of pthread_cond_t
+      *
+      *      attr
+      *              specifies optional creation attributes.
+      *
+      *
+      * DESCRIPTION
+      *      This function initializes a condition variable.
+      *
+      * RESULTS
+      *              0               successfully created condition variable,
+      *              EINVAL          'attr' is invalid,
+      *              EAGAIN          insufficient resources (other than
+      *                              memory,
+      *              ENOMEM          insufficient memory,
+      *              EBUSY           'cond' is already initialized,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+  pthread_cond_t cv = NULL;
+
+  if (cond == NULL)
+    {
+      return EINVAL;
+    }
+
+  if ((attr != NULL && *attr != NULL) &&
+      ((*attr)->pshared == PTHREAD_PROCESS_SHARED))
+    {
+      /*
+       * Creating condition variable that can be shared between
+       * processes.
+       */
+      result = ENOSYS;
+      goto DONE;
+    }
+
+  cv = (pthread_cond_t) calloc (1, sizeof (*cv));
+
+  if (cv == NULL)
+    {
+      result = ENOMEM;
+      goto DONE;
+    }
+
+  cv->nWaitersBlocked = 0;
+  cv->nWaitersToUnblock = 0;
+  cv->nWaitersGone = 0;
+
+  if (sem_init (&(cv->semBlockLock), 0, 1) != 0)
+    {
+      result = errno;
+      goto FAIL0;
+    }
+
+  if (sem_init (&(cv->semBlockQueue), 0, 0) != 0)
+    {
+      result = errno;
+      goto FAIL1;
+    }
+
+  if ((result = pthread_mutex_init (&(cv->mtxUnblockLock), 0)) != 0)
+    {
+      goto FAIL2;
+    }
+
+  result = 0;
+
+  goto DONE;
+
+  /*
+   * -------------
+   * Failed...
+   * -------------
+   */
+FAIL2:
+  (void) sem_destroy (&(cv->semBlockQueue));
+
+FAIL1:
+  (void) sem_destroy (&(cv->semBlockLock));
+
+FAIL0:
+  (void) free (cv);
+  cv = NULL;
+
+DONE:
+  if (0 == result)
+    {
+      EnterCriticalSection (&ptw32_cond_list_lock);
+
+      cv->next = NULL;
+      cv->prev = ptw32_cond_list_tail;
+
+      if (ptw32_cond_list_tail != NULL)
+	{
+	  ptw32_cond_list_tail->next = cv;
+	}
+
+      ptw32_cond_list_tail = cv;
+
+      if (ptw32_cond_list_head == NULL)
+	{
+	  ptw32_cond_list_head = cv;
+	}
+
+      LeaveCriticalSection (&ptw32_cond_list_lock);
+    }
+
+  *cond = cv;
+
+  return result;
+
+}				/* pthread_cond_init */
diff --git a/pthread_cond_signal.c b/pthread_cond_signal.c
new file mode 100644
index 0000000..2b4f6d4
--- /dev/null
+++ b/pthread_cond_signal.c
@@ -0,0 +1,231 @@
+/*
+ * pthread_cond_signal.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * -------------------------------------------------------------
+ * Algorithm:
+ * See the comments at the top of pthread_cond_wait.c.
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+static INLINE int
+ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll)
+     /*
+      * Notes.
+      *
+      * Does not use the external mutex for synchronisation,
+      * therefore semBlockLock is needed.
+      * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the
+      * state where the external mutex is not necessarily locked by
+      * any thread, ie. between cond_wait unlocking and re-acquiring
+      * the lock after having been signaled or a timeout or
+      * cancellation.
+      *
+      * Uses the following CV elements:
+      *   nWaitersBlocked
+      *   nWaitersToUnblock
+      *   nWaitersGone
+      *   mtxUnblockLock
+      *   semBlockLock
+      *   semBlockQueue
+      */
+{
+  int result;
+  pthread_cond_t cv;
+  int nSignalsToIssue;
+
+  if (cond == NULL || *cond == NULL)
+    {
+      return EINVAL;
+    }
+
+  cv = *cond;
+
+  /*
+   * No-op if the CV is static and hasn't been initialised yet.
+   * Assuming that any race condition is harmless.
+   */
+  if (cv == PTHREAD_COND_INITIALIZER)
+    {
+      return 0;
+    }
+
+  if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
+    {
+      return result;
+    }
+
+  if (0 != cv->nWaitersToUnblock)
+    {
+      if (0 == cv->nWaitersBlocked)
+	{
+	  return pthread_mutex_unlock (&(cv->mtxUnblockLock));
+	}
+      if (unblockAll)
+	{
+	  cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked);
+	  cv->nWaitersBlocked = 0;
+	}
+      else
+	{
+	  nSignalsToIssue = 1;
+	  cv->nWaitersToUnblock++;
+	  cv->nWaitersBlocked--;
+	}
+    }
+  else if (cv->nWaitersBlocked > cv->nWaitersGone)
+    {
+      /* Use the non-cancellable version of sem_wait() */
+      if (ptw32_semwait (&(cv->semBlockLock)) != 0)
+	{
+	  result = errno;
+	  (void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
+	  return result;
+	}
+      if (0 != cv->nWaitersGone)
+	{
+	  cv->nWaitersBlocked -= cv->nWaitersGone;
+	  cv->nWaitersGone = 0;
+	}
+      if (unblockAll)
+	{
+	  nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked;
+	  cv->nWaitersBlocked = 0;
+	}
+      else
+	{
+	  nSignalsToIssue = cv->nWaitersToUnblock = 1;
+	  cv->nWaitersBlocked--;
+	}
+    }
+  else
+    {
+      return pthread_mutex_unlock (&(cv->mtxUnblockLock));
+    }
+
+  if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
+    {
+      if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0)
+	{
+	  result = errno;
+	}
+    }
+
+  return result;
+
+}				/* ptw32_cond_unblock */
+
+int
+pthread_cond_signal (pthread_cond_t * cond)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function signals a condition variable, waking
+      *      one waiting thread.
+      *      If SCHED_FIFO or SCHED_RR policy threads are waiting
+      *      the highest priority waiter is awakened; otherwise,
+      *      an unspecified waiter is awakened.
+      *
+      * PARAMETERS
+      *      cond
+      *              pointer to an instance of pthread_cond_t
+      *
+      *
+      * DESCRIPTION
+      *      This function signals a condition variable, waking
+      *      one waiting thread.
+      *      If SCHED_FIFO or SCHED_RR policy threads are waiting
+      *      the highest priority waiter is awakened; otherwise,
+      *      an unspecified waiter is awakened.
+      *
+      *      NOTES:
+      *
+      *      1)      Use when any waiter can respond and only one need
+      *              respond (all waiters being equal).
+      *
+      * RESULTS
+      *              0               successfully signaled condition,
+      *              EINVAL          'cond' is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  /*
+   * The '0'(FALSE) unblockAll arg means unblock ONE waiter.
+   */
+  return (ptw32_cond_unblock (cond, 0));
+
+}				/* pthread_cond_signal */
+
+int
+pthread_cond_broadcast (pthread_cond_t * cond)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function broadcasts the condition variable,
+      *      waking all current waiters.
+      *
+      * PARAMETERS
+      *      cond
+      *              pointer to an instance of pthread_cond_t
+      *
+      *
+      * DESCRIPTION
+      *      This function signals a condition variable, waking
+      *      all waiting threads.
+      *
+      *      NOTES:
+      *
+      *      1)      Use when more than one waiter may respond to
+      *              predicate change or if any waiting thread may
+      *              not be able to respond
+      *
+      * RESULTS
+      *              0               successfully signalled condition to all
+      *                              waiting threads,
+      *              EINVAL          'cond' is invalid
+      *              ENOSPC          a required resource has been exhausted,
+      *
+      * ------------------------------------------------------
+      */
+{
+  /*
+   * The TRUE unblockAll arg means unblock ALL waiters.
+   */
+  return (ptw32_cond_unblock (cond, PTW32_TRUE));
+
+}				/* pthread_cond_broadcast */
diff --git a/pthread_cond_wait.c b/pthread_cond_wait.c
new file mode 100644
index 0000000..5511c58
--- /dev/null
+++ b/pthread_cond_wait.c
@@ -0,0 +1,567 @@
+/*
+ * pthread_cond_wait.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * -------------------------------------------------------------
+ * Algorithm:
+ * The algorithm used in this implementation is that developed by
+ * Alexander Terekhov in colaboration with Louis Thomas. The bulk
+ * of the discussion is recorded in the file README.CV, which contains
+ * several generations of both colaborators original algorithms. The final
+ * algorithm used here is the one referred to as
+ *
+ *     Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+ * 
+ * presented below in pseudo-code as it appeared:
+ *
+ *
+ * given:
+ * semBlockLock - bin.semaphore
+ * semBlockQueue - semaphore
+ * mtxExternal - mutex or CS
+ * mtxUnblockLock - mutex or CS
+ * nWaitersGone - int
+ * nWaitersBlocked - int
+ * nWaitersToUnblock - int
+ * 
+ * wait( timeout ) {
+ * 
+ *   [auto: register int result          ]     // error checking omitted
+ *   [auto: register int nSignalsWasLeft ]
+ *   [auto: register int nWaitersWasGone ]
+ * 
+ *   sem_wait( semBlockLock );
+ *   nWaitersBlocked++;
+ *   sem_post( semBlockLock );
+ * 
+ *   unlock( mtxExternal );
+ *   bTimedOut = sem_wait( semBlockQueue,timeout );
+ * 
+ *   lock( mtxUnblockLock );
+ *   if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+ *     if ( bTimeout ) {                       // timeout (or canceled)
+ *       if ( 0 != nWaitersBlocked ) {
+ *         nWaitersBlocked--;
+ *       }
+ *       else {
+ *         nWaitersGone++;                     // count spurious wakeups.
+ *       }
+ *     }
+ *     if ( 0 == --nWaitersToUnblock ) {
+ *       if ( 0 != nWaitersBlocked ) {
+ *         sem_post( semBlockLock );           // open the gate.
+ *         nSignalsWasLeft = 0;                // do not open the gate
+ *                                             // below again.
+ *       }
+ *       else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+ *         nWaitersGone = 0;
+ *       }
+ *     }
+ *   }
+ *   else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+ *                                             // spurious semaphore :-)
+ *     sem_wait( semBlockLock );
+ *     nWaitersBlocked -= nWaitersGone;     // something is going on here
+ *                                          //  - test of timeouts? :-)
+ *     sem_post( semBlockLock );
+ *     nWaitersGone = 0;
+ *   }
+ *   unlock( mtxUnblockLock );
+ * 
+ *   if ( 1 == nSignalsWasLeft ) {
+ *     if ( 0 != nWaitersWasGone ) {
+ *       // sem_adjust( semBlockQueue,-nWaitersWasGone );
+ *       while ( nWaitersWasGone-- ) {
+ *         sem_wait( semBlockQueue );       // better now than spurious later
+ *       }
+ *     } sem_post( semBlockLock );          // open the gate
+ *   }
+ * 
+ *   lock( mtxExternal );
+ * 
+ *   return ( bTimedOut ) ? ETIMEOUT : 0;
+ * }
+ * 
+ * signal(bAll) {
+ * 
+ *   [auto: register int result         ]
+ *   [auto: register int nSignalsToIssue]
+ * 
+ *   lock( mtxUnblockLock );
+ * 
+ *   if ( 0 != nWaitersToUnblock ) {        // the gate is closed!!!
+ *     if ( 0 == nWaitersBlocked ) {        // NO-OP
+ *       return unlock( mtxUnblockLock );
+ *     }
+ *     if (bAll) {
+ *       nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+ *       nWaitersBlocked = 0;
+ *     }
+ *     else {
+ *       nSignalsToIssue = 1;
+ *       nWaitersToUnblock++;
+ *       nWaitersBlocked--;
+ *     }
+ *   }
+ *   else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+ *     sem_wait( semBlockLock );                  // close the gate
+ *     if ( 0 != nWaitersGone ) {
+ *       nWaitersBlocked -= nWaitersGone;
+ *       nWaitersGone = 0;
+ *     }
+ *     if (bAll) {
+ *       nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+ *       nWaitersBlocked = 0;
+ *     }
+ *     else {
+ *       nSignalsToIssue = nWaitersToUnblock = 1;
+ *       nWaitersBlocked--;
+ *     }
+ *   }
+ *   else { // NO-OP
+ *     return unlock( mtxUnblockLock );
+ *   }
+ * 
+ *   unlock( mtxUnblockLock );
+ *   sem_post( semBlockQueue,nSignalsToIssue );
+ *   return result;
+ * }
+ * -------------------------------------------------------------
+ *
+ *     Algorithm 9 / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+ * 
+ * presented below in pseudo-code; basically 8a...
+ *                                      ...BUT W/O "spurious wakes" prevention:
+ *
+ *
+ * given:
+ * semBlockLock - bin.semaphore
+ * semBlockQueue - semaphore
+ * mtxExternal - mutex or CS
+ * mtxUnblockLock - mutex or CS
+ * nWaitersGone - int
+ * nWaitersBlocked - int
+ * nWaitersToUnblock - int
+ * 
+ * wait( timeout ) {
+ * 
+ *   [auto: register int result          ]     // error checking omitted
+ *   [auto: register int nSignalsWasLeft ]
+ * 
+ *   sem_wait( semBlockLock );
+ *   ++nWaitersBlocked;
+ *   sem_post( semBlockLock );
+ * 
+ *   unlock( mtxExternal );
+ *   bTimedOut = sem_wait( semBlockQueue,timeout );
+ * 
+ *   lock( mtxUnblockLock );
+ *   if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+ *     --nWaitersToUnblock;
+ *   }
+ *   else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+ *                                             // spurious semaphore :-)
+ *     sem_wait( semBlockLock );
+ *     nWaitersBlocked -= nWaitersGone;        // something is going on here
+ *                                             //  - test of timeouts? :-)
+ *     sem_post( semBlockLock );
+ *     nWaitersGone = 0;
+ *   }
+ *   unlock( mtxUnblockLock );
+ * 
+ *   if ( 1 == nSignalsWasLeft ) {
+ *     sem_post( semBlockLock );               // open the gate
+ *   }
+ * 
+ *   lock( mtxExternal );
+ * 
+ *   return ( bTimedOut ) ? ETIMEOUT : 0;
+ * }
+ * 
+ * signal(bAll) {
+ * 
+ *   [auto: register int result         ]
+ *   [auto: register int nSignalsToIssue]
+ * 
+ *   lock( mtxUnblockLock );
+ * 
+ *   if ( 0 != nWaitersToUnblock ) {        // the gate is closed!!!
+ *     if ( 0 == nWaitersBlocked ) {        // NO-OP
+ *       return unlock( mtxUnblockLock );
+ *     }
+ *     if (bAll) {
+ *       nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+ *       nWaitersBlocked = 0;
+ *     }
+ *     else {
+ *       nSignalsToIssue = 1;
+ *       ++nWaitersToUnblock;
+ *       --nWaitersBlocked;
+ *     }
+ *   }
+ *   else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+ *     sem_wait( semBlockLock );                  // close the gate
+ *     if ( 0 != nWaitersGone ) {
+ *       nWaitersBlocked -= nWaitersGone;
+ *       nWaitersGone = 0;
+ *     }
+ *     if (bAll) {
+ *       nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+ *       nWaitersBlocked = 0;
+ *     }
+ *     else {
+ *       nSignalsToIssue = nWaitersToUnblock = 1;
+ *       --nWaitersBlocked;
+ *     }
+ *   }
+ *   else { // NO-OP
+ *     return unlock( mtxUnblockLock );
+ *   }
+ *
+ *   unlock( mtxUnblockLock );
+ *   sem_post( semBlockQueue,nSignalsToIssue );
+ *   return result;
+ * }
+ * -------------------------------------------------------------
+ *
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Arguments for cond_wait_cleanup, since we can only pass a
+ * single void * to it.
+ */
+typedef struct
+{
+  pthread_mutex_t *mutexPtr;
+  pthread_cond_t cv;
+  int *resultPtr;
+} ptw32_cond_wait_cleanup_args_t;
+
+static void PTW32_CDECL
+ptw32_cond_wait_cleanup (void *args)
+{
+  ptw32_cond_wait_cleanup_args_t *cleanup_args =
+    (ptw32_cond_wait_cleanup_args_t *) args;
+  pthread_cond_t cv = cleanup_args->cv;
+  int *resultPtr = cleanup_args->resultPtr;
+  int nSignalsWasLeft;
+  int result;
+
+  /*
+   * 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
+   * longer waiting. The waiter is responsible for adjusting waiters
+   * (to)unblock(ed) counts (protected by unblock lock).
+   */
+  if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
+    {
+      *resultPtr = result;
+      return;
+    }
+
+  if (0 != (nSignalsWasLeft = cv->nWaitersToUnblock))
+    {
+      --(cv->nWaitersToUnblock);
+    }
+  else if (INT_MAX / 2 == ++(cv->nWaitersGone))
+    {
+      /* Use the non-cancellable version of sem_wait() */
+      if (ptw32_semwait (&(cv->semBlockLock)) != 0)
+	{
+	  *resultPtr = errno;
+	  /*
+	   * This is a fatal error for this CV,
+	   * so we deliberately don't unlock
+	   * cv->mtxUnblockLock before returning.
+	   */
+	  return;
+	}
+      cv->nWaitersBlocked -= cv->nWaitersGone;
+      if (sem_post (&(cv->semBlockLock)) != 0)
+	{
+	  *resultPtr = errno;
+	  /*
+	   * This is a fatal error for this CV,
+	   * so we deliberately don't unlock
+	   * cv->mtxUnblockLock before returning.
+	   */
+	  return;
+	}
+      cv->nWaitersGone = 0;
+    }
+
+  if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) != 0)
+    {
+      *resultPtr = result;
+      return;
+    }
+
+  if (1 == nSignalsWasLeft)
+    {
+      if (sem_post (&(cv->semBlockLock)) != 0)
+	{
+	  *resultPtr = errno;
+	  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
+ptw32_cond_timedwait (pthread_cond_t * cond,
+		      pthread_mutex_t * mutex, const struct timespec *abstime)
+{
+  int result = 0;
+  pthread_cond_t cv;
+  ptw32_cond_wait_cleanup_args_t cleanup_args;
+
+  if (cond == NULL || *cond == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static condition variable. We check
+   * again inside the guarded section of ptw32_cond_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*cond == PTHREAD_COND_INITIALIZER)
+    {
+      result = ptw32_cond_check_need_init (cond);
+    }
+
+  if (result != 0 && result != EBUSY)
+    {
+      return result;
+    }
+
+  cv = *cond;
+
+  /* Thread can be cancelled in sem_wait() but this is OK */
+  if (sem_wait (&(cv->semBlockLock)) != 0)
+    {
+      return errno;
+    }
+
+  ++(cv->nWaitersBlocked);
+
+  if (sem_post (&(cv->semBlockLock)) != 0)
+    {
+      return errno;
+    }
+
+  /*
+   * Setup this waiter cleanup handler
+   */
+  cleanup_args.mutexPtr = mutex;
+  cleanup_args.cv = cv;
+  cleanup_args.resultPtr = &result;
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args);
+
+  /*
+   * Now we can release 'mutex' and...
+   */
+  if ((result = pthread_mutex_unlock (mutex)) == 0)
+    {
+
+      /*
+       * ...wait to be awakened by
+       *              pthread_cond_signal, or
+       *              pthread_cond_broadcast, or
+       *              timeout, or
+       *              thread cancellation
+       *
+       * Note:
+       *
+       *      sem_timedwait is a cancellation point,
+       *      hence providing the mechanism for making
+       *      pthread_cond_wait a cancellation point.
+       *      We use the cleanup mechanism to ensure we
+       *      re-lock the mutex and adjust (to)unblock(ed) waiters
+       *      counts if we are cancelled, timed out or signalled.
+       */
+      if (sem_timedwait (&(cv->semBlockQueue), abstime) != 0)
+	{
+	  result = errno;
+	}
+    }
+
+  /*
+   * Always cleanup
+   */
+  pthread_cleanup_pop (1);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  /*
+   * "result" can be modified by the cleanup handler.
+   */
+  return result;
+
+}				/* ptw32_cond_timedwait */
+
+
+int
+pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function waits on a condition variable until
+      *      awakened by a signal or broadcast.
+      *
+      *      Caller MUST be holding the mutex lock; the
+      *      lock is released and the caller is blocked waiting
+      *      on 'cond'. When 'cond' is signaled, the mutex
+      *      is re-acquired before returning to the caller.
+      *
+      * PARAMETERS
+      *      cond
+      *              pointer to an instance of pthread_cond_t
+      *
+      *      mutex
+      *              pointer to an instance of pthread_mutex_t
+      *
+      *
+      * DESCRIPTION
+      *      This function waits on a condition variable until
+      *      awakened by a signal or broadcast.
+      *
+      *      NOTES:
+      *
+      *      1)      The function must be called with 'mutex' LOCKED
+      *              by the calling thread, or undefined behaviour
+      *              will result.
+      *
+      *      2)      This routine atomically releases 'mutex' and causes
+      *              the calling thread to block on the condition variable.
+      *              The blocked thread may be awakened by 
+      *                      pthread_cond_signal or 
+      *                      pthread_cond_broadcast.
+      *
+      * Upon successful completion, the 'mutex' has been locked and 
+      * is owned by the calling thread.
+      *
+      *
+      * RESULTS
+      *              0               caught condition; mutex released,
+      *              EINVAL          'cond' or 'mutex' is invalid,
+      *              EINVAL          different mutexes for concurrent waits,
+      *              EINVAL          mutex is not held by the calling thread,
+      *
+      * ------------------------------------------------------
+      */
+{
+  /*
+   * The NULL abstime arg means INFINITE waiting.
+   */
+  return (ptw32_cond_timedwait (cond, mutex, NULL));
+
+}				/* pthread_cond_wait */
+
+
+int
+pthread_cond_timedwait (pthread_cond_t * cond,
+			pthread_mutex_t * mutex,
+			const struct timespec *abstime)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function waits on a condition variable either until
+      *      awakened by a signal or broadcast; or until the time
+      *      specified by abstime passes.
+      *
+      * PARAMETERS
+      *      cond
+      *              pointer to an instance of pthread_cond_t
+      *
+      *      mutex
+      *              pointer to an instance of pthread_mutex_t
+      *
+      *      abstime
+      *              pointer to an instance of (const struct timespec)
+      *
+      *
+      * DESCRIPTION
+      *      This function waits on a condition variable either until
+      *      awakened by a signal or broadcast; or until the time
+      *      specified by abstime passes.
+      *
+      *      NOTES:
+      *      1)      The function must be called with 'mutex' LOCKED
+      *              by the calling thread, or undefined behaviour
+      *              will result.
+      *
+      *      2)      This routine atomically releases 'mutex' and causes
+      *              the calling thread to block on the condition variable.
+      *              The blocked thread may be awakened by 
+      *                      pthread_cond_signal or 
+      *                      pthread_cond_broadcast.
+      *
+      *
+      * RESULTS
+      *              0               caught condition; mutex released,
+      *              EINVAL          'cond', 'mutex', or abstime is invalid,
+      *              EINVAL          different mutexes for concurrent waits,
+      *              EINVAL          mutex is not held by the calling thread,
+      *              ETIMEDOUT       abstime ellapsed before cond was signaled.
+      *
+      * ------------------------------------------------------
+      */
+{
+  if (abstime == NULL)
+    {
+      return EINVAL;
+    }
+
+  return (ptw32_cond_timedwait (cond, mutex, abstime));
+
+}				/* pthread_cond_timedwait */
diff --git a/pthread_condattr_destroy.c b/pthread_condattr_destroy.c
new file mode 100644
index 0000000..58a1482
--- /dev/null
+++ b/pthread_condattr_destroy.c
@@ -0,0 +1,86 @@
+/*
+ * condvar_attr_destroy.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_destroy (pthread_condattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Destroys a condition variable attributes object.
+      *      The object can no longer be used.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_condattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Destroys a condition variable attributes object.
+      *      The object can no longer be used.
+      *
+      *      NOTES:
+      *      1)      Does not affect condition variables created
+      *              using 'attr'
+      *
+      * RESULTS
+      *              0               successfully released attr,
+      *              EINVAL          'attr' is invalid.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+
+  if (attr == NULL || *attr == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      (void) free (*attr);
+
+      *attr = NULL;
+      result = 0;
+    }
+
+  return result;
+
+}				/* pthread_condattr_destroy */
diff --git a/pthread_condattr_getpshared.c b/pthread_condattr_getpshared.c
new file mode 100644
index 0000000..a0ac6d8
--- /dev/null
+++ b/pthread_condattr_getpshared.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_condattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Determine whether condition variables created with 'attr'
+      *      can be shared between processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_condattr_t
+      *
+      *      pshared
+      *              will be set to one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      *
+      * DESCRIPTION
+      *      Condition Variables created with 'attr' can be shared
+      *      between processes if pthread_cond_t variable is allocated
+      *      in memory shared by these processes.
+      *      NOTES:
+      *      1)      pshared condition variables MUST be allocated in
+      *              shared memory.
+      *
+      *      2)      The following macro is defined if shared mutexes
+      *              are supported:
+      *                      _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully retrieved attribute,
+      *              EINVAL          'attr' or 'pshared' is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+    {
+      *pshared = (*attr)->pshared;
+      result = 0;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return result;
+
+}				/* pthread_condattr_getpshared */
diff --git a/pthread_condattr_init.c b/pthread_condattr_init.c
new file mode 100644
index 0000000..5987878
--- /dev/null
+++ b/pthread_condattr_init.c
@@ -0,0 +1,87 @@
+/*
+ * pthread_condattr_init.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_init (pthread_condattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Initializes a condition variable attributes object
+      *      with default attributes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_condattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Initializes a condition variable attributes object
+      *      with default attributes.
+      *
+      *      NOTES:
+      *              1)      Use to define condition variable types
+      *              2)      It is up to the application to ensure
+      *                      that it doesn't re-init an attribute
+      *                      without destroying it first. Otherwise
+      *                      a memory leak is created.
+      *
+      * RESULTS
+      *              0               successfully initialized attr,
+      *              ENOMEM          insufficient memory for attr.
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_condattr_t attr_result;
+  int result = 0;
+
+  attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result));
+
+  if (attr_result == NULL)
+    {
+      result = ENOMEM;
+    }
+
+  *attr = attr_result;
+
+  return result;
+
+}				/* pthread_condattr_init */
diff --git a/pthread_condattr_setpshared.c b/pthread_condattr_setpshared.c
new file mode 100644
index 0000000..954fb38
--- /dev/null
+++ b/pthread_condattr_setpshared.c
@@ -0,0 +1,117 @@
+/*
+ * pthread_condattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Mutexes created with 'attr' can be shared between
+      *      processes if pthread_mutex_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_mutexattr_t
+      *
+      *      pshared
+      *              must be one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      * DESCRIPTION
+      *      Mutexes creatd with 'attr' can be shared between
+      *      processes if pthread_mutex_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      *      NOTES:
+      *              1)      pshared mutexes MUST be allocated in shared
+      *                      memory.
+      *
+      *              2)      The following macro is defined if shared mutexes
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully set attribute,
+      *              EINVAL          'attr' or pshared is invalid,
+      *              ENOSYS          PTHREAD_PROCESS_SHARED not supported,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL)
+      && ((pshared == PTHREAD_PROCESS_SHARED)
+	  || (pshared == PTHREAD_PROCESS_PRIVATE)))
+    {
+      if (pshared == PTHREAD_PROCESS_SHARED)
+	{
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+	  result = ENOSYS;
+	  pshared = PTHREAD_PROCESS_PRIVATE;
+#else
+	  result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+	}
+      else
+	{
+	  result = 0;
+	}
+
+      (*attr)->pshared = pshared;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return result;
+
+}				/* pthread_condattr_setpshared */
diff --git a/pthread_delay_np.c b/pthread_delay_np.c
new file mode 100644
index 0000000..7fe9ae0
--- /dev/null
+++ b/pthread_delay_np.c
@@ -0,0 +1,171 @@
+/*
+ * pthreads_delay_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * pthread_delay_np
+ *
+ * DESCRIPTION
+ *
+ *       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. 
+ *
+ *       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. 
+ *
+ * Example
+ *
+ * The following code segment would wait for 5 and 1/2 seconds
+ *
+ *  struct timespec tsWait;
+ *  int      intRC;
+ *
+ *  tsWait.tv_sec  = 5;
+ *  tsWait.tv_nsec = 500000000L;
+ *  intRC = pthread_delay_np(&tsWait);
+ */
+int
+pthread_delay_np (struct timespec *interval)
+{
+  DWORD wait_time;
+  DWORD secs_in_millisecs;
+  DWORD millisecs;
+  DWORD status;
+  pthread_t self;
+  ptw32_thread_t * sp;
+
+  if (interval == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (interval->tv_sec == 0L && interval->tv_nsec == 0L)
+    {
+      pthread_testcancel ();
+      Sleep (0);
+      pthread_testcancel ();
+      return (0);
+    }
+
+  /* convert secs to millisecs */
+  secs_in_millisecs = interval->tv_sec * 1000L;
+
+  /* convert nanosecs to millisecs (rounding up) */
+  millisecs = (interval->tv_nsec + 999999L) / 1000000L;
+
+#if defined(__WATCOMC__)
+#pragma disable_message (124)
+#endif
+
+  /*
+   * Most compilers will issue a warning 'comparison always 0'
+   * because the variable type is unsigned, but we need to keep this
+   * for some reason I can't recall now.
+   */
+  if (0 > (wait_time = secs_in_millisecs + millisecs))
+    {
+      return EINVAL;
+    }
+
+#if defined(__WATCOMC__)
+#pragma enable_message (124)
+#endif
+
+  if (NULL == (self = pthread_self ()).p)
+    {
+      return ENOMEM;
+    }
+
+  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 (sp->cancelEvent, wait_time)))
+	{
+	  /*
+	   * Canceling!
+	   */
+	  (void) pthread_mutex_lock (&sp->cancelLock);
+	  if (sp->state < PThreadStateCanceling)
+	    {
+	      sp->state = PThreadStateCanceling;
+	      sp->cancelState = PTHREAD_CANCEL_DISABLE;
+	      (void) pthread_mutex_unlock (&sp->cancelLock);
+
+	      ptw32_throw (PTW32_EPS_CANCEL);
+	    }
+
+	  (void) pthread_mutex_unlock (&sp->cancelLock);
+	  return ESRCH;
+	}
+      else if (status != WAIT_TIMEOUT)
+	{
+	  return EINVAL;
+	}
+    }
+  else
+    {
+      Sleep (wait_time);
+    }
+
+  return (0);
+}
diff --git a/pthread_detach.c b/pthread_detach.c
new file mode 100644
index 0000000..1273931
--- /dev/null
+++ b/pthread_detach.c
@@ -0,0 +1,140 @@
+/*
+ * pthread_detach.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Not needed yet, but defining it should indicate clashes with build target
+ * environment that should be fixed.
+ */
+#ifndef WINCE
+#include <signal.h>
+#endif
+
+int
+pthread_detach (pthread_t thread)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function detaches the given thread.
+      *
+      * PARAMETERS
+      *      thread
+      *              an instance of a pthread_t
+      *
+      *
+      * DESCRIPTION
+      *      This function detaches the given thread. You may use it to
+      *      detach the main thread or to detach a joinable thread.
+      *      NOTE:   detached threads cannot be joined;
+      *              storage is freed immediately on termination.
+      *
+      * RESULTS
+      *              0               successfully detached the thread,
+      *              EINVAL          thread is not a joinable thread,
+      *              ENOSPC          a required resource has been exhausted,
+      *              ESRCH           no thread could be found for 'thread',
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+  BOOL destroyIt = PTW32_FALSE;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+
+  EnterCriticalSection (&ptw32_thread_reuse_lock);
+
+  if (NULL == tp
+      || thread.x != tp->ptHandle.x)
+    {
+      result = ESRCH;
+    }
+  else if (PTHREAD_CREATE_DETACHED == tp->detachState)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      /*
+       * Joinable ptw32_thread_t structs are not scavenged until
+       * a join or detach is done. The thread may have exited already,
+       * but all of the state and locks etc are still there.
+       */
+      result = 0;
+
+      if (pthread_mutex_lock (&tp->cancelLock) == 0)
+	{
+	  if (tp->state != PThreadStateLast)
+	    {
+	      tp->detachState = PTHREAD_CREATE_DETACHED;
+	    }
+	  else if (tp->detachState != PTHREAD_CREATE_DETACHED)
+	    {
+	      /*
+	       * Thread is joinable and has exited or is exiting.
+	       */
+	      destroyIt = PTW32_TRUE;
+	    }
+	  (void) pthread_mutex_unlock (&tp->cancelLock);
+	}
+      else
+	{
+	  /* cancelLock shouldn't fail, but if it does ... */
+	  result = ESRCH;
+	}
+    }
+
+  LeaveCriticalSection (&ptw32_thread_reuse_lock);
+
+  if (result == 0)
+    {
+      /* Thread is joinable */
+
+      if (destroyIt)
+	{
+	  /* The thread has exited or is exiting but has not been joined or
+	   * detached. Need to wait in case it's still exiting.
+	   */
+	  (void) WaitForSingleObject(tp->threadH, INFINITE);
+	  ptw32_threadDestroy (thread);
+	}
+    }
+
+  return (result);
+
+}				/* pthread_detach */
diff --git a/pthread_equal.c b/pthread_equal.c
new file mode 100644
index 0000000..f96372e
--- /dev/null
+++ b/pthread_equal.c
@@ -0,0 +1,76 @@
+/*
+ * pthread_equal.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_equal (pthread_t t1, pthread_t t2)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function returns nonzero if t1 and t2 are equal, else
+      *      returns nonzero
+      *
+      * PARAMETERS
+      *      t1,
+      *      t2
+      *              thread IDs
+      *
+      *
+      * DESCRIPTION
+      *      This function returns nonzero if t1 and t2 are equal, else
+      *      returns zero.
+      *
+      * RESULTS
+      *              non-zero        if t1 and t2 refer to the same thread,
+      *              0               t1 and t2 do not refer to the same thread
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  /*
+   * 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.p == t2.p && t1.x == t2.x );
+
+  return (result);
+
+}				/* pthread_equal */
diff --git a/pthread_exit.c b/pthread_exit.c
new file mode 100644
index 0000000..a490312
--- /dev/null
+++ b/pthread_exit.c
@@ -0,0 +1,106 @@
+/*
+ * pthread_exit.c
+ *
+ * Description:
+ * This translation unit implements routines associated with exiting from
+ * a thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#ifndef _UWIN
+//#   include <process.h>
+#endif
+
+void
+pthread_exit (void *value_ptr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function terminates the calling thread, returning
+      *      the value 'value_ptr' to any joining thread.
+      *
+      * PARAMETERS
+      *      value_ptr
+      *              a generic data value (i.e. not the address of a value)
+      *
+      *
+      * DESCRIPTION
+      *      This function terminates the calling thread, returning
+      *      the value 'value_ptr' to any joining thread.
+      *      NOTE: thread should be joinable.
+      *
+      * RESULTS
+      *              N/A
+      *
+      * ------------------------------------------------------
+      */
+{
+  ptw32_thread_t * sp;
+
+  /*
+   * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
+   * unnecessarily.
+   */
+  sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+#ifdef _UWIN
+  if (--pthread_count <= 0)
+    exit ((int) value_ptr);
+#endif
+
+  if (NULL == sp)
+    {
+      /*
+       * A POSIX thread handle was never created. I.e. this is a
+       * Win32 thread that has never called a pthreads-win32 routine that
+       * required a POSIX handle.
+       *
+       * Implicit POSIX handles are cleaned up in ptw32_throw() now.
+       */
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)  || defined (__DMC__)
+      _endthreadex ((unsigned) value_ptr);
+#else
+      _endthread ();
+#endif
+
+      /* Never reached */
+    }
+
+  sp->exitStatus = value_ptr;
+
+  ptw32_throw (PTW32_EPS_EXIT);
+
+  /* Never reached. */
+
+}
diff --git a/pthread_getconcurrency.c b/pthread_getconcurrency.c
new file mode 100644
index 0000000..cf9e9c8
--- /dev/null
+++ b/pthread_getconcurrency.c
@@ -0,0 +1,45 @@
+/*
+ * pthread_getconcurrency.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_getconcurrency (void)
+{
+  return ptw32_concurrency;
+}
diff --git a/pthread_getschedparam.c b/pthread_getschedparam.c
new file mode 100644
index 0000000..0afcfb7
--- /dev/null
+++ b/pthread_getschedparam.c
@@ -0,0 +1,75 @@
+/*
+ * sched_getschedparam.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_getschedparam (pthread_t thread, int *policy,
+		       struct sched_param *param)
+{
+  int result;
+
+  /* Validate the thread id. */
+  result = pthread_kill (thread, 0);
+  if (0 != result)
+    {
+      return result;
+    }
+
+  /*
+   * Validate the policy and param args.
+   * Check that a policy constant wasn't passed rather than &policy.
+   */
+  if (policy <= (int *) SCHED_MAX || param == NULL)
+    {
+      return EINVAL;
+    }
+
+  /* Fill out the policy. */
+  *policy = SCHED_OTHER;
+
+  /*
+   * This function must return the priority value set by
+   * the most recent pthread_setschedparam() or pthread_create()
+   * for the target thread. It must not return the actual thread
+   * priority as altered by any system priority adjustments etc.
+   */
+  param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority;
+
+  return 0;
+}
diff --git a/pthread_getspecific.c b/pthread_getspecific.c
new file mode 100644
index 0000000..b05ff41
--- /dev/null
+++ b/pthread_getspecific.c
@@ -0,0 +1,84 @@
+/*
+ * pthread_getspecific.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void *
+pthread_getspecific (pthread_key_t key)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function returns the current value of key in the
+      *      calling thread. If no value has been set for 'key' in 
+      *      the thread, NULL is returned.
+      *
+      * PARAMETERS
+      *      key
+      *              an instance of pthread_key_t
+      *
+      *
+      * DESCRIPTION
+      *      This function returns the current value of key in the
+      *      calling thread. If no value has been set for 'key' in 
+      *      the thread, NULL is returned.
+      *
+      * RESULTS
+      *              key value or NULL on failure
+      *
+      * ------------------------------------------------------
+      */
+{
+  void * ptr;
+
+  if (key == NULL)
+    {
+      ptr = NULL;
+    }
+  else
+    {
+      int lasterror = GetLastError ();
+      int lastWSAerror = WSAGetLastError ();
+
+      ptr = TlsGetValue (key->key);
+
+      SetLastError (lasterror);
+      WSASetLastError (lastWSAerror);
+    }
+
+  return ptr;
+}
diff --git a/pthread_getw32threadhandle_np.c b/pthread_getw32threadhandle_np.c
new file mode 100644
index 0000000..9d22def
--- /dev/null
+++ b/pthread_getw32threadhandle_np.c
@@ -0,0 +1,53 @@
+/*
+ * pthread_getw32threadhandle_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * pthread_getw32threadhandle_np()
+ *
+ * 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.
+ */
+HANDLE
+pthread_getw32threadhandle_np (pthread_t thread)
+{
+  return ((ptw32_thread_t *)thread.p)->threadH;
+}
diff --git a/pthread_join.c b/pthread_join.c
new file mode 100644
index 0000000..a6b3276
--- /dev/null
+++ b/pthread_join.c
@@ -0,0 +1,155 @@
+/*
+ * pthread_join.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Not needed yet, but defining it should indicate clashes with build target
+ * environment that should be fixed.
+ */
+#ifndef WINCE
+#include <signal.h>
+#endif
+
+int
+pthread_join (pthread_t thread, void **value_ptr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function waits for 'thread' to terminate and
+      *      returns the thread's exit value if 'value_ptr' is not
+      *      NULL. This also detaches the thread on successful
+      *      completion.
+      *
+      * PARAMETERS
+      *      thread
+      *              an instance of pthread_t
+      *
+      *      value_ptr
+      *              pointer to an instance of pointer to void
+      *
+      *
+      * DESCRIPTION
+      *      This function waits for 'thread' to terminate and
+      *      returns the thread's exit value if 'value_ptr' is not
+      *      NULL. This also detaches the thread on successful
+      *      completion.
+      *      NOTE:   detached threads cannot be joined or canceled
+      *
+      * RESULTS
+      *              0               'thread' has completed
+      *              EINVAL          thread is not a joinable thread,
+      *              ESRCH           no thread could be found with ID 'thread',
+      *              ENOENT          thread couldn't find it's own valid handle,
+      *              EDEADLK         attempt to join thread with self
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+  pthread_t self;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+
+  EnterCriticalSection (&ptw32_thread_reuse_lock);
+
+  if (NULL == tp
+      || thread.x != tp->ptHandle.x)
+    {
+      result = ESRCH;
+    }
+  else if (PTHREAD_CREATE_DETACHED == tp->detachState)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      result = 0;
+    }
+
+  LeaveCriticalSection (&ptw32_thread_reuse_lock);
+
+  if (result == 0)
+    {
+      /* 
+       * The target thread is joinable and can't be reused before we join it.
+       */
+      self = pthread_self();
+
+      if (NULL == self.p)
+	{
+	  result = ENOENT;
+	}
+      else if (pthread_equal (self, thread))
+	{
+	  result = EDEADLK;
+	}
+      else
+	{
+	  /*
+	   * Pthread_join is a cancelation point.
+	   * If we are canceled then our target thread must not be
+	   * detached (destroyed). This is guarranteed because
+	   * pthreadCancelableWait will not return if we
+	   * are canceled.
+	   */
+	  result = pthreadCancelableWait (tp->threadH);
+
+	  if (0 == result)
+	    {
+	      if (value_ptr != NULL)
+		{
+		  *value_ptr = tp->exitStatus;
+		}
+
+	      /*
+	       * The result of making multiple simultaneous calls to
+	       * pthread_join() or pthread_detach() specifying the same
+	       * target is undefined.
+	       */
+	      result = pthread_detach (thread);
+	    }
+	  else
+	    {
+	      result = ESRCH;
+	    }
+	}
+    }
+
+  return (result);
+
+}				/* pthread_join */
diff --git a/pthread_key_create.c b/pthread_key_create.c
new file mode 100644
index 0000000..5e278c2
--- /dev/null
+++ b/pthread_key_create.c
@@ -0,0 +1,108 @@
+/*
+ * pthread_key_create.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/* TLS_OUT_OF_INDEXES not defined on WinCE */
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+
+int
+pthread_key_create (pthread_key_t * key, void (*destructor) (void *))
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function creates a thread-specific data key visible
+      *      to all threads. All existing and new threads have a value
+      *      NULL for key until set using pthread_setspecific. When any
+      *      thread with a non-NULL value for key terminates, 'destructor'
+      *      is called with key's current value for that thread.
+      *
+      * PARAMETERS
+      *      key
+      *              pointer to an instance of pthread_key_t
+      *
+      *
+      * DESCRIPTION
+      *      This function creates a thread-specific data key visible
+      *      to all threads. All existing and new threads have a value
+      *      NULL for key until set using pthread_setspecific. When any
+      *      thread with a non-NULL value for key terminates, 'destructor'
+      *      is called with key's current value for that thread.
+      *
+      * RESULTS
+      *              0               successfully created semaphore,
+      *              EAGAIN          insufficient resources or PTHREAD_KEYS_MAX
+      *                              exceeded,
+      *              ENOMEM          insufficient memory to create the key,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  pthread_key_t newkey;
+
+  if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL)
+    {
+      result = ENOMEM;
+    }
+  else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
+    {
+      result = EAGAIN;
+
+      free (newkey);
+      newkey = NULL;
+    }
+  else if (destructor != NULL)
+    {
+      /*
+       * Have to manage associations between thread and key;
+       * Therefore, need a lock that allows multiple threads
+       * to gain exclusive access to the key->threads list.
+       *
+       * The mutex will only be created when it is first locked.
+       */
+      newkey->keyLock = PTHREAD_MUTEX_INITIALIZER;
+      newkey->destructor = destructor;
+    }
+
+  *key = newkey;
+
+  return (result);
+}
diff --git a/pthread_key_delete.c b/pthread_key_delete.c
new file mode 100644
index 0000000..7da9b2f
--- /dev/null
+++ b/pthread_key_delete.c
@@ -0,0 +1,133 @@
+/*
+ * pthread_key_delete.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_key_delete (pthread_key_t key)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function deletes a thread-specific data key. This
+      *      does not change the value of the thread specific data key
+      *      for any thread and does not run the key's destructor
+      *      in any thread so it should be used with caution.
+      *
+      * PARAMETERS
+      *      key
+      *              pointer to an instance of pthread_key_t
+      *
+      *
+      * DESCRIPTION
+      *      This function deletes a thread-specific data key. This
+      *      does not change the value of the thread specific data key
+      *      for any thread and does not run the key's destructor
+      *      in any thread so it should be used with caution.
+      *
+      * RESULTS
+      *              0               successfully deleted the key,
+      *              EINVAL          key is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+
+  if (key != NULL)
+    {
+      if (key->threads != NULL &&
+	  key->destructor != NULL &&
+	  pthread_mutex_lock (&(key->keyLock)) == 0)
+	{
+	  ThreadKeyAssoc *assoc;
+	  /*
+	   * Run through all Thread<-->Key associations
+	   * for this key.
+	   *
+	   * While we hold at least one of the locks guarding
+	   * the assoc, we know that the assoc pointed to by
+	   * key->threads is valid.
+	   */
+	  while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL)
+	    {
+	      ptw32_thread_t * thread = assoc->thread;
+
+	      if (assoc == NULL)
+		{
+		  /* Finished */
+		  break;
+		}
+
+	      if (pthread_mutex_lock (&(thread->threadLock)) == 0)
+		{
+		  /*
+		   * Since we are starting at the head of the key's threads
+		   * chain, this will also point key->threads at the next assoc.
+		   * While we hold key->keyLock, no other thread can insert
+		   * a new assoc via pthread_setspecific.
+		   */
+		  ptw32_tkAssocDestroy (assoc);
+		  (void) pthread_mutex_unlock (&(thread->threadLock));
+		}
+	      else
+		{
+		  /* Thread or lock is no longer valid? */
+		  ptw32_tkAssocDestroy (assoc);
+		}
+	    }
+	  pthread_mutex_unlock (&(key->keyLock));
+	}
+
+      TlsFree (key->key);
+      if (key->destructor != NULL)
+	{
+	  /* A thread could be holding the keyLock */
+	  while (EBUSY == pthread_mutex_destroy (&(key->keyLock)))
+	    {
+	      Sleep(1); // Ugly.
+	    }
+	}
+
+#if defined( _DEBUG )
+      memset ((char *) key, 0, sizeof (*key));
+#endif
+      free (key);
+    }
+
+  return (result);
+}
diff --git a/pthread_kill.c b/pthread_kill.c
new file mode 100644
index 0000000..f97f830
--- /dev/null
+++ b/pthread_kill.c
@@ -0,0 +1,104 @@
+/*
+ * pthread_kill.c
+ *
+ * Description:
+ * This translation unit implements the pthread_kill routine.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Not needed yet, but defining it should indicate clashes with build target
+ * environment that should be fixed.
+ */
+#ifndef WINCE
+#include <signal.h>
+#endif
+
+int
+pthread_kill (pthread_t thread, int sig)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function requests that a signal be delivered to the
+      *      specified thread. If sig is zero, error checking is
+      *      performed but no signal is actually sent such that this
+      *      function can be used to check for a valid thread ID.
+      *
+      * PARAMETERS
+      *      thread  reference to an instances of pthread_t
+      *      sig     signal. Currently only a value of 0 is supported.
+      *
+      *
+      * DESCRIPTION
+      *      This function requests that a signal be delivered to the
+      *      specified thread. If sig is zero, error checking is
+      *      performed but no signal is actually sent such that this
+      *      function can be used to check for a valid thread ID.
+      *
+      * RESULTS
+      *              ESRCH           the thread is not a valid thread ID,
+      *              EINVAL          the value of the signal is invalid
+      *                              or unsupported.
+      *              0               the signal was successfully sent.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  ptw32_thread_t * tp;
+
+  EnterCriticalSection (&ptw32_thread_reuse_lock);
+
+  tp = (ptw32_thread_t *) thread.p;
+
+  if (NULL == tp
+      || thread.x != tp->ptHandle.x
+      || NULL == tp->threadH)
+    {
+      result = ESRCH;
+    }
+
+  LeaveCriticalSection (&ptw32_thread_reuse_lock);
+
+  if (0 == result && 0 != sig)
+    {
+      /*
+       * Currently does not support any signals.
+       */
+      result = EINVAL;
+    }
+
+  return result;
+
+}				/* pthread_kill */
diff --git a/pthread_mutex_destroy.c b/pthread_mutex_destroy.c
new file mode 100644
index 0000000..95509b3
--- /dev/null
+++ b/pthread_mutex_destroy.c
@@ -0,0 +1,146 @@
+/*
+ * pthread_mutex_destroy.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_destroy (pthread_mutex_t * mutex)
+{
+  int result = 0;
+  pthread_mutex_t mx;
+
+  /*
+   * Let the system deal with invalid pointers.
+   */
+
+  /*
+   * Check to see if we have something to delete.
+   */
+  if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+    {
+      mx = *mutex;
+
+      result = pthread_mutex_trylock (&mx);
+
+      /*
+       * If trylock succeeded and the mutex is not recursively locked it
+       * can be destroyed.
+       */
+      if (result == 0)
+	{
+	  if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count)
+	    {
+	      /*
+	       * FIXME!!!
+	       * The mutex isn't held by another thread but we could still
+	       * be too late invalidating the mutex below since another thread
+	       * may already have entered mutex_lock and the check for a valid
+	       * *mutex != NULL.
+	       *
+	       * Note that this would be an unusual situation because it is not
+	       * common that mutexes are destroyed while they are still in
+	       * use by other threads.
+	       */
+	      *mutex = NULL;
+
+	      result = pthread_mutex_unlock (&mx);
+
+	      if (result == 0)
+		{
+		  if (!CloseHandle (mx->event))
+		    {
+		      *mutex = mx;
+		      result = EINVAL;
+		    }
+		  else
+		    {
+		      free (mx);
+		    }
+		}
+	      else
+		{
+		  /*
+		   * Restore the mutex before we return the error.
+		   */
+		  *mutex = mx;
+		}
+	    }
+	  else			/* mx->recursive_count > 1 */
+	    {
+	      /*
+	       * The mutex must be recursive and already locked by us (this thread).
+	       */
+	      mx->recursive_count--;	/* Undo effect of pthread_mutex_trylock() above */
+	      result = EBUSY;
+	    }
+	}
+    }
+  else
+    {
+      /*
+       * See notes in ptw32_mutex_check_need_init() above also.
+       */
+      EnterCriticalSection (&ptw32_mutex_test_init_lock);
+
+      /*
+       * Check again.
+       */
+      if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+	{
+	  /*
+	   * This is all we need to do to destroy a statically
+	   * initialised mutex that has not yet been used (initialised).
+	   * If we get to here, another thread
+	   * waiting to initialise this mutex will get an EINVAL.
+	   */
+	  *mutex = NULL;
+	}
+      else
+	{
+	  /*
+	   * The mutex has been initialised while we were waiting
+	   * so assume it's in use.
+	   */
+	  result = EBUSY;
+	}
+
+      LeaveCriticalSection (&ptw32_mutex_test_init_lock);
+    }
+
+  return (result);
+}
diff --git a/pthread_mutex_init.c b/pthread_mutex_init.c
new file mode 100644
index 0000000..cff8e50
--- /dev/null
+++ b/pthread_mutex_init.c
@@ -0,0 +1,104 @@
+/*
+ * pthread_mutex_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
+{
+  int result = 0;
+  pthread_mutex_t mx;
+
+  if (mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (attr != NULL
+      && *attr != NULL && (*attr)->pshared == PTHREAD_PROCESS_SHARED)
+    {
+      /*
+       * Creating mutex that can be shared between
+       * processes.
+       */
+#if _POSIX_THREAD_PROCESS_SHARED >= 0
+
+      /*
+       * Not implemented yet.
+       */
+
+#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet.
+
+#else
+
+      return ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+    }
+
+  mx = (pthread_mutex_t) calloc (1, sizeof (*mx));
+
+  if (mx == NULL)
+    {
+      result = ENOMEM;
+    }
+  else
+    {
+      mx->lock_idx = 0;
+      mx->recursive_count = 0;
+      mx->kind = (attr == NULL || *attr == NULL
+		  ? PTHREAD_MUTEX_DEFAULT : (*attr)->kind);
+      mx->ownerThread.p = NULL;
+
+      mx->event = CreateEvent (NULL, PTW32_FALSE,    /* manual reset = No */
+                              PTW32_FALSE,           /* initial state = not signaled */
+                              NULL);                 /* event name */
+
+      if (0 == mx->event)
+        {
+          result = ENOSPC;
+          free (mx);
+          mx = NULL;
+        }
+    }
+
+  *mutex = mx;
+
+  return (result);
+}
diff --git a/pthread_mutex_lock.c b/pthread_mutex_lock.c
new file mode 100644
index 0000000..4ca5c25
--- /dev/null
+++ b/pthread_mutex_lock.c
@@ -0,0 +1,139 @@
+/*
+ * pthread_mutex_lock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef _UWIN
+//#   include <process.h>
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutex_lock (pthread_mutex_t * mutex)
+{
+  int result = 0;
+  pthread_mutex_t mx;
+
+  /*
+   * Let the system deal with invalid pointers.
+   */
+  if (*mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static mutex. We check
+   * again inside the guarded section of ptw32_mutex_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+    {
+      if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+	{
+	  return (result);
+	}
+    }
+
+  mx = *mutex;
+
+  if (mx->kind == PTHREAD_MUTEX_NORMAL)
+    {
+      if ((LONG) PTW32_INTERLOCKED_EXCHANGE(
+		   (LPLONG) &mx->lock_idx,
+		   (LONG) 1) != 0)
+	{
+	  while ((LONG) PTW32_INTERLOCKED_EXCHANGE(
+                          (LPLONG) &mx->lock_idx,
+			  (LONG) -1) != 0)
+	    {
+	      if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
+	        {
+	          result = EINVAL;
+		  break;
+	        }
+	    }
+	}
+    }
+  else
+    {
+      pthread_t self = pthread_self();
+
+      if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE(
+                   (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx,
+		   (PTW32_INTERLOCKED_LONG) 1,
+		   (PTW32_INTERLOCKED_LONG) 0) == 0)
+	{
+	  mx->recursive_count = 1;
+	  mx->ownerThread = self;
+	}
+      else
+	{
+	  if (pthread_equal (mx->ownerThread, self))
+	    {
+	      if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
+		{
+		  mx->recursive_count++;
+		}
+	      else
+		{
+		  result = EDEADLK;
+		}
+	    }
+	  else
+	    {
+	      while ((LONG) PTW32_INTERLOCKED_EXCHANGE(
+                              (LPLONG) &mx->lock_idx,
+			      (LONG) -1) != 0)
+		{
+	          if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
+		    {
+	              result = EINVAL;
+		      break;
+		    }
+		}
+
+	      if (0 == result)
+		{
+		  mx->recursive_count = 1;
+		  mx->ownerThread = self;
+		}
+	    }
+	}
+    }
+
+  return (result);
+}
diff --git a/pthread_mutex_timedlock.c b/pthread_mutex_timedlock.c
new file mode 100644
index 0000000..a238552
--- /dev/null
+++ b/pthread_mutex_timedlock.c
@@ -0,0 +1,196 @@
+/*
+ * pthread_mutex_timedlock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+static INLINE int
+ptw32_timed_eventwait (HANDLE event, const struct timespec *abstime)
+     /*
+      * ------------------------------------------------------
+      * DESCRIPTION
+      *      This function waits on an event until signaled or until
+      *      abstime passes.
+      *      If abstime has passed when this routine is called then
+      *      it returns a result to indicate this.
+      *
+      *      If 'abstime' is a NULL pointer then this function will
+      *      block until it can successfully decrease the value or
+      *      until interrupted by a signal.
+      *
+      *      This routine is not a cancelation point.
+      *
+      * RESULTS
+      *              0               successfully signaled,
+      *              ETIMEDOUT       abstime passed
+      *              EINVAL          'event' is not a valid event,
+      *
+      * ------------------------------------------------------
+      */
+{
+
+  DWORD milliseconds;
+  DWORD status;
+
+  if (event == NULL)
+    {
+      return EINVAL;
+    }
+  else
+    {
+      if (abstime == NULL)
+	{
+	  milliseconds = INFINITE;
+	}
+      else
+	{
+	  /* 
+	   * Calculate timeout as milliseconds from current system time. 
+	   */
+	  milliseconds = ptw32_relmillisecs (abstime);
+	}
+
+      status = WaitForSingleObject (event, milliseconds);
+
+      if (status == WAIT_OBJECT_0)
+	{
+	  return 0;
+	}
+      else if (status == WAIT_TIMEOUT)
+	{
+	  return ETIMEDOUT;
+	}
+      else
+	{
+	  return EINVAL;
+	}
+    }
+
+  return 0;
+
+}				/* ptw32_timed_semwait */
+
+
+int
+pthread_mutex_timedlock (pthread_mutex_t * mutex,
+			 const struct timespec *abstime)
+{
+  int result;
+  pthread_mutex_t mx;
+
+  /*
+   * Let the system deal with invalid pointers.
+   */
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static mutex. We check
+   * again inside the guarded section of ptw32_mutex_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+    {
+      if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+	{
+	  return (result);
+	}
+    }
+
+  mx = *mutex;
+
+  if (mx->kind == PTHREAD_MUTEX_NORMAL)
+    {
+      if ((LONG) PTW32_INTERLOCKED_EXCHANGE(
+		   (LPLONG) &mx->lock_idx,
+		   (LONG) 1) != 0)
+	{
+          while ((LONG) PTW32_INTERLOCKED_EXCHANGE(
+                          (LPLONG) &mx->lock_idx,
+			  (LONG) -1) != 0)
+            {
+	      if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
+		{
+		  return result;
+		}
+	    }
+	}
+    }
+  else
+    {
+      pthread_t self = pthread_self();
+
+      if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE(
+                   (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx,
+		   (PTW32_INTERLOCKED_LONG) 1,
+		   (PTW32_INTERLOCKED_LONG) 0) == 0)
+	{
+	  mx->recursive_count = 1;
+	  mx->ownerThread = self;
+	}
+      else
+	{
+	  if (pthread_equal (mx->ownerThread, self))
+	    {
+	      if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
+		{
+		  mx->recursive_count++;
+		}
+	      else
+		{
+		  return EDEADLK;
+		}
+	    }
+	  else
+	    {
+              while ((LONG) PTW32_INTERLOCKED_EXCHANGE(
+                              (LPLONG) &mx->lock_idx,
+			      (LONG) -1) != 0)
+                {
+		  if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
+		    {
+		      return result;
+		    }
+		}
+
+	      mx->recursive_count = 1;
+	      mx->ownerThread = self;
+	    }
+	}
+    }
+
+  return 0;
+}
diff --git a/pthread_mutex_trylock.c b/pthread_mutex_trylock.c
new file mode 100644
index 0000000..50e8bc6
--- /dev/null
+++ b/pthread_mutex_trylock.c
@@ -0,0 +1,92 @@
+/*
+ * pthread_mutex_trylock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_trylock (pthread_mutex_t * mutex)
+{
+  int result = 0;
+  pthread_mutex_t mx;
+
+  /*
+   * Let the system deal with invalid pointers.
+   */
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static mutex. We check
+   * again inside the guarded section of ptw32_mutex_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+    {
+      if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+	{
+	  return (result);
+	}
+    }
+
+  mx = *mutex;
+
+  if (0 == (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE (
+		     (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx,
+		     (PTW32_INTERLOCKED_LONG) 1,
+		     (PTW32_INTERLOCKED_LONG) 0))
+    {
+      if (mx->kind != PTHREAD_MUTEX_NORMAL)
+	{
+	  mx->recursive_count = 1;
+	  mx->ownerThread = pthread_self ();
+	}
+    }
+  else
+    {
+      if (mx->kind == PTHREAD_MUTEX_RECURSIVE &&
+	  pthread_equal (mx->ownerThread, pthread_self ()))
+	{
+	  mx->recursive_count++;
+	}
+      else
+	{
+	  result = EBUSY;
+	}
+    }
+
+  return (result);
+}
diff --git a/pthread_mutex_unlock.c b/pthread_mutex_unlock.c
new file mode 100644
index 0000000..9ebe4e3
--- /dev/null
+++ b/pthread_mutex_unlock.c
@@ -0,0 +1,119 @@
+/*
+ * pthread_mutex_unlock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_unlock (pthread_mutex_t * mutex)
+{
+  int result = 0;
+  pthread_mutex_t mx;
+
+  /*
+   * Let the system deal with invalid pointers.
+   */
+
+  mx = *mutex;
+
+  /*
+   * If the thread calling us holds the mutex then there is no
+   * race condition. If another thread holds the
+   * lock then we shouldn't be in here.
+   */
+  if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+    {
+      if (mx->kind == PTHREAD_MUTEX_NORMAL)
+	{
+	  LONG idx;
+
+	  idx = (LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx,
+						   (LONG) 0);
+	  if (idx != 0)
+	    {
+	      if (idx < 0)
+		{
+		  /*
+		   * Someone may be waiting on that mutex.
+		   */
+		  if (SetEvent (mx->event) == 0)
+		    {
+		      result = EINVAL;
+		    }
+		}
+	    }
+	  else
+	    {
+	      /*
+	       * Was not locked (so can't be owned by us).
+	       */
+	      result = EPERM;
+	    }
+	}
+      else
+	{
+	  if (pthread_equal (mx->ownerThread, pthread_self ()))
+	    {
+	      if (mx->kind != PTHREAD_MUTEX_RECURSIVE
+		  || 0 == --mx->recursive_count)
+		{
+		  mx->ownerThread.p = NULL;
+
+		  if ((LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx,
+							 (LONG) 0) < 0)
+		    {
+		      /* Someone may be waiting on that mutex */
+		      if (SetEvent (mx->event) == 0)
+			{
+			  result = EINVAL;
+			}
+		    }
+		}
+	    }
+	  else
+	    {
+	      result = EPERM;
+	    }
+	}
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+}
diff --git a/pthread_mutexattr_destroy.c b/pthread_mutexattr_destroy.c
new file mode 100644
index 0000000..9d424bf
--- /dev/null
+++ b/pthread_mutexattr_destroy.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_mutexattr_destroy.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Destroys a mutex attributes object. The object can
+      *      no longer be used.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_mutexattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Destroys a mutex attributes object. The object can
+      *      no longer be used.
+      *
+      *      NOTES:
+      *              1)      Does not affect mutexes created using 'attr'
+      *
+      * RESULTS
+      *              0               successfully released attr,
+      *              EINVAL          'attr' is invalid.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+
+  if (attr == NULL || *attr == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      pthread_mutexattr_t ma = *attr;
+
+      *attr = NULL;
+      free (ma);
+    }
+
+  return (result);
+}				/* pthread_mutexattr_destroy */
diff --git a/pthread_mutexattr_getkind_np.c b/pthread_mutexattr_getkind_np.c
new file mode 100644
index 0000000..2d82ec6
--- /dev/null
+++ b/pthread_mutexattr_getkind_np.c
@@ -0,0 +1,44 @@
+/*
+ * pthread_mutexattr_getkind_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutexattr_getkind_np (pthread_mutexattr_t * attr, int *kind)
+{
+  return pthread_mutexattr_gettype (attr, kind);
+}
diff --git a/pthread_mutexattr_getpshared.c b/pthread_mutexattr_getpshared.c
new file mode 100644
index 0000000..42f9589
--- /dev/null
+++ b/pthread_mutexattr_getpshared.c
@@ -0,0 +1,95 @@
+/*
+ * pthread_mutexattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Determine whether mutexes created with 'attr' can be
+      *      shared between processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_mutexattr_t
+      *
+      *      pshared
+      *              will be set to one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      *
+      * DESCRIPTION
+      *      Mutexes creatd with 'attr' can be shared between
+      *      processes if pthread_mutex_t variable is allocated
+      *      in memory shared by these processes.
+      *      NOTES:
+      *              1)      pshared mutexes MUST be allocated in shared
+      *                      memory.
+      *              2)      The following macro is defined if shared mutexes
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully retrieved attribute,
+      *              EINVAL          'attr' is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+    {
+      *pshared = (*attr)->pshared;
+      result = 0;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+
+}				/* pthread_mutexattr_getpshared */
diff --git a/pthread_mutexattr_gettype.c b/pthread_mutexattr_gettype.c
new file mode 100644
index 0000000..b60ca30
--- /dev/null
+++ b/pthread_mutexattr_gettype.c
@@ -0,0 +1,56 @@
+/*
+ * pthread_mutexattr_gettype.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind)
+{
+  int result = 0;
+
+  if (attr != NULL && *attr != NULL && kind != NULL)
+    {
+      *kind = (*attr)->kind;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+}
diff --git a/pthread_mutexattr_init.c b/pthread_mutexattr_init.c
new file mode 100644
index 0000000..d2797ff
--- /dev/null
+++ b/pthread_mutexattr_init.c
@@ -0,0 +1,86 @@
+/*
+ * pthread_mutexattr_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_init (pthread_mutexattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Initializes a mutex attributes object with default
+      *      attributes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_mutexattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Initializes a mutex attributes object with default
+      *      attributes.
+      *
+      *      NOTES:
+      *              1)      Used to define mutex types
+      *
+      * RESULTS
+      *              0               successfully initialized attr,
+      *              ENOMEM          insufficient memory for attr.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  pthread_mutexattr_t ma;
+
+  ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
+
+  if (ma == NULL)
+    {
+      result = ENOMEM;
+    }
+  else
+    {
+      ma->pshared = PTHREAD_PROCESS_PRIVATE;
+      ma->kind = PTHREAD_MUTEX_DEFAULT;
+    }
+
+  *attr = ma;
+
+  return (result);
+}				/* pthread_mutexattr_init */
diff --git a/pthread_mutexattr_setkind_np.c b/pthread_mutexattr_setkind_np.c
new file mode 100644
index 0000000..faa9366
--- /dev/null
+++ b/pthread_mutexattr_setkind_np.c
@@ -0,0 +1,44 @@
+/*
+ * pthread_mutexattr_setkind_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutexattr_setkind_np (pthread_mutexattr_t * attr, int kind)
+{
+  return pthread_mutexattr_settype (attr, kind);
+}
diff --git a/pthread_mutexattr_setpshared.c b/pthread_mutexattr_setpshared.c
new file mode 100644
index 0000000..cfa6f71
--- /dev/null
+++ b/pthread_mutexattr_setpshared.c
@@ -0,0 +1,119 @@
+/*
+ * pthread_mutexattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Mutexes created with 'attr' can be shared between
+      *      processes if pthread_mutex_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_mutexattr_t
+      *
+      *      pshared
+      *              must be one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      * DESCRIPTION
+      *      Mutexes creatd with 'attr' can be shared between
+      *      processes if pthread_mutex_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      *      NOTES:
+      *              1)      pshared mutexes MUST be allocated in shared
+      *                      memory.
+      *
+      *              2)      The following macro is defined if shared mutexes
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully set attribute,
+      *              EINVAL          'attr' or pshared is invalid,
+      *              ENOSYS          PTHREAD_PROCESS_SHARED not supported,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) &&
+      ((pshared == PTHREAD_PROCESS_SHARED) ||
+       (pshared == PTHREAD_PROCESS_PRIVATE)))
+    {
+      if (pshared == PTHREAD_PROCESS_SHARED)
+	{
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+	  result = ENOSYS;
+	  pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+	  result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+	}
+      else
+	{
+	  result = 0;
+	}
+
+      (*attr)->pshared = pshared;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+
+}				/* pthread_mutexattr_setpshared */
diff --git a/pthread_mutexattr_settype.c b/pthread_mutexattr_settype.c
new file mode 100644
index 0000000..8365daf
--- /dev/null
+++ b/pthread_mutexattr_settype.c
@@ -0,0 +1,143 @@
+/*
+ * pthread_mutexattr_settype.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind)
+     /*
+      * ------------------------------------------------------
+      *
+      * DOCPUBLIC
+      * The pthread_mutexattr_settype() and
+      * pthread_mutexattr_gettype() functions  respectively set and
+      * get the mutex type  attribute. This attribute is set in  the
+      * type parameter to these functions.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_mutexattr_t
+      *
+      *      type
+      *              must be one of:
+      *
+      *                      PTHREAD_MUTEX_DEFAULT
+      *
+      *                      PTHREAD_MUTEX_NORMAL
+      *
+      *                      PTHREAD_MUTEX_ERRORCHECK
+      *
+      *                      PTHREAD_MUTEX_RECURSIVE
+      *
+      * DESCRIPTION
+      * The pthread_mutexattr_settype() and
+      * pthread_mutexattr_gettype() functions  respectively set and
+      * get the mutex type  attribute. This attribute is set in  the
+      * type  parameter to these functions. The default value of the
+      * type  attribute is  PTHREAD_MUTEX_DEFAULT.
+      * 
+      * The type of mutex is contained in the type  attribute of the
+      * mutex attributes. Valid mutex types include:
+      *
+      * PTHREAD_MUTEX_NORMAL
+      *          This type of mutex does  not  detect  deadlock.  A
+      *          thread  attempting  to  relock  this mutex without
+      *          first unlocking it will  deadlock.  Attempting  to
+      *          unlock  a  mutex  locked  by  a  different  thread
+      *          results  in  undefined  behavior.  Attempting   to
+      *          unlock  an  unlocked  mutex  results  in undefined
+      *          behavior.
+      * 
+      * PTHREAD_MUTEX_ERRORCHECK
+      *          This type of  mutex  provides  error  checking.  A
+      *          thread  attempting  to  relock  this mutex without
+      *          first unlocking it will return with  an  error.  A
+      *          thread  attempting to unlock a mutex which another
+      *          thread has locked will return  with  an  error.  A
+      *          thread attempting to unlock an unlocked mutex will
+      *          return with an error.
+      *
+      * PTHREAD_MUTEX_DEFAULT
+      *          Same as PTHREAD_MUTEX_NORMAL.
+      * 
+      * PTHREAD_MUTEX_RECURSIVE
+      *          A thread attempting to relock this  mutex  without
+      *          first  unlocking  it  will  succeed in locking the
+      *          mutex. The relocking deadlock which can occur with
+      *          mutexes of type  PTHREAD_MUTEX_NORMAL cannot occur
+      *          with this type of mutex. Multiple  locks  of  this
+      *          mutex  require  the  same  number  of  unlocks  to
+      *          release  the  mutex  before  another  thread   can
+      *          acquire the mutex. A thread attempting to unlock a
+      *          mutex which another thread has locked will  return
+      *          with  an  error. A thread attempting to  unlock an
+      *          unlocked mutex will return  with  an  error.  This
+      *          type  of mutex is only supported for mutexes whose
+      *          process        shared         attribute         is
+      *          PTHREAD_PROCESS_PRIVATE.
+      *
+      * RESULTS
+      *              0               successfully set attribute,
+      *              EINVAL          'attr' or 'type' is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+
+  if ((attr != NULL && *attr != NULL))
+    {
+      switch (kind)
+	{
+	case PTHREAD_MUTEX_FAST_NP:
+	case PTHREAD_MUTEX_RECURSIVE_NP:
+	case PTHREAD_MUTEX_ERRORCHECK_NP:
+	  (*attr)->kind = kind;
+	  break;
+	default:
+	  result = EINVAL;
+	  break;
+	}
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+}				/* pthread_mutexattr_settype */
diff --git a/pthread_num_processors_np.c b/pthread_num_processors_np.c
new file mode 100644
index 0000000..3067d11
--- /dev/null
+++ b/pthread_num_processors_np.c
@@ -0,0 +1,56 @@
+/*
+ * pthread_num_processors_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * pthread_num_processors_np()
+ *
+ * Get the number of CPUs available to the process.
+ */
+int
+pthread_num_processors_np (void)
+{
+  int count;
+
+  if (ptw32_getprocessors (&count) != 0)
+    {
+      count = 1;
+    }
+
+  return (count);
+}
diff --git a/pthread_once.c b/pthread_once.c
new file mode 100644
index 0000000..96d45f2
--- /dev/null
+++ b/pthread_once.c
@@ -0,0 +1,86 @@
+/*
+ * pthread_once.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+static void PTW32_CDECL
+ptw32_once_on_init_cancel (void * arg)
+{
+  /* when the initting thread is cancelled we have to release the lock */
+  ptw32_mcs_local_node_t *node = (ptw32_mcs_local_node_t *)arg;
+  ptw32_mcs_lock_release(node);
+}
+
+int
+pthread_once (pthread_once_t * once_control, void (*init_routine) (void))
+{
+  if (once_control == NULL || init_routine == NULL)
+    {
+      return EINVAL;
+    }
+  
+  if (!InterlockedExchangeAdd((LPLONG)&once_control->done, 0)) /* MBR fence */
+    {
+      ptw32_mcs_local_node_t node;
+
+      ptw32_mcs_lock_acquire((ptw32_mcs_lock_t *)&once_control->lock, &node);
+
+      if (!once_control->done)
+	{
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+
+	  pthread_cleanup_push(ptw32_once_on_init_cancel, (void *)&node);
+	  (*init_routine)();
+	  pthread_cleanup_pop(0);
+
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+	  once_control->done = PTW32_TRUE;
+	}
+
+	ptw32_mcs_lock_release(&node);
+    }
+
+  return 0;
+
+}				/* pthread_once */
diff --git a/pthread_rwlock_destroy.c b/pthread_rwlock_destroy.c
new file mode 100644
index 0000000..c691d6b
--- /dev/null
+++ b/pthread_rwlock_destroy.c
@@ -0,0 +1,145 @@
+/*
+ * pthread_rwlock_destroy.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_destroy (pthread_rwlock_t * rwlock)
+{
+  pthread_rwlock_t rwl;
+  int result = 0, result1 = 0, result2 = 0;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*rwlock != PTHREAD_RWLOCK_INITIALIZER)
+    {
+      rwl = *rwlock;
+
+      if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+	{
+	  return EINVAL;
+	}
+
+      if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
+	{
+	  return result;
+	}
+
+      if ((result =
+	   pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+
+      /*
+       * Check whether any threads own/wait for the lock (wait for ex.access);
+       * report "BUSY" if so.
+       */
+      if (rwl->nExclusiveAccessCount > 0
+	  || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount)
+	{
+	  result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+	  result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  result2 = EBUSY;
+	}
+      else
+	{
+	  rwl->nMagic = 0;
+
+	  if ((result =
+	       pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	    {
+	      pthread_mutex_unlock (&rwl->mtxExclusiveAccess);
+	      return result;
+	    }
+
+	  if ((result =
+	       pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0)
+	    {
+	      return result;
+	    }
+
+	  *rwlock = NULL;	/* Invalidate rwlock before anything else */
+	  result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted));
+	  result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
+	  result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
+	  (void) free (rwl);
+	}
+    }
+  else
+    {
+      /*
+       * See notes in ptw32_rwlock_check_need_init() above also.
+       */
+      EnterCriticalSection (&ptw32_rwlock_test_init_lock);
+
+      /*
+       * Check again.
+       */
+      if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+	{
+	  /*
+	   * This is all we need to do to destroy a statically
+	   * initialised rwlock that has not yet been used (initialised).
+	   * If we get to here, another thread
+	   * waiting to initialise this rwlock will get an EINVAL.
+	   */
+	  *rwlock = NULL;
+	}
+      else
+	{
+	  /*
+	   * The rwlock has been initialised while we were waiting
+	   * so assume it's in use.
+	   */
+	  result = EBUSY;
+	}
+
+      LeaveCriticalSection (&ptw32_rwlock_test_init_lock);
+    }
+
+  return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
+}
diff --git a/pthread_rwlock_init.c b/pthread_rwlock_init.c
new file mode 100644
index 0000000..8015f9b
--- /dev/null
+++ b/pthread_rwlock_init.c
@@ -0,0 +1,112 @@
+/*
+ * pthread_rwlock_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_init (pthread_rwlock_t * rwlock,
+		     const pthread_rwlockattr_t * attr)
+{
+  int result;
+  pthread_rwlock_t rwl = 0;
+
+  if (rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (attr != NULL && *attr != NULL)
+    {
+      result = EINVAL;		/* Not supported */
+      goto DONE;
+    }
+
+  rwl = (pthread_rwlock_t) calloc (1, sizeof (*rwl));
+
+  if (rwl == NULL)
+    {
+      result = ENOMEM;
+      goto DONE;
+    }
+
+  rwl->nSharedAccessCount = 0;
+  rwl->nExclusiveAccessCount = 0;
+  rwl->nCompletedSharedAccessCount = 0;
+
+  result = pthread_mutex_init (&rwl->mtxExclusiveAccess, NULL);
+  if (result != 0)
+    {
+      goto FAIL0;
+    }
+
+  result = pthread_mutex_init (&rwl->mtxSharedAccessCompleted, NULL);
+  if (result != 0)
+    {
+      goto FAIL1;
+    }
+
+  result = pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL);
+  if (result != 0)
+    {
+      goto FAIL2;
+    }
+
+  rwl->nMagic = PTW32_RWLOCK_MAGIC;
+
+  result = 0;
+  goto DONE;
+
+FAIL2:
+  (void) pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
+
+FAIL1:
+  (void) pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
+
+FAIL0:
+  (void) free (rwl);
+  rwl = NULL;
+
+DONE:
+  *rwlock = rwl;
+
+  return result;
+}
diff --git a/pthread_rwlock_rdlock.c b/pthread_rwlock_rdlock.c
new file mode 100644
index 0000000..71f2a6e
--- /dev/null
+++ b/pthread_rwlock_rdlock.c
@@ -0,0 +1,105 @@
+/*
+ * pthread_rwlock_rdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_rdlock (pthread_rwlock_t * rwlock)
+{
+  int result;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static rwlock. We check
+   * again inside the guarded section of ptw32_rwlock_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = ptw32_rwlock_check_need_init (rwlock);
+
+      if (result != 0 && result != EBUSY)
+	{
+	  return result;
+	}
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
+    {
+      return result;
+    }
+
+  if (++rwl->nSharedAccessCount == INT_MAX)
+    {
+      if ((result =
+	   pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+
+      rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+      rwl->nCompletedSharedAccessCount = 0;
+
+      if ((result =
+	   pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+    }
+
+  return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
+}
diff --git a/pthread_rwlock_timedrdlock.c b/pthread_rwlock_timedrdlock.c
new file mode 100644
index 0000000..fbd7be1
--- /dev/null
+++ b/pthread_rwlock_timedrdlock.c
@@ -0,0 +1,112 @@
+/*
+ * pthread_rwlock_timedrdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock,
+			    const struct timespec *abstime)
+{
+  int result;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static rwlock. We check
+   * again inside the guarded section of ptw32_rwlock_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = ptw32_rwlock_check_need_init (rwlock);
+
+      if (result != 0 && result != EBUSY)
+	{
+	  return result;
+	}
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if ((result =
+       pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
+    {
+      return result;
+    }
+
+  if (++rwl->nSharedAccessCount == INT_MAX)
+    {
+      if ((result =
+	   pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
+				    abstime)) != 0)
+	{
+	  if (result == ETIMEDOUT)
+	    {
+	      ++rwl->nCompletedSharedAccessCount;
+	    }
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+
+      rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+      rwl->nCompletedSharedAccessCount = 0;
+
+      if ((result =
+	   pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+    }
+
+  return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
+}
diff --git a/pthread_rwlock_timedwrlock.c b/pthread_rwlock_timedwrlock.c
new file mode 100644
index 0000000..8c74109
--- /dev/null
+++ b/pthread_rwlock_timedwrlock.c
@@ -0,0 +1,142 @@
+/*
+ * pthread_rwlock_timedwrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,
+			    const struct timespec *abstime)
+{
+  int result;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static rwlock. We check
+   * again inside the guarded section of ptw32_rwlock_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = ptw32_rwlock_check_need_init (rwlock);
+
+      if (result != 0 && result != EBUSY)
+	{
+	  return result;
+	}
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if ((result =
+       pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
+    {
+      return result;
+    }
+
+  if ((result =
+       pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
+				abstime)) != 0)
+    {
+      (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+      return result;
+    }
+
+  if (rwl->nExclusiveAccessCount == 0)
+    {
+      if (rwl->nCompletedSharedAccessCount > 0)
+	{
+	  rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+	  rwl->nCompletedSharedAccessCount = 0;
+	}
+
+      if (rwl->nSharedAccessCount > 0)
+	{
+	  rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
+
+	  /*
+	   * This routine may be a cancelation point
+	   * according to POSIX 1003.1j section 18.1.2.
+	   */
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+	  pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
+
+	  do
+	    {
+	      result =
+		pthread_cond_timedwait (&(rwl->cndSharedAccessCompleted),
+					&(rwl->mtxSharedAccessCompleted),
+					abstime);
+	    }
+	  while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
+
+	  pthread_cleanup_pop ((result != 0) ? 1 : 0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+	  if (result == 0)
+	    {
+	      rwl->nSharedAccessCount = 0;
+	    }
+	}
+    }
+
+  if (result == 0)
+    {
+      rwl->nExclusiveAccessCount++;
+    }
+
+  return result;
+}
diff --git a/pthread_rwlock_tryrdlock.c b/pthread_rwlock_tryrdlock.c
new file mode 100644
index 0000000..7178b34
--- /dev/null
+++ b/pthread_rwlock_tryrdlock.c
@@ -0,0 +1,105 @@
+/*
+ * pthread_rwlock_tryrdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_tryrdlock (pthread_rwlock_t * rwlock)
+{
+  int result;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static rwlock. We check
+   * again inside the guarded section of ptw32_rwlock_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = ptw32_rwlock_check_need_init (rwlock);
+
+      if (result != 0 && result != EBUSY)
+	{
+	  return result;
+	}
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
+    {
+      return result;
+    }
+
+  if (++rwl->nSharedAccessCount == INT_MAX)
+    {
+      if ((result =
+	   pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+
+      rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+      rwl->nCompletedSharedAccessCount = 0;
+
+      if ((result =
+	   pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	  return result;
+	}
+    }
+
+  return (pthread_mutex_unlock (&rwl->mtxExclusiveAccess));
+}
diff --git a/pthread_rwlock_trywrlock.c b/pthread_rwlock_trywrlock.c
new file mode 100644
index 0000000..c9f1343
--- /dev/null
+++ b/pthread_rwlock_trywrlock.c
@@ -0,0 +1,125 @@
+/*
+ * pthread_rwlock_trywrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_trywrlock (pthread_rwlock_t * rwlock)
+{
+  int result, result1;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static rwlock. We check
+   * again inside the guarded section of ptw32_rwlock_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = ptw32_rwlock_check_need_init (rwlock);
+
+      if (result != 0 && result != EBUSY)
+	{
+	  return result;
+	}
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
+    {
+      return result;
+    }
+
+  if ((result =
+       pthread_mutex_trylock (&(rwl->mtxSharedAccessCompleted))) != 0)
+    {
+      result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+      return ((result1 != 0) ? result1 : result);
+    }
+
+  if (rwl->nExclusiveAccessCount == 0)
+    {
+      if (rwl->nCompletedSharedAccessCount > 0)
+	{
+	  rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+	  rwl->nCompletedSharedAccessCount = 0;
+	}
+
+      if (rwl->nSharedAccessCount > 0)
+	{
+	  if ((result =
+	       pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	    {
+	      (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+	      return result;
+	    }
+
+	  if ((result =
+	       pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) == 0)
+	    {
+	      result = EBUSY;
+	    }
+	}
+      else
+	{
+	  rwl->nExclusiveAccessCount = 1;
+	}
+    }
+  else
+    {
+      result = EBUSY;
+    }
+
+  return result;
+}
diff --git a/pthread_rwlock_unlock.c b/pthread_rwlock_unlock.c
new file mode 100644
index 0000000..9f5ae6b
--- /dev/null
+++ b/pthread_rwlock_unlock.c
@@ -0,0 +1,95 @@
+/*
+ * pthread_rwlock_unlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_unlock (pthread_rwlock_t * rwlock)
+{
+  int result, result1;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return (EINVAL);
+    }
+
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      /*
+       * Assume any race condition here is harmless.
+       */
+      return 0;
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if (rwl->nExclusiveAccessCount == 0)
+    {
+      if ((result =
+	   pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+	{
+	  return result;
+	}
+
+      if (++rwl->nCompletedSharedAccessCount == 0)
+	{
+	  result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted));
+	}
+
+      result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+    }
+  else
+    {
+      rwl->nExclusiveAccessCount--;
+
+      result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+      result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+
+    }
+
+  return ((result != 0) ? result : result1);
+}
diff --git a/pthread_rwlock_wrlock.c b/pthread_rwlock_wrlock.c
new file mode 100644
index 0000000..58931bf
--- /dev/null
+++ b/pthread_rwlock_wrlock.c
@@ -0,0 +1,136 @@
+/*
+ * pthread_rwlock_wrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)
+{
+  int result;
+  pthread_rwlock_t rwl;
+
+  if (rwlock == NULL || *rwlock == NULL)
+    {
+      return EINVAL;
+    }
+
+  /*
+   * We do a quick check to see if we need to do more work
+   * to initialise a static rwlock. We check
+   * again inside the guarded section of ptw32_rwlock_check_need_init()
+   * to avoid race conditions.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = ptw32_rwlock_check_need_init (rwlock);
+
+      if (result != 0 && result != EBUSY)
+	{
+	  return result;
+	}
+    }
+
+  rwl = *rwlock;
+
+  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+    {
+      return EINVAL;
+    }
+
+  if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
+    {
+      return result;
+    }
+
+  if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+    {
+      (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+      return result;
+    }
+
+  if (rwl->nExclusiveAccessCount == 0)
+    {
+      if (rwl->nCompletedSharedAccessCount > 0)
+	{
+	  rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+	  rwl->nCompletedSharedAccessCount = 0;
+	}
+
+      if (rwl->nSharedAccessCount > 0)
+	{
+	  rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
+
+	  /*
+	   * This routine may be a cancelation point
+	   * according to POSIX 1003.1j section 18.1.2.
+	   */
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+	  pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
+
+	  do
+	    {
+	      result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted),
+					  &(rwl->mtxSharedAccessCompleted));
+	    }
+	  while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
+
+	  pthread_cleanup_pop ((result != 0) ? 1 : 0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+	  if (result == 0)
+	    {
+	      rwl->nSharedAccessCount = 0;
+	    }
+	}
+    }
+
+  if (result == 0)
+    {
+      rwl->nExclusiveAccessCount++;
+    }
+
+  return result;
+}
diff --git a/pthread_rwlockattr_destroy.c b/pthread_rwlockattr_destroy.c
new file mode 100644
index 0000000..6d161e8
--- /dev/null
+++ b/pthread_rwlockattr_destroy.c
@@ -0,0 +1,87 @@
+/*
+ * pthread_rwlockattr_destroy.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Destroys a rwlock attributes object. The object can
+      *      no longer be used.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_rwlockattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Destroys a rwlock attributes object. The object can
+      *      no longer be used.
+      *
+      *      NOTES:
+      *              1)      Does not affect rwlockss created using 'attr'
+      *
+      * RESULTS
+      *              0               successfully released attr,
+      *              EINVAL          'attr' is invalid.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+
+  if (attr == NULL || *attr == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      pthread_rwlockattr_t rwa = *attr;
+
+      *attr = NULL;
+      free (rwa);
+    }
+
+  return (result);
+}				/* pthread_rwlockattr_destroy */
diff --git a/pthread_rwlockattr_getpshared.c b/pthread_rwlockattr_getpshared.c
new file mode 100644
index 0000000..123f52c
--- /dev/null
+++ b/pthread_rwlockattr_getpshared.c
@@ -0,0 +1,100 @@
+/*
+ * pthread_rwlockattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+			       int *pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Determine whether rwlocks created with 'attr' can be
+      *      shared between processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_rwlockattr_t
+      *
+      *      pshared
+      *              will be set to one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      *
+      * DESCRIPTION
+      *      Rwlocks creatd with 'attr' can be shared between
+      *      processes if pthread_rwlock_t variable is allocated
+      *      in memory shared by these processes.
+      *      NOTES:
+      *              1)      pshared rwlocks MUST be allocated in shared
+      *                      memory.
+      *              2)      The following macro is defined if shared rwlocks
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully retrieved attribute,
+      *              EINVAL          'attr' is invalid,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+    {
+      *pshared = (*attr)->pshared;
+      result = 0;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+
+}				/* pthread_rwlockattr_getpshared */
diff --git a/pthread_rwlockattr_init.c b/pthread_rwlockattr_init.c
new file mode 100644
index 0000000..a58b694
--- /dev/null
+++ b/pthread_rwlockattr_init.c
@@ -0,0 +1,86 @@
+/*
+ * pthread_rwlockattr_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Initializes a rwlock attributes object with default
+      *      attributes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_rwlockattr_t
+      *
+      *
+      * DESCRIPTION
+      *      Initializes a rwlock attributes object with default
+      *      attributes.
+      *
+      * RESULTS
+      *              0               successfully initialized attr,
+      *              ENOMEM          insufficient memory for attr.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  pthread_rwlockattr_t rwa;
+
+  rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa));
+
+  if (rwa == NULL)
+    {
+      result = ENOMEM;
+    }
+  else
+    {
+      rwa->pshared = PTHREAD_PROCESS_PRIVATE;
+    }
+
+  *attr = rwa;
+
+  return (result);
+}				/* pthread_rwlockattr_init */
diff --git a/pthread_rwlockattr_setpshared.c b/pthread_rwlockattr_setpshared.c
new file mode 100644
index 0000000..c731978
--- /dev/null
+++ b/pthread_rwlockattr_setpshared.c
@@ -0,0 +1,123 @@
+/*
+ * pthread_rwlockattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef WINCE
+#include <errno.h>
+#endif
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Rwlocks created with 'attr' can be shared between
+      *      processes if pthread_rwlock_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      * PARAMETERS
+      *      attr
+      *              pointer to an instance of pthread_rwlockattr_t
+      *
+      *      pshared
+      *              must be one of:
+      *
+      *                      PTHREAD_PROCESS_SHARED
+      *                              May be shared if in shared memory
+      *
+      *                      PTHREAD_PROCESS_PRIVATE
+      *                              Cannot be shared.
+      *
+      * DESCRIPTION
+      *      Rwlocks creatd with 'attr' can be shared between
+      *      processes if pthread_rwlock_t variable is allocated
+      *      in memory shared by these processes.
+      *
+      *      NOTES:
+      *              1)      pshared rwlocks MUST be allocated in shared
+      *                      memory.
+      *
+      *              2)      The following macro is defined if shared rwlocks
+      *                      are supported:
+      *                              _POSIX_THREAD_PROCESS_SHARED
+      *
+      * RESULTS
+      *              0               successfully set attribute,
+      *              EINVAL          'attr' or pshared is invalid,
+      *              ENOSYS          PTHREAD_PROCESS_SHARED not supported,
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result;
+
+  if ((attr != NULL && *attr != NULL) &&
+      ((pshared == PTHREAD_PROCESS_SHARED) ||
+       (pshared == PTHREAD_PROCESS_PRIVATE)))
+    {
+      if (pshared == PTHREAD_PROCESS_SHARED)
+	{
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+	  result = ENOSYS;
+	  pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+	  result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+	}
+      else
+	{
+	  result = 0;
+	}
+
+      (*attr)->pshared = pshared;
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return (result);
+
+}				/* pthread_rwlockattr_setpshared */
diff --git a/pthread_self.c b/pthread_self.c
new file mode 100644
index 0000000..d72a097
--- /dev/null
+++ b/pthread_self.c
@@ -0,0 +1,138 @@
+/*
+ * pthread_self.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+pthread_t
+pthread_self (void)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function returns a reference to the current running
+      *      thread.
+      *
+      * PARAMETERS
+      *      N/A
+      *
+      *
+      * DESCRIPTION
+      *      This function returns a reference to the current running
+      *      thread.
+      *
+      * RESULTS
+      *              pthread_t       reference to the current thread
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_t self;
+  pthread_t nil = {NULL, 0};
+  ptw32_thread_t * sp;
+
+#ifdef _UWIN
+  if (!ptw32_selfThreadKey)
+    return nil;
+#endif
+
+  sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+  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 (sp != NULL)
+	{
+	  /*
+	   * This is a non-POSIX thread which has chosen to call
+	   * a POSIX threads function for some reason. We assume that
+	   * it isn't joinable, but we do assume that it's
+	   * (deferred) cancelable.
+	   */
+	  sp->implicit = 1;
+	  sp->detachState = PTHREAD_CREATE_DETACHED;
+	  sp->thread = GetCurrentThreadId ();
+
+#ifdef NEED_DUPLICATEHANDLE
+	  /*
+	   * DuplicateHandle does not exist on WinCE.
+	   *
+	   * NOTE:
+	   * GetCurrentThread only returns a pseudo-handle
+	   * which is only valid in the current thread context.
+	   * Therefore, you should not pass the handle to
+	   * other threads for whatever purpose.
+	   */
+	  sp->threadH = GetCurrentThread ();
+#else
+	  if (!DuplicateHandle (GetCurrentProcess (),
+				GetCurrentThread (),
+				GetCurrentProcess (),
+				&sp->threadH,
+				0, FALSE, DUPLICATE_SAME_ACCESS))
+	    {
+	      /*
+	       * 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 nil;
+	    }
+#endif
+
+	  /*
+	   * No need to explicitly serialise access to sched_priority
+	   * because the new handle is not yet public.
+	   */
+	  sp->sched_priority = GetThreadPriority (sp->threadH);
+
+          pthread_setspecific (ptw32_selfThreadKey, (void *) sp);
+	}
+    }
+
+  return (self);
+
+}				/* pthread_self */
diff --git a/pthread_setcancelstate.c b/pthread_setcancelstate.c
new file mode 100644
index 0000000..002cfe5
--- /dev/null
+++ b/pthread_setcancelstate.c
@@ -0,0 +1,124 @@
+/*
+ * pthread_setcancelstate.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setcancelstate (int state, int *oldstate)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function atomically sets the calling thread's
+      *      cancelability state to 'state' and returns the previous
+      *      cancelability state at the location referenced by
+      *      'oldstate'
+      *
+      * PARAMETERS
+      *      state,
+      *      oldstate
+      *              PTHREAD_CANCEL_ENABLE
+      *                      cancellation is enabled,
+      *
+      *              PTHREAD_CANCEL_DISABLE
+      *                      cancellation is disabled
+      *
+      *
+      * DESCRIPTION
+      *      This function atomically sets the calling thread's
+      *      cancelability state to 'state' and returns the previous
+      *      cancelability state at the location referenced by
+      *      'oldstate'.
+      *
+      *      NOTES:
+      *      1)      Use to disable cancellation around 'atomic' code that
+      *              includes cancellation points
+      *
+      * COMPATIBILITY ADDITIONS
+      *      If 'oldstate' is NULL then the previous state is not returned
+      *      but the function still succeeds. (Solaris)
+      *
+      * RESULTS
+      *              0               successfully set cancelability type,
+      *              EINVAL          'state' is invalid
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+  if (sp == NULL
+      || (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE))
+    {
+      return EINVAL;
+    }
+
+  /*
+   * Lock for async-cancel safety.
+   */
+  (void) pthread_mutex_lock (&sp->cancelLock);
+
+  if (oldstate != NULL)
+    {
+      *oldstate = sp->cancelState;
+    }
+
+  sp->cancelState = state;
+
+  /*
+   * Check if there is a pending asynchronous cancel
+   */
+  if (state == PTHREAD_CANCEL_ENABLE
+      && sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
+      && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
+    {
+      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 (&sp->cancelLock);
+
+  return (result);
+
+}				/* pthread_setcancelstate */
diff --git a/pthread_setcanceltype.c b/pthread_setcanceltype.c
new file mode 100644
index 0000000..3fb3f0e
--- /dev/null
+++ b/pthread_setcanceltype.c
@@ -0,0 +1,125 @@
+/*
+ * pthread_setcanceltype.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setcanceltype (int type, int *oldtype)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function atomically sets the calling thread's
+      *      cancelability type to 'type' and returns the previous
+      *      cancelability type at the location referenced by
+      *      'oldtype'
+      *
+      * PARAMETERS
+      *      type,
+      *      oldtype
+      *              PTHREAD_CANCEL_DEFERRED
+      *                      only deferred cancelation is allowed,
+      *
+      *              PTHREAD_CANCEL_ASYNCHRONOUS
+      *                      Asynchronous cancellation is allowed
+      *
+      *
+      * DESCRIPTION
+      *      This function atomically sets the calling thread's
+      *      cancelability type to 'type' and returns the previous
+      *      cancelability type at the location referenced by
+      *      'oldtype'
+      *
+      *      NOTES:
+      *      1)      Use with caution; most code is not safe for use
+      *              with asynchronous cancelability.
+      *
+      * COMPATIBILITY ADDITIONS
+      *      If 'oldtype' is NULL then the previous type is not returned
+      *      but the function still succeeds. (Solaris)
+      *
+      * RESULTS
+      *              0               successfully set cancelability type,
+      *              EINVAL          'type' is invalid
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+  if (sp == NULL
+      || (type != PTHREAD_CANCEL_DEFERRED
+	  && type != PTHREAD_CANCEL_ASYNCHRONOUS))
+    {
+      return EINVAL;
+    }
+
+  /*
+   * Lock for async-cancel safety.
+   */
+  (void) pthread_mutex_lock (&sp->cancelLock);
+
+  if (oldtype != NULL)
+    {
+      *oldtype = sp->cancelType;
+    }
+
+  sp->cancelType = type;
+
+  /*
+   * Check if there is a pending asynchronous cancel
+   */
+  if (sp->cancelState == PTHREAD_CANCEL_ENABLE
+      && type == PTHREAD_CANCEL_ASYNCHRONOUS
+      && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
+    {
+      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 (&sp->cancelLock);
+
+  return (result);
+
+}				/* pthread_setcanceltype */
diff --git a/pthread_setconcurrency.c b/pthread_setconcurrency.c
new file mode 100644
index 0000000..f62346f
--- /dev/null
+++ b/pthread_setconcurrency.c
@@ -0,0 +1,53 @@
+/*
+ * pthread_setconcurrency.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setconcurrency (int level)
+{
+  if (level < 0)
+    {
+      return EINVAL;
+    }
+  else
+    {
+      ptw32_concurrency = level;
+      return 0;
+    }
+}
diff --git a/pthread_setschedparam.c b/pthread_setschedparam.c
new file mode 100644
index 0000000..a122eac
--- /dev/null
+++ b/pthread_setschedparam.c
@@ -0,0 +1,125 @@
+/*
+ * sched_setschedparam.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_setschedparam (pthread_t thread, int policy,
+		       const struct sched_param *param)
+{
+  int result;
+
+  /* Validate the thread id. */
+  result = pthread_kill (thread, 0);
+  if (0 != result)
+    {
+      return result;
+    }
+
+  /* Validate the scheduling policy. */
+  if (policy < SCHED_MIN || policy > SCHED_MAX)
+    {
+      return EINVAL;
+    }
+
+  /* Ensure the policy is SCHED_OTHER. */
+  if (policy != SCHED_OTHER)
+    {
+      return ENOTSUP;
+    }
+
+  return (ptw32_setthreadpriority (thread, policy, param->sched_priority));
+}
+
+
+int
+ptw32_setthreadpriority (pthread_t thread, int policy, int priority)
+{
+  int prio;
+  int result;
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+
+  prio = priority;
+
+  /* Validate priority level. */
+  if (prio < sched_get_priority_min (policy) ||
+      prio > sched_get_priority_max (policy))
+    {
+      return EINVAL;
+    }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+/* WinCE */
+#else
+/* Everything else */
+
+  if (THREAD_PRIORITY_IDLE < prio && THREAD_PRIORITY_LOWEST > prio)
+    {
+      prio = THREAD_PRIORITY_LOWEST;
+    }
+  else if (THREAD_PRIORITY_TIME_CRITICAL > prio
+	   && THREAD_PRIORITY_HIGHEST < prio)
+    {
+      prio = THREAD_PRIORITY_HIGHEST;
+    }
+
+#endif
+
+  result = pthread_mutex_lock (&tp->threadLock);
+
+  if (0 == result)
+    {
+      /* If this fails, the current priority is unchanged. */
+      if (0 == SetThreadPriority (tp->threadH, prio))
+	{
+	  result = EINVAL;
+	}
+      else
+	{
+	  /*
+	   * Must record the thread's sched_priority as given,
+	   * not as finally adjusted.
+	   */
+	  tp->sched_priority = priority;
+	}
+
+      (void) pthread_mutex_unlock (&tp->threadLock);
+    }
+
+  return result;
+}
diff --git a/pthread_setspecific.c b/pthread_setspecific.c
new file mode 100644
index 0000000..f06b696
--- /dev/null
+++ b/pthread_setspecific.c
@@ -0,0 +1,168 @@
+/*
+ * pthread_setspecific.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setspecific (pthread_key_t key, const void *value)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function sets the value of the thread specific
+      *      key in the calling thread.
+      *
+      * PARAMETERS
+      *      key
+      *              an instance of pthread_key_t
+      *      value
+      *              the value to set key to
+      *
+      *
+      * DESCRIPTION
+      *      This function sets the value of the thread specific
+      *      key in the calling thread.
+      *
+      * RESULTS
+      *              0               successfully set value
+      *              EAGAIN          could not set value
+      *              ENOENT          SERIOUS!!
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_t self;
+  int result = 0;
+
+  if (key != ptw32_selfThreadKey)
+    {
+      /*
+       * Using pthread_self will implicitly create
+       * an instance of pthread_t for the current
+       * thread if one wasn't explicitly created
+       */
+      self = pthread_self ();
+      if (self.p == NULL)
+	{
+	  return ENOENT;
+	}
+    }
+  else
+    {
+      /*
+       * Resolve catch-22 of registering thread with selfThread
+       * key
+       */
+      ptw32_thread_t * 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;
+
+  if (key != NULL)
+    {
+      if (self.p != NULL && key->destructor != NULL && value != NULL)
+	{
+	  /*
+	   * Only require associations if we have to
+	   * call user destroy routine.
+	   * Don't need to locate an existing association
+	   * when setting data to NULL for WIN32 since the
+	   * data is stored with the operating system; not
+	   * on the association; setting assoc to NULL short
+	   * circuits the search.
+	   */
+	  ThreadKeyAssoc *assoc;
+
+	  if (pthread_mutex_lock(&(key->keyLock)) == 0)
+	    {
+	      ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+	      (void) pthread_mutex_lock(&(sp->threadLock));
+
+	      assoc = (ThreadKeyAssoc *) sp->keys;
+	      /*
+	       * Locate existing association
+	       */
+	      while (assoc != NULL)
+		{
+		  if (assoc->key == key)
+		    {
+		      /*
+		       * Association already exists
+		       */
+		      break;
+		    }
+		  assoc = assoc->nextKey;
+		}
+
+	      /*
+	       * create an association if not found
+	       */
+	      if (assoc == NULL)
+		{
+		  result = ptw32_tkAssocCreate (sp, key);
+		}
+
+	      (void) pthread_mutex_unlock(&(sp->threadLock));
+	    }
+	  (void) pthread_mutex_unlock(&(key->keyLock));
+	}
+
+	if (result == 0)
+	  {
+	    if (!TlsSetValue (key->key, (LPVOID) value))
+	      {
+		result = EAGAIN;
+	      }
+	  }
+    }
+
+  return (result);
+}				/* pthread_setspecific */
diff --git a/pthread_spin_destroy.c b/pthread_spin_destroy.c
new file mode 100644
index 0000000..8fe2267
--- /dev/null
+++ b/pthread_spin_destroy.c
@@ -0,0 +1,112 @@
+/*
+ * pthread_spin_destroy.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_destroy (pthread_spinlock_t * lock)
+{
+  register pthread_spinlock_t s;
+  int result = 0;
+
+  if (lock == NULL || *lock == NULL)
+    {
+      return EINVAL;
+    }
+
+  if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER)
+    {
+      if (s->interlock == PTW32_SPIN_USE_MUTEX)
+	{
+	  result = pthread_mutex_destroy (&(s->u.mutex));
+	}
+      else if ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED !=
+	       PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG)
+						   & (s->interlock),
+						   (PTW32_INTERLOCKED_LONG)
+						   PTW32_OBJECT_INVALID,
+						   (PTW32_INTERLOCKED_LONG)
+						   PTW32_SPIN_UNLOCKED))
+	{
+	  result = EINVAL;
+	}
+
+      if (0 == result)
+	{
+	  /*
+	   * We are relying on the application to ensure that all other threads
+	   * have finished with the spinlock before destroying it.
+	   */
+	  *lock = NULL;
+	  (void) free (s);
+	}
+    }
+  else
+    {
+      /*
+       * See notes in ptw32_spinlock_check_need_init() above also.
+       */
+      EnterCriticalSection (&ptw32_spinlock_test_init_lock);
+
+      /*
+       * Check again.
+       */
+      if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+	{
+	  /*
+	   * This is all we need to do to destroy a statically
+	   * initialised spinlock that has not yet been used (initialised).
+	   * If we get to here, another thread
+	   * waiting to initialise this mutex will get an EINVAL.
+	   */
+	  *lock = NULL;
+	}
+      else
+	{
+	  /*
+	   * The spinlock has been initialised while we were waiting
+	   * so assume it's in use.
+	   */
+	  result = EBUSY;
+	}
+
+      LeaveCriticalSection (&ptw32_spinlock_test_init_lock);
+    }
+
+  return (result);
+}
diff --git a/pthread_spin_init.c b/pthread_spin_init.c
new file mode 100644
index 0000000..553af7e
--- /dev/null
+++ b/pthread_spin_init.c
@@ -0,0 +1,123 @@
+/*
+ * pthread_spin_init.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_init (pthread_spinlock_t * lock, int pshared)
+{
+  pthread_spinlock_t s;
+  int cpus = 0;
+  int result = 0;
+
+  if (lock == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (0 != ptw32_getprocessors (&cpus))
+    {
+      cpus = 1;
+    }
+
+  if (cpus > 1)
+    {
+      if (pshared == PTHREAD_PROCESS_SHARED)
+	{
+	  /*
+	   * Creating spinlock that can be shared between
+	   * processes.
+	   */
+#if _POSIX_THREAD_PROCESS_SHARED >= 0
+
+	  /*
+	   * Not implemented yet.
+	   */
+
+#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet.
+
+#else
+
+	  return ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+	}
+    }
+
+  s = (pthread_spinlock_t) calloc (1, sizeof (*s));
+
+  if (s == NULL)
+    {
+      return ENOMEM;
+    }
+
+  if (cpus > 1)
+    {
+      s->u.cpus = cpus;
+      s->interlock = PTW32_SPIN_UNLOCKED;
+    }
+  else
+    {
+      pthread_mutexattr_t ma;
+      result = pthread_mutexattr_init (&ma);
+
+      if (0 == result)
+	{
+	  ma->pshared = pshared;
+	  result = pthread_mutex_init (&(s->u.mutex), &ma);
+	  if (0 == result)
+	    {
+	      s->interlock = PTW32_SPIN_USE_MUTEX;
+	    }
+	}
+      (void) pthread_mutexattr_destroy (&ma);
+    }
+
+  if (0 == result)
+    {
+      *lock = s;
+    }
+  else
+    {
+      (void) free (s);
+      *lock = NULL;
+    }
+
+  return (result);
+}
diff --git a/pthread_spin_lock.c b/pthread_spin_lock.c
new file mode 100644
index 0000000..90b3abe
--- /dev/null
+++ b/pthread_spin_lock.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_spin_lock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_lock (pthread_spinlock_t * lock)
+{
+  register pthread_spinlock_t s;
+
+  if (NULL == lock || NULL == *lock)
+    {
+      return (EINVAL);
+    }
+
+  if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+    {
+      int result;
+
+      if ((result = ptw32_spinlock_check_need_init (lock)) != 0)
+	{
+	  return (result);
+	}
+    }
+
+  s = *lock;
+
+  while ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ==
+	 PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) &
+					     (s->interlock),
+					     (PTW32_INTERLOCKED_LONG)
+					     PTW32_SPIN_LOCKED,
+					     (PTW32_INTERLOCKED_LONG)
+					     PTW32_SPIN_UNLOCKED))
+    {
+    }
+
+  if (s->interlock == PTW32_SPIN_LOCKED)
+    {
+      return 0;
+    }
+  else if (s->interlock == PTW32_SPIN_USE_MUTEX)
+    {
+      return pthread_mutex_lock (&(s->u.mutex));
+    }
+
+  return EINVAL;
+}
diff --git a/pthread_spin_trylock.c b/pthread_spin_trylock.c
new file mode 100644
index 0000000..c601a19
--- /dev/null
+++ b/pthread_spin_trylock.c
@@ -0,0 +1,80 @@
+/*
+ * pthread_spin_trylock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_trylock (pthread_spinlock_t * lock)
+{
+  register pthread_spinlock_t s;
+
+  if (NULL == lock || NULL == *lock)
+    {
+      return (EINVAL);
+    }
+
+  if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+    {
+      int result;
+
+      if ((result = ptw32_spinlock_check_need_init (lock)) != 0)
+	{
+	  return (result);
+	}
+    }
+
+  s = *lock;
+
+  switch ((long)
+	  PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) &
+					      (s->interlock),
+					      (PTW32_INTERLOCKED_LONG)
+					      PTW32_SPIN_LOCKED,
+					      (PTW32_INTERLOCKED_LONG)
+					      PTW32_SPIN_UNLOCKED))
+    {
+    case PTW32_SPIN_UNLOCKED:
+      return 0;
+    case PTW32_SPIN_LOCKED:
+      return EBUSY;
+    case PTW32_SPIN_USE_MUTEX:
+      return pthread_mutex_trylock (&(s->u.mutex));
+    }
+
+  return EINVAL;
+}
diff --git a/pthread_spin_unlock.c b/pthread_spin_unlock.c
new file mode 100644
index 0000000..67bc2c2
--- /dev/null
+++ b/pthread_spin_unlock.c
@@ -0,0 +1,75 @@
+/*
+ * pthread_spin_unlock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_unlock (pthread_spinlock_t * lock)
+{
+  register pthread_spinlock_t s;
+
+  if (NULL == lock || NULL == *lock)
+    {
+      return (EINVAL);
+    }
+
+  s = *lock;
+
+  if (s == PTHREAD_SPINLOCK_INITIALIZER)
+    {
+      return EPERM;
+    }
+
+  switch ((long)
+	  PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) &
+					      (s->interlock),
+					      (PTW32_INTERLOCKED_LONG)
+					      PTW32_SPIN_UNLOCKED,
+					      (PTW32_INTERLOCKED_LONG)
+					      PTW32_SPIN_LOCKED))
+    {
+    case PTW32_SPIN_LOCKED:
+      return 0;
+    case PTW32_SPIN_UNLOCKED:
+      return EPERM;
+    case PTW32_SPIN_USE_MUTEX:
+      return pthread_mutex_unlock (&(s->u.mutex));
+    }
+
+  return EINVAL;
+}
diff --git a/pthread_testcancel.c b/pthread_testcancel.c
new file mode 100644
index 0000000..ad7cdb9
--- /dev/null
+++ b/pthread_testcancel.c
@@ -0,0 +1,102 @@
+/*
+ * pthread_testcancel.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+pthread_testcancel (void)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function creates a deferred cancellation point
+      *      in the calling thread. The call has no effect if the
+      *      current cancelability state is
+      *              PTHREAD_CANCEL_DISABLE
+      *
+      * PARAMETERS
+      *      N/A
+      *
+      *
+      * DESCRIPTION
+      *      This function creates a deferred cancellation point
+      *      in the calling thread. The call has no effect if the
+      *      current cancelability state is
+      *              PTHREAD_CANCEL_DISABLE
+      *
+      *      NOTES:
+      *      1)      Cancellation is asynchronous. Use pthread_join
+      *              to wait for termination of thread if necessary
+      *
+      * RESULTS
+      *              N/A
+      *
+      * ------------------------------------------------------
+      */
+{
+  pthread_t self = pthread_self ();
+  ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+  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 (sp->cancelState != PTHREAD_CANCEL_DISABLE)
+    {
+      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 (&sp->cancelLock);
+}				/* pthread_testcancel */
diff --git a/pthread_timechange_handler_np.c b/pthread_timechange_handler_np.c
new file mode 100644
index 0000000..7d8170a
--- /dev/null
+++ b/pthread_timechange_handler_np.c
@@ -0,0 +1,107 @@
+/*
+ * pthread_timechange_handler_np.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Notes on handling system time adjustments (especially negative ones).
+ * ---------------------------------------------------------------------
+ *
+ * This solution was suggested by Alexander Terekhov, but any errors
+ * in the implementation are mine - [Ross Johnson]
+ *
+ * 1) The problem: threads doing a timedwait on a CV may expect to timeout
+ *    at a specific absolute time according to a system timer. If the
+ *    system clock is adjusted backwards then those threads sleep longer than
+ *    expected. Also, pthreads-win32 converts absolute times to intervals in
+ *    order to make use of the underlying Win32, and so waiting threads may
+ *    awake before their proper abstimes.
+ *
+ * 2) We aren't able to distinquish between threads on timed or untimed waits,
+ *    so we wake them all at the time of the adjustment so that they can
+ *    re-evaluate their conditions and re-compute their timeouts.
+ *
+ * 3) We rely on correctly written applications for this to work. Specifically,
+ *    they must be able to deal properly with spurious wakeups. That is,
+ *    they must re-test their condition upon wakeup and wait again if
+ *    the condition is not satisfied.
+ */
+
+void *
+pthread_timechange_handler_np (void *arg)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      Broadcasts all CVs to force re-evaluation and
+      *      new timeouts if required.
+      *
+      * PARAMETERS
+      *      NONE
+      *
+      *
+      * DESCRIPTION
+      *      Broadcasts all CVs to force re-evaluation and
+      *      new timeouts if required.
+      *
+      *      This routine may be passed directly to pthread_create()
+      *      as a new thread in order to run asynchronously.
+      *
+      *
+      * RESULTS
+      *              0               successfully broadcast all CVs
+      *              EAGAIN          Not all CVs were broadcast
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  pthread_cond_t cv;
+
+  EnterCriticalSection (&ptw32_cond_list_lock);
+
+  cv = ptw32_cond_list_head;
+
+  while (cv != NULL && 0 == result)
+    {
+      result = pthread_cond_broadcast (&cv);
+      cv = cv->next;
+    }
+
+  LeaveCriticalSection (&ptw32_cond_list_lock);
+
+  return (void *) (result != 0 ? EAGAIN : 0);
+}
diff --git a/pthread_win32_attach_detach_np.c b/pthread_win32_attach_detach_np.c
new file mode 100644
index 0000000..2f0bc37
--- /dev/null
+++ b/pthread_win32_attach_detach_np.c
@@ -0,0 +1,303 @@
+/*
+ * pthread_win32_attach_detach_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Handle to kernel32.dll 
+ */
+static HINSTANCE ptw32_h_kernel32;
+
+/*
+ * Handle to quserex.dll 
+ */
+static HINSTANCE ptw32_h_quserex;
+
+BOOL
+pthread_win32_process_attach_np ()
+{
+  BOOL result = TRUE;
+  DWORD_PTR vProcessCPUs;
+  DWORD_PTR vSystemCPUs;
+
+  result = ptw32_processInitialize ();
+
+#ifdef _UWIN
+  pthread_count++;
+#endif
+
+  ptw32_features = 0;
+
+
+#if defined(NEED_PROCESS_AFFINITY_MASK)
+
+  ptw32_smp_system = PTW32_FALSE;
+
+#else
+
+  if (GetProcessAffinityMask (GetCurrentProcess (),
+			      &vProcessCPUs, &vSystemCPUs))
+    {
+      int CPUs = 0;
+      DWORD_PTR bit;
+
+      for (bit = 1; bit != 0; bit <<= 1)
+	{
+	  if (vSystemCPUs & bit)
+	    {
+	      CPUs++;
+	    }
+	}
+      ptw32_smp_system = (CPUs > 1);
+    }
+  else
+    {
+      ptw32_smp_system = PTW32_FALSE;
+    }
+
+#endif
+
+#ifdef WINCE
+
+  /*
+   * Load COREDLL and try to get address of InterlockedCompareExchange
+   */
+  ptw32_h_kernel32 = LoadLibrary (TEXT ("COREDLL.DLL"));
+
+#else
+
+  /*
+   * Load KERNEL32 and try to get address of InterlockedCompareExchange
+   */
+  ptw32_h_kernel32 = LoadLibrary (TEXT ("KERNEL32.DLL"));
+
+#endif
+
+  ptw32_interlocked_compare_exchange =
+    (PTW32_INTERLOCKED_LONG (WINAPI *)
+     (PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG,
+      PTW32_INTERLOCKED_LONG))
+#if defined(NEED_UNICODE_CONSTS)
+    GetProcAddress (ptw32_h_kernel32,
+		    (const TCHAR *) TEXT ("InterlockedCompareExchange"));
+#else
+    GetProcAddress (ptw32_h_kernel32, (LPCSTR) "InterlockedCompareExchange");
+#endif
+
+  if (ptw32_interlocked_compare_exchange == NULL)
+    {
+      ptw32_interlocked_compare_exchange = ptw32_InterlockedCompareExchange;
+
+      /*
+       * If InterlockedCompareExchange 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 InterlockedCompareExchange, the bug will be
+       * effortlessly avoided.
+       */
+      (void) FreeLibrary (ptw32_h_kernel32);
+      ptw32_h_kernel32 = 0;
+    }
+  else
+    {
+      ptw32_features |= PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE;
+    }
+
+  /*
+   * Load QUSEREX.DLL and try to get address of QueueUserAPCEx
+   */
+  ptw32_h_quserex = LoadLibrary (TEXT ("QUSEREX.DLL"));
+
+  if (ptw32_h_quserex != NULL)
+    {
+      ptw32_register_cancelation = (DWORD (*)(PAPCFUNC, HANDLE, DWORD))
+#if defined(NEED_UNICODE_CONSTS)
+	GetProcAddress (ptw32_h_quserex,
+			(const TCHAR *) TEXT ("QueueUserAPCEx"));
+#else
+	GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx");
+#endif
+    }
+
+  if (NULL == ptw32_register_cancelation)
+    {
+      ptw32_register_cancelation = ptw32_RegisterCancelation;
+
+      if (ptw32_h_quserex != NULL)
+	{
+	  (void) FreeLibrary (ptw32_h_quserex);
+	}
+      ptw32_h_quserex = 0;
+    }
+  else
+    {
+      /* Initialise QueueUserAPCEx */
+      BOOL (*queue_user_apc_ex_init) (VOID);
+
+      queue_user_apc_ex_init = (BOOL (*)(VOID))
+#if defined(NEED_UNICODE_CONSTS)
+	GetProcAddress (ptw32_h_quserex,
+			(const TCHAR *) TEXT ("QueueUserAPCEx_Init"));
+#else
+	GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Init");
+#endif
+
+      if (queue_user_apc_ex_init == NULL || !queue_user_apc_ex_init ())
+	{
+	  ptw32_register_cancelation = ptw32_RegisterCancelation;
+
+	  (void) FreeLibrary (ptw32_h_quserex);
+	  ptw32_h_quserex = 0;
+	}
+    }
+
+  if (ptw32_h_quserex)
+    {
+      ptw32_features |= PTW32_ALERTABLE_ASYNC_CANCEL;
+    }
+
+  return result;
+}
+
+
+BOOL
+pthread_win32_process_detach_np ()
+{
+  if (ptw32_processInitialized)
+    {
+      ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+      if (sp != 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);
+	    }
+	}
+
+      /*
+       * The DLL is being unmapped from the process's address space
+       */
+      ptw32_processTerminate ();
+
+      if (ptw32_h_quserex)
+	{
+	  /* Close QueueUserAPCEx */
+	  BOOL (*queue_user_apc_ex_fini) (VOID);
+
+	  queue_user_apc_ex_fini = (BOOL (*)(VOID))
+#if defined(NEED_UNICODE_CONSTS)
+	    GetProcAddress (ptw32_h_quserex,
+			    (const TCHAR *) TEXT ("QueueUserAPCEx_Fini"));
+#else
+	    GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Fini");
+#endif
+
+	  if (queue_user_apc_ex_fini != NULL)
+	    {
+	      (void) queue_user_apc_ex_fini ();
+	    }
+	  (void) FreeLibrary (ptw32_h_quserex);
+	}
+
+      if (ptw32_h_kernel32)
+	{
+	  (void) FreeLibrary (ptw32_h_kernel32);
+	}
+    }
+
+  return TRUE;
+}
+
+BOOL
+pthread_win32_thread_attach_np ()
+{
+  return TRUE;
+}
+
+BOOL
+pthread_win32_thread_detach_np ()
+{
+  if (ptw32_processInitialized)
+    {
+      /*
+       * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle
+       * unnecessarily.
+       */
+      ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+      if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle.
+	{
+	  ptw32_callUserDestroyRoutines (sp->ptHandle);
+
+	  (void) pthread_mutex_lock (&sp->cancelLock);
+	  sp->state = PThreadStateLast;
+	  /*
+	   * If the thread is joinable at this point then it MUST be joined
+	   * or detached explicitly by the application.
+	   */
+	  (void) pthread_mutex_unlock (&sp->cancelLock);
+
+	  if (sp->detachState == PTHREAD_CREATE_DETACHED)
+	    {
+	      ptw32_threadDestroy (sp->ptHandle);
+
+	      TlsSetValue (ptw32_selfThreadKey->key, NULL);
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+BOOL
+pthread_win32_test_features_np (int feature_mask)
+{
+  return ((ptw32_features & feature_mask) == feature_mask);
+}
diff --git a/ptw32_InterlockedCompareExchange.c b/ptw32_InterlockedCompareExchange.c
new file mode 100644
index 0000000..0094635
--- /dev/null
+++ b/ptw32_InterlockedCompareExchange.c
@@ -0,0 +1,303 @@
+/*
+ * ptw32_InterlockedCompareExchange.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * ptw32_InterlockedCompareExchange --
+ *
+ * Originally needed because W9x doesn't support InterlockedCompareExchange.
+ * We now use this version wherever possible so we can inline it.
+ */
+
+PTW32_INTERLOCKED_LONG WINAPI
+ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
+				  PTW32_INTERLOCKED_LONG value,
+				  PTW32_INTERLOCKED_LONG comparand)
+{
+
+#if defined(__WATCOMC__)
+/* Don't report that result is not assigned a value before being referenced */
+#pragma disable_message (200)
+#endif
+
+  PTW32_INTERLOCKED_LONG result;
+
+  /*
+   * Using the LOCK prefix on uni-processor machines is significantly slower
+   * and it is not necessary. The overhead of the conditional below is
+   * negligible in comparison. Since an optimised DLL will inline this
+   * routine, this will be faster than calling the system supplied
+   * Interlocked routine, which appears to avoid the LOCK prefix on
+   * uniprocessor systems. So one DLL works for all systems.
+   */
+  if (ptw32_smp_system)
+
+/* *INDENT-OFF* */
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
+#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG
+    {
+      _asm {
+	PUSH         ecx
+	PUSH         edx
+	MOV          ecx,dword ptr [location]
+	MOV          edx,dword ptr [value]
+	MOV          eax,dword ptr [comparand]
+	LOCK CMPXCHG dword ptr [ecx],edx
+	MOV          dword ptr [result], eax
+	POP          edx
+	POP          ecx
+      }
+    }
+  else
+    {
+      _asm {
+	PUSH         ecx
+	PUSH         edx
+	MOV          ecx,dword ptr [location]
+	MOV          edx,dword ptr [value]
+	MOV          eax,dword ptr [comparand]
+	CMPXCHG      dword ptr [ecx],edx
+	MOV          dword ptr [result], eax
+	POP          edx
+	POP          ecx
+      }
+    }
+
+#elif defined(__GNUC__)
+#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG
+
+    {
+      __asm__ __volatile__
+	(
+	 "lock\n\t"
+	 "cmpxchgl       %2,%1"      /* if (EAX == [location])  */
+	                             /*   [location] = value    */
+                                     /* else                    */
+                                     /*   EAX = [location]      */
+	 :"=a" (result)
+	 :"m"  (*location), "r" (value), "a" (comparand));
+    }
+  else
+    {
+      __asm__ __volatile__
+	(
+	 "cmpxchgl       %2,%1"      /* if (EAX == [location])  */
+	                             /*   [location] = value    */
+                                     /* else                    */
+                                     /*   EAX = [location]      */
+	 :"=a" (result)
+	 :"m"  (*location), "r" (value), "a" (comparand));
+    }
+
+#endif
+
+#else
+
+  /*
+   * If execution gets to here then we're running on a currently
+   * unsupported processor or compiler.
+   */
+
+  result = 0;
+
+#endif
+
+/* *INDENT-ON* */
+
+  return result;
+
+#if defined(__WATCOMC__)
+#pragma enable_message (200)
+#endif
+
+}
+
+/*
+ * ptw32_InterlockedExchange --
+ *
+ * We now use this version wherever possible so we can inline it.
+ */
+
+LONG WINAPI
+ptw32_InterlockedExchange (LPLONG location,
+			   LONG value)
+{
+
+#if defined(__WATCOMC__)
+/* Don't report that result is not assigned a value before being referenced */
+#pragma disable_message (200)
+#endif
+
+  LONG result;
+
+  /*
+   * The XCHG instruction always locks the bus with or without the
+   * LOCKED prefix. This makes it significantly slower than CMPXCHG on
+   * uni-processor machines. The Windows InterlockedExchange function
+   * is nearly 3 times faster than the XCHG instruction, so this routine
+   * is not yet very useful for speeding up pthreads.
+   */
+  if (ptw32_smp_system)
+
+/* *INDENT-OFF* */
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
+#define HAVE_INLINABLE_INTERLOCKED_XCHG
+
+    {
+      _asm {
+	PUSH         ecx
+	MOV          ecx,dword ptr [location]
+	MOV          eax,dword ptr [value]
+	XCHG         dword ptr [ecx],eax
+	MOV          dword ptr [result], eax
+        POP          ecx
+      }
+    }
+  else
+    {
+      /*
+       * Faster version of XCHG for uni-processor systems because
+       * it doesn't lock the bus. If an interrupt or context switch
+       * occurs between the MOV and the CMPXCHG then the value in
+       * 'location' may have changed, in which case we will loop
+       * back to do the MOV again.
+       *
+       * FIXME! Need memory barriers for the MOV+CMPXCHG combo?
+       *
+       * Tests show that this routine has almost identical timing
+       * to Win32's InterlockedExchange(), which is much faster than
+       * using the inlined 'xchg' instruction above, so it's probably
+       * doing something similar to this (on UP systems).
+       *
+       * Can we do without the PUSH/POP instructions?
+       */
+      _asm {
+	PUSH         ecx
+	PUSH         edx
+	MOV          ecx,dword ptr [location]
+	MOV          edx,dword ptr [value]
+L1:	MOV          eax,dword ptr [ecx]
+	CMPXCHG      dword ptr [ecx],edx
+	JNZ          L1
+	MOV          dword ptr [result], eax
+	POP          edx
+        POP          ecx
+      }
+    }
+
+#elif defined(__GNUC__)
+#define HAVE_INLINABLE_INTERLOCKED_XCHG
+
+    {
+      __asm__ __volatile__
+	(
+	 "xchgl          %2,%1"
+	 :"=r" (result)
+	 :"m"  (*location), "0" (value));
+    }
+  else
+    {
+      /*
+       * Faster version of XCHG for uni-processor systems because
+       * it doesn't lock the bus. If an interrupt or context switch
+       * occurs between the movl and the cmpxchgl then the value in
+       * 'location' may have changed, in which case we will loop
+       * back to do the movl again.
+       *
+       * FIXME! Need memory barriers for the MOV+CMPXCHG combo?
+       *
+       * Tests show that this routine has almost identical timing
+       * to Win32's InterlockedExchange(), which is much faster than
+       * using the an inlined 'xchg' instruction, so it's probably
+       * doing something similar to this (on UP systems).
+       */
+      __asm__ __volatile__
+	(
+	 "0:\n\t"
+	 "movl           %1,%%eax\n\t"
+	 "cmpxchgl       %2,%1\n\t"
+	 "jnz            0b"
+	 :"=&a" (result)
+	 :"m"  (*location), "r" (value));
+    }
+
+#endif
+
+#else
+
+  /*
+   * If execution gets to here then we're running on a currently
+   * unsupported processor or compiler.
+   */
+
+  result = 0;
+
+#endif
+
+/* *INDENT-ON* */
+
+  return result;
+
+#if defined(__WATCOMC__)
+#pragma enable_message (200)
+#endif
+
+}
+
+
+#if 1
+
+#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_CMPXCHG)
+#undef PTW32_INTERLOCKED_COMPARE_EXCHANGE
+#define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_InterlockedCompareExchange
+#endif
+
+#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_XCHG)
+#undef PTW32_INTERLOCKED_EXCHANGE
+#define PTW32_INTERLOCKED_EXCHANGE ptw32_InterlockedExchange
+#endif
+
+#endif
diff --git a/ptw32_MCS_lock.c b/ptw32_MCS_lock.c
new file mode 100644
index 0000000..1a143ea
--- /dev/null
+++ b/ptw32_MCS_lock.c
@@ -0,0 +1,210 @@
+/*
+ * ptw32_MCS_lock.c
+ *
+ * Description:
+ * This translation unit implements queue-based locks.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+/*
+ * About MCS locks:
+ *
+ * MCS locks are queue-based locks, where the queue nodes are local to the
+ * thread. The 'lock' is nothing more than a global pointer that points to
+ * the last node in the queue, or is NULL if the queue is empty.
+ * 
+ * Originally designed for use as spin locks requiring no kernel resources
+ * for synchronisation or blocking, the implementation below has adapted
+ * the MCS spin lock for use as a general mutex that will suspend threads
+ * when there is lock contention.
+ *
+ * Because the queue nodes are thread-local, most of the memory read/write
+ * operations required to add or remove nodes from the queue do not trigger
+ * cache-coherence updates.
+ *
+ * Like 'named' mutexes, MCS locks consume system resources transiently -
+ * they are able to acquire and free resources automatically - but MCS
+ * locks do not require any unique 'name' to identify the lock to all
+ * threads using it.
+ *
+ * Usage of MCS locks:
+ *
+ * - you need a global ptw32_mcs_lock_t instance initialised to 0 or NULL.
+ * - you need a local thread-scope ptw32_mcs_local_node_t instance, which
+ *   may serve several different locks but you need at least one node for
+ *   every lock held concurrently by a thread.
+ *
+ * E.g.:
+ * 
+ * ptw32_mcs_lock_t lock1 = 0;
+ * ptw32_mcs_lock_t lock2 = 0;
+ *
+ * void *mythread(void *arg)
+ * {
+ *   ptw32_mcs_local_node_t node;
+ *
+ *   ptw32_mcs_acquire (&lock1, &node);
+ *   ptw32_mcs_release (&node);
+ *
+ *   ptw32_mcs_acquire (&lock2, &node);
+ *   ptw32_mcs_release (&node);
+ *   {
+ *      ptw32_mcs_local_node_t nodex;
+ *
+ *      ptw32_mcs_acquire (&lock1, &node);
+ *      ptw32_mcs_acquire (&lock2, &nodex);
+ *
+ *      ptw32_mcs_release (&nodex);
+ *      ptw32_mcs_release (&node);
+ *   }
+ *   return (void *)0;
+ * }
+ */
+
+#include "implement.h"
+#include "pthread.h"
+
+/*
+ * ptw32_mcs_flag_set -- notify another thread about an event.
+ * 
+ * Set event if an event handle has been stored in the flag, and
+ * set flag to -1 otherwise. Note that -1 cannot be a valid handle value.
+ */
+INLINE void 
+ptw32_mcs_flag_set (LONG * flag)
+{
+  HANDLE e = (HANDLE)PTW32_INTERLOCKED_COMPARE_EXCHANGE(
+						(PTW32_INTERLOCKED_LPLONG)flag,
+						(PTW32_INTERLOCKED_LONG)-1,
+						(PTW32_INTERLOCKED_LONG)0);
+  if ((HANDLE)0 != e)
+    {
+      /* another thread has already stored an event handle in the flag */
+      SetEvent(e);
+    }
+}
+
+/*
+ * ptw32_mcs_flag_set -- wait for notification from another.
+ * 
+ * Store an event handle in the flag and wait on it if the flag has not been
+ * set, and proceed without creating an event otherwise.
+ */
+INLINE void 
+ptw32_mcs_flag_wait (LONG * flag)
+{
+  if (0 == InterlockedExchangeAdd((LPLONG)flag, 0)) /* MBR fence */
+    {
+      /* the flag is not set. create event. */
+
+      HANDLE e = CreateEvent(NULL, PTW32_FALSE, PTW32_FALSE, NULL);
+
+      if (0 == PTW32_INTERLOCKED_COMPARE_EXCHANGE(
+			                  (PTW32_INTERLOCKED_LPLONG)flag,
+			                  (PTW32_INTERLOCKED_LONG)e,
+			                  (PTW32_INTERLOCKED_LONG)0))
+	{
+	  /* stored handle in the flag. wait on it now. */
+	  WaitForSingleObject(e, INFINITE);
+	}
+
+      CloseHandle(e);
+    }
+}
+
+/*
+ * ptw32_mcs_lock_acquire -- acquire an MCS lock.
+ * 
+ * See: 
+ * J. M. Mellor-Crummey and M. L. Scott.
+ * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
+ * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
+ */
+INLINE void 
+ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
+{
+  ptw32_mcs_local_node_t  *pred;
+  
+  node->lock = lock;
+  node->nextFlag = 0;
+  node->readyFlag = 0;
+  node->next = 0; /* initially, no successor */
+  
+  /* queue for the lock */
+  pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE((LPLONG)lock,
+						              (LONG)node);
+
+  if (0 != pred)
+    {
+      /* the lock was not free. link behind predecessor. */
+      pred->next = node;
+      ptw32_mcs_flag_set(&pred->nextFlag);
+      ptw32_mcs_flag_wait(&node->readyFlag);
+    }
+}
+
+/*
+ * ptw32_mcs_lock_release -- release an MCS lock.
+ * 
+ * See: 
+ * J. M. Mellor-Crummey and M. L. Scott.
+ * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
+ * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
+ */
+INLINE void 
+ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node)
+{
+  ptw32_mcs_lock_t *lock = node->lock;
+  ptw32_mcs_local_node_t *next = (ptw32_mcs_local_node_t *)
+    InterlockedExchangeAdd((LPLONG)&node->next, 0); /* MBR fence */
+
+  if (0 == next)
+    {
+      /* no known successor */
+
+      if (node == (ptw32_mcs_local_node_t *)
+	  PTW32_INTERLOCKED_COMPARE_EXCHANGE((PTW32_INTERLOCKED_LPLONG)lock,
+					     (PTW32_INTERLOCKED_LONG)0,
+					     (PTW32_INTERLOCKED_LONG)node))
+	{
+	  /* no successor, lock is free now */
+	  return;
+	}
+  
+      /* wait for successor */
+      ptw32_mcs_flag_wait(&node->nextFlag);
+      next = (ptw32_mcs_local_node_t *)
+	InterlockedExchangeAdd((LPLONG)&node->next, 0); /* MBR fence */
+    }
+
+  /* pass the lock */
+  ptw32_mcs_flag_set(&next->readyFlag);
+}
diff --git a/ptw32_callUserDestroyRoutines.c b/ptw32_callUserDestroyRoutines.c
new file mode 100644
index 0000000..a583f18
--- /dev/null
+++ b/ptw32_callUserDestroyRoutines.c
@@ -0,0 +1,220 @@
+/*
+ * ptw32_callUserDestroyRoutines.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#ifdef __cplusplus
+# if ! defined (_MSC_VER) && ! (defined(__GNUC__) && __GNUC__ < 3) && ! defined(__WATCOMC__)
+using
+  std::terminate;
+# endif
+#endif
+
+void
+ptw32_callUserDestroyRoutines (pthread_t thread)
+     /*
+      * -------------------------------------------------------------------
+      * DOCPRIVATE
+      *
+      * This the routine runs through all thread keys and calls
+      * the destroy routines on the user's data for the current thread.
+      * It simulates the behaviour of POSIX Threads.
+      *
+      * PARAMETERS
+      *              thread
+      *                      an instance of pthread_t
+      *
+      * RETURNS
+      *              N/A
+      * -------------------------------------------------------------------
+      */
+{
+  ThreadKeyAssoc * assoc;
+
+  if (thread.p != NULL)
+    {
+      int assocsRemaining;
+      int iterations = 0;
+      ptw32_thread_t * sp = (ptw32_thread_t *) thread.p;
+
+      /*
+       * Run through all Thread<-->Key associations
+       * for the current thread.
+       *
+       * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
+       */
+      do
+	{
+	  assocsRemaining = 0;
+	  iterations++;
+
+	  (void) pthread_mutex_lock(&(sp->threadLock));
+	  /*
+	   * The pointer to the next assoc is stored in the thread struct so that
+	   * the assoc destructor in pthread_key_delete can adjust it
+	   * if it deletes this assoc. This can happen if we fail to acquire
+	   * both locks below, and are forced to release all of our locks,
+	   * leaving open the opportunity for pthread_key_delete to get in
+	   * before us.
+	   */
+	  sp->nextAssoc = sp->keys;
+	  (void) pthread_mutex_unlock(&(sp->threadLock));
+
+	  for (;;)
+	    {
+	      void * value;
+	      pthread_key_t k;
+	      void (*destructor) (void *);
+
+	      /*
+	       * First we need to serialise with pthread_key_delete by locking
+	       * both assoc guards, but in the reverse order to our convention,
+	       * so we must be careful to avoid deadlock.
+	       */
+	      (void) pthread_mutex_lock(&(sp->threadLock));
+
+	      if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
+		{
+		  /* Finished */
+		  pthread_mutex_unlock(&(sp->threadLock));
+		  break;
+		}
+	      else
+		{
+		  /*
+		   * assoc->key must be valid because assoc can't change or be
+		   * removed from our chain while we hold at least one lock. If
+		   * the assoc was on our key chain then the key has not been
+		   * deleted yet.
+		   *
+		   * Now try to acquire the second lock without deadlocking.
+		   * If we fail, we need to relinquish the first lock and the
+		   * processor and then try to acquire them all again.
+		   */
+		  if (pthread_mutex_trylock(&(assoc->key->keyLock)) == EBUSY)
+		    {
+		      pthread_mutex_unlock(&(sp->threadLock));
+		      Sleep(1); // Ugly but necessary to avoid priority effects.
+		      /*
+		       * Go around again.
+		       * If pthread_key_delete has removed this assoc in the meantime,
+		       * sp->nextAssoc will point to a new assoc.
+		       */
+		      continue;
+		    }
+		}
+
+	      /* We now hold both locks */
+
+	      sp->nextAssoc = assoc->nextKey;
+
+	      /*
+	       * Key still active; pthread_key_delete
+	       * will block on these same mutexes before
+	       * it can release actual key; therefore,
+	       * key is valid and we can call the destroy
+	       * routine;
+	       */
+	      k = assoc->key;
+	      destructor = k->destructor;
+	      value = TlsGetValue(k->key);
+	      TlsSetValue (k->key, NULL);
+
+	      // Every assoc->key exists and has a destructor
+	      if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
+		{
+		  /*
+		   * Unlock both locks before the destructor runs.
+		   * POSIX says pthread_key_delete can be run from destructors,
+		   * and that probably includes with this key as target.
+		   * pthread_setspecific can also be run from destructors and
+		   * also needs to be able to access the assocs.
+		   */
+		  (void) pthread_mutex_unlock(&(sp->threadLock));
+		  (void) pthread_mutex_unlock(&(k->keyLock));
+
+		  assocsRemaining++;
+
+#ifdef __cplusplus
+
+		  try
+		    {
+		      /*
+		       * Run the caller's cleanup routine.
+		       */
+		      destructor (value);
+		    }
+		  catch (...)
+		    {
+		      /*
+		       * A system unexpected exception has occurred
+		       * running the user's destructor.
+		       * We get control back within this block in case
+		       * the application has set up it's own terminate
+		       * handler. Since we are leaving the thread we
+		       * should not get any internal pthreads
+		       * exceptions.
+		       */
+		      terminate ();
+		    }
+
+#else /* __cplusplus */
+
+		  /*
+		   * Run the caller's cleanup routine.
+		   */
+		  destructor (value);
+
+#endif /* __cplusplus */
+
+		}
+	      else
+		{
+		  /*
+		   * Remove association from both the key and thread chains
+		   * and reclaim it's memory resources.
+		   */
+		  ptw32_tkAssocDestroy (assoc);
+		  (void) pthread_mutex_unlock(&(sp->threadLock));
+		  (void) pthread_mutex_unlock(&(k->keyLock));
+		}
+	    }
+	}
+      while (assocsRemaining);
+    }
+}				/* ptw32_callUserDestroyRoutines */
diff --git a/ptw32_calloc.c b/ptw32_calloc.c
new file mode 100644
index 0000000..eea7c74
--- /dev/null
+++ b/ptw32_calloc.c
@@ -0,0 +1,56 @@
+/*
+ * ptw32_calloc.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#ifdef NEED_CALLOC
+void *
+ptw32_calloc (size_t n, size_t s)
+{
+  unsigned int m = n * s;
+  void *p;
+
+  p = malloc (m);
+  if (p == NULL)
+    return NULL;
+
+  memset (p, 0, m);
+
+  return p;
+}
+#endif
diff --git a/ptw32_cond_check_need_init.c b/ptw32_cond_check_need_init.c
new file mode 100644
index 0000000..31359ad
--- /dev/null
+++ b/ptw32_cond_check_need_init.c
@@ -0,0 +1,94 @@
+/*
+ * ptw32_cond_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+INLINE int
+ptw32_cond_check_need_init (pthread_cond_t * cond)
+{
+  int result = 0;
+
+  /*
+   * The following guarded test is specifically for statically
+   * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER).
+   *
+   * Note that by not providing this synchronisation we risk
+   * introducing race conditions into applications which are
+   * correctly written.
+   *
+   * Approach
+   * --------
+   * We know that static condition variables will not be PROCESS_SHARED
+   * so we can serialise access to internal state using
+   * Win32 Critical Sections rather than Win32 Mutexes.
+   *
+   * If using a single global lock slows applications down too much,
+   * multiple global locks could be created and hashed on some random
+   * value associated with each mutex, the pointer perhaps. At a guess,
+   * a good value for the optimal number of global locks might be
+   * the number of processors + 1.
+   *
+   */
+  EnterCriticalSection (&ptw32_cond_test_init_lock);
+
+  /*
+   * We got here possibly under race
+   * conditions. Check again inside the critical section.
+   * If a static cv has been destroyed, the application can
+   * re-initialise it only by calling pthread_cond_init()
+   * explicitly.
+   */
+  if (*cond == PTHREAD_COND_INITIALIZER)
+    {
+      result = pthread_cond_init (cond, NULL);
+    }
+  else if (*cond == NULL)
+    {
+      /*
+       * The cv has been destroyed while we were waiting to
+       * initialise it, so the operation that caused the
+       * auto-initialisation should fail.
+       */
+      result = EINVAL;
+    }
+
+  LeaveCriticalSection (&ptw32_cond_test_init_lock);
+
+  return result;
+}
diff --git a/ptw32_getprocessors.c b/ptw32_getprocessors.c
new file mode 100644
index 0000000..e60c314
--- /dev/null
+++ b/ptw32_getprocessors.c
@@ -0,0 +1,91 @@
+/*
+ * ptw32_getprocessors.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * ptw32_getprocessors()
+ *
+ * Get the number of CPUs available to the process.
+ *
+ * If the available number of CPUs is 1 then pthread_spin_lock()
+ * will block rather than spin if the lock is already owned.
+ *
+ * pthread_spin_init() calls this routine when initialising
+ * a spinlock. If the number of available processors changes
+ * (after a call to SetProcessAffinityMask()) then only
+ * newly initialised spinlocks will notice.
+ */
+int
+ptw32_getprocessors (int *count)
+{
+  DWORD_PTR vProcessCPUs;
+  DWORD_PTR vSystemCPUs;
+  int result = 0;
+
+#if defined(NEED_PROCESS_AFFINITY_MASK)
+
+  *count = 1;
+
+#else
+
+  if (GetProcessAffinityMask (GetCurrentProcess (),
+			      &vProcessCPUs, &vSystemCPUs))
+    {
+      DWORD_PTR bit;
+      int CPUs = 0;
+
+      for (bit = 1; bit != 0; bit <<= 1)
+	{
+	  if (vProcessCPUs & bit)
+	    {
+	      CPUs++;
+	    }
+	}
+      *count = CPUs;
+    }
+  else
+    {
+      result = EAGAIN;
+    }
+
+#endif
+
+  return (result);
+}
diff --git a/ptw32_is_attr.c b/ptw32_is_attr.c
new file mode 100644
index 0000000..36395f8
--- /dev/null
+++ b/ptw32_is_attr.c
@@ -0,0 +1,47 @@
+/*
+ * ptw32_is_attr.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+ptw32_is_attr (const pthread_attr_t * attr)
+{
+  /* Return 0 if the attr object is valid, non-zero otherwise. */
+
+  return (attr == NULL ||
+	  *attr == NULL || (*attr)->valid != PTW32_ATTR_VALID);
+}
diff --git a/ptw32_mutex_check_need_init.c b/ptw32_mutex_check_need_init.c
new file mode 100644
index 0000000..35ec366
--- /dev/null
+++ b/ptw32_mutex_check_need_init.c
@@ -0,0 +1,112 @@
+/*
+ * ptw32_mutex_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+static struct pthread_mutexattr_t_ ptw32_recursive_mutexattr_s =
+  {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_RECURSIVE};
+static struct pthread_mutexattr_t_ ptw32_errorcheck_mutexattr_s =
+  {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_ERRORCHECK};
+static pthread_mutexattr_t ptw32_recursive_mutexattr = &ptw32_recursive_mutexattr_s;
+static pthread_mutexattr_t ptw32_errorcheck_mutexattr = &ptw32_errorcheck_mutexattr_s;
+
+
+INLINE int
+ptw32_mutex_check_need_init (pthread_mutex_t * mutex)
+{
+  register int result = 0;
+  register pthread_mutex_t mtx;
+
+  /*
+   * The following guarded test is specifically for statically
+   * initialised mutexes (via PTHREAD_MUTEX_INITIALIZER).
+   *
+   * Note that by not providing this synchronisation we risk
+   * introducing race conditions into applications which are
+   * correctly written.
+   *
+   * Approach
+   * --------
+   * We know that static mutexes will not be PROCESS_SHARED
+   * so we can serialise access to internal state using
+   * Win32 Critical Sections rather than Win32 Mutexes.
+   *
+   * If using a single global lock slows applications down too much,
+   * multiple global locks could be created and hashed on some random
+   * value associated with each mutex, the pointer perhaps. At a guess,
+   * a good value for the optimal number of global locks might be
+   * the number of processors + 1.
+   *
+   */
+  EnterCriticalSection (&ptw32_mutex_test_init_lock);
+
+  /*
+   * We got here possibly under race
+   * conditions. Check again inside the critical section
+   * and only initialise if the mutex is valid (not been destroyed).
+   * If a static mutex has been destroyed, the application can
+   * re-initialise it only by calling pthread_mutex_init()
+   * explicitly.
+   */
+  mtx = *mutex;
+
+  if (mtx == PTHREAD_MUTEX_INITIALIZER)
+    {
+      result = pthread_mutex_init (mutex, NULL);
+    }
+  else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
+    {
+      result = pthread_mutex_init (mutex, &ptw32_recursive_mutexattr);
+    }
+  else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+    {
+      result = pthread_mutex_init (mutex, &ptw32_errorcheck_mutexattr);
+    }
+  else if (mtx == NULL)
+    {
+      /*
+       * The mutex has been destroyed while we were waiting to
+       * initialise it, so the operation that caused the
+       * auto-initialisation should fail.
+       */
+      result = EINVAL;
+    }
+
+  LeaveCriticalSection (&ptw32_mutex_test_init_lock);
+
+  return (result);
+}
diff --git a/ptw32_new.c b/ptw32_new.c
new file mode 100644
index 0000000..2812567
--- /dev/null
+++ b/ptw32_new.c
@@ -0,0 +1,91 @@
+/*
+ * ptw32_new.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+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.p)
+    {
+      tp = (ptw32_thread_t *) t.p;
+    }
+  else
+    {
+      /* No reuse threads available */
+      tp = (ptw32_thread_t *) calloc (1, sizeof(ptw32_thread_t));
+
+      if (tp == 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_processInitialize.c b/ptw32_processInitialize.c
new file mode 100644
index 0000000..d13b022
--- /dev/null
+++ b/ptw32_processInitialize.c
@@ -0,0 +1,102 @@
+/*
+ * ptw32_processInitialize.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_processInitialize (void)
+     /*
+      * ------------------------------------------------------
+      * DOCPRIVATE
+      *      This function performs process wide initialization for
+      *      the pthread library.
+      *
+      * PARAMETERS
+      *      N/A
+      *
+      * DESCRIPTION
+      *      This function performs process wide initialization for
+      *      the pthread library.
+      *      If successful, this routine sets the global variable
+      *      ptw32_processInitialized to TRUE.
+      *
+      * RESULTS
+      *              TRUE    if successful,
+      *              FALSE   otherwise
+      *
+      * ------------------------------------------------------
+      */
+{
+  if (ptw32_processInitialized)
+    {
+      /* 
+       * Ignore if already initialized. this is useful for 
+       * programs that uses a non-dll pthread
+       * library. Such programs must call ptw32_processInitialize() explicitly,
+       * since this initialization routine is automatically called only when
+       * the dll is loaded.
+       */
+      return PTW32_TRUE;
+    }
+
+  ptw32_processInitialized = PTW32_TRUE;
+
+  /*
+   * Initialize Keys
+   */
+  if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) ||
+      (pthread_key_create (&ptw32_cleanupKey, NULL) != 0))
+    {
+
+      ptw32_processTerminate ();
+    }
+
+  /* 
+   * Set up the global locks.
+   */
+  InitializeCriticalSection (&ptw32_thread_reuse_lock);
+  InitializeCriticalSection (&ptw32_mutex_test_init_lock);
+  InitializeCriticalSection (&ptw32_cond_list_lock);
+  InitializeCriticalSection (&ptw32_cond_test_init_lock);
+  InitializeCriticalSection (&ptw32_rwlock_test_init_lock);
+  InitializeCriticalSection (&ptw32_spinlock_test_init_lock);
+
+  return (ptw32_processInitialized);
+
+}				/* processInitialize */
diff --git a/ptw32_processTerminate.c b/ptw32_processTerminate.c
new file mode 100644
index 0000000..d2dfa7a
--- /dev/null
+++ b/ptw32_processTerminate.c
@@ -0,0 +1,114 @@
+/*
+ * ptw32_processTerminate.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_processTerminate (void)
+     /*
+      * ------------------------------------------------------
+      * DOCPRIVATE
+      *      This function performs process wide termination for
+      *      the pthread library.
+      *
+      * PARAMETERS
+      *      N/A
+      *
+      * DESCRIPTION
+      *      This function performs process wide termination for
+      *      the pthread library.
+      *      This routine sets the global variable
+      *      ptw32_processInitialized to FALSE
+      *
+      * RESULTS
+      *              N/A
+      *
+      * ------------------------------------------------------
+      */
+{
+  if (ptw32_processInitialized)
+    {
+      ptw32_thread_t * tp, * tpNext;
+
+      if (ptw32_selfThreadKey != NULL)
+	{
+	  /*
+	   * Release ptw32_selfThreadKey
+	   */
+	  pthread_key_delete (ptw32_selfThreadKey);
+
+	  ptw32_selfThreadKey = NULL;
+	}
+
+      if (ptw32_cleanupKey != NULL)
+	{
+	  /*
+	   * Release ptw32_cleanupKey
+	   */
+	  pthread_key_delete (ptw32_cleanupKey);
+
+	  ptw32_cleanupKey = NULL;
+	}
+
+      EnterCriticalSection (&ptw32_thread_reuse_lock);
+
+      tp = ptw32_threadReuseTop;
+      while (tp != PTW32_THREAD_REUSE_EMPTY)
+	{
+	  tpNext = tp->prevReuse;
+	  free (tp);
+	  tp = tpNext;
+	}
+
+      LeaveCriticalSection (&ptw32_thread_reuse_lock);
+
+      /* 
+       * Destroy the global locks and other objects.
+       */
+      DeleteCriticalSection (&ptw32_spinlock_test_init_lock);
+      DeleteCriticalSection (&ptw32_rwlock_test_init_lock);
+      DeleteCriticalSection (&ptw32_cond_test_init_lock);
+      DeleteCriticalSection (&ptw32_cond_list_lock);
+      DeleteCriticalSection (&ptw32_mutex_test_init_lock);
+      DeleteCriticalSection (&ptw32_thread_reuse_lock);
+
+      ptw32_processInitialized = PTW32_FALSE;
+    }
+
+}				/* processTerminate */
diff --git a/ptw32_relmillisecs.c b/ptw32_relmillisecs.c
new file mode 100644
index 0000000..f3e7b76
--- /dev/null
+++ b/ptw32_relmillisecs.c
@@ -0,0 +1,120 @@
+/*
+ * ptw32_relmillisecs.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef _UWIN
+//#include <process.h>
+#endif
+#include "pthread.h"
+#include "implement.h"
+#ifndef NEED_FTIME
+#include <sys/timeb.h>
+#endif
+
+
+INLINE DWORD
+ptw32_relmillisecs (const struct timespec * abstime)
+{
+  const int64_t NANOSEC_PER_MILLISEC = 1000000;
+  const int64_t MILLISEC_PER_SEC = 1000;
+  DWORD milliseconds;
+  int64_t tmpAbsMilliseconds;
+  int64_t tmpCurrMilliseconds;
+#ifdef NEED_FTIME
+  struct timespec currSysTime;
+  FILETIME ft;
+  SYSTEMTIME st;
+#else /* ! NEED_FTIME */
+  struct _timeb currSysTime;
+#endif /* NEED_FTIME */
+
+
+  /* 
+   * Calculate timeout as milliseconds from current system time. 
+   */
+
+  /*
+   * subtract current system time from abstime in a way that checks
+   * that abstime is never in the past, or is never equivalent to the
+   * defined INFINITE value (0xFFFFFFFF).
+   *
+   * Assume all integers are unsigned, i.e. cannot test if less than 0.
+   */
+  tmpAbsMilliseconds =  (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
+  tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
+
+  /* get current system time */
+
+#ifdef NEED_FTIME
+
+  GetSystemTime(&st);
+  SystemTimeToFileTime(&st, &ft);
+  /*
+   * GetSystemTimeAsFileTime(&ft); would be faster,
+   * but it does not exist on WinCE
+   */
+
+  ptw32_filetime_to_timespec(&ft, &currSysTime);
+
+  tmpCurrMilliseconds = (int64_t)currSysTime.tv_sec * MILLISEC_PER_SEC;
+  tmpCurrMilliseconds += ((int64_t)currSysTime.tv_nsec + (NANOSEC_PER_MILLISEC/2))
+			   / NANOSEC_PER_MILLISEC;
+
+#else /* ! NEED_FTIME */
+
+  _ftime(&currSysTime);
+
+  tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC;
+  tmpCurrMilliseconds += (int64_t) currSysTime.millitm;
+
+#endif /* NEED_FTIME */
+
+  if (tmpAbsMilliseconds > tmpCurrMilliseconds)
+    {
+      milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds);
+      if (milliseconds == INFINITE)
+        {
+          /* Timeouts must be finite */
+          milliseconds--;
+        }
+    }
+  else
+    {
+      /* The abstime given is in the past */
+      milliseconds = 0;
+    }
+
+  return milliseconds;
+}
diff --git a/ptw32_reuse.c b/ptw32_reuse.c
new file mode 100644
index 0000000..0e86984
--- /dev/null
+++ b/ptw32_reuse.c
@@ -0,0 +1,147 @@
+/*
+ * ptw32_threadReuse.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * 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 ptw32_thread_t_ struct is not freed until the process exits.
+ * 
+ * The thread reuse stack is a simple LILO stack managed through a singly
+ * 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 counters 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)
+ *
+ */
+
+/*
+ * Pop a clean pthread_t struct off the reuse stack.
+ */
+pthread_t
+ptw32_threadReusePop (void)
+{
+  pthread_t t = {NULL, 0};
+
+  EnterCriticalSection (&ptw32_thread_reuse_lock);
+
+  if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop)
+    {
+      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);
+
+  return t;
+
+}
+
+/*
+ * 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);
+
+  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 */
+#ifdef PTW32_THREAD_ID_REUSE_INCREMENT
+  tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT;
+#else
+  tp->ptHandle.x++;
+#endif
+
+  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_rwlock_cancelwrwait.c b/ptw32_rwlock_cancelwrwait.c
new file mode 100644
index 0000000..a057bd1
--- /dev/null
+++ b/ptw32_rwlock_cancelwrwait.c
@@ -0,0 +1,50 @@
+/*
+ * ptw32_rwlock_cancelwrwait.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+void
+ptw32_rwlock_cancelwrwait (void *arg)
+{
+  pthread_rwlock_t rwl = (pthread_rwlock_t) arg;
+
+  rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount;
+  rwl->nCompletedSharedAccessCount = 0;
+
+  (void) pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+  (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+}
diff --git a/ptw32_rwlock_check_need_init.c b/ptw32_rwlock_check_need_init.c
new file mode 100644
index 0000000..ea2561e
--- /dev/null
+++ b/ptw32_rwlock_check_need_init.c
@@ -0,0 +1,93 @@
+/*
+ * pthread_rwlock_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+INLINE int
+ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock)
+{
+  int result = 0;
+
+  /*
+   * The following guarded test is specifically for statically
+   * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER).
+   *
+   * Note that by not providing this synchronisation we risk
+   * introducing race conditions into applications which are
+   * correctly written.
+   *
+   * Approach
+   * --------
+   * We know that static rwlocks will not be PROCESS_SHARED
+   * so we can serialise access to internal state using
+   * Win32 Critical Sections rather than Win32 Mutexes.
+   *
+   * If using a single global lock slows applications down too much,
+   * multiple global locks could be created and hashed on some random
+   * value associated with each mutex, the pointer perhaps. At a guess,
+   * a good value for the optimal number of global locks might be
+   * the number of processors + 1.
+   *
+   */
+  EnterCriticalSection (&ptw32_rwlock_test_init_lock);
+
+  /*
+   * We got here possibly under race
+   * conditions. Check again inside the critical section
+   * and only initialise if the rwlock is valid (not been destroyed).
+   * If a static rwlock has been destroyed, the application can
+   * re-initialise it only by calling pthread_rwlock_init()
+   * explicitly.
+   */
+  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+    {
+      result = pthread_rwlock_init (rwlock, NULL);
+    }
+  else if (*rwlock == NULL)
+    {
+      /*
+       * The rwlock has been destroyed while we were waiting to
+       * initialise it, so the operation that caused the
+       * auto-initialisation should fail.
+       */
+      result = EINVAL;
+    }
+
+  LeaveCriticalSection (&ptw32_rwlock_test_init_lock);
+
+  return result;
+}
diff --git a/ptw32_semwait.c b/ptw32_semwait.c
new file mode 100644
index 0000000..8b23d11
--- /dev/null
+++ b/ptw32_semwait.c
@@ -0,0 +1,118 @@
+/*
+ * ptw32_semwait.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef _UWIN
+//#   include <process.h>
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_semwait (sem_t * sem)
+     /*
+      * ------------------------------------------------------
+      * DESCRIPTION
+      *      This function waits on a POSIX semaphore. If the
+      *      semaphore value is greater than zero, it decreases
+      *      its value by one. If the semaphore value is zero, then
+      *      the calling thread (or process) is blocked until it can
+      *      successfully decrease the value.
+      *
+      *      Unlike sem_wait(), this routine is non-cancelable.
+      *
+      * RESULTS
+      *              0               successfully decreased semaphore,
+      *              -1              failed, error in errno.
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore,
+      *              ENOSYS          semaphores are not supported,
+      *              EINTR           the function was interrupted by a signal,
+      *              EDEADLK         a deadlock condition was detected.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = *sem;
+
+  if (s == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      if ((result = pthread_mutex_lock (&s->lock)) == 0)
+        {
+          int v = --s->value;
+
+          (void) pthread_mutex_unlock (&s->lock);
+
+          if (v < 0)
+            {
+              /* Must wait */
+              if (WaitForSingleObject (s->sem, INFINITE) == WAIT_OBJECT_0)
+		{
+#ifdef NEED_SEM
+		  if (pthread_mutex_lock (&s->lock) == 0)
+		    {
+		      if (s->leftToUnblock > 0)
+			{
+			  --s->leftToUnblock;
+			  SetEvent(s->sem);
+			}
+		      (void) pthread_mutex_unlock (&s->lock);
+		    }
+#endif
+		  return 0;
+		}
+            }
+          else
+	    {
+	      return 0;
+	    }
+        }
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  return 0;
+
+}				/* ptw32_semwait */
diff --git a/ptw32_spinlock_check_need_init.c b/ptw32_spinlock_check_need_init.c
new file mode 100644
index 0000000..bf45bc3
--- /dev/null
+++ b/ptw32_spinlock_check_need_init.c
@@ -0,0 +1,81 @@
+/*
+ * ptw32_spinlock_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+INLINE int
+ptw32_spinlock_check_need_init (pthread_spinlock_t * lock)
+{
+  int result = 0;
+
+  /*
+   * The following guarded test is specifically for statically
+   * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER).
+   *
+   * Note that by not providing this synchronisation we risk
+   * introducing race conditions into applications which are
+   * correctly written.
+   */
+  EnterCriticalSection (&ptw32_spinlock_test_init_lock);
+
+  /*
+   * We got here possibly under race
+   * conditions. Check again inside the critical section
+   * and only initialise if the spinlock is valid (not been destroyed).
+   * If a static spinlock has been destroyed, the application can
+   * re-initialise it only by calling pthread_spin_init()
+   * explicitly.
+   */
+  if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+    {
+      result = pthread_spin_init (lock, PTHREAD_PROCESS_PRIVATE);
+    }
+  else if (*lock == NULL)
+    {
+      /*
+       * The spinlock has been destroyed while we were waiting to
+       * initialise it, so the operation that caused the
+       * auto-initialisation should fail.
+       */
+      result = EINVAL;
+    }
+
+  LeaveCriticalSection (&ptw32_spinlock_test_init_lock);
+
+  return (result);
+}
diff --git a/ptw32_threadDestroy.c b/ptw32_threadDestroy.c
new file mode 100644
index 0000000..eb9abfc
--- /dev/null
+++ b/ptw32_threadDestroy.c
@@ -0,0 +1,82 @@
+/*
+ * ptw32_threadDestroy.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_threadDestroy (pthread_t thread)
+{
+  ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+  ptw32_thread_t threadCopy;
+
+  if (tp != NULL)
+    {
+      /*
+       * Copy thread state so that the thread can be atomically NULLed.
+       */
+      memcpy (&threadCopy, tp, sizeof (threadCopy));
+
+      /*
+       * Thread ID structs are never freed. They're NULLed and reused.
+       * This also sets the thread to PThreadStateInitial (invalid).
+       */
+      ptw32_threadReusePush (thread);
+
+      /* Now work on the copy. */
+      if (threadCopy.cancelEvent != NULL)
+	{
+	  CloseHandle (threadCopy.cancelEvent);
+	}
+
+      (void) pthread_mutex_destroy(&threadCopy.cancelLock);
+      (void) pthread_mutex_destroy(&threadCopy.threadLock);
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
+      /*
+       * See documentation for endthread vs endthreadex.
+       */
+      if (threadCopy.threadH != 0)
+	{
+	  CloseHandle (threadCopy.threadH);
+	}
+#endif
+
+    }
+}				/* ptw32_threadDestroy */
+
diff --git a/ptw32_threadStart.c b/ptw32_threadStart.c
new file mode 100644
index 0000000..5c0fe0e
--- /dev/null
+++ b/ptw32_threadStart.c
@@ -0,0 +1,360 @@
+/*
+ * ptw32_threadStart.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#ifdef __CLEANUP_SEH
+
+static DWORD
+ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
+{
+  switch (ep->ExceptionRecord->ExceptionCode)
+    {
+    case EXCEPTION_PTW32_SERVICES:
+      {
+	DWORD param;
+	DWORD numParams = ep->ExceptionRecord->NumberParameters;
+
+	numParams = (numParams > 3) ? 3 : numParams;
+
+	for (param = 0; param < numParams; param++)
+	  {
+	    ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
+	  }
+
+	return EXCEPTION_EXECUTE_HANDLER;
+	break;
+      }
+    default:
+      {
+	/*
+	 * A system unexpected exception has occurred running the user's
+	 * routine. We need to cleanup before letting the exception
+	 * out of thread scope.
+	 */
+	pthread_t self = pthread_self ();
+
+	(void) pthread_mutex_destroy (&((ptw32_thread_t *)self.p)->cancelLock);
+	ptw32_callUserDestroyRoutines (self);
+
+	return EXCEPTION_CONTINUE_SEARCH;
+	break;
+      }
+    }
+}
+
+#elif defined(__CLEANUP_CXX)
+
+#if defined(_MSC_VER)
+# include <eh.h>
+#elif defined(__WATCOMC__)
+# include <eh.h>
+# include <exceptio.h>
+typedef terminate_handler
+  terminate_function;
+#else
+# if defined(__GNUC__) && __GNUC__ < 3
+#   include <new.h>
+# else
+#   include <new>
+using
+  std::terminate_handler;
+using
+  std::terminate;
+using
+  std::set_terminate;
+# endif
+typedef terminate_handler
+  terminate_function;
+#endif
+
+static terminate_function
+  ptw32_oldTerminate;
+
+void
+ptw32_terminate ()
+{
+  set_terminate (ptw32_oldTerminate);
+  (void) pthread_win32_thread_detach_np ();
+  terminate ();
+}
+
+#endif
+
+#if ! defined (__MINGW32__) || (defined (__MSVCRT__) && ! defined (__DMC__))
+unsigned
+  __stdcall
+#else
+void
+#endif
+ptw32_threadStart (void *vthreadParms)
+{
+  ThreadParms * threadParms = (ThreadParms *) vthreadParms;
+  pthread_t self;
+  ptw32_thread_t * sp;
+  void *(*start) (void *);
+  void * arg;
+
+#ifdef __CLEANUP_SEH
+  DWORD
+  ei[] = { 0, 0, 0 };
+#endif
+
+#ifdef __CLEANUP_C
+  int setjmp_rc;
+#endif
+
+  void * status = (void *) 0;
+
+  self = threadParms->tid;
+  sp = (ptw32_thread_t *) self.p;
+  start = threadParms->start;
+  arg = threadParms->arg;
+
+  free (threadParms);
+
+#if defined (__MINGW32__) && ! defined (__MSVCRT__)
+  /*
+   * beginthread does not return the thread id and is running
+   * before it returns us the thread handle, and so we do it here.
+   */
+  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 (&sp->cancelLock) == 0)
+    {
+      (void) pthread_mutex_unlock (&sp->cancelLock);
+    }
+#endif
+
+  pthread_setspecific (ptw32_selfThreadKey, sp);
+
+  sp->state = PThreadStateRunning;
+
+#ifdef __CLEANUP_SEH
+
+  __try
+  {
+    /*
+     * Run the caller's routine;
+     */
+    status = sp->exitStatus = (*start) (arg);
+
+#ifdef _UWIN
+    if (--pthread_count <= 0)
+      exit (0);
+#endif
+
+  }
+  __except (ExceptionFilter (GetExceptionInformation (), ei))
+  {
+    switch (ei[0])
+      {
+      case PTW32_EPS_CANCEL:
+	status = sp->exitStatus = PTHREAD_CANCELED;
+#ifdef _UWIN
+	if (--pthread_count <= 0)
+	  exit (0);
+#endif
+	break;
+      case PTW32_EPS_EXIT:
+	status = sp->exitStatus;
+	break;
+      default:
+	status = sp->exitStatus = PTHREAD_CANCELED;
+	break;
+      }
+  }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+  setjmp_rc = setjmp (sp->start_mark);
+
+  if (0 == setjmp_rc)
+    {
+
+      /*
+       * Run the caller's routine;
+       */
+      status = sp->exitStatus = (*start) (arg);
+    }
+  else
+    {
+      switch (setjmp_rc)
+	{
+	case PTW32_EPS_CANCEL:
+	  status = sp->exitStatus = PTHREAD_CANCELED;
+	  break;
+	case PTW32_EPS_EXIT:
+	  status = sp->exitStatus;
+	  break;
+	default:
+	  status = sp->exitStatus = PTHREAD_CANCELED;
+	  break;
+	}
+    }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+  ptw32_oldTerminate = set_terminate (&ptw32_terminate);
+
+  try
+  {
+    /*
+     * Run the caller's routine in a nested try block so that we
+     * can run the user's terminate function, which may call
+     * pthread_exit() or be canceled.
+     */
+    try
+    {
+      status = sp->exitStatus = (*start) (arg);
+    }
+    catch (ptw32_exception &)
+    {
+      /*
+       * Pass these through to the outer block.
+       */
+      throw;
+    }
+    catch (...)
+    {
+      /*
+       * We want to run the user's terminate function if supplied.
+       * That function may call pthread_exit() or be canceled, which will
+       * be handled by the outer try block.
+       *
+       * ptw32_terminate() will be called if there is no user
+       * supplied function.
+       */
+
+      terminate_function
+	term_func = set_terminate (0);
+      set_terminate (term_func);
+
+      if (term_func != 0)
+	{
+	  term_func ();
+	}
+
+      throw;
+    }
+  }
+  catch (ptw32_exception_cancel &)
+  {
+    /*
+     * Thread was canceled.
+     */
+    status = sp->exitStatus = PTHREAD_CANCELED;
+  }
+  catch (ptw32_exception_exit &)
+  {
+    /*
+     * Thread was exited via pthread_exit().
+     */
+    status = sp->exitStatus;
+  }
+  catch (...)
+  {
+    /*
+     * A system unexpected exception has occurred running the user's
+     * terminate routine. We get control back within this block - cleanup
+     * and release the exception out of thread scope.
+     */
+    status = sp->exitStatus = PTHREAD_CANCELED;
+    (void) pthread_mutex_lock (&sp->cancelLock);
+    sp->state = PThreadStateException;
+    (void) pthread_mutex_unlock (&sp->cancelLock);
+    (void) pthread_win32_thread_detach_np ();
+    (void) set_terminate (ptw32_oldTerminate);
+    throw;
+
+    /*
+     * Never reached.
+     */
+  }
+
+  (void) set_terminate (ptw32_oldTerminate);
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+#endif /* __CLEANUP_C */
+#endif /* __CLEANUP_SEH */
+
+#if defined(PTW32_STATIC_LIB)
+  /*
+   * We need to cleanup the pthread now if we have
+   * been statically linked, in which case the cleanup
+   * in dllMain won't get done. Joinable threads will
+   * only be partially cleaned up and must be fully cleaned
+   * up by pthread_join() or pthread_detach().
+   *
+   * Note: if this library has been statically linked,
+   * implicitly created pthreads (those created
+   * for Win32 threads which have called pthreads routines)
+   * must be cleaned up explicitly by the application
+   * (by calling pthread_win32_thread_detach_np()).
+   * For the dll, dllMain will do the cleanup automatically.
+   */
+  (void) pthread_win32_thread_detach_np ();
+#endif
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
+  _endthreadex ((unsigned) status);
+#else
+  _endthread ();
+#endif
+
+  /*
+   * Never reached.
+   */
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
+  return (unsigned) status;
+#endif
+
+}				/* ptw32_threadStart */
diff --git a/ptw32_throw.c b/ptw32_throw.c
new file mode 100644
index 0000000..493f4e4
--- /dev/null
+++ b/ptw32_throw.c
@@ -0,0 +1,167 @@
+/*
+ * ptw32_throw.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * ptw32_throw
+ *
+ * All canceled and explicitly exited POSIX threads go through
+ * here. This routine knows how to exit both POSIX initiated threads and
+ * 'implicit' POSIX threads for each of the possible language modes (C,
+ * C++, and SEH).
+ */
+void
+ptw32_throw (DWORD exception)
+{
+  /*
+   * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
+   * unnecessarily.
+   */
+  ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+#ifdef __CLEANUP_SEH
+  DWORD exceptionInformation[3];
+#endif
+
+  if (exception != PTW32_EPS_CANCEL && exception != PTW32_EPS_EXIT)
+    {
+      /* Should never enter here */
+      exit (1);
+    }
+
+  if (NULL == sp || sp->implicit)
+    {
+      /*
+       * We're inside a non-POSIX initialised Win32 thread
+       * so there is no point to jump or throw back to. Just do an
+       * explicit thread exit here after cleaning up POSIX
+       * residue (i.e. cleanup handlers, POSIX thread handle etc).
+       */
+      unsigned exitCode = 0;
+
+      switch (exception)
+	{
+	case PTW32_EPS_CANCEL:
+	  exitCode = (unsigned) PTHREAD_CANCELED;
+	  break;
+	case PTW32_EPS_EXIT:
+	  exitCode = (unsigned) sp->exitStatus;;
+	  break;
+	}
+
+#if defined(PTW32_STATIC_LIB)
+
+      pthread_win32_thread_detach_np ();
+
+#endif
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
+      _endthreadex (exitCode);
+#else
+      _endthread ();
+#endif
+
+    }
+
+#ifdef __CLEANUP_SEH
+
+
+  exceptionInformation[0] = (DWORD) (exception);
+  exceptionInformation[1] = (DWORD) (0);
+  exceptionInformation[2] = (DWORD) (0);
+
+  RaiseException (EXCEPTION_PTW32_SERVICES, 0, 3, exceptionInformation);
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+  ptw32_pop_cleanup_all (1);
+  longjmp (sp->start_mark, exception);
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+  switch (exception)
+    {
+    case PTW32_EPS_CANCEL:
+      throw ptw32_exception_cancel ();
+      break;
+    case PTW32_EPS_EXIT:
+      throw ptw32_exception_exit ();
+      break;
+    }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+  /* Never reached */
+}
+
+
+void
+ptw32_pop_cleanup_all (int execute)
+{
+  while (NULL != ptw32_pop_cleanup (execute))
+    {
+    }
+}
+
+
+DWORD
+ptw32_get_exception_services_code (void)
+{
+#ifdef __CLEANUP_SEH
+
+  return EXCEPTION_PTW32_SERVICES;
+
+#else
+
+  return (DWORD) NULL;
+
+#endif
+}
diff --git a/ptw32_timespec.c b/ptw32_timespec.c
new file mode 100644
index 0000000..6a2cb56
--- /dev/null
+++ b/ptw32_timespec.c
@@ -0,0 +1,83 @@
+/*
+ * ptw32_timespec.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#ifdef NEED_FTIME
+
+/*
+ * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
+ */
+#define PTW32_TIMESPEC_TO_FILETIME_OFFSET \
+	  ( ((LONGLONG) 27111902 << 32) + (LONGLONG) 3577643008 )
+
+INLINE void
+ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft)
+     /*
+      * -------------------------------------------------------------------
+      * converts struct timespec
+      * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+      * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+      * expressed in 100 nanoseconds from Jan 1, 1601,
+      * -------------------------------------------------------------------
+      */
+{
+  *(LONGLONG *) ft = ts->tv_sec * 10000000
+    + (ts->tv_nsec + 50) / 100 + PTW32_TIMESPEC_TO_FILETIME_OFFSET;
+}
+
+INLINE void
+ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts)
+     /*
+      * -------------------------------------------------------------------
+      * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+      * expressed in 100 nanoseconds from Jan 1, 1601,
+      * into struct timespec
+      * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+      * -------------------------------------------------------------------
+      */
+{
+  ts->tv_sec =
+    (int) ((*(LONGLONG *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
+  ts->tv_nsec =
+    (int) ((*(LONGLONG *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET -
+	    ((LONGLONG) ts->tv_sec * (LONGLONG) 10000000)) * 100);
+}
+
+#endif /* NEED_FTIME */
diff --git a/ptw32_tkAssocCreate.c b/ptw32_tkAssocCreate.c
new file mode 100644
index 0000000..5ba24bb
--- /dev/null
+++ b/ptw32_tkAssocCreate.c
@@ -0,0 +1,118 @@
+/*
+ * ptw32_tkAssocCreate.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_tkAssocCreate (ptw32_thread_t * sp, pthread_key_t key)
+     /*
+      * -------------------------------------------------------------------
+      * This routine creates an association that
+      * is unique for the given (thread,key) combination.The association 
+      * is referenced by both the thread and the key.
+      * This association allows us to determine what keys the
+      * current thread references and what threads a given key
+      * references.
+      * See the detailed description
+      * at the beginning of this file for further details.
+      *
+      * Notes:
+      *      1)      New associations are pushed to the beginning of the
+      *              chain so that the internal ptw32_selfThreadKey association
+      *              is always last, thus allowing selfThreadExit to
+      *              be implicitly called last by pthread_exit.
+      *      2)      
+      *
+      * Parameters:
+      *              thread
+      *                      current running thread.
+      *              key
+      *                      key on which to create an association.
+      * Returns:
+      *       0              - if successful,
+      *       ENOMEM         - not enough memory to create assoc or other object
+      *       EINVAL         - an internal error occurred
+      *       ENOSYS         - an internal error occurred
+      * -------------------------------------------------------------------
+      */
+{
+  ThreadKeyAssoc *assoc;
+
+  /*
+   * Have to create an association and add it
+   * to both the key and the thread.
+   *
+   * Both key->keyLock and thread->threadLock are locked on
+   * entry to this routine.
+   */
+  assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
+
+  if (assoc == NULL)
+    {
+      return ENOMEM;
+    }
+
+  assoc->thread = sp;
+  assoc->key = key;
+
+  /*
+   * Register assoc with key
+   */
+  assoc->prevThread = NULL;
+  assoc->nextThread = (ThreadKeyAssoc *) key->threads;
+  if (assoc->nextThread != NULL)
+    {
+      assoc->nextThread->prevThread = assoc;
+    }
+  key->threads = (void *) assoc;
+
+  /*
+   * Register assoc with thread
+   */
+  assoc->prevKey = NULL;
+  assoc->nextKey = (ThreadKeyAssoc *) sp->keys;
+  if (assoc->nextKey != NULL)
+    {
+      assoc->nextKey->prevKey = assoc;
+    }
+  sp->keys = (void *) assoc;
+
+  return (0);
+
+}				/* ptw32_tkAssocCreate */
diff --git a/ptw32_tkAssocDestroy.c b/ptw32_tkAssocDestroy.c
new file mode 100644
index 0000000..a7842ea
--- /dev/null
+++ b/ptw32_tkAssocDestroy.c
@@ -0,0 +1,114 @@
+/*
+ * ptw32_tkAssocDestroy.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
+     /*
+      * -------------------------------------------------------------------
+      * This routine releases all resources for the given ThreadKeyAssoc
+      * once it is no longer being referenced
+      * ie) either the key or thread has stopped referencing it.
+      *
+      * Parameters:
+      *              assoc
+      *                      an instance of ThreadKeyAssoc.
+      * Returns:
+      *      N/A
+      * -------------------------------------------------------------------
+      */
+{
+
+  /*
+   * Both key->keyLock and thread->threadLock are locked on
+   * entry to this routine.
+   */
+  if (assoc != NULL)
+    {
+      ThreadKeyAssoc * prev, * next;
+
+      /* Remove assoc from thread's keys chain */
+      prev = assoc->prevKey;
+      next = assoc->nextKey;
+      if (prev != NULL)
+	{
+	  prev->nextKey = next;
+	}
+      if (next != NULL)
+	{
+	  next->prevKey = prev;
+	}
+
+      if (assoc->thread->keys == assoc)
+	{
+	  /* We're at the head of the thread's keys chain */
+	  assoc->thread->keys = next;
+	}
+      if (assoc->thread->nextAssoc == assoc)
+	{
+	  /*
+	   * Thread is exiting and we're deleting the assoc to be processed next.
+	   * Hand thread the assoc after this one.
+	   */
+	  assoc->thread->nextAssoc = next;
+	}
+
+      /* Remove assoc from key's threads chain */
+      prev = assoc->prevThread;
+      next = assoc->nextThread;
+      if (prev != NULL)
+	{
+	  prev->nextThread = next;
+	}
+      if (next != NULL)
+	{
+	  next->prevThread = prev;
+	}
+
+      if (assoc->key->threads == assoc)
+	{
+	  /* We're at the head of the key's threads chain */
+	  assoc->key->threads = next;
+	}
+
+      free (assoc);
+    }
+
+}				/* ptw32_tkAssocDestroy */
diff --git a/rwlock.c b/rwlock.c
new file mode 100644
index 0000000..4a3cd25
--- /dev/null
+++ b/rwlock.c
@@ -0,0 +1,51 @@
+/*
+ * rwlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "ptw32_rwlock_check_need_init.c"
+#include "ptw32_rwlock_cancelwrwait.c"
+#include "pthread_rwlock_init.c"
+#include "pthread_rwlock_destroy.c"
+#include "pthread_rwlockattr_init.c"
+#include "pthread_rwlockattr_destroy.c"
+#include "pthread_rwlockattr_getpshared.c"
+#include "pthread_rwlockattr_setpshared.c"
+#include "pthread_rwlock_rdlock.c"
+#include "pthread_rwlock_timedrdlock.c"
+#include "pthread_rwlock_wrlock.c"
+#include "pthread_rwlock_timedwrlock.c"
+#include "pthread_rwlock_unlock.c"
+#include "pthread_rwlock_tryrdlock.c"
+#include "pthread_rwlock_trywrlock.c"
diff --git a/sched.c b/sched.c
new file mode 100644
index 0000000..ed30ea7
--- /dev/null
+++ b/sched.c
@@ -0,0 +1,53 @@
+/*
+ * sched.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+#include "pthread_attr_setschedpolicy.c"
+#include "pthread_attr_getschedpolicy.c"
+#include "pthread_attr_setschedparam.c"
+#include "pthread_attr_getschedparam.c"
+#include "pthread_attr_setinheritsched.c"
+#include "pthread_attr_getinheritsched.c"
+#include "pthread_setschedparam.c"
+#include "pthread_getschedparam.c"
+#include "sched_get_priority_max.c"
+#include "sched_get_priority_min.c"
+#include "sched_setscheduler.c"
+#include "sched_getscheduler.c"
+#include "sched_yield.c"
diff --git a/sched.h b/sched.h
new file mode 100644
index 0000000..dfb8e93
--- /dev/null
+++ b/sched.h
@@ -0,0 +1,178 @@
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ *      Provides an implementation of POSIX realtime extensions
+ *      as defined in 
+ *
+ *              POSIX 1003.1b-1993      (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+#ifndef _SCHED_H
+#define _SCHED_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+#  ifdef PTW32_BUILD
+#    define PTW32_DLLPORT __declspec (dllexport)
+#  else
+#    define PTW32_DLLPORT __declspec (dllimport)
+#  endif
+#else
+#  define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+#  if defined(WINCE)
+#    define NEED_ERRNO
+#    define NEED_SEM
+#  endif
+#  if defined(_UWIN) || defined(__MINGW32__)
+#    define HAVE_MODE_T
+#  endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if defined(__MINGW32__) || defined(_UWIN)
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+/* For pid_t */
+#  include <sys/types.h>
+/* Required by Unix 98 */
+#  include <time.h>
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+#else
+typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+  SCHED_OTHER = 0,
+  SCHED_FIFO,
+  SCHED_RR,
+  SCHED_MIN   = SCHED_OTHER,
+  SCHED_MAX   = SCHED_RR
+};
+
+struct sched_param {
+  int sched_priority;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif                          /* __cplusplus */
+
+PTW32_DLLPORT int __cdecl sched_yield (void);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+  ( errno = ENOTSUP, (int) -1 )
+
+
+#ifdef __cplusplus
+}                               /* End of extern "C" */
+#endif                          /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif                          /* !_SCHED_H */
+
diff --git a/sched_get_priority_max.c b/sched_get_priority_max.c
new file mode 100644
index 0000000..cabf232
--- /dev/null
+++ b/sched_get_priority_max.c
@@ -0,0 +1,134 @@
+/*
+ * sched_get_priority_max.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+/*
+ * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and 
+ * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
+ * 
+ * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
+ * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
+ * highest priority use smaller numbers) and the following happens:
+ * 
+ * sched_get_priority_min() returns 5
+ * sched_get_priority_max() returns 1
+ *
+ * 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.
+ */
+
+
+int
+sched_get_priority_max (int policy)
+{
+  if (policy < SCHED_MIN || policy > SCHED_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+  /* WinCE? */
+  return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#else
+  /* This is independent of scheduling policy in Win32. */
+  return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#endif
+}
diff --git a/sched_get_priority_min.c b/sched_get_priority_min.c
new file mode 100644
index 0000000..9c4f859
--- /dev/null
+++ b/sched_get_priority_min.c
@@ -0,0 +1,135 @@
+/*
+ * sched_get_priority_min.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+/*
+ * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and 
+ * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
+ * 
+ * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
+ * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
+ * highest priority use smaller numbers) and the following happens:
+ * 
+ * sched_get_priority_min() returns 5
+ * sched_get_priority_max() returns 1
+ *
+ * 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.
+ *
+ */
+
+
+int
+sched_get_priority_min (int policy)
+{
+  if (policy < SCHED_MIN || policy > SCHED_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+  /* WinCE? */
+  return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#else
+  /* This is independent of scheduling policy in Win32. */
+  return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#endif
+}
diff --git a/sched_getscheduler.c b/sched_getscheduler.c
new file mode 100644
index 0000000..9bc819e
--- /dev/null
+++ b/sched_getscheduler.c
@@ -0,0 +1,69 @@
+/*
+ * sched_getscheduler.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_getscheduler (pid_t pid)
+{
+  /*
+   * Win32 only has one policy which we call SCHED_OTHER.
+   * However, we try to provide other valid side-effects
+   * such as EPERM and ESRCH errors.
+   */
+  if (0 != pid)
+    {
+      int selfPid = (int) GetCurrentProcessId ();
+
+      if (pid != selfPid)
+	{
+	  HANDLE h =
+	    OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) pid);
+
+	  if (NULL == h)
+	    {
+	      errno =
+		(GetLastError () ==
+		 (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+	      return -1;
+	    }
+	}
+    }
+
+  return SCHED_OTHER;
+}
diff --git a/sched_setscheduler.c b/sched_setscheduler.c
new file mode 100644
index 0000000..4e060c7
--- /dev/null
+++ b/sched_setscheduler.c
@@ -0,0 +1,81 @@
+/*
+ * sched_setscheduler.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_setscheduler (pid_t pid, int policy)
+{
+  /*
+   * Win32 only has one policy which we call SCHED_OTHER.
+   * However, we try to provide other valid side-effects
+   * such as EPERM and ESRCH errors. Choosing to check
+   * for a valid policy last allows us to get the most value out
+   * of this function.
+   */
+  if (0 != pid)
+    {
+      int selfPid = (int) GetCurrentProcessId ();
+
+      if (pid != selfPid)
+	{
+	  HANDLE h =
+	    OpenProcess (PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) pid);
+
+	  if (NULL == h)
+	    {
+	      errno =
+		(GetLastError () ==
+		 (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+	      return -1;
+	    }
+	}
+    }
+
+  if (SCHED_OTHER != policy)
+    {
+      errno = ENOSYS;
+      return -1;
+    }
+
+  /*
+   * Don't set anything because there is nothing to set.
+   * Just return the current (the only possible) value.
+   */
+  return SCHED_OTHER;
+}
diff --git a/sched_yield.c b/sched_yield.c
new file mode 100644
index 0000000..6ac5ed9
--- /dev/null
+++ b/sched_yield.c
@@ -0,0 +1,71 @@
+/*
+ * sched_yield.c
+ * 
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_yield (void)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function indicates that the calling thread is
+      *      willing to give up some time slices to other threads.
+      *
+      * PARAMETERS
+      *      N/A
+      *
+      *
+      * DESCRIPTION
+      *      This function indicates that the calling thread is
+      *      willing to give up some time slices to other threads.
+      *      NOTE: Since this is part of POSIX 1003.1b
+      *                (realtime extensions), it is defined as returning
+      *                -1 if an error occurs and sets errno to the actual
+      *                error.
+      *
+      * RESULTS
+      *              0               successfully created semaphore,
+      *              ENOSYS          sched_yield not supported,
+      *
+      * ------------------------------------------------------
+      */
+{
+  Sleep (0);
+
+  return 0;
+}
diff --git a/sem_close.c b/sem_close.c
new file mode 100644
index 0000000..2f95c87
--- /dev/null
+++ b/sem_close.c
@@ -0,0 +1,58 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_close.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+sem_close (sem_t * sem)
+{
+  errno = ENOSYS;
+  return -1;
+}				/* sem_close */
diff --git a/sem_destroy.c b/sem_destroy.c
new file mode 100644
index 0000000..6c98e80
--- /dev/null
+++ b/sem_destroy.c
@@ -0,0 +1,144 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_destroy.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_destroy (sem_t * sem)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function destroys an unnamed semaphore.
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      * DESCRIPTION
+      *      This function destroys an unnamed semaphore.
+      *
+      * RESULTS
+      *              0               successfully destroyed semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore,
+      *              ENOSYS          semaphores are not supported,
+      *              EBUSY           threads (or processes) are currently
+      *                                      blocked on 'sem'
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = NULL;
+
+  if (sem == NULL || *sem == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      s = *sem;
+
+      if ((result = pthread_mutex_lock (&s->lock)) == 0)
+        {
+          if (s->value < 0)
+            {
+              (void) pthread_mutex_unlock (&s->lock);
+              result = EBUSY;
+            }
+          else
+            {
+              /* There are no threads currently blocked on this semaphore. */
+
+              if (!CloseHandle (s->sem))
+	        {
+                  (void) pthread_mutex_unlock (&s->lock);
+	          result = EINVAL;
+	        }
+	      else
+	        {
+                  /*
+                   * Invalidate the semaphore handle when we have the lock.
+                   * Other sema operations should test this after acquiring the lock
+                   * to check that the sema is still valid, i.e. before performing any
+                   * operations. This may only be necessary before the sema op routine
+                   * returns so that the routine can return EINVAL - e.g. if setting
+                   * s->value to SEM_VALUE_MAX below does force a fall-through.
+                   */
+                  *sem = NULL;
+
+                  /* Prevent anyone else actually waiting on or posting this sema.
+                   */
+                  s->value = SEM_VALUE_MAX;
+
+                  (void) pthread_mutex_unlock (&s->lock);
+
+                  do
+                    {
+                      /* Give other threads a chance to run and exit any sema op
+                       * routines. Due to the SEM_VALUE_MAX value, if sem_post or
+                       * sem_wait were blocked by us they should fall through.
+                       */
+                      Sleep(0);
+                    }
+                  while (pthread_mutex_destroy (&s->lock) == EBUSY);
+                }
+            }
+        }
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  free (s);
+
+  return 0;
+
+}				/* sem_destroy */
diff --git a/sem_getvalue.c b/sem_getvalue.c
new file mode 100644
index 0000000..baafb02
--- /dev/null
+++ b/sem_getvalue.c
@@ -0,0 +1,110 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_getvalue.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of PThreads.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1-2001
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_getvalue (sem_t * sem, int *sval)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function stores the current count value of the
+      *      semaphore.
+      * RESULTS
+      *
+      * Return value
+      *
+      *       0                  sval has been set.
+      *      -1                  failed, error in errno
+      *
+      *  in global errno
+      *
+      *      EINVAL              'sem' is not a valid semaphore,
+      *      ENOSYS              this function is not supported,
+      *
+      *
+      * PARAMETERS
+      *
+      *      sem                 pointer to an instance of sem_t
+      *
+      *      sval                pointer to int.
+      *
+      * DESCRIPTION
+      *      This function stores the current count value of the semaphore
+      *      pointed to by sem in the int pointed to by sval.
+      */
+{
+  if (sem == NULL || *sem == NULL || sval == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  else
+    {
+      long value;
+      register sem_t s = *sem;
+      int result = 0;
+
+      if ((result = pthread_mutex_lock(&s->lock)) == 0)
+        {
+	  /* See sem_destroy.c
+	   */
+	  if (*sem == NULL)
+	    {
+	      (void) pthread_mutex_unlock (&s->lock);
+	      errno = EINVAL;
+	      return -1;
+	    }
+
+          value = s->value;
+          (void) pthread_mutex_unlock(&s->lock);
+          *sval = value;
+        }
+
+      return result;
+    }
+
+}				/* sem_getvalue */
diff --git a/sem_init.c b/sem_init.c
new file mode 100644
index 0000000..02acd90
--- /dev/null
+++ b/sem_init.c
@@ -0,0 +1,169 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_init.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of PThreads.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1-2001
+ *
+ * -------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+int
+sem_init (sem_t * sem, int pshared, unsigned int value)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function initializes a semaphore. The
+      *      initial value of the semaphore is 'value'
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      *      pshared
+      *              if zero, this semaphore may only be shared between
+      *              threads in the same process.
+      *              if nonzero, the semaphore can be shared between
+      *              processes
+      *
+      *      value
+      *              initial value of the semaphore counter
+      *
+      * DESCRIPTION
+      *      This function initializes a semaphore. The
+      *      initial value of the semaphore is set to 'value'.
+      *
+      * RESULTS
+      *              0               successfully created semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore, or
+      *                              'value' >= SEM_VALUE_MAX
+      *              ENOMEM          out of memory,
+      *              ENOSPC          a required resource has been exhausted,
+      *              ENOSYS          semaphores are not supported,
+      *              EPERM           the process lacks appropriate privilege
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = NULL;
+
+  if (pshared != 0)
+    {
+      /*
+       * Creating a semaphore that can be shared between
+       * processes
+       */
+      result = EPERM;
+    }
+  else if (value > (unsigned int)SEM_VALUE_MAX)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      s = (sem_t) calloc (1, sizeof (*s));
+
+      if (NULL == s)
+	{
+	  result = ENOMEM;
+	}
+      else
+	{
+
+	  s->value = value;
+	  if (pthread_mutex_init(&s->lock, NULL) == 0)
+	    {
+
+#ifdef NEED_SEM
+
+	  s->sem = CreateEvent (NULL,
+				PTW32_FALSE,	/* auto (not manual) reset */
+				PTW32_FALSE,	/* initial state is unset */
+				NULL);
+
+	  if (0 == s->sem)
+	    {
+	      free (s);
+	      (void) pthread_mutex_destroy(&s->lock);
+	      result = ENOSPC;
+	    }
+	  else
+	    {
+	      s->leftToUnblock = 0;
+	    }
+
+#else /* NEED_SEM */
+
+	      if ((s->sem = CreateSemaphore (NULL,	/* Always NULL */
+					     (long) 0,	/* Force threads to wait */
+					     (long) SEM_VALUE_MAX,	/* Maximum value */
+					     NULL)) == 0)	/* Name */
+		{
+		  (void) pthread_mutex_destroy(&s->lock);
+		  result = ENOSPC;
+		}
+
+#endif /* NEED_SEM */
+
+	    }
+	  else
+	    {
+	      result = ENOSPC;
+	    }
+
+	  if (result != 0)
+	    {
+	      free(s);
+	    }
+	}
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  *sem = s;
+
+  return 0;
+
+}				/* sem_init */
diff --git a/sem_open.c b/sem_open.c
new file mode 100644
index 0000000..bf48c83
--- /dev/null
+++ b/sem_open.c
@@ -0,0 +1,58 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_open.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
+{
+  errno = ENOSYS;
+  return -1;
+}				/* sem_open */
diff --git a/sem_post.c b/sem_post.c
new file mode 100644
index 0000000..c7a7a3c
--- /dev/null
+++ b/sem_post.c
@@ -0,0 +1,128 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_post.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_post (sem_t * sem)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function posts a wakeup to a semaphore.
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      * DESCRIPTION
+      *      This function posts a wakeup to a semaphore. If there
+      *      are waiting threads (or processes), one is awakened;
+      *      otherwise, the semaphore value is incremented by one.
+      *
+      * RESULTS
+      *              0               successfully posted semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore,
+      *              ENOSYS          semaphores are not supported,
+      *              ERANGE          semaphore count is too big
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = *sem;
+
+  if (s == NULL)
+    {
+      result = EINVAL;
+    }
+  else if ((result = pthread_mutex_lock (&s->lock)) == 0)
+    {
+      /* See sem_destroy.c
+       */
+      if (*sem == NULL)
+        {
+          (void) pthread_mutex_unlock (&s->lock);
+          result = EINVAL;
+          return -1;
+        }
+
+      if (s->value < SEM_VALUE_MAX)
+	{
+#ifdef NEED_SEM
+	  if (++s->value <= 0
+	      && !SetEvent(s->sem))
+	    {
+	      s->value--;
+	      result = EINVAL;
+	    }
+#else
+	  if (++s->value <= 0
+	      && !ReleaseSemaphore (s->sem, 1, NULL))
+	    {
+	      s->value--;
+	      result = EINVAL;
+	    }
+#endif /* NEED_SEM */
+	}
+      else
+	{
+	  result = ERANGE;
+	}
+
+      (void) pthread_mutex_unlock (&s->lock);
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  return 0;
+
+}				/* sem_post */
diff --git a/sem_post_multiple.c b/sem_post_multiple.c
new file mode 100644
index 0000000..3d1e4ef
--- /dev/null
+++ b/sem_post_multiple.c
@@ -0,0 +1,142 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_post_multiple.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_post_multiple (sem_t * sem, int count)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function posts multiple wakeups to a semaphore.
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      *      count
+      *              counter, must be greater than zero.
+      *
+      * DESCRIPTION
+      *      This function posts multiple wakeups to a semaphore. If there
+      *      are waiting threads (or processes), n <= count are awakened;
+      *      the semaphore value is incremented by count - n.
+      *
+      * RESULTS
+      *              0               successfully posted semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore
+      *                              or count is less than or equal to zero.
+      *              ERANGE          semaphore count is too big
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  long waiters;
+  sem_t s = *sem;
+
+  if (s == NULL || count <= 0)
+    {
+      result = EINVAL;
+    }
+  else if ((result = pthread_mutex_lock (&s->lock)) == 0)
+    {
+      /* See sem_destroy.c
+       */
+      if (*sem == NULL)
+        {
+          (void) pthread_mutex_unlock (&s->lock);
+          result = EINVAL;
+          return -1;
+        }
+
+      if (s->value <= (SEM_VALUE_MAX - count))
+	{
+	  waiters = -s->value;
+	  s->value += count;
+	  if (waiters > 0)
+	    {
+#ifdef NEED_SEM
+	      if (SetEvent(s->sem))
+		{
+		  waiters--;
+		  s->leftToUnblock += count - 1;
+		  if (s->leftToUnblock > waiters)
+		    {
+		      s->leftToUnblock = waiters;
+		    }
+		}
+#else
+	      if (ReleaseSemaphore (s->sem,  (waiters<=count)?waiters:count, 0))
+		{
+		  /* No action */
+		}
+#endif
+	      else
+		{
+		  s->value -= count;
+		  result = EINVAL;
+		}
+	    }
+	}
+      else
+	{
+	  result = ERANGE;
+	}
+      (void) pthread_mutex_unlock (&s->lock);
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  return 0;
+
+}				/* sem_post_multiple */
diff --git a/sem_timedwait.c b/sem_timedwait.c
new file mode 100644
index 0000000..52146b4
--- /dev/null
+++ b/sem_timedwait.c
@@ -0,0 +1,238 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_timedwait.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+typedef struct {
+  sem_t sem;
+  int * resultPtr;
+} sem_timedwait_cleanup_args_t;
+
+
+static void PTW32_CDECL
+ptw32_sem_timedwait_cleanup (void * args)
+{
+  sem_timedwait_cleanup_args_t * a = (sem_timedwait_cleanup_args_t *)args;
+  sem_t s = a->sem;
+
+  if (pthread_mutex_lock (&s->lock) == 0)
+    {
+      /*
+       * We either timed out or were cancelled.
+       * If someone has posted between then and now we try to take the semaphore.
+       * Otherwise the semaphore count may be wrong after we
+       * return. In the case of a cancellation, it is as if we
+       * were cancelled just before we return (after taking the semaphore)
+       * which is ok.
+       */
+      if (WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)
+	{
+	  /* We got the semaphore on the second attempt */
+	  *(a->resultPtr) = 0;
+	}
+      else
+	{
+	  /* Indicate we're no longer waiting */
+	  s->value++;
+#ifdef NEED_SEM
+	  if (s->value > 0)
+	    {
+	      s->leftToUnblock = 0;
+	    }
+#else
+          /*
+           * Don't release the W32 sema, it doesn't need adjustment
+           * because it doesn't record the number of waiters.
+           */
+#endif
+	}
+      (void) pthread_mutex_unlock (&s->lock);
+    }
+}
+
+
+int
+sem_timedwait (sem_t * sem, const struct timespec *abstime)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function waits on a semaphore possibly until
+      *      'abstime' time.
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      *      abstime
+      *              pointer to an instance of struct timespec
+      *
+      * DESCRIPTION
+      *      This function waits on a semaphore. If the
+      *      semaphore value is greater than zero, it decreases
+      *      its value by one. If the semaphore value is zero, then
+      *      the calling thread (or process) is blocked until it can
+      *      successfully decrease the value or until interrupted by
+      *      a signal.
+      *
+      *      If 'abstime' is a NULL pointer then this function will
+      *      block until it can successfully decrease the value or
+      *      until interrupted by a signal.
+      *
+      * RESULTS
+      *              0               successfully decreased semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore,
+      *              ENOSYS          semaphores are not supported,
+      *              EINTR           the function was interrupted by a signal,
+      *              EDEADLK         a deadlock condition was detected.
+      *              ETIMEDOUT       abstime elapsed before success.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = *sem;
+
+  pthread_testcancel();
+
+  if (sem == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      DWORD milliseconds;
+
+      if (abstime == NULL)
+	{
+	  milliseconds = INFINITE;
+	}
+      else
+	{
+	  /* 
+	   * Calculate timeout as milliseconds from current system time. 
+	   */
+	  milliseconds = ptw32_relmillisecs (abstime);
+	}
+
+      if ((result = pthread_mutex_lock (&s->lock)) == 0)
+	{
+	  int v;
+
+	  /* See sem_destroy.c
+	   */
+	  if (*sem == NULL)
+	    {
+	      (void) pthread_mutex_unlock (&s->lock);
+	      errno = EINVAL;
+	      return -1;
+	    }
+
+	  v = --s->value;
+	  (void) pthread_mutex_unlock (&s->lock);
+
+	  if (v < 0)
+	    {
+#ifdef NEED_SEM
+	      int timedout;
+#endif
+	      sem_timedwait_cleanup_args_t cleanup_args;
+
+	      cleanup_args.sem = s;
+	      cleanup_args.resultPtr = &result;
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+	      /* Must wait */
+              pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) &cleanup_args);
+#ifdef NEED_SEM
+	      timedout =
+#endif
+	      result = pthreadCancelableTimedWait (s->sem, milliseconds);
+	      pthread_cleanup_pop(result);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+#ifdef NEED_SEM
+
+	      if (!timedout && pthread_mutex_lock (&s->lock) == 0)
+	        {
+        	  if (*sem == NULL)
+        	    {
+        	      (void) pthread_mutex_unlock (&s->lock);
+        	      errno = EINVAL;
+        	      return -1;
+        	    }
+
+	          if (s->leftToUnblock > 0)
+	            {
+		      --s->leftToUnblock;
+		      SetEvent(s->sem);
+		    }
+	          (void) pthread_mutex_unlock (&s->lock);
+	        }
+
+#endif /* NEED_SEM */
+
+	    }
+	}
+
+    }
+
+  if (result != 0)
+    {
+
+      errno = result;
+      return -1;
+
+    }
+
+  return 0;
+
+}				/* sem_timedwait */
diff --git a/sem_trywait.c b/sem_trywait.c
new file mode 100644
index 0000000..63614ba
--- /dev/null
+++ b/sem_trywait.c
@@ -0,0 +1,117 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_trywait.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_trywait (sem_t * sem)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function tries to wait on a semaphore.
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      * DESCRIPTION
+      *      This function tries to wait on a semaphore. If the
+      *      semaphore value is greater than zero, it decreases
+      *      its value by one. If the semaphore value is zero, then
+      *      this function returns immediately with the error EAGAIN
+      *
+      * RESULTS
+      *              0               successfully decreased semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EAGAIN          the semaphore was already locked,
+      *              EINVAL          'sem' is not a valid semaphore,
+      *              ENOTSUP         sem_trywait is not supported,
+      *              EINTR           the function was interrupted by a signal,
+      *              EDEADLK         a deadlock condition was detected.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = *sem;
+
+  if (s == NULL)
+    {
+      result = EINVAL;
+    }
+  else if ((result = pthread_mutex_lock (&s->lock)) == 0)
+    {
+      /* See sem_destroy.c
+       */
+     if (*sem == NULL)
+        {
+          (void) pthread_mutex_unlock (&s->lock);
+          errno = EINVAL;
+          return -1;
+        }
+
+      if (s->value > 0)
+	{
+	  s->value--;
+	}
+      else
+	{
+	  result = EAGAIN;
+	}
+
+      (void) pthread_mutex_unlock (&s->lock);
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  return 0;
+
+}				/* sem_trywait */
diff --git a/sem_unlink.c b/sem_unlink.c
new file mode 100644
index 0000000..a6c6f81
--- /dev/null
+++ b/sem_unlink.c
@@ -0,0 +1,58 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_unlink.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#ifdef _MSC_VER
+#pragma warning( disable : 4100 )
+#endif
+
+int
+sem_unlink (const char *name)
+{
+  errno = ENOSYS;
+  return -1;
+}				/* sem_unlink */
diff --git a/sem_wait.c b/sem_wait.c
new file mode 100644
index 0000000..d39d2b4
--- /dev/null
+++ b/sem_wait.c
@@ -0,0 +1,187 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_wait.c
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+static void PTW32_CDECL
+ptw32_sem_wait_cleanup(void * sem)
+{
+  sem_t s = (sem_t) sem;
+
+  if (pthread_mutex_lock (&s->lock) == 0)
+    {
+      /*
+       * If sema is destroyed do nothing, otherwise:-
+       * If the sema is posted between us being cancelled and us locking
+       * the sema again above then we need to consume that post but cancel
+       * anyway. If we don't get the semaphore we indicate that we're no
+       * longer waiting.
+       */
+      if (*((sem_t *)sem) != NULL && !(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0))
+	{
+	  ++s->value;
+#ifdef NEED_SEM
+	  if (s->value > 0)
+	    {
+	      s->leftToUnblock = 0;
+	    }
+#else
+	  /*
+	   * Don't release the W32 sema, it doesn't need adjustment
+	   * because it doesn't record the number of waiters.
+	   */
+#endif /* NEED_SEM */
+	}
+      (void) pthread_mutex_unlock (&s->lock);
+    }
+}
+
+int
+sem_wait (sem_t * sem)
+     /*
+      * ------------------------------------------------------
+      * DOCPUBLIC
+      *      This function  waits on a semaphore.
+      *
+      * PARAMETERS
+      *      sem
+      *              pointer to an instance of sem_t
+      *
+      * DESCRIPTION
+      *      This function waits on a semaphore. If the
+      *      semaphore value is greater than zero, it decreases
+      *      its value by one. If the semaphore value is zero, then
+      *      the calling thread (or process) is blocked until it can
+      *      successfully decrease the value or until interrupted by
+      *      a signal.
+      *
+      * RESULTS
+      *              0               successfully decreased semaphore,
+      *              -1              failed, error in errno
+      * ERRNO
+      *              EINVAL          'sem' is not a valid semaphore,
+      *              ENOSYS          semaphores are not supported,
+      *              EINTR           the function was interrupted by a signal,
+      *              EDEADLK         a deadlock condition was detected.
+      *
+      * ------------------------------------------------------
+      */
+{
+  int result = 0;
+  sem_t s = *sem;
+
+  pthread_testcancel();
+
+  if (s == NULL)
+    {
+      result = EINVAL;
+    }
+  else
+    {
+      if ((result = pthread_mutex_lock (&s->lock)) == 0)
+	{
+	  int v;
+
+	  /* See sem_destroy.c
+	   */
+	  if (*sem == NULL)
+	    {
+	      (void) pthread_mutex_unlock (&s->lock);
+	      errno = EINVAL;
+	      return -1;
+	    }
+
+          v = --s->value;
+	  (void) pthread_mutex_unlock (&s->lock);
+
+	  if (v < 0)
+	    {
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+	      /* Must wait */
+	      pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s);
+	      result = pthreadCancelableWait (s->sem);
+	      /* Cleanup if we're canceled or on any other error */
+	      pthread_cleanup_pop(result);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+	    }
+#ifdef NEED_SEM
+
+	  if (!result && pthread_mutex_lock (&s->lock) == 0)
+	    {
+	      if (*sem == NULL)
+	        {
+	          (void) pthread_mutex_unlock (&s->lock);
+	          errno = EINVAL;
+	          return -1;
+	        }
+
+	      if (s->leftToUnblock > 0)
+		{
+		  --s->leftToUnblock;
+		  SetEvent(s->sem);
+		}
+	      (void) pthread_mutex_unlock (&s->lock);
+	    }
+
+#endif /* NEED_SEM */
+
+	}
+
+    }
+
+  if (result != 0)
+    {
+      errno = result;
+      return -1;
+    }
+
+  return 0;
+
+}				/* sem_wait */
diff --git a/semaphore.c b/semaphore.c
new file mode 100644
index 0000000..6b2b10e
--- /dev/null
+++ b/semaphore.c
@@ -0,0 +1,69 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: semaphore.c
+ *
+ * Purpose:
+ *	Concatenated version of separate modules to allow
+ *	inlining optimisation, which it is assumed can only
+ *	be effective within a single module.
+ *
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#ifndef NEED_FTIME
+#  include <sys/timeb.h>
+#endif
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+#include "sem_init.c"
+#include "sem_destroy.c"
+#include "sem_trywait.c"
+#include "sem_wait.c"
+#include "sem_timedwait.c"
+#include "sem_post.c"
+#include "sem_post_multiple.c"
+#include "sem_getvalue.c"
+#include "sem_open.c"
+#include "sem_close.c"
+#include "sem_unlink.c"
diff --git a/semaphore.h b/semaphore.h
new file mode 100644
index 0000000..a3330a6
--- /dev/null
+++ b/semaphore.h
@@ -0,0 +1,166 @@
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+#  ifdef PTW32_BUILD
+#    define PTW32_DLLPORT __declspec (dllexport)
+#  else
+#    define PTW32_DLLPORT __declspec (dllimport)
+#  endif
+#else
+#  define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+#  if defined(WINCE)
+#    define NEED_ERRNO
+#    define NEED_SEM
+#  endif
+#  if defined(_UWIN) || defined(__MINGW32__)
+#    define HAVE_MODE_T
+#  endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#define _POSIX_SEMAPHORES
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif				/* __cplusplus */
+
+#ifndef HAVE_MODE_T
+typedef unsigned int mode_t;
+#endif
+
+
+typedef struct sem_t_ * sem_t;
+
+PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
+			    int pshared,
+			    unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
+				 const struct timespec * abstime);
+
+PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
+				     int count);
+
+PTW32_DLLPORT int __cdecl sem_open (const char * name,
+			    int oflag,
+			    mode_t mode,
+			    unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
+
+PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
+				int * sval);
+
+#ifdef __cplusplus
+}				/* End of extern "C" */
+#endif				/* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif				/* !SEMAPHORE_H */
diff --git a/signal.c b/signal.c
new file mode 100644
index 0000000..8f56c48
--- /dev/null
+++ b/signal.c
@@ -0,0 +1,179 @@
+/*
+ * signal.c
+ *
+ * Description:
+ * Thread-aware signal functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+/*
+ * Possible future strategy for implementing pthread_kill()
+ * ========================================================
+ *
+ * Win32 does not implement signals.
+ * Signals are simply software interrupts.
+ * pthread_kill() asks the system to deliver a specified
+ * signal (interrupt) to a specified thread in the same
+ * process.
+ * Signals are always asynchronous (no deferred signals).
+ * Pthread-win32 has an async cancelation mechanism.
+ * A similar system can be written to deliver signals
+ * within the same process (on ix86 processors at least).
+ *
+ * Each thread maintains information about which
+ * signals it will respond to. Handler routines
+ * are set on a per-process basis - not per-thread.
+ * When signalled, a thread will check it's sigmask
+ * and, if the signal is not being ignored, call the
+ * handler routine associated with the signal. The
+ * thread must then (except for some signals) return to
+ * the point where it was interrupted.
+ *
+ * Ideally the system itself would check the target thread's
+ * mask before possibly needlessly bothering the thread
+ * itself. This could be done by pthread_kill(), that is,
+ * in the signaling thread since it has access to
+ * all pthread_t structures. It could also retrieve
+ * the handler routine address to minimise the target
+ * threads response overhead. This may also simplify
+ * serialisation of the access to the per-thread signal
+ * structures.
+ *
+ * pthread_kill() eventually calls a routine similar to
+ * ptw32_cancel_thread() which manipulates the target
+ * threads processor context to cause the thread to
+ * run the handler launcher routine. pthread_kill() must
+ * save the target threads current context so that the
+ * handler launcher routine can restore the context after
+ * the signal handler has returned. Some handlers will not
+ * return, eg. the default SIGKILL handler may simply
+ * call pthread_exit().
+ *
+ * The current context is saved in the target threads
+ * pthread_t structure.
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#if HAVE_SIGSET_T
+
+static void
+ptw32_signal_thread ()
+{
+}
+
+static void
+ptw32_signal_callhandler ()
+{
+}
+
+int
+pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
+{
+  pthread_t thread = pthread_self ();
+
+  if (thread.p == NULL)
+    {
+      return ENOENT;
+    }
+
+  /* Validate the `how' argument. */
+  if (set != NULL)
+    {
+      switch (how)
+	{
+	case SIG_BLOCK:
+	  break;
+	case SIG_UNBLOCK:
+	  break;
+	case SIG_SETMASK:
+	  break;
+	default:
+	  /* Invalid `how' argument. */
+	  return EINVAL;
+	}
+    }
+
+  /* Copy the old mask before modifying it. */
+  if (oset != NULL)
+    {
+      memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t));
+    }
+
+  if (set != NULL)
+    {
+      unsigned int i;
+
+      /* FIXME: this code assumes that sigmask is an even multiple of
+         the size of a long integer. */
+
+      unsigned long *src = (unsigned long const *) set;
+      unsigned long *dest = (unsigned long *) &(thread.p->sigmask);
+
+      switch (how)
+	{
+	case SIG_BLOCK:
+	  for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
+	    {
+	      /* OR the bit field longword-wise. */
+	      *dest++ |= *src++;
+	    }
+	  break;
+	case SIG_UNBLOCK:
+	  for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
+	    {
+	      /* XOR the bitfield longword-wise. */
+	      *dest++ ^= *src++;
+	    }
+	case SIG_SETMASK:
+	  /* Replace the whole sigmask. */
+	  memcpy (&(thread.p->sigmask), set, sizeof (sigset_t));
+	  break;
+	}
+    }
+
+  return 0;
+}
+
+int
+sigwait (const sigset_t * set, int *sig)
+{
+  /* This routine is a cancellation point */
+  pthread_test_cancel();
+}
+
+int
+sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+}
+
+#endif /* HAVE_SIGSET_T */
diff --git a/spin.c b/spin.c
new file mode 100644
index 0000000..41b5aa5
--- /dev/null
+++ b/spin.c
@@ -0,0 +1,46 @@
+/*
+ * spin.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "ptw32_spinlock_check_need_init.c"
+#include "pthread_spin_init.c"
+#include "pthread_spin_destroy.c"
+#include "pthread_spin_lock.c"
+#include "pthread_spin_unlock.c"
+#include "pthread_spin_trylock.c"
diff --git a/sync.c b/sync.c
new file mode 100644
index 0000000..5e56fa9
--- /dev/null
+++ b/sync.c
@@ -0,0 +1,43 @@
+/*
+ * sync.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_detach.c"
+#include "pthread_join.c"
diff --git a/tests/Bmakefile b/tests/Bmakefile
new file mode 100644
index 0000000..9a2c2b4
--- /dev/null
+++ b/tests/Bmakefile
@@ -0,0 +1,350 @@
+# 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,2005 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
+#
+
+DLL_VER	= 2
+
+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
+
+XXLIBS	= cw32mti.lib ws2_32.lib
+
+# C++ Exceptions
+BCEFLAGS	= -P -DPtW32NoCatchWarn -D__CLEANUP_CXX
+BCELIB	= pthreadBCE$(DLL_VER).lib
+BCEDLL	= pthreadBCE$(DLL_VER).dll
+# C cleanup code
+BCFLAGS	= -D__CLEANUP_C
+BCLIB	= pthreadBC$(DLL_VER).lib
+BCDLL	= pthreadBC$(DLL_VER).dll
+# C++ Exceptions in application - using VC version of pthreads dll
+BCXFLAGS	= -D__CLEANUP_C
+
+# Defaults
+CPLIB	= $(BCLIB)
+CPDLL	= $(BCDLL)
+
+CFLAGS= -q $(OPTIM) /D_WIN32_WINNT=0x400 -w -tWC -tWM -4 -w-aus -w-asc -w-par
+LFLAGS= 
+INCLUDES=-I.
+BUILD_DIR=..
+
+COPYFILES	= $(CPHDR) $(CPLIB) $(CPDLL) $(QAPC)
+
+EHFLAGS	=
+
+# If a test case returns a non-zero exit code to the shell, make will
+# stop.
+
+PASSES=   loadfree.pass \
+	  errno1.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.pass  exit5.pass  \
+	  join0.pass  join1.pass  detach1.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  once2.pass  once3.pass  once4.pass  \
+	  self2.pass  \
+	  cancel1.pass  cancel2.pass  \
+	  semaphore4.pass  semaphore4t.pass  semaphore5.pass  \
+	  barrier1.pass  barrier2.pass  barrier3.pass  barrier4.pass  barrier5.pass  \
+	  tsd1.pass  tsd2.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  \
+	  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.pass  cancel8.pass  \
+	  cleanup0.pass  cleanup1.pass  cleanup2.pass  cleanup3.pass  \
+	  priority1.pass priority2.pass inherit1.pass  \
+	  spin1.pass  spin2.pass  spin3.pass  spin4.pass  \
+	  exception1.pass  exception2.pass  exception3.pass  \
+	  cancel9.pass  create3.pass  stress1.pass
+
+BENCHRESULTS = \
+	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench
+
+help:
+	@ $(ECHO) Run one of the following command lines:
+	@ $(ECHO) make clean BC    (to test using BC dll with VC (no EH) applications)
+	@ $(ECHO) make clean BCX   (to test using BC dll with VC++ (EH) applications)
+	@ $(ECHO) make clean BCE   (to test using the BCE dll with VC++ EH applications)
+	@ $(ECHO) make clean BC-bench    (to benchtest using BC dll with C bench app)
+	@ $(ECHO) make clean BCX-bench   (to benchtest using BC dll with C++ bench app)
+	@ $(ECHO) make clean BCE-bench   (to benchtest using BCE dll with C++ bench app)
+
+all:
+	@ make clean BC
+	@ make clean BCX
+	@ make clean BCE
+	@ make clean BC-bench
+
+# This allows an individual test application to be made using the default lib.
+# e.g. make clean test cancel3.exe
+test: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC)
+
+tests: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) sizes.pass $(PASSES)
+	@ $(ECHO) ALL TESTS PASSED! Congratulations!
+
+benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(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
+
+BCE:
+	@ make -f Bmakefile TEST="$@" CPLIB="$(BCELIB)" CPDLL="$(BCEDLL)" EHFLAGS="$(BCEFLAGS)" tests
+
+BC:
+	@ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCFLAGS)" tests
+
+BCX:
+	@ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCXFLAGS)" tests
+
+BCE-bench:
+	@ make -f Bmakefile TEST="$@" CPLIB="$(BCELIB)" CPDLL="$(BCEDLL)" EHFLAGS="$(BCEFLAGS)" XXLIBS="benchlib.o" benchtests
+
+BC-bench:
+	@ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCFLAGS)" XXLIBS="benchlib.o" benchtests
+
+BCX-bench:
+	@ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCXFLAGS)" XXLIBS="benchlib.o" benchtests
+
+.exe.pass:
+	@ $(ECHO) ... Running $(TEST) test: $<
+	@ .\$<
+	@ $(ECHO) ...... Passed
+	@ $(TOUCH) $@
+
+.exe.bench:
+	@ $(ECHO) ... Running $(TEST) benchtest: $<
+	@ .\$<
+	@ $(ECHO) ...... Done
+	@ $(TOUCH) $@
+
+.c.exe:
+	@ $(ECHO) $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< -e$@ $(LFLAGS) $(CPLIB) $(XXLIBS)
+	@ $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< -e$@ $(LFLAGS) $(CPLIB) $(XXLIBS)
+
+.c.o:
+	@ $(ECHO) $(CC) $(EHFLAGS) -c $(CFLAGS) $(INCLUDES) $< -o$@
+	@ $(CC) $(EHFLAGS) $(CFLAGS) -c $(INCLUDES) $< -o$@
+
+
+.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) *.tds
+	- $(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: semaphore4.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
+cancel9.pass: cancel8.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
+detach1.pass: join0.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
+once2.pass: once1.pass
+once3.pass: once2.pass
+once4.pass: once3.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
+semaphore5.pass: semaphore4.pass
+sizes.pass:
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
+stress1.pass:
+tsd1.pass: barrier5.pass join1.pass
+tsd2.pass: tsd1.pass
+valid1.pass: join1.pass
+valid2.pass: valid1.pass
diff --git a/tests/ChangeLog b/tests/ChangeLog
new file mode 100644
index 0000000..6b2c742
--- /dev/null
+++ b/tests/ChangeLog
@@ -0,0 +1,894 @@
+2005-06-12  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* stress1.c (millisecondsFromNow): Remove limit 0 <= millisecs < 1000;
+	now works for -INT_MAX <= millisecs <= INT_MAX; not needed for
+	stress1.c but should be general anyway.
+
+2005-05-18  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* reuse2.c (main): Must use a read with memory barrier semantics
+	when polling 'done' to force the cache into coherence on MP systems.
+
+2005-05-15  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* detach1.c: New test.
+	* join1.c: Reduce sleep times.
+	* join0.c: Remove MSVCRT conditional compile - join should always
+	return the thread exit code.
+	* join1.c: Likewise.
+	* join2.c: Likewise.
+	* join3.c: Likewise.
+
+2005-04-18  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* condvar3.c: Remove locks from around signalling calls - should not
+	be required for normal operation and only serve to mask deficiencies;
+	ensure that CV destruction is not premature after removing guards.
+	* condvar3_1.c: Likewise.
+	* condvar3_2.c: Likewise.
+	* condvar3_3.c: Likewise.
+	* condvar4.c: Likewise.
+	* condvar5.c: Likewise.
+	* condvar6.c: Likewise.
+	* condvar7.c: Likewise.
+	* condvar8.c: Likewise.
+	* condvar9.c: Likewise.
+
+2005-04-11  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+        * once4.c: New test; tries to test priority adjustments
+        in pthread_once(); set priority class to realtime so that
+        any failures can be seen.
+
+2005-04-06  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* cleanup0.c: Fix unguarded global variable accesses.
+	* cleanup1.c: Likewise.
+	* cleanup2.c: Likewise.
+	* cleanup3.c: Likewise.
+	* once2.c: Likewise.
+	* once3.c: Likewise.
+
+2005-04-01  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* GNUmakefile: Add target to test linking static link library.
+	* Makefile: Likewise.
+	* self1.c: Run process attach/detach routines when static linked.
+
+2005-03-16  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* mutex5.c: Prevent optimiser from removing asserts.
+
+2005-03-12  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* once3.c: New test.
+
+2005-03-08  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+        * once2.c: New test.
+
+2004-11-19  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* Bmakefile: New makefile for Borland.
+	* Makefile (DLL_VER): Added.
+	* GNUmakefile (DLL_VER): Added.
+	* Wmakefile (DLL_VER): Added.
+
+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.
+	The error became evident after sem_destroy() was rewritten
+	and conditions for destroing the semaphore were tightened.
+	As a result, pthread_cond_destroy() was not able to
+	destroy the cv queueing sempahore.
+	* condvar3_1.c: Likewise.
+	* condvar3_2.c: Likewise.
+	* condvar4.c: Likewise.
+	* condvar5.c: Likewise.
+	* condvar6.c: Likewise.
+	* condvar7.c: Likewise.
+	* condvar8.c: Likewise.
+	* condvar9.c: Likewise.
+
+2004-10-19  Ross Johnson  <rpj@callisto.canberra.edu.au>
+
+	* semaphore3.c: New test.
+
+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>
+
+	* exit2.c: New file; test pthread_exit() harder.
+
+	* exit1.c: New file; test pthread_exit().
diff --git a/tests/Debug.dsp b/tests/Debug.dsp
new file mode 100644
index 0000000..7a35ffd
--- /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 /W3 /WX /Gm /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 pthreadVC2d.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=.\semaphore1.c

+# End Source File

+# End Target

+# End Project

diff --git a/tests/Debug.dsw b/tests/Debug.dsw
new file mode 100644
index 0000000..cb90db8
--- /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.plg b/tests/Debug.plg
new file mode 100644
index 0000000..22ce672
--- /dev/null
+++ b/tests/Debug.plg
@@ -0,0 +1,32 @@
+<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\RSP9.tmp" with contents
+[
+/nologo /MDd /W3 /WX /Gm /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.2\tests\semaphore1.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP9.tmp" 
+Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSPA.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 pthreadVC2d.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/Debug.pdb" /debug /machine:I386 /out:"Debug/Debug.exe" /pdbtype:sept /libpath:".." 
+.\Debug\semaphore1.obj
+]
+Creating command line "link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSPA.tmp"
+<h3>Output Window</h3>
+Compiling...
+semaphore1.c
+Linking...
+
+
+
+<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
new file mode 100644
index 0000000..1762b6c
--- /dev/null
+++ b/tests/GNUmakefile
@@ -0,0 +1,375 @@
+# 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,2005 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
+#
+
+DLL_VER	= 2
+
+CP	= cp -f
+MV	= mv -f
+RM	= rm -f
+CAT	= cat
+#CP	= copy
+#MV	= rename
+#RM	= erase
+#CAT	= type
+MKDIR	= mkdir
+TOUCH	= echo Passed >
+ECHO	= @echo
+MAKE	= make
+
+#
+# Mingw32
+#
+XXCFLAGS	= 
+XXLIBS	= -lws2_32
+#CFLAGS	= -O3 -UNDEBUG -Wall $(XXCFLAGS)
+CFLAGS	= -g -UNDEBUG -Wall $(XXCFLAGS)
+BUILD_DIR	= ..
+INCLUDES	= -I.
+
+
+TEST	= GC
+
+# Default lib version
+GCX	= $(TEST)$(DLL_VER)
+
+# Files we need to run the tests
+# - paths are relative to pthreads build dir.
+HDR	= pthread.h semaphore.h sched.h
+LIB	= libpthread$(GCX).a
+DLL	= pthread$(GCX).dll
+QAPC	= ../QueueUserAPCEx/User/quserex.dll
+
+COPYFILES	= $(HDR) $(LIB) $(DLL) $(QAPC)
+
+# If a test case returns a non-zero exit code to the shell, make will
+# stop.
+
+TESTS	= sizes loadfree \
+	  self1 mutex5 mutex1 mutex1e mutex1n mutex1r \
+	  semaphore1 semaphore2 semaphore3 \
+	  condvar1 condvar1_1 condvar1_2 condvar2 condvar2_1 exit1 \
+	  create1 create2 reuse1 reuse2 equal1 \
+	  kill1 valid1 valid2 \
+	  exit2 exit3 exit4 exit5 \
+	  join0 join1 detach1 join2 join3 \
+	  mutex2 mutex2r mutex2e mutex3 mutex3r mutex3e \
+	  mutex4 mutex6 mutex6n mutex6e mutex6r \
+	  mutex6s mutex6es mutex6rs \
+	  mutex7 mutex7n mutex7e mutex7r mutex8 mutex8n mutex8e mutex8r \
+	  count1 \
+	  once1 once2 once3 once4 self2 \
+	  cancel1 cancel2 \
+	  semaphore4 semaphore4t semaphore5 \
+	  barrier1 barrier2 barrier3 barrier4 barrier5 \
+	  tsd1 tsd2 delay1 delay2 eyal1 \
+	  condvar3 condvar3_1 condvar3_2 condvar3_3 \
+	  condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \
+	  errno1 \
+	  rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 rwlock7 rwlock8 \
+	  rwlock2_t rwlock3_t rwlock4_t rwlock5_t rwlock6_t rwlock6_t2 \
+	  context1 cancel3 cancel4 cancel5 cancel6a cancel6d \
+	  cancel7 cancel8 \
+	  cleanup0 cleanup1 cleanup2 cleanup3 \
+	  priority1 priority2 inherit1 \
+	  spin1 spin2 spin3 spin4 \
+	  exception1 exception2 exception3 \
+	  cancel9 create3 stress1
+
+STRESSTESTS = \
+	stress1
+
+BENCHTESTS = \
+	benchtest1 benchtest2 benchtest3 benchtest4 benchtest5
+
+STATICTESTS = \
+	self1
+
+PASSES		= $(TESTS:%=%.pass)
+BENCHRESULTS	= $(BENCHTESTS:%=%.bench)
+STRESSRESULTS	= $(STRESSTESTS:%=%.pass)
+STATICRESULTS	= $(STATICTESTS:%=%.pass)
+
+help:
+	@ $(ECHO) "Run one of the following command lines:"
+	@ $(ECHO) "make clean GC    (to test using GC dll with C (no EH) applications)"
+	@ $(ECHO) "make clean GCX   (to test using GC dll with C++ (EH) applications)"
+	@ $(ECHO) "make clean GCE   (to test using GCE dll with C++ (EH) applications)"
+	@ $(ECHO) "make clean GC-bench	  (to benchtest using GNU C dll with C cleanup code)"
+	@ $(ECHO) "make clean GCE-bench   (to benchtest using GNU C dll with C++ exception handling)"
+	@ $(ECHO) "make clean GC-stress	  (to stresstest using GNU C dll with C cleanup code)"
+	@ $(ECHO) "make clean GCE-stress   (to stresstest using GNU C dll with C++ exception handling)"
+	@ $(ECHO) "make clean GC-static   (to test using GC static lib with C (no EH) applications)"
+
+all:
+	@ $(MAKE) clean GC
+	@ $(MAKE) clean GCX
+	@ $(MAKE) clean GCE
+
+GC:
+	$(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" all-pass
+
+GCE:
+	$(MAKE) TEST=GCE CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" all-pass
+
+GCX:
+	$(MAKE) TEST=GC CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_C" all-pass
+
+GC-bench:
+	$(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" XXLIBS="benchlib.o" all-bench
+
+GCE-bench:
+	$(MAKE) TEST=GCE  CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" XXLIBS="benchlib." all-bench
+
+GC-debug:
+	$(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" DLL_VER="$(DLL_VER)d" all-pass
+
+GC-static:
+	$(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C -DPTW32_STATIC_LIB" DLL="" all-static
+
+GC-stress:
+	$(ECHO) Stress tests can take a long time since they are trying to
+	$(ECHO) expose weaknesses that may be intermittant or statistically rare.
+	$(ECHO) A pass does not prove correctness, but may give greater confidence.
+	$(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" all-stress
+
+GCE-stress:
+	$(MAKE) TEST=GCE  CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" all-stress
+
+all-pass: $(PASSES)
+	@ $(ECHO) ALL TESTS PASSED! Congratulations!
+
+all-bench: $(BENCHRESULTS)
+	@ $(ECHO) BENCH TESTS COMPLETED.
+
+all-stress: $(STRESSRESULTS)
+	@ $(ECHO) STRESS TESTS COMPLETED.
+
+all-static: $(STATICRESULTS)
+	@ $(ECHO) ALL STATIC TESTS PASSED! Congratulations!
+	@ $(ECHO) Build and test the DLL to run all tests.
+	@ $(ECHO) This test only confirms that the static lib links correctly.
+
+benchtest1.bench:
+benchtest2.bench:
+benchtest3.bench:
+benchtest4.bench:
+benchtest5.bench:
+
+barrier1.pass: semaphore4.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
+cancel2_1.pass: cancel2.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
+cancel9.pass: cancel8.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: cancel2.pass
+delay2.pass: delay1.pass
+detach1.pass: join0.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: exit4.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
+once2.pass: once1.pass
+once3.pass: once2.pass
+once4.pass: once3.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
+semaphore5.pass: semaphore4.pass
+sizes.pass:
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
+stress1.pass:
+tsd1.pass: barrier5.pass join1.pass
+tsd2.pass: tsd1.pass
+valid1.pass: join1.pass
+valid2.pass: valid1.pass
+
+sizes.pass: sizes.exe
+	@ $(ECHO) Running $*
+	$< > SIZES.$(TEST)
+	@ $(CAT) SIZES.$(TEST)
+	@ $(ECHO) Passed
+	@ $(TOUCH) $@
+
+%.pass: %.exe
+	@ $(ECHO) Running $*
+	$*
+	@ $(ECHO) Passed
+	@ $(TOUCH) $@
+
+%.bench: $(LIB) $(DLL) $(HDR) $(QAPC) $(XXLIBS) %.exe
+	@ $(ECHO) Running $*
+	$*
+	@ $(ECHO) Done
+	@ $(TOUCH) $@
+
+%.exe: %.c $(LIB) $(DLL) $(HDR) $(QAPC)
+	@ $(ECHO) Compiling $@
+	@ $(ECHO) $(CC) $(CFLAGS) -o $@ $< $(INCLUDES) -L. -lpthread$(GCX) -lsupc++ $(XXLIBS)
+	@ $(CC) $(CFLAGS) -o $@ $< $(INCLUDES) -L. -lpthread$(GCX) -lsupc++ $(XXLIBS)
+
+%.pre: %.c $(HDR)
+	@ $(CC) -E $(CFLAGS) -o $@ $< $(INCLUDES)
+
+%.s: %.c $(HDR)
+	@ $(CC) -S $(CFLAGS) -o $@ $< $(INCLUDES)
+
+$(COPYFILES):
+	@ $(ECHO) Copying $@
+	@ $(CP) $(BUILD_DIR)/$@ .
+
+benchlib.o: benchlib.c
+	@ $(ECHO) Compiling $@
+	@ $(ECHO) $(CC) -c $(CFLAGS) $< $(INCLUDES)
+	@ $(CC) -c $(CFLAGS) $< $(INCLUDES)
+
+pthread.dll: $(DLL)
+	@ $(CP) $(DLL) $@
+
+clean:
+	- $(RM) *.dll
+	- $(RM) *.lib
+	- $(RM) pthread.h
+	- $(RM) semaphore.h
+	- $(RM) sched.h
+	- $(RM) *.a
+	- $(RM) *.e
+	- $(RM) *.i
+	- $(RM) *.o
+	- $(RM) *.obj
+	- $(RM) *.pdb
+	- $(RM) *.exe
+	- $(RM) *.pass
+	- $(RM) *.bench
+	- $(RM) *.static
+	- $(RM) *.log
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..69dc39c
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,404 @@
+# 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,2005 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
+#
+
+DLL_VER	= 2
+
+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$(DLL_VER).lib
+VCEDLL	= pthreadVCE$(DLL_VER).dll
+# Structured Exceptions
+VSEFLAGS	= /D__CLEANUP_SEH
+VSELIB	= pthreadVSE$(DLL_VER).lib
+VSEDLL	= pthreadVSE$(DLL_VER).dll
+# C cleanup code
+VCFLAGS	= /D__CLEANUP_C
+VCLIB	= pthreadVC$(DLL_VER).lib
+VCDLL	= pthreadVC$(DLL_VER).dll
+# C++ Exceptions in application - using VC version of pthreads dll
+VCXFLAGS	= /GX /TP /D__CLEANUP_C
+
+# Defaults
+CPLIB	= $(VCLIB)
+CPDLL	= $(VCDLL)
+
+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.pass  exit5.pass  \
+	  join0.pass  join1.pass  detach1.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  once2.pass  once3.pass  once4.pass  \
+	  self2.pass  \
+	  cancel1.pass  cancel2.pass  \
+	  semaphore4.pass  semaphore4t.pass  semaphore5.pass  \
+	  barrier1.pass  barrier2.pass  barrier3.pass  barrier4.pass  barrier5.pass  \
+	  tsd1.pass  tsd2.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.pass  cancel8.pass  \
+	  cleanup0.pass  cleanup1.pass  cleanup2.pass  cleanup3.pass  \
+	  priority1.pass priority2.pass inherit1.pass  \
+	  spin1.pass  spin2.pass  spin3.pass  spin4.pass  \
+	  exception1.pass  exception2.pass  exception3.pass  \
+	  cancel9.pass  create3.pass  stress1.pass
+
+BENCHRESULTS = \
+	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench
+
+STRESSRESULTS = \
+	  stress1.stress
+
+STATICRESULTS = \
+	  self1.pass
+
+help:
+	@ $(ECHO) Run one of the following command lines:
+	@ $(ECHO) nmake clean VC          (to test using VC dll with VC (no EH) apps)
+	@ $(ECHO) nmake clean VC-bench    (to benchtest using VC dll with C bench apps)
+	@ $(ECHO) nmake clean VC-stress   (to stresstest using VC dll with C stress apps)
+	@ $(ECHO) nmake clean VC-static   (to test using VC static lib with VC (no EH) apps)
+	@ $(ECHO) nmake clean VCX         (to test using VC dll with VC++ (EH) applications)
+	@ $(ECHO) nmake clean VCX-bench   (to benchtest using VC dll with C++ bench apps)
+	@ $(ECHO) nmake clean VCX-stress  (to stresstest using VC dll with C++ stress apps)
+	@ $(ECHO) nmake clean VCE         (to test using the VCE dll with VC++ EH applications)
+	@ $(ECHO) nmake clean VCE-bench   (to benchtest using VCE dll with C++ bench apps)
+	@ $(ECHO) nmake clean VCE-stress  (to stresstest using VCE dll with C++ stress apps)
+	@ $(ECHO) nmake clean VSE         (to test using VSE dll with VC (SEH) apps)
+	@ $(ECHO) nmake clean VSE-bench   (to benchtest using VSE dll with SEH bench apps)
+	@ $(ECHO) nmake clean VSE-stress  (to stresstest using VSE dll with SEH stress apps)
+
+all:
+	@ nmake clean VC
+	@ nmake clean VCX
+	@ nmake clean VCE
+	@ nmake clean VSE
+	@ nmake clean VC-bench
+	@ nmake clean VC-stress
+
+# 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.
+
+stresstests: $(CPLIB) $(CPDLL) $(CPHDR) $(STRESSRESULTS)
+	@ $(ECHO) ALL STRESS TESTS DONE.
+
+statictests: $(CPLIB) $(CPDLL) $(CPHDR) $(STATICRESULTS)
+	@ $(ECHO) ALL STATIC TESTS DONE.
+	@ $(ECHO) Build and test the DLL to run all tests.
+	@ $(ECHO) The static test only confirms that the .lib links correctly.
+
+sizes.pass: sizes.exe
+	@ $(ECHO) ... Running $(TEST)$(DLL_VER) 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
+
+$(STRESSRESULTS): $*.exe
+	@ $(ECHO) ... Running $(TEST) stresstest: $*.exe
+	@ .\$*.exe
+	@ $(ECHO) ...... Done
+	@ $(TOUCH) $*.pass
+
+VC:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests
+
+VCE:
+	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" tests
+
+VSE:	
+	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" tests
+
+VCX:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" tests
+
+VC-bench:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" XXLIBS="benchlib.o" benchtests
+
+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
+
+VCX-bench:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" XXLIBS="benchlib.o" benchtests
+
+VC-stress:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" stresstests
+
+VCE-stress:
+	@ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" stresstests
+
+VSE-stress:
+	@ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" stresstests
+
+VCX-stress:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" stresstests
+
+VC-static:
+	@ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="" EHFLAGS="$(VCFLAGS) /DPTW32_STATIC_LIB" statictests
+
+.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: semaphore4.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
+cancel9.pass: cancel8.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
+detach1.pass: join0.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
+once2.pass: once1.pass
+once3.pass: once2.pass
+once4.pass: once3.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
+semaphore5.pass: semaphore4.pass
+sizes.pass:
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
+stress1.pass: condvar9.pass barrier5.pass
+tsd1.pass: barrier5.pass join1.pass
+tsd2.pass: tsd1.pass
+valid1.pass: join1.pass
+valid2.pass: valid1.pass
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..a1b5646
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,44 @@
+Running test cases in this directory
+------------------------------------
+
+These make scripts expect to be able to copy the dll, library
+and header files from this directory's parent directory,
+which should be the pthreads-win32 source directory.
+
+MS VC nmake
+-------------
+
+Run the target corresponding to the DLL version being tested:
+ 
+nmake clean VC
+ 
+or:
+ 
+nmake clean VS
+
+
+GNU GCC make
+------------
+
+Run "make clean" and then "make". See the "Known bugs" section
+in ..\README.
+
+
+Writing Test Cases
+------------------
+
+Tests written in this test suite should behave in the following manner:
+
+	* If a test fails, leave main() with a result of 1.
+
+	* If a test succeeds, leave main() with a result of 0.
+
+	* 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
new file mode 100644
index 0000000..448570c
--- /dev/null
+++ b/tests/README.BENCHTESTS
@@ -0,0 +1,74 @@
+
+------------
+Benchmarking
+------------
+There is a 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.
+
+
+Semaphore benchtests
+--------------------
+
+benchtest5 - Timing for various uncontended cases.
+
+
+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.
+
diff --git a/tests/SIZES.GC b/tests/SIZES.GC
new file mode 100644
index 0000000..ae09a84
--- /dev/null
+++ b/tests/SIZES.GC
@@ -0,0 +1,20 @@
+Sizes of pthreads-win32 structs
+-------------------------------
+                    pthread_t_  124
+               pthread_attr_t_   28
+                        sem_t_    4
+              pthread_mutex_t_   44
+          pthread_mutexattr_t_    8
+           pthread_spinlock_t_    8
+            pthread_barrier_t_   24
+        pthread_barrierattr_t_    4
+                pthread_key_t_   16
+               pthread_cond_t_   32
+           pthread_condattr_t_    4
+             pthread_rwlock_t_   28
+         pthread_rwlockattr_t_    4
+               pthread_once_t_    8
+               ptw32_cleanup_t   12
+                   sched_param    4
+-------------------------------
+
diff --git a/tests/SIZES.GCE b/tests/SIZES.GCE
new file mode 100644
index 0000000..f36d0d2
--- /dev/null
+++ b/tests/SIZES.GCE
@@ -0,0 +1,20 @@
+Sizes of pthreads-win32 structs
+-------------------------------
+                    pthread_t_   60
+               pthread_attr_t_   28
+                        sem_t_    4
+              pthread_mutex_t_   44
+          pthread_mutexattr_t_    8
+           pthread_spinlock_t_    8
+            pthread_barrier_t_   24
+        pthread_barrierattr_t_    4
+                pthread_key_t_   16
+               pthread_cond_t_   32
+           pthread_condattr_t_    4
+             pthread_rwlock_t_   28
+         pthread_rwlockattr_t_    4
+               pthread_once_t_    8
+               ptw32_cleanup_t   12
+                   sched_param    4
+-------------------------------
+
diff --git a/tests/SIZES.VC b/tests/SIZES.VC
new file mode 100644
index 0000000..ae09a84
--- /dev/null
+++ b/tests/SIZES.VC
@@ -0,0 +1,20 @@
+Sizes of pthreads-win32 structs
+-------------------------------
+                    pthread_t_  124
+               pthread_attr_t_   28
+                        sem_t_    4
+              pthread_mutex_t_   44
+          pthread_mutexattr_t_    8
+           pthread_spinlock_t_    8
+            pthread_barrier_t_   24
+        pthread_barrierattr_t_    4
+                pthread_key_t_   16
+               pthread_cond_t_   32
+           pthread_condattr_t_    4
+             pthread_rwlock_t_   28
+         pthread_rwlockattr_t_    4
+               pthread_once_t_    8
+               ptw32_cleanup_t   12
+                   sched_param    4
+-------------------------------
+
diff --git a/tests/SIZES.VCE b/tests/SIZES.VCE
new file mode 100644
index 0000000..edc6427
--- /dev/null
+++ b/tests/SIZES.VCE
@@ -0,0 +1,19 @@
+Sizes of pthreads-win32 structs
+-------------------------------
+                    pthread_t_   68
+               pthread_attr_t_   28
+                        sem_t_    4
+              pthread_mutex_t_   44
+          pthread_mutexattr_t_    8
+           pthread_spinlock_t_    8
+            pthread_barrier_t_   24
+        pthread_barrierattr_t_    4
+                pthread_key_t_   16
+               pthread_cond_t_   32
+           pthread_condattr_t_    4
+             pthread_rwlock_t_   28
+         pthread_rwlockattr_t_    4
+               pthread_once_t_    8
+               ptw32_cleanup_t   12
+                   sched_param    4
+-------------------------------
diff --git a/tests/SIZES.VSE b/tests/SIZES.VSE
new file mode 100644
index 0000000..edc6427
--- /dev/null
+++ b/tests/SIZES.VSE
@@ -0,0 +1,19 @@
+Sizes of pthreads-win32 structs
+-------------------------------
+                    pthread_t_   68
+               pthread_attr_t_   28
+                        sem_t_    4
+              pthread_mutex_t_   44
+          pthread_mutexattr_t_    8
+           pthread_spinlock_t_    8
+            pthread_barrier_t_   24
+        pthread_barrierattr_t_    4
+                pthread_key_t_   16
+               pthread_cond_t_   32
+           pthread_condattr_t_    4
+             pthread_rwlock_t_   28
+         pthread_rwlockattr_t_    4
+               pthread_once_t_    8
+               ptw32_cleanup_t   12
+                   sched_param    4
+-------------------------------
diff --git a/tests/Wmakefile b/tests/Wmakefile
new file mode 100644
index 0000000..83cd34b
--- /dev/null
+++ b/tests/Wmakefile
@@ -0,0 +1,346 @@
+# Watcom 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,2005 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
+#
+
+
+DLL_VER	= 2
+
+.EXTENSIONS:
+
+.EXTENSIONS: .pass .exe .obj .i .c
+
+CP	= copy
+RM	= erase
+CAT	= type
+MKDIR	= mkdir
+TOUCH	= echo Passed >
+ECHO	= @echo
+
+CPHDR	= pthread.h semaphore.h sched.h
+
+OPTIM	= -od
+
+XXLIBS	=
+
+# C++ Exceptions
+WCEFLAGS	= -xs -dPtW32NoCatchWarn -d__CLEANUP_CXX
+WCELIB	= pthreadWCE$(DLL_VER).lib
+WCEDLL	= pthreadWCE$(DLL_VER).dll
+# C cleanup code
+WCFLAGS	= -d__CLEANUP_C
+WCLIB	= pthreadWC$(DLL_VER).lib
+WCDLL	= pthreadWC$(DLL_VER).dll
+# C++ Exceptions in application - using WC version of pthreads dll
+WCXFLAGS	= -xs -d__CLEANUP_C
+
+CFLAGS= -w4 -e25 -d_WIN32_WINNT=0x400 -d_REENTRANT -zq -bm $(OPTIM) -5r -bt=nt -mf -d2
+
+LFLAGS= 
+INCLUDES= -i=.
+BUILD_DIR=..
+
+COPYFILES	= $(CPHDR) $(CPLIB) $(CPDLL)
+
+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  detach1.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  once2.pass  once3.pass  once4.pass  tsd1.pass  &
+	  self2.pass  &
+	  cancel1.pass  cancel2.pass  &
+	  semaphore4.pass semaphore4t.pass semaphore5.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.pass  create3.pass  stress1.pass
+
+BENCHRESULTS = &
+	  benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench
+
+help: .SYMBOLIC
+	@ $(ECHO) Run one of the following command lines:
+	@ $(ECHO) wmake /f Wmakefile clean WC    (to test using WC dll with wcc386 (no EH) applications)
+	@ $(ECHO) wmake /f Wmakefile clean WCX   (to test using WC dll with wpp386 (EH) applications)
+	@ $(ECHO) wmake /f Wmakefile clean WCE   (to test using the WCE dll with wpp386 EH applications)
+	@ $(ECHO) wmake /f Wmakefile clean WC-bench    (to benchtest using WC dll with C bench app)
+	@ $(ECHO) wmake /f Wmakefile clean WCX-bench   (to benchtest using WC dll with C++ bench app)
+	@ $(ECHO) wmake /f Wmakefile clean WCE-bench   (to benchtest using WCE dll with C++ bench app)
+
+all: .SYMBOLIC
+	@ wmake /f Wmakefile clean WC
+	@ wmake /f Wmakefile clean WCX
+	@ wmake /f Wmakefile clean WCE
+	@ wmake /f Wmakefile clean WSE
+	@ wmake /f Wmakefile clean WC-bench
+
+tests: $(CPLIB) $(CPDLL) $(CPHDR) $(PASSES) .SYMBOLIC
+	@ $(ECHO) ALL TESTS PASSED! Congratulations!
+
+benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(XXLIBS) $(BENCHRESULTS) .SYMBOLIC
+	@ $(ECHO) ALL BENCH TESTS DONE.
+
+$(BENCHRESULTS): ($[*).exe
+	@ $(ECHO) ... Running $(TEST) benchtest: ($[*).exe
+	@ .\($[*).exe
+	@ $(ECHO) ...... Done
+	@ $(TOUCH) ($[*).bench
+
+WCE: .SYMBOLIC
+	@ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCELIB)" CPDLL="$(WCEDLL)" EHFLAGS="$(WCEFLAGS)" tests
+
+WC: .SYMBOLIC
+	@ wmake /f Wmakefile CC=wcc386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCFLAGS)" tests
+
+WCX: .SYMBOLIC
+	@ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCXFLAGS)" tests
+
+WCE-bench: .SYMBOLIC
+	@ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCELIB)" CPDLL="$(WCEDLL)" EHFLAGS="$(WCEFLAGS)" XXLIBS="benchlib.o" benchtests
+
+WC-bench: .SYMBOLIC
+	@ wmake /f Wmakefile CC=wcc386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCFLAGS)" XXLIBS="benchlib.o" benchtests
+
+WCX-bench: .SYMBOLIC
+	@ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCXFLAGS)" XXLIBS="benchlib.o" benchtests
+
+sizes.pass: sizes.exe
+	@ $(ECHO) ... Running $(TEST) test: $^*
+	@ $[@ > SIZES.$(TEST)
+	@ $(CAT) SIZES.$(TEST)
+	@ $(ECHO) ...... Passed
+	@ $(TOUCH) $^@
+
+.exe.pass:
+	@ $(ECHO) ... Running $(TEST) test: $^*
+	@ $[@
+	@ $(ECHO) ...... Passed
+	@ $(TOUCH) $^@
+
+.obj.exe:
+	@ $(ECHO) wlink NAME $^@ FILE $[@ LIBRARY $(CPLIB) OPTION quiet
+	@ wlink NAME $^@ FILE $[@ LIBRARY $(CPLIB) OPTION quiet
+
+.c.obj:
+	@ $(ECHO) $(CC) $^* $(EHFLAGS) $(CFLAGS) $(INCLUDES)
+	@ $(CC) $^* $(EHFLAGS) $(CFLAGS) $(INCLUDES)
+
+.c.i:
+	@ $(CC) /P $(EHFLAGS) $(CFLAGS) $(INCLUDES) $<
+
+$(COPYFILES): .SYMBOLIC
+	@ $(ECHO) Copying $@
+	@ $(CP) $(BUILD_DIR)\$@ .
+
+pthread.dll:
+	@ $(CP) $(CPDLL) $*.dll
+	@ $(CP) $(CPLIB) $*.lib
+
+clean: .SYMBOLIC
+	@ if exist *.dll $(RM) *.dll
+	@ if exist *.lib $(RM) *.lib
+	@ if exist *.err $(RM) *.err
+	@ if exist pthread.h $(RM) pthread.h
+	@ if exist semaphore.h $(RM) semaphore.h
+	@ if exist sched.h $(RM) sched.h
+	@ if exist *.e $(RM) *.e
+	@ if exist *.i $(RM) *.i
+	@ if exist *.obj $(RM) *.obj
+	@ if exist *.pdb $(RM) *.pdb
+	@ if exist *.o $(RM) *.o
+	@ if exist *.asm $(RM) *.asm
+	@ if exist *.exe $(RM) *.exe
+	@ if exist *.pass $(RM) *.pass
+	@ if exist *.bench $(RM) *.bench
+	@ if exist *.log $(RM) *.log
+	@ $(ECHO) Clean completed.
+
+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
+detach1.pass: join0.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
+once2.pass: once1.pass
+once3.pass: once2.pass
+once4.pass: once3.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
+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
+semaphore5.pass: semaphore4.pass
+sizes.pass:
+spin1.pass:
+spin2.pass: spin1.pass
+spin3.pass: spin2.pass
+spin4.pass: spin3.pass
+stress1.pass:
+tsd1.pass: join1.pass
+valid1.pass: join1.pass
+valid2.pass: valid1.pass
+cancel9.pass: cancel8.pass
diff --git a/tests/barrier1.c b/tests/barrier1.c
new file mode 100644
index 0000000..76f78df
--- /dev/null
+++ b/tests/barrier1.c
@@ -0,0 +1,58 @@
+/* 
+ * barrier1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create a barrier object and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+pthread_barrier_t barrier = NULL;
+
+int
+main()
+{
+  assert(barrier == NULL);
+
+  assert(pthread_barrier_init(&barrier, NULL, 1) == 0);
+
+  assert(barrier != NULL);
+
+  assert(pthread_barrier_destroy(&barrier) == 0);
+
+  assert(barrier == NULL);
+
+  return 0;
+}
diff --git a/tests/barrier2.c b/tests/barrier2.c
new file mode 100644
index 0000000..28aa238
--- /dev/null
+++ b/tests/barrier2.c
@@ -0,0 +1,55 @@
+/* 
+ * barrier2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a single barrier object, wait on it, 
+ * and then destroy it.
+ *
+ */
+
+#include "test.h"
+ 
+pthread_barrier_t barrier = NULL;
+
+int
+main()
+{
+  assert(pthread_barrier_init(&barrier, NULL, 1) == 0);
+
+  assert(pthread_barrier_wait(&barrier) == PTHREAD_BARRIER_SERIAL_THREAD);
+
+  assert(pthread_barrier_destroy(&barrier) == 0);
+
+  return 0;
+}
diff --git a/tests/barrier3.c b/tests/barrier3.c
new file mode 100644
index 0000000..3e40090
--- /dev/null
+++ b/tests/barrier3.c
@@ -0,0 +1,71 @@
+/*
+ * barrier3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a single barrier object with barrier attribute, wait on it, 
+ * and then destroy it.
+ *
+ */
+
+#include "test.h"
+ 
+pthread_barrier_t barrier = NULL;
+static int result = 1;
+
+void * func(void * arg)
+{
+  return (void *) pthread_barrier_wait(&barrier);
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  pthread_barrierattr_t ba;
+
+  assert(pthread_barrierattr_init(&ba) == 0);
+  assert(pthread_barrierattr_setpshared(&ba, PTHREAD_PROCESS_PRIVATE) == 0);
+  assert(pthread_barrier_init(&barrier, &ba, 1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+
+  assert(result == PTHREAD_BARRIER_SERIAL_THREAD);
+
+  assert(pthread_barrier_destroy(&barrier) == 0);
+  assert(pthread_barrierattr_destroy(&ba) == 0);
+
+  return 0;
+}
diff --git a/tests/barrier4.c b/tests/barrier4.c
new file mode 100644
index 0000000..042992d
--- /dev/null
+++ b/tests/barrier4.c
@@ -0,0 +1,110 @@
+/*
+ * barrier4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a single barrier object, multiple wait on it, 
+ * and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+enum {
+  NUMTHREADS = 16
+};
+ 
+pthread_barrier_t barrier = NULL;
+pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;
+static int serialThreadCount = 0;
+static int otherThreadCount = 0;
+
+void *
+func(void * arg)
+{
+  int result = pthread_barrier_wait(&barrier);
+
+  assert(pthread_mutex_lock(&mx) == 0);
+
+  if (result == PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      serialThreadCount++;
+    }
+  else if (0 == result)
+    {
+      otherThreadCount++;
+    }
+  else
+    {
+      printf("Barrier wait failed: error = %s\n", error_string[result]);
+      fflush(stdout);
+      return NULL;
+    }
+  assert(pthread_mutex_unlock(&mx) == 0);
+
+  return NULL;
+}
+
+int
+main()
+{
+  int i, j;
+  pthread_t t[NUMTHREADS + 1];
+
+  for (j = 1; j <= NUMTHREADS; j++)
+    {
+      printf("Barrier height = %d\n", j);
+
+      serialThreadCount = 0;
+
+      assert(pthread_barrier_init(&barrier, NULL, j) == 0);
+
+      for (i = 1; i <= j; i++)
+        {
+          assert(pthread_create(&t[i], NULL, func, NULL) == 0);
+        }
+
+      for (i = 1; i <= j; i++)
+        {
+          assert(pthread_join(t[i], NULL) == 0);
+        }
+
+      assert(serialThreadCount == 1);
+
+      assert(pthread_barrier_destroy(&barrier) == 0);
+    }
+
+  assert(pthread_mutex_destroy(&mx) == 0);
+
+  return 0;
+}
diff --git a/tests/barrier5.c b/tests/barrier5.c
new file mode 100644
index 0000000..5b598c9
--- /dev/null
+++ b/tests/barrier5.c
@@ -0,0 +1,128 @@
+/*
+ * barrier5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a single barrier object, set up a sequence of
+ * barrier points to prove lockstepness, and then destroy it.
+ *
+ */
+
+#include "test.h"
+
+enum {
+  NUMTHREADS = 16,
+  BARRIERS = 10000
+};
+ 
+pthread_barrier_t barrier = NULL;
+pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;
+
+int barrierReleases[BARRIERS + 1];
+
+void *
+func(void * barrierHeight)
+{
+  int i;
+  int result;
+  int serialThreads = 0;
+
+  for (i = 1; i < BARRIERS; i++)
+    {
+      result = pthread_barrier_wait(&barrier);
+
+      assert(pthread_mutex_lock(&mx) == 0);
+      barrierReleases[i]++;
+      assert(pthread_mutex_unlock(&mx) == 0);
+      /*
+       * Confirm the correct number of releases from the previous
+       * barrier. We can't do the current barrier yet because there may
+       * still be threads waking up.
+       */
+      if (result == PTHREAD_BARRIER_SERIAL_THREAD)
+        {
+          serialThreads++;
+          assert(barrierReleases[i - 1] == (int) barrierHeight);
+          barrierReleases[i + 1] = 0;
+        }
+      else if (result != 0)
+        {
+          printf("Barrier failed: result = %s\n", error_string[result]);
+          fflush(stdout);
+          return NULL;
+        }
+    }
+
+  return (void *) serialThreads;
+}
+
+int
+main()
+{
+  int i, j;
+  int result;
+  int serialThreadsTotal;
+  pthread_t t[NUMTHREADS + 1];
+
+  for (j = 1; j <= NUMTHREADS; j++)
+    {
+      printf("Barrier height = %d\n", j);
+
+      barrierReleases[0] = j;
+      barrierReleases[1] = 0;
+
+      assert(pthread_barrier_init(&barrier, NULL, j) == 0);
+
+      for (i = 1; i <= j; i++)
+        {
+          assert(pthread_create(&t[i], NULL, func, (void *) j) == 0);
+        }
+
+      serialThreadsTotal = 0;
+      for (i = 1; i <= j; i++)
+        {
+          assert(pthread_join(t[i], (void **) &result) == 0);
+          serialThreadsTotal += result;
+        }
+
+      assert(serialThreadsTotal == BARRIERS - 1);
+      assert(barrierReleases[BARRIERS - 1] == j);
+      assert(barrierReleases[BARRIERS] == 0);
+
+      assert(pthread_barrier_destroy(&barrier) == 0);
+    }
+
+  assert(pthread_mutex_destroy(&mx) == 0);
+
+  return 0;
+}
diff --git a/tests/benchlib.c b/tests/benchlib.c
new file mode 100644
index 0000000..bf60ae5
--- /dev/null
+++ b/tests/benchlib.c
@@ -0,0 +1,363 @@
+/*
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ */
+
+#include "../config.h"
+
+#include "pthread.h"
+#include "sched.h"
+#include "semaphore.h"
+#include <windows.h>
+#include <stdio.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+int old_mutex_use = OLD_WIN32CS;
+
+BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL;
+HINSTANCE ptw32_h_kernel32;
+
+void
+dummy_call(int * a)
+{
+}
+
+void
+interlocked_inc_with_conditionals(int * a)
+{
+  if (a != NULL)
+    if (InterlockedIncrement((long *) a) == -1)
+      {
+        *a = 0;
+      }
+}
+
+void
+interlocked_dec_with_conditionals(int * a)
+{
+  if (a != NULL)
+    if (InterlockedDecrement((long *) a) == -1)
+      {
+        *a = 0;
+      }
+}
+
+int
+old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  mx = (old_mutex_t) calloc(1, sizeof(*mx));
+
+  if (mx == NULL)
+    {
+      result = ENOMEM;
+      goto FAIL0;
+    }
+
+  mx->mutex = 0;
+
+  if (attr != NULL
+      && *attr != NULL
+      && (*attr)->pshared == PTHREAD_PROCESS_SHARED
+      )
+    {
+      result = ENOSYS;
+    }
+  else
+    {
+        CRITICAL_SECTION cs;
+
+        /*
+         * Load KERNEL32 and try to get address of TryEnterCriticalSection
+         */
+        ptw32_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));
+        ptw32_try_enter_critical_section = (BOOL (WINAPI *)(LPCRITICAL_SECTION))
+
+#if defined(NEED_UNICODE_CONSTS)
+        GetProcAddress(ptw32_h_kernel32,
+                       (const TCHAR *)TEXT("TryEnterCriticalSection"));
+#else
+        GetProcAddress(ptw32_h_kernel32,
+                       (LPCSTR) "TryEnterCriticalSection");
+#endif
+
+        if (ptw32_try_enter_critical_section != NULL)
+          {
+            InitializeCriticalSection(&cs);
+            if ((*ptw32_try_enter_critical_section)(&cs))
+              {
+                LeaveCriticalSection(&cs);
+              }
+            else
+              {
+                /*
+                 * Not really supported (Win98?).
+                 */
+                ptw32_try_enter_critical_section = NULL;
+              }
+            DeleteCriticalSection(&cs);
+          }
+
+        if (ptw32_try_enter_critical_section == NULL)
+          {
+            (void) FreeLibrary(ptw32_h_kernel32);
+            ptw32_h_kernel32 = 0;
+          }
+
+      if (old_mutex_use == OLD_WIN32CS)
+	{
+	  InitializeCriticalSection(&mx->cs);
+	}
+      else if (old_mutex_use == OLD_WIN32MUTEX)
+      {
+	  mx->mutex = CreateMutex (NULL,
+				   FALSE,
+				   NULL);
+
+	  if (mx->mutex == 0)
+	    {
+	      result = EAGAIN;
+	    }
+	}
+      else
+	{
+        result = EINVAL;
+      }
+    }
+
+  if (result != 0 && mx != NULL)
+    {
+      free(mx);
+      mx = NULL;
+    }
+
+FAIL0:
+  *mutex = mx;
+
+  return(result);
+}
+
+
+int
+old_mutex_lock(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      /*
+       * Don't use initialisers when benchtesting.
+       */
+      result = EINVAL;
+    }
+
+  mx = *mutex;
+
+  if (result == 0)
+    {
+      if (mx->mutex == 0)
+	{
+	  EnterCriticalSection(&mx->cs);
+	}
+      else
+	{
+	  result = (WaitForSingleObject(mx->mutex, INFINITE) 
+		    == WAIT_OBJECT_0)
+	    ? 0
+	    : EINVAL;
+	}
+    }
+
+  return(result);
+}
+
+int
+old_mutex_unlock(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  mx = *mutex;
+
+  if (mx != (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      if (mx->mutex == 0)
+	{
+	  LeaveCriticalSection(&mx->cs);
+	}
+      else
+	{
+	  result = (ReleaseMutex (mx->mutex) ? 0 : EINVAL);
+	}
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  return(result);
+}
+
+
+int
+old_mutex_trylock(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      /*
+       * Don't use initialisers when benchtesting.
+       */
+      result = EINVAL;
+    }
+
+  mx = *mutex;
+
+  if (result == 0)
+    {
+      if (mx->mutex == 0)
+	{
+	  if (ptw32_try_enter_critical_section == NULL)
+          {
+            result = 0;
+          }
+        else if ((*ptw32_try_enter_critical_section)(&mx->cs) != TRUE)
+	    {
+	      result = EBUSY;
+	    }
+	}
+      else
+	{
+	  DWORD status;
+
+	  status = WaitForSingleObject (mx->mutex, 0);
+
+	  if (status != WAIT_OBJECT_0)
+	    {
+	      result = ((status == WAIT_TIMEOUT)
+			? EBUSY
+			: EINVAL);
+	    }
+	}
+    }
+
+  return(result);
+}
+
+
+int
+old_mutex_destroy(old_mutex_t *mutex)
+{
+  int result = 0;
+  old_mutex_t mx;
+
+  if (mutex == NULL
+      || *mutex == NULL)
+    {
+      return EINVAL;
+    }
+
+  if (*mutex != (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
+    {
+      mx = *mutex;
+
+      if ((result = old_mutex_trylock(&mx)) == 0)
+        {
+          *mutex = NULL;
+
+          (void) old_mutex_unlock(&mx);
+
+          if (mx->mutex == 0)
+            {
+              DeleteCriticalSection(&mx->cs);
+            }
+          else
+            {
+              result = (CloseHandle (mx->mutex) ? 0 : EINVAL);
+            }
+
+          if (result == 0)
+            {
+              mx->mutex = 0;
+              free(mx);
+            }
+          else
+            {
+              *mutex = mx;
+            }
+        }
+    }
+  else
+    {
+      result = EINVAL;
+    }
+
+  if (ptw32_try_enter_critical_section != NULL)
+    {
+      (void) FreeLibrary(ptw32_h_kernel32);
+      ptw32_h_kernel32 = 0;
+    }
+
+  return(result);
+}
+
+/****************************************************************************************/
diff --git a/tests/benchtest.h b/tests/benchtest.h
new file mode 100644
index 0000000..8090578
--- /dev/null
+++ b/tests/benchtest.h
@@ -0,0 +1,70 @@
+/*
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ */
+
+#include "../config.h"
+
+enum {
+  OLD_WIN32CS,
+  OLD_WIN32MUTEX
+};
+
+extern int old_mutex_use;
+
+struct old_mutex_t_ {
+  HANDLE mutex;
+  CRITICAL_SECTION cs;
+};
+
+typedef struct old_mutex_t_ * old_mutex_t;
+
+struct old_mutexattr_t_ {
+  int pshared;
+};
+
+typedef struct old_mutexattr_t_ * old_mutexattr_t;
+
+extern BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION);
+extern HINSTANCE ptw32_h_kernel32;
+
+#define PTW32_OBJECT_AUTO_INIT ((void *) -1)
+
+void dummy_call(int * a);
+void interlocked_inc_with_conditionals(int *a);
+void interlocked_dec_with_conditionals(int *a);
+int old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr);
+int old_mutex_lock(old_mutex_t *mutex);
+int old_mutex_unlock(old_mutex_t *mutex);
+int old_mutex_trylock(old_mutex_t *mutex);
+int old_mutex_destroy(old_mutex_t *mutex);
+/****************************************************************************************/
diff --git a/tests/benchtest1.c b/tests/benchtest1.c
new file mode 100644
index 0000000..116dad0
--- /dev/null
+++ b/tests/benchtest1.c
@@ -0,0 +1,249 @@
+/*
+ * benchtest1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Mutex
+ *   Single thread iteration over lock/unlock for each mutex type.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
+#define ITERATIONS      10000000L
+
+pthread_mutex_t mx;
+pthread_mutexattr_t ma;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+int one = 1;
+int zero = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void
+runTest (char * testNameString, int mType)
+{
+#ifdef PTW32_MUTEX_TYPES
+  assert(pthread_mutexattr_settype(&ma, mType) == 0);
+#endif
+  assert(pthread_mutex_init(&mx, &ma) == 0);
+
+  TESTSTART
+  assert(pthread_mutex_lock(&mx) == zero);
+  assert(pthread_mutex_unlock(&mx) == zero);
+  TESTSTOP
+
+  assert(pthread_mutex_destroy(&mx) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int i = 0;
+  CRITICAL_SECTION cs;
+  old_mutex_t ox;
+  pthread_mutexattr_init(&ma);
+
+  printf( "=============================================================================\n");
+  printf( "\nLock plus unlock on an unlocked mutex.\n%ld iterations\n\n",
+          ITERATIONS);
+  printf( "%-45s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "-----------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  TESTSTART
+  assert(1 == one);
+  assert(1 == one);
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+
+  TESTSTART
+  assert((dummy_call(&i), 1) == one);
+  assert((dummy_call(&i), 1) == one);
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    "Dummy call x 2",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  TESTSTART
+  assert((interlocked_inc_with_conditionals(&i), 1) == one);
+  assert((interlocked_dec_with_conditionals(&i), 1) == one);
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    "Dummy call -> Interlocked with cond x 2",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  TESTSTART
+  assert((InterlockedIncrement((LPLONG)&i), 1) == (LONG)one);
+  assert((InterlockedDecrement((LPLONG)&i), 1) == (LONG)one);
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    "InterlockedOp x 2",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  InitializeCriticalSection(&cs);
+
+  TESTSTART
+  assert((EnterCriticalSection(&cs), 1) == one);
+  assert((LeaveCriticalSection(&cs), 1) == one);
+  TESTSTOP
+
+  DeleteCriticalSection(&cs);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    "Simple Critical Section",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox, NULL) == 0);
+
+  TESTSTART
+  assert(old_mutex_lock(&ox) == zero);
+  assert(old_mutex_unlock(&ox) == zero);
+  TESTSTOP
+
+  assert(old_mutex_destroy(&ox) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox, NULL) == 0);
+
+  TESTSTART
+  assert(old_mutex_lock(&ox) == zero);
+  assert(old_mutex_unlock(&ox) == zero);
+  TESTSTOP
+
+  assert(old_mutex_destroy(&ox) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  printf( ".............................................................................\n");
+
+  /*
+   * Now we can start the actual tests
+   */
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
+
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
+
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
+
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
+#else
+  runTest("Non-blocking lock", 0);
+#endif
+
+  printf( "=============================================================================\n");
+
+  /*
+   * End of tests.
+   */
+
+  pthread_mutexattr_destroy(&ma);
+
+  one = i; /* Dummy assignment to avoid 'variable unused' warning */
+  return 0;
+}
diff --git a/tests/benchtest2.c b/tests/benchtest2.c
new file mode 100644
index 0000000..d92bb3c
--- /dev/null
+++ b/tests/benchtest2.c
@@ -0,0 +1,311 @@
+/*
+ * benchtest1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Mutex
+ *   Two threads iterate over lock/unlock for each mutex type.
+ *   The two threads are forced into lock-step using two mutexes,
+ *   forcing the threads to block on each lock operation. The
+ *   time measured is therefore the worst case senario.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
+#define ITERATIONS      100000L
+
+pthread_mutex_t gate1, gate2;
+old_mutex_t ox1, ox2;
+CRITICAL_SECTION cs1, cs2;
+pthread_mutexattr_t ma;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+pthread_t worker;
+int running = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void *
+overheadThread(void * arg)
+{
+  do
+    {
+      sched_yield();
+    }
+  while (running);
+
+  return NULL;
+}
+
+
+void *
+oldThread(void * arg)
+{
+  do
+    {
+      (void) old_mutex_lock(&ox1);
+      (void) old_mutex_lock(&ox2);
+      (void) old_mutex_unlock(&ox1);
+      sched_yield();
+      (void) old_mutex_unlock(&ox2);
+    }
+  while (running);
+
+  return NULL;
+}
+
+void *
+workerThread(void * arg)
+{
+  do
+    {
+      (void) pthread_mutex_lock(&gate1);
+      (void) pthread_mutex_lock(&gate2);
+      (void) pthread_mutex_unlock(&gate1);
+      sched_yield();
+      (void) pthread_mutex_unlock(&gate2);
+    }
+  while (running);
+
+  return NULL;
+}
+
+void *
+CSThread(void * arg)
+{
+  do
+    {
+      EnterCriticalSection(&cs1);
+      EnterCriticalSection(&cs2);
+      LeaveCriticalSection(&cs1);
+      sched_yield();
+      LeaveCriticalSection(&cs2);
+    }
+  while (running);
+
+  return NULL;
+}
+
+void
+runTest (char * testNameString, int mType)
+{
+#ifdef PTW32_MUTEX_TYPES
+  assert(pthread_mutexattr_settype(&ma, mType) == 0);
+#endif
+  assert(pthread_mutex_init(&gate1, &ma) == 0);
+  assert(pthread_mutex_init(&gate2, &ma) == 0);
+  assert(pthread_mutex_lock(&gate1) == 0);
+  assert(pthread_mutex_lock(&gate2) == 0);
+  running = 1;
+  assert(pthread_create(&worker, NULL, workerThread, NULL) == 0);
+  TESTSTART
+  (void) pthread_mutex_unlock(&gate1);
+  sched_yield();
+  (void) pthread_mutex_unlock(&gate2);
+  (void) pthread_mutex_lock(&gate1);
+  (void) pthread_mutex_lock(&gate2);
+  TESTSTOP
+  running = 0;
+  assert(pthread_mutex_unlock(&gate2) == 0);
+  assert(pthread_mutex_unlock(&gate1) == 0);
+  assert(pthread_join(worker, NULL) == 0);
+  assert(pthread_mutex_destroy(&gate2) == 0);
+  assert(pthread_mutex_destroy(&gate1) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4   /* Four locks/unlocks per iteration */);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  assert(pthread_mutexattr_init(&ma) == 0);
+
+  printf( "=============================================================================\n");
+  printf( "\nLock plus unlock on a locked mutex.\n");
+  printf("%ld iterations, four locks/unlocks per iteration.\n\n", ITERATIONS);
+
+  printf( "%-45s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "-----------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  running = 1;
+  assert(pthread_create(&worker, NULL, overheadThread, NULL) == 0);
+  TESTSTART
+  sched_yield();
+  sched_yield();
+  TESTSTOP
+  running = 0;
+  assert(pthread_join(worker, NULL) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+
+  InitializeCriticalSection(&cs1);
+  InitializeCriticalSection(&cs2);
+  EnterCriticalSection(&cs1);
+  EnterCriticalSection(&cs2);
+  running = 1;
+  assert(pthread_create(&worker, NULL, CSThread, NULL) == 0);
+  TESTSTART
+  LeaveCriticalSection(&cs1);
+  sched_yield();
+  LeaveCriticalSection(&cs2);
+  EnterCriticalSection(&cs1);
+  EnterCriticalSection(&cs2);
+  TESTSTOP
+  running = 0;
+  LeaveCriticalSection(&cs2);
+  LeaveCriticalSection(&cs1);
+  assert(pthread_join(worker, NULL) == 0);
+  DeleteCriticalSection(&cs2);
+  DeleteCriticalSection(&cs1);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Simple Critical Section",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4 );
+
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox1, NULL) == 0);
+  assert(old_mutex_init(&ox2, NULL) == 0);
+  assert(old_mutex_lock(&ox1) == 0);
+  assert(old_mutex_lock(&ox2) == 0);
+  running = 1;
+  assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_unlock(&ox1);
+  sched_yield();
+  (void) old_mutex_unlock(&ox2);
+  (void) old_mutex_lock(&ox1);
+  (void) old_mutex_lock(&ox2);
+  TESTSTOP
+  running = 0;
+  assert(old_mutex_unlock(&ox1) == 0);
+  assert(old_mutex_unlock(&ox2) == 0);
+  assert(pthread_join(worker, NULL) == 0);
+  assert(old_mutex_destroy(&ox2) == 0);
+  assert(old_mutex_destroy(&ox1) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4);
+
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox1, NULL) == 0);
+  assert(old_mutex_init(&ox2, NULL) == 0);
+  assert(old_mutex_lock(&ox1) == 0);
+  assert(old_mutex_lock(&ox2) == 0);
+  running = 1;
+  assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_unlock(&ox1);
+  sched_yield();
+  (void) old_mutex_unlock(&ox2);
+  (void) old_mutex_lock(&ox1);
+  (void) old_mutex_lock(&ox2);
+  TESTSTOP
+  running = 0;
+  assert(old_mutex_unlock(&ox1) == 0);
+  assert(old_mutex_unlock(&ox2) == 0);
+  assert(pthread_join(worker, NULL) == 0);
+  assert(old_mutex_destroy(&ox2) == 0);
+  assert(old_mutex_destroy(&ox1) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS / 4);
+
+  printf( ".............................................................................\n");
+
+  /*
+   * Now we can start the actual tests
+   */
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
+
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
+
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
+
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
+#else
+  runTest("Blocking locks", 0);
+#endif
+
+  printf( "=============================================================================\n");
+  /*
+   * End of tests.
+   */
+
+  pthread_mutexattr_destroy(&ma);
+
+  return 0;
+}
diff --git a/tests/benchtest3.c b/tests/benchtest3.c
new file mode 100644
index 0000000..023460d
--- /dev/null
+++ b/tests/benchtest3.c
@@ -0,0 +1,201 @@
+/*
+ * benchtest3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Mutex
+ *   Single thread iteration over a trylock on a locked mutex for each mutex type.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
+#define ITERATIONS      10000000L
+
+pthread_mutex_t mx;
+old_mutex_t ox;
+pthread_mutexattr_t ma;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void *
+trylockThread (void * arg)
+{
+  TESTSTART
+  (void) pthread_mutex_trylock(&mx);
+  TESTSTOP
+
+  return NULL;
+}
+
+
+void *
+oldTrylockThread (void * arg)
+{
+  TESTSTART
+  (void) old_mutex_trylock(&ox);
+  TESTSTOP
+
+  return NULL;
+}
+
+
+void
+runTest (char * testNameString, int mType)
+{
+  pthread_t t;
+
+#ifdef PTW32_MUTEX_TYPES
+  (void) pthread_mutexattr_settype(&ma, mType);
+#endif
+  assert(pthread_mutex_init(&mx, &ma) == 0);
+  assert(pthread_mutex_lock(&mx) == 0);
+  assert(pthread_create(&t, NULL, trylockThread, 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_mutex_unlock(&mx) == 0);
+  assert(pthread_mutex_destroy(&mx) == 0);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  pthread_t t;
+
+  assert(pthread_mutexattr_init(&ma) == 0);
+
+  printf( "=============================================================================\n");
+  printf( "\nTrylock on a locked mutex.\n");
+  printf( "%ld iterations.\n\n", ITERATIONS);
+  printf( "%-45s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "-----------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  TESTSTART
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  assert(old_mutex_lock(&ox) == 0);
+  assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(old_mutex_unlock(&ox) == 0);
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  assert(old_mutex_lock(&ox) == 0);
+  assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(old_mutex_unlock(&ox) == 0);
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  printf( ".............................................................................\n");
+
+  /*
+   * Now we can start the actual tests
+   */
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
+
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
+
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
+
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
+#else
+  runTest("Non-blocking lock", 0);
+#endif
+
+  printf( "=============================================================================\n");
+
+  /*
+   * End of tests.
+   */
+
+  pthread_mutexattr_destroy(&ma);
+
+  return 0;
+}
diff --git a/tests/benchtest4.c b/tests/benchtest4.c
new file mode 100644
index 0000000..772d100
--- /dev/null
+++ b/tests/benchtest4.c
@@ -0,0 +1,182 @@
+/*
+ * benchtest4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Mutex
+ *   Single thread iteration over trylock/unlock for each mutex type.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define PTW32_MUTEX_TYPES
+#define ITERATIONS      10000000L
+
+pthread_mutex_t mx;
+old_mutex_t ox;
+pthread_mutexattr_t ma;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void
+oldRunTest (char * testNameString, int mType)
+{
+}
+
+
+void
+runTest (char * testNameString, int mType)
+{
+#ifdef PTW32_MUTEX_TYPES
+  pthread_mutexattr_settype(&ma, mType);
+#endif
+  pthread_mutex_init(&mx, &ma);
+
+  TESTSTART
+  (void) pthread_mutex_trylock(&mx);
+  (void) pthread_mutex_unlock(&mx);
+  TESTSTOP
+
+  pthread_mutex_destroy(&mx);
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  pthread_mutexattr_init(&ma);
+
+  printf( "=============================================================================\n");
+  printf( "Trylock plus unlock on an unlocked mutex.\n");
+  printf( "%ld iterations.\n\n", ITERATIONS);
+  printf( "%-45s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "-----------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  TESTSTART
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+  old_mutex_use = OLD_WIN32CS;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_trylock(&ox);
+  (void) old_mutex_unlock(&ox);
+  TESTSTOP
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Critical Section (WNT)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  old_mutex_use = OLD_WIN32MUTEX;
+  assert(old_mutex_init(&ox, NULL) == 0);
+  TESTSTART
+  (void) old_mutex_trylock(&ox);
+  (void) old_mutex_unlock(&ox);
+  TESTSTOP
+  assert(old_mutex_destroy(&ox) == 0);
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  printf( "%-45s %15ld %15.3f\n",
+	    "Old PT Mutex using a Win32 Mutex (W9x)",
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+
+  printf( ".............................................................................\n");
+
+  /*
+   * Now we can start the actual tests
+   */
+#ifdef PTW32_MUTEX_TYPES
+  runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT);
+
+  runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL);
+
+  runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK);
+
+  runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE);
+#else
+  runTest("Non-blocking lock", 0);
+#endif
+
+  printf( "=============================================================================\n");
+
+  /*
+   * End of tests.
+   */
+
+  pthread_mutexattr_destroy(&ma);
+
+  return 0;
+}
diff --git a/tests/benchtest5.c b/tests/benchtest5.c
new file mode 100644
index 0000000..7700fde
--- /dev/null
+++ b/tests/benchtest5.c
@@ -0,0 +1,159 @@
+/*
+ * benchtest5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Measure time taken to complete an elementary operation.
+ *
+ * - Semaphore
+ *   Single thread iteration over post/wait for a semaphore.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "benchtest.h"
+
+#define ITERATIONS      1000000L
+
+sem_t sema;
+HANDLE w32sema;
+
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+long durationMilliSecs;
+long overHeadMilliSecs = 0;
+int one = 1;
+int zero = 0;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+                                               - (_TStart.time*1000+_TStart.millitm))
+
+/*
+ * Dummy use of j, otherwise the loop may be removed by the optimiser
+ * when doing the overhead timing with an empty loop.
+ */
+#define TESTSTART \
+  { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++;
+
+#define TESTSTOP \
+  }; _ftime(&currSysTimeStop); if (j + k == i) j++; }
+
+
+void
+reportTest (char * testNameString)
+{
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+
+  printf( "%-45s %15ld %15.3f\n",
+	    testNameString,
+          durationMilliSecs,
+          (float) durationMilliSecs * 1E3 / ITERATIONS);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  printf( "=============================================================================\n");
+  printf( "\nOperations on a semaphore.\n%ld iterations\n\n",
+          ITERATIONS);
+  printf( "%-45s %15s %15s\n",
+	    "Test",
+	    "Total(msec)",
+	    "average(usec)");
+  printf( "-----------------------------------------------------------------------------\n");
+
+  /*
+   * Time the loop overhead so we can subtract it from the actual test times.
+   */
+
+  TESTSTART
+  assert(1 == one);
+  TESTSTOP
+
+  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
+  overHeadMilliSecs = durationMilliSecs;
+
+
+  /*
+   * Now we can start the actual tests
+   */
+  assert((w32sema = CreateSemaphore(NULL, (long) 0, (long) ITERATIONS, NULL)) != 0);
+  TESTSTART
+  assert(ReleaseSemaphore(w32sema, 1, NULL) != zero);
+  TESTSTOP
+  assert(CloseHandle(w32sema) != 0);
+
+  reportTest("W32 Post with no waiters");
+
+
+  assert((w32sema = CreateSemaphore(NULL, (long) ITERATIONS, (long) ITERATIONS, NULL)) != 0);
+  TESTSTART
+  assert(WaitForSingleObject(w32sema, INFINITE) == WAIT_OBJECT_0);
+  TESTSTOP
+  assert(CloseHandle(w32sema) != 0);
+
+  reportTest("W32 Wait without blocking");
+
+
+  assert(sem_init(&sema, 0, 0) == 0);
+  TESTSTART
+  assert(sem_post(&sema) == zero);
+  TESTSTOP
+  assert(sem_destroy(&sema) == 0);
+
+  reportTest("POSIX Post with no waiters");
+
+
+  assert(sem_init(&sema, 0, ITERATIONS) == 0);
+  TESTSTART
+  assert(sem_wait(&sema) == zero);
+  TESTSTOP
+  assert(sem_destroy(&sema) == 0);
+
+  reportTest("POSIX Wait without blocking");
+
+
+  printf( "=============================================================================\n");
+
+  /*
+   * End of tests.
+   */
+
+  return 0;
+}
diff --git a/tests/cancel1.c b/tests/cancel1.c
new file mode 100644
index 0000000..be9b102
--- /dev/null
+++ b/tests/cancel1.c
@@ -0,0 +1,179 @@
+/*
+ * File: cancel1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test setting cancel state and cancel type.
+ * - 
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * Requirements Tested:
+ * - pthread_setcancelstate function
+ * - pthread_setcanceltype function
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - 
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - pthread_create, pthread_self work.
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 2
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* ... */
+  {
+    int oldstate;
+    int oldtype;
+
+    assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) == 0);
+    assert(oldstate == PTHREAD_CANCEL_ENABLE); /* Check default */
+    assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+    assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) == 0);
+    assert(pthread_setcancelstate(oldstate, &oldstate) == 0);
+    assert(oldstate == PTHREAD_CANCEL_DISABLE); /* Check setting */
+
+    assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype) == 0);
+    assert(oldtype == PTHREAD_CANCEL_DEFERRED); /* Check default */
+    assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0);
+    assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+    assert(pthread_setcanceltype(oldtype, &oldtype) == 0);
+    assert(oldtype == PTHREAD_CANCEL_ASYNCHRONOUS); /* Check setting */
+  }
+
+  return 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 1000);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      failed = !threadbag[i].started;
+
+      if (failed)
+	{
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print ouput on failure.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      /* ... */
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cancel2.c b/tests/cancel2.c
new file mode 100644
index 0000000..6ef2043
--- /dev/null
+++ b/tests/cancel2.c
@@ -0,0 +1,251 @@
+/*
+ * File: cancel2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test SEH or C++ cancel exception handling within
+ * application exception blocks.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 1
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+static pthread_mutex_t waitLock = PTHREAD_MUTEX_INITIALIZER;
+
+void *
+mythread(void * arg)
+{
+  int result = 0;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  switch (bag->threadnum % 2)
+    {
+    case 0:
+      assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+      result = 0;
+      break;
+    case 1:
+      assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0);
+      result = 1;
+      break;
+    }
+
+#if defined(_MSC_VER) && !defined(__cplusplus)
+  __try
+#else
+  try
+#endif
+    {
+      /* Wait for go from main */
+      assert(pthread_mutex_lock(&waitLock) == 0);
+      assert(pthread_mutex_unlock(&waitLock) == 0);
+      sched_yield();
+
+      for (;;)
+	{
+	  pthread_testcancel();
+	}
+    }
+#if defined(_MSC_VER) && !defined(__cplusplus)
+  __except(EXCEPTION_EXECUTE_HANDLER)
+#else
+#if defined(PtW32CatchAll)
+  PtW32CatchAll
+#else
+  catch(...)
+#endif
+#endif
+    {
+      /*
+       * Should not get into here.
+       */
+      result += 100;
+    }
+
+  /* 
+   * Should not get to here either.
+   */
+  result += 1000;
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  assert((t[0] = pthread_self()).p != NULL);
+  assert(pthread_mutex_lock(&waitLock) == 0);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  assert(pthread_mutex_unlock(&waitLock) == 0);
+
+  Sleep(500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_cancel(t[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      assert(pthread_join(t[i], (void **) &result) == 0);
+      fail = (result != (int) PTHREAD_CANCELED);
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: location %d: cancel type %s\n",
+		  i,
+		  threadbag[i].started,
+		  result,
+		  ((result % 2) == 0) ? "ASYNCHRONOUS" : "DEFERRED");
+	}
+      failed |= fail;
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+int
+main()
+{
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/cancel3.c b/tests/cancel3.c
new file mode 100644
index 0000000..1560ccf
--- /dev/null
+++ b/tests/cancel3.c
@@ -0,0 +1,201 @@
+/*
+ * File: cancel3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test asynchronous cancelation (alertable or non-alertable).
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * Requirements Tested:
+ * - Async cancel if thread is not blocked (i.e. voluntarily resumes if blocked).
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - 
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join.
+ * - quserex.dll and alertdrv.sys are not available.
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum
+{
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_
+{
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+void *
+mythread (void *arg)
+{
+  int result = ((int) PTHREAD_CANCELED + 1);
+  bag_t *bag = (bag_t *) arg;
+
+  assert (bag == &threadbag[bag->threadnum]);
+  assert (bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+  /*
+   * We wait up to 10 seconds, waking every 0.1 seconds,
+   * for a cancelation to be applied to us.
+   */
+  for (bag->count = 0; bag->count < 100; bag->count++)
+    Sleep (100);
+
+  return (void *) result;
+}
+
+int
+main ()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  assert ((t[0] = pthread_self ()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert (pthread_create (&t[i], NULL, mythread, (void *) &threadbag[i])
+	      == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep (500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert (pthread_cancel (t[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep (NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf (stderr, "Thread %d: started %d\n", i,
+		   threadbag[i].started);
+	}
+    }
+
+  assert (!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      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);
+
+      if (fail)
+	{
+	  fprintf (stderr, "Thread %d: started %d: count %d\n",
+		   i, threadbag[i].started, threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert (!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cancel4.c b/tests/cancel4.c
new file mode 100644
index 0000000..6d6d3dc
--- /dev/null
+++ b/tests/cancel4.c
@@ -0,0 +1,203 @@
+/*
+ * File: cancel4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test cancelation does not occur in deferred
+ *                cancelation threads with no cancelation points.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - pthread_create
+ *   pthread_self
+ *   pthread_cancel
+ *   pthread_join
+ *   pthread_setcancelstate
+ *   pthread_setcanceltype
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+void *
+mythread(void * arg)
+{
+  int result = ((int)PTHREAD_CANCELED + 1);
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0);
+
+  /*
+   * We wait up to 2 seconds, waking every 0.1 seconds,
+   * for a cancelation to be applied to us.
+   */
+  for (bag->count = 0; bag->count < 20; bag->count++)
+    Sleep(100);
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_cancel(t[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      /*
+       * The thread does not contain any cancelation points, so
+       * a return value of PTHREAD_CANCELED indicates that async
+       * cancelation occurred.
+       */
+      assert(pthread_join(t[i], (void **) &result) == 0);
+
+      fail = (result == (int) PTHREAD_CANCELED);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cancel5.c b/tests/cancel5.c
new file mode 100644
index 0000000..dd6cb8b
--- /dev/null
+++ b/tests/cancel5.c
@@ -0,0 +1,199 @@
+/*
+ * File: cancel5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test calling pthread_cancel from the main thread
+ *                without calling pthread_self() in main.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum
+{
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_
+{
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+void *
+mythread (void *arg)
+{
+  int result = ((int) PTHREAD_CANCELED + 1);
+  bag_t *bag = (bag_t *) arg;
+
+  assert (bag == &threadbag[bag->threadnum]);
+  assert (bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+  /*
+   * We wait up to 10 seconds, waking every 0.1 seconds,
+   * for a cancelation to be applied to us.
+   */
+  for (bag->count = 0; bag->count < 100; bag->count++)
+    Sleep (100);
+
+  return (void *) result;
+}
+
+int
+main ()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert (pthread_create (&t[i], NULL, mythread, (void *) &threadbag[i])
+	      == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep (500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert (pthread_cancel (t[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep (NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf (stderr, "Thread %d: started %d\n", i,
+		   threadbag[i].started);
+	}
+    }
+
+  assert (!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      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);
+
+      if (fail)
+	{
+	  fprintf (stderr, "Thread %d: started %d: count %d\n",
+		   i, threadbag[i].started, threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert (!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cancel6a.c b/tests/cancel6a.c
new file mode 100644
index 0000000..644cd4a
--- /dev/null
+++ b/tests/cancel6a.c
@@ -0,0 +1,191 @@
+/*
+ * File: cancel6a.c
+ *
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998 Ben Elliston and Ross Johnson
+ * Copyright (C) 1999,2000,2001 Ross Johnson
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * 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.1 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis: Test double cancelation - asynchronous.
+ * Second attempt should fail (ESRCH).
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+void *
+mythread(void * arg)
+{
+  int result = ((int)PTHREAD_CANCELED + 1);
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+  /*
+   * We wait up to 10 seconds, waking every 0.1 seconds,
+   * for a cancelation to be applied to us.
+   */
+  for (bag->count = 0; bag->count < 100; bag->count++)
+    Sleep(100);
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_cancel(t[i]) == 0);
+      assert(pthread_cancel(t[i]) == ESRCH);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      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);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cancel6d.c b/tests/cancel6d.c
new file mode 100644
index 0000000..d0ad7ac
--- /dev/null
+++ b/tests/cancel6d.c
@@ -0,0 +1,190 @@
+/*
+ * File: cancel6d.c
+ *
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998 Ben Elliston and Ross Johnson
+ * Copyright (C) 1999,2000,2001 Ross Johnson
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * 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.1 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis: Test double cancelation - deferred.
+ * Second attempt should succeed (unless the canceled thread has started
+ * cancelation already - not tested here).
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+void *
+mythread(void * arg)
+{
+  int result = ((int)PTHREAD_CANCELED + 1);
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0);
+
+  /*
+   * We wait up to 10 seconds, waking every 0.1 seconds,
+   * for a cancelation to be applied to us.
+   */
+  for (bag->count = 0; bag->count < 100; bag->count++)
+    {
+      Sleep(100);
+      pthread_testcancel();
+    }
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_cancel(t[i]) == 0);
+      assert(pthread_cancel(t[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      assert(pthread_join(t[i], (void **) &result) == 0);
+
+      fail = (result != (int) PTHREAD_CANCELED);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cancel7.c b/tests/cancel7.c
new file mode 100644
index 0000000..9fb2e61
--- /dev/null
+++ b/tests/cancel7.c
@@ -0,0 +1,216 @@
+/*
+ * File: cancel7.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test canceling a Win32 thread having created an
+ * implicit POSIX handle for it.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validate return value and that POSIX handle is created and destroyed.
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#ifndef _UWIN
+#include <process.h>
+#endif
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+  pthread_t self;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+unsigned __stdcall
+#else
+void
+#endif
+Win32thread(void * arg)
+{
+  int i;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  assert((bag->self = pthread_self()).p != NULL);
+  assert(pthread_kill(bag->self, 0) == 0);
+
+  for (i = 0; i < 100; i++)
+    {
+      Sleep(100);
+      pthread_testcancel();
+    }
+
+  return 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  HANDLE h[NUMTHREADS + 1];
+  unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr);
+#else
+      h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]);
+#endif
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  /*
+   * Cancel all threads.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_kill(threadbag[i].self, 0) == 0);
+      assert(pthread_cancel(threadbag[i].self) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE);
+#else
+      /*
+       * Can't get a result code.
+       */
+      result = (int) PTHREAD_CANCELED;
+#endif
+
+      assert(threadbag[i].self.p != NULL);
+      assert(pthread_kill(threadbag[i].self, 0) == ESRCH);
+
+      fail = (result != (int) PTHREAD_CANCELED);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
diff --git a/tests/cancel8.c b/tests/cancel8.c
new file mode 100644
index 0000000..69eafe9
--- /dev/null
+++ b/tests/cancel8.c
@@ -0,0 +1,217 @@
+/*
+ * File: cancel8.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test cancelling a blocked Win32 thread having created an
+ * implicit POSIX handle for it.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validate return value and that POSIX handle is created and destroyed.
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#ifndef _UWIN
+#include <process.h>
+#endif
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+  pthread_t self;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+pthread_cond_t CV = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t CVLock = PTHREAD_MUTEX_INITIALIZER;
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+unsigned __stdcall
+#else
+void
+#endif
+Win32thread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  assert((bag->self = pthread_self()).p != NULL);
+  assert(pthread_kill(bag->self, 0) == 0);
+
+  assert(pthread_mutex_lock(&CVLock) == 0);
+  pthread_cleanup_push(pthread_mutex_unlock, &CVLock);
+  pthread_cond_wait(&CV, &CVLock);
+  pthread_cleanup_pop(1);
+
+  return 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  HANDLE h[NUMTHREADS + 1];
+  unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr);
+#else
+      h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]);
+#endif
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  /*
+   * Cancel all threads.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_kill(threadbag[i].self, 0) == 0);
+      assert(pthread_cancel(threadbag[i].self) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE);
+#else
+      /*
+       * Can't get a result code.
+       */
+      result = (int) PTHREAD_CANCELED;
+#endif
+
+      assert(threadbag[i].self.p != NULL);
+      assert(pthread_kill(threadbag[i].self, 0) == ESRCH);
+
+      fail = (result != (int) PTHREAD_CANCELED);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
diff --git a/tests/cancel9.c b/tests/cancel9.c
new file mode 100644
index 0000000..b009161
--- /dev/null
+++ b/tests/cancel9.c
@@ -0,0 +1,202 @@
+/*
+ * File: cancel9.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test true asynchronous cancelation with Alert driver.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * Requirements Tested:
+ * - Cancel threads, including those blocked on system recources
+ *   such as network I/O.
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - 
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#include <windows.h>
+
+
+void *
+test_udp (void *arg)
+{
+  struct sockaddr_in serverAddress;
+  struct sockaddr_in clientAddress;
+  SOCKET UDPSocket;
+  int addr_len;
+  int nbyte, bytes;
+  char buffer[4096];
+  WORD wsaVersion = MAKEWORD (2, 2);
+  WSADATA wsaData;
+
+  pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
+  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+  if (WSAStartup (wsaVersion, &wsaData) != 0)
+    {
+      return NULL;
+    }
+
+  UDPSocket = socket (AF_INET, SOCK_DGRAM, 0);
+  if ((int)UDPSocket == -1)
+    {
+      printf ("Server: socket ERROR \n");
+      exit (-1);
+    }
+
+  serverAddress.sin_family = AF_INET;
+  serverAddress.sin_addr.s_addr = INADDR_ANY;
+  serverAddress.sin_port = htons (9003);
+
+  if (bind
+      (UDPSocket, (struct sockaddr *) &serverAddress,
+       sizeof (struct sockaddr_in)))
+    {
+      printf ("Server: ERROR can't bind UDPSocket");
+      exit (-1);
+    }
+
+  addr_len = sizeof (struct sockaddr);
+
+  nbyte = 512;
+
+  bytes =
+    recvfrom (UDPSocket, (char *) buffer, nbyte, 0,
+	      (struct sockaddr *) &clientAddress, &addr_len);
+
+  closesocket (UDPSocket);
+  WSACleanup ();
+
+  return NULL;
+}
+
+
+void *
+test_sleep (void *arg)
+{
+  pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
+  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+  Sleep (1000);
+  return NULL;
+
+}
+
+void *
+test_wait (void *arg)
+{
+  HANDLE hEvent;
+  DWORD dwEvent;
+
+  pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
+  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+  hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+  dwEvent = WaitForSingleObject (hEvent, 1000);	/* WAIT_IO_COMPLETION */
+
+  return NULL;
+}
+
+
+int
+main ()
+{
+  pthread_t t;
+  void *result;
+
+  if (pthread_win32_test_features_np (PTW32_ALERTABLE_ASYNC_CANCEL))
+    {
+      printf ("Cancel sleeping thread.\n");
+      assert (pthread_create (&t, NULL, test_sleep, NULL) == 0);
+      /* Sleep for a while; then cancel */
+      Sleep (100);
+      assert (pthread_cancel (t) == 0);
+      assert (pthread_join (t, &result) == 0);
+      assert (result == PTHREAD_CANCELED && "test_sleep" != NULL);
+
+      printf ("Cancel waiting thread.\n");
+      assert (pthread_create (&t, NULL, test_wait, NULL) == 0);
+      /* Sleep for a while; then cancel. */
+      Sleep (100);
+      assert (pthread_cancel (t) == 0);
+      assert (pthread_join (t, &result) == 0);
+      assert (result == PTHREAD_CANCELED && "test_wait");
+
+      printf ("Cancel blocked thread (blocked on network I/O).\n");
+      assert (pthread_create (&t, NULL, test_udp, NULL) == 0);
+      /* Sleep for a while; then cancel. */
+      Sleep (100);
+      assert (pthread_cancel (t) == 0);
+      assert (pthread_join (t, &result) == 0);
+      assert (result == PTHREAD_CANCELED && "test_udp" != NULL);
+    }
+  else
+    {
+      printf ("Alertable async cancel not available.\n");
+    }
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/cleanup0.c b/tests/cleanup0.c
new file mode 100644
index 0000000..77626eb
--- /dev/null
+++ b/tests/cleanup0.c
@@ -0,0 +1,229 @@
+/*
+ * File: cleanup1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test cleanup handler executes (when thread is not canceled).
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 10
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t pop_count = {0, {0}};
+
+static void
+increment_pop_count(void * arg)
+{
+  sharedInt_t * sI = (sharedInt_t *) arg;
+
+  EnterCriticalSection(&sI->cs);
+  sI->i++;
+  LeaveCriticalSection(&sI->cs);
+}
+
+void *
+mythread(void * arg)
+{
+  int result = 0;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
+
+  Sleep(100);
+
+  pthread_cleanup_pop(1);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  InitializeCriticalSection(&pop_count.cs);
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      assert(pthread_join(t[i], (void **) &result) == 0);
+
+      fail = (result == (int) PTHREAD_CANCELED);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: result %d\n",
+		  i,
+		  threadbag[i].started,
+		result);
+	  fflush(stderr);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  assert(pop_count.i == NUMTHREADS);
+
+  DeleteCriticalSection(&pop_count.cs);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+int
+main()
+{
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/cleanup1.c b/tests/cleanup1.c
new file mode 100644
index 0000000..385aed9
--- /dev/null
+++ b/tests/cleanup1.c
@@ -0,0 +1,242 @@
+/*
+ * File: cleanup1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test cleanup handler executes (when thread is canceled).
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 10
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t pop_count = {0, {0}};
+
+static void
+#ifdef __CLEANUP_C
+__cdecl
+#endif
+increment_pop_count(void * arg)
+{
+  sharedInt_t * sI = (sharedInt_t *) arg;
+
+  EnterCriticalSection(&sI->cs);
+  sI->i++;
+  LeaveCriticalSection(&sI->cs);
+}
+
+void *
+mythread(void * arg)
+{
+  int result = 0;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Set to known state and type */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
+  /*
+   * We don't have true async cancelation - it relies on the thread
+   * at least re-entering the run state at some point.
+   * We wait up to 10 seconds, waking every 0.1 seconds,
+   * for a cancelation to be applied to us.
+   */
+  for (bag->count = 0; bag->count < 100; bag->count++)
+    Sleep(100);
+
+  pthread_cleanup_pop(0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  InitializeCriticalSection(&pop_count.cs);
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_cancel(t[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      assert(pthread_join(t[i], (void **) &result) == 0);
+
+      fail = (result != (int) PTHREAD_CANCELED);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: result %d\n",
+		  i,
+		  threadbag[i].started,
+		  result);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  assert(pop_count.i == NUMTHREADS);
+
+  DeleteCriticalSection(&pop_count.cs);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+int
+main()
+{
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/cleanup2.c b/tests/cleanup2.c
new file mode 100644
index 0000000..4c63918
--- /dev/null
+++ b/tests/cleanup2.c
@@ -0,0 +1,217 @@
+/*
+ * File: cleanup2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test cleanup handler executes (when thread is not canceled).
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 10
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t pop_count = {0, {0}};
+
+static void
+increment_pop_count(void * arg)
+{
+  sharedInt_t * sI = (sharedInt_t *) arg;
+
+  EnterCriticalSection(&sI->cs);
+  sI->i++;
+  LeaveCriticalSection(&sI->cs);
+}
+
+void *
+mythread(void * arg)
+{
+  int result = 0;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
+
+  sched_yield();
+
+  pthread_cleanup_pop(1);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  InitializeCriticalSection(&pop_count.cs);
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(1000);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      assert(pthread_join(t[i], (void **) &result) == 0);
+
+      fail = (result != 0);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: result: %d\n",
+		  i,
+		  threadbag[i].started,
+		  result);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  assert(pop_count.i == NUMTHREADS);
+
+  DeleteCriticalSection(&pop_count.cs);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+int
+main()
+{
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/cleanup3.c b/tests/cleanup3.c
new file mode 100644
index 0000000..b595ab4
--- /dev/null
+++ b/tests/cleanup3.c
@@ -0,0 +1,222 @@
+/*
+ * File: cleanup3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test cleanup handler does not execute (when thread is
+ * not canceled).
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 10
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t pop_count = {0, {0}};
+
+static void
+increment_pop_count(void * arg)
+{
+  sharedInt_t * sI = (sharedInt_t *) arg;
+
+  EnterCriticalSection(&sI->cs);
+  sI->i++;
+  LeaveCriticalSection(&sI->cs);
+}
+
+void *
+mythread(void * arg)
+{
+  int result = 0;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
+
+  sched_yield();
+
+  EnterCriticalSection(&pop_count.cs);
+  pop_count.i--;
+  LeaveCriticalSection(&pop_count.cs);
+
+  pthread_cleanup_pop(0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  InitializeCriticalSection(&pop_count.cs);
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(1000);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+      assert(pthread_join(t[i], (void **) &result) == 0);
+
+      fail = (result != 0);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: result: %d\n",
+		  i,
+		  threadbag[i].started,
+		  result);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  assert(pop_count.i == -(NUMTHREADS));
+
+  DeleteCriticalSection(&pop_count.cs);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+int
+main()
+{
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/condvar1.c b/tests/condvar1.c
new file mode 100644
index 0000000..380ab1a
--- /dev/null
+++ b/tests/condvar1.c
@@ -0,0 +1,97 @@
+/*
+ * File: condvar1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test initialisation and destruction of a CV.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Creates and then imediately destroys a CV. Does not
+ *   test the CV.
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_init returns 0, and
+ * - pthread_cond_destroy returns 0.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_init returns non-zero, or
+ * - pthread_cond_destroy returns non-zero.
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+static pthread_cond_t cv = NULL;
+
+int
+main()
+{
+  assert(cv == NULL);
+
+  assert(pthread_cond_init(&cv, NULL) == 0);
+
+  assert(cv != NULL);
+
+  assert(pthread_cond_destroy(&cv) == 0);
+
+  assert(cv == NULL);
+
+  return 0;
+}
diff --git a/tests/condvar1_1.c b/tests/condvar1_1.c
new file mode 100644
index 0000000..a05e113
--- /dev/null
+++ b/tests/condvar1_1.c
@@ -0,0 +1,115 @@
+/*
+ * File: condvar1_1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test CV linked list management.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation:
+ *   Initiate and destroy several CVs in random order.
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Creates and then imediately destroys a CV. Does not
+ *   test the CV.
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - All initialised CVs destroyed without segfault.
+ * - Successfully broadcasts all remaining CVs after
+ *   each CV is removed.
+ *
+ * Fail Criteria:
+ */
+
+#include <stdlib.h>
+#include "test.h"
+
+enum {
+  NUM_CV = 100
+};
+
+static pthread_cond_t cv[NUM_CV];
+
+int
+main()
+{
+  int i, j;
+
+  for (i = 0; i < NUM_CV; i++)
+    {
+      /* Traverse the list before every init of a CV. */
+      assert(pthread_timechange_handler_np(NULL) == (void *) 0);
+      assert(pthread_cond_init(&cv[i], NULL) == 0);
+    }
+
+  j = NUM_CV;
+  (void) srand((unsigned)time(NULL));
+
+  do
+    {
+      i = (NUM_CV - 1) * rand() / RAND_MAX;
+      if (cv[i] != NULL)
+        {
+          j--;
+          assert(pthread_cond_destroy(&cv[i]) == 0);
+          /* Traverse the list every time we remove a CV. */
+          assert(pthread_timechange_handler_np(NULL) == (void *) 0);
+        }
+    }
+  while (j > 0);
+
+  return 0;
+}
diff --git a/tests/condvar1_2.c b/tests/condvar1_2.c
new file mode 100644
index 0000000..503e821
--- /dev/null
+++ b/tests/condvar1_2.c
@@ -0,0 +1,124 @@
+/*
+ * File: condvar1_2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test CV linked list management and serialisation.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation:
+ *   Initiate and destroy several CVs in random order.
+ *   Asynchronously traverse the CV list and broadcast.
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Creates and then imediately destroys a CV. Does not
+ *   test the CV.
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - All initialised CVs destroyed without segfault.
+ * - Successfully broadcasts all remaining CVs after
+ *   each CV is removed.
+ *
+ * Fail Criteria:
+ */
+
+#include <stdlib.h>
+#include "test.h"
+
+enum {
+  NUM_CV = 5,
+  NUM_LOOPS = 5
+};
+
+static pthread_cond_t cv[NUM_CV];
+
+int
+main()
+{
+  int i, j, k;
+  int result = -1;
+  pthread_t t;
+
+  for (k = 0; k < NUM_LOOPS; k++)
+    {
+      for (i = 0; i < NUM_CV; i++)
+        {
+          assert(pthread_cond_init(&cv[i], NULL) == 0);
+        }
+
+      j = NUM_CV;
+      (void) srand((unsigned)time(NULL));
+
+      /* Traverse the list asynchronously. */
+      assert(pthread_create(&t, NULL, pthread_timechange_handler_np, NULL) == 0);
+
+      do
+        {
+          i = (NUM_CV - 1) * rand() / RAND_MAX;
+          if (cv[i] != NULL)
+            {
+              j--;
+              assert(pthread_cond_destroy(&cv[i]) == 0);
+            }
+        }
+      while (j > 0);
+
+      assert(pthread_join(t, (void **) &result) == 0);
+      assert (result == 0);
+    }
+
+  return 0;
+}
diff --git a/tests/condvar2.c b/tests/condvar2.c
new file mode 100644
index 0000000..33f1d3f
--- /dev/null
+++ b/tests/condvar2.c
@@ -0,0 +1,125 @@
+/*
+ * File: condvar2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test timed wait on a CV.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Because the CV is never signaled, we expect the wait to time out.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait does not return ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#define _WIN32_WINNT 0x400
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_cond_t cv;
+pthread_mutex_t mutex;
+
+#include "../implement.h"
+
+int
+main()
+{
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert(pthread_cond_init(&cv, NULL) == 0);
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT);
+  
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  {
+  int result = pthread_cond_destroy(&cv);
+  if (result != 0)
+    {
+      fprintf(stderr, "Result = %s\n", error_string[result]);
+	fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked);
+	fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone);
+	fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock);
+	fflush(stderr);
+    }
+  assert(result == 0);
+  }
+
+  return 0;
+}
diff --git a/tests/condvar2_1.c b/tests/condvar2_1.c
new file mode 100644
index 0000000..92dddfd
--- /dev/null
+++ b/tests/condvar2_1.c
@@ -0,0 +1,153 @@
+/*
+ * File: condvar2_1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test timeout of multiple waits on a CV with no signal/broadcast.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Because the CV is never signaled, we expect the waits to time out.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait does not return ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#define _WIN32_WINNT 0x400
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static pthread_cond_t cv;
+static pthread_mutex_t mutex;
+static struct timespec abstime = { 0, 0 };
+
+enum {
+  NUMTHREADS = 30
+};
+
+void *
+mythread(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return arg;
+}
+
+#include "../implement.h"
+
+int
+main()
+{
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+  int result = 0;
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert(pthread_cond_init(&cv, NULL) == 0);
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
+    }
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_join(t[i], (void **) &result) == 0);
+	assert(result == i);
+    }
+
+  {
+  int result = pthread_cond_destroy(&cv);
+  if (result != 0)
+    {
+      fprintf(stderr, "Result = %s\n", error_string[result]);
+	fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked);
+	fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone);
+	fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock);
+	fflush(stderr);
+    }
+  assert(result == 0);
+  }
+
+  return 0;
+}
diff --git a/tests/condvar3.c b/tests/condvar3.c
new file mode 100644
index 0000000..e3a23f5
--- /dev/null
+++ b/tests/condvar3.c
@@ -0,0 +1,148 @@
+/*
+ * File: condvar3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test basic function of a CV
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - The primary thread takes the lock before creating any threads.
+ *   The secondary thread blocks on the lock allowing the primary
+ *   thread to enter the cv wait state which releases the lock.
+ *   The secondary thread then takes the lock and signals the waiting
+ *   primary thread.
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns 0.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static pthread_cond_t cv;
+static pthread_mutex_t mutex;
+static int shared = 0;
+
+enum {
+  NUMTHREADS = 2         /* Including the primary thread. */
+};
+
+void *
+mythread(void * arg)
+{
+  int result = 0;
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+  shared++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  if ((result = pthread_cond_signal(&cv)) != 0)
+    {
+      printf("Error = %s\n", error_string[result]);
+    }
+  assert(result == 0);
+
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  pthread_t t[NUMTHREADS];
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(pthread_cond_init(&cv, NULL) == 0);
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
+
+  abstime.tv_sec += 5;
+
+  while (! (shared > 0))
+    assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == 0);
+
+  assert(shared > 0);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_join(t[1], NULL) == 0);
+
+  assert(pthread_cond_destroy(&cv) == 0);
+
+  return 0;
+}
diff --git a/tests/condvar3_1.c b/tests/condvar3_1.c
new file mode 100644
index 0000000..25a50e4
--- /dev/null
+++ b/tests/condvar3_1.c
@@ -0,0 +1,201 @@
+/*
+ * File: condvar3_1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test timeout of multiple waits on a CV with some signaled.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Because some CVs are never signaled, we expect their waits to time out.
+ *   Some are signaled, the rest time out. Pthread_cond_destroy() will fail
+ *   unless all are accounted for, either signaled or timedout.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait does not return ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#define _WIN32_WINNT 0x400
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static pthread_cond_t cv;
+static pthread_cond_t cv1;
+static pthread_mutex_t mutex;
+static pthread_mutex_t mutex1;
+static struct timespec abstime = { 0, 0 };
+static int timedout = 0;
+static int signaled = 0;
+static int awoken = 0;
+static int waiting = 0;
+
+enum {
+  NUMTHREADS = 30
+};
+
+void *
+mythread(void * arg)
+{
+  int result;
+
+  assert(pthread_mutex_lock(&mutex1) == 0);
+  ++waiting;
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+  assert(pthread_cond_signal(&cv1) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+  result = pthread_cond_timedwait(&cv, &mutex, &abstime);
+  if (result == ETIMEDOUT)
+    {
+      timedout++;
+    }
+  else
+    {
+      awoken++;
+    }
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return arg;
+}
+
+#include "../implement.h"
+
+int
+main()
+{
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+  int result = 0;
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert(pthread_cond_init(&cv, NULL) == 0);
+  assert(pthread_cond_init(&cv1, NULL) == 0);
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+  assert(pthread_mutex_init(&mutex1, NULL) == 0);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  assert(pthread_mutex_lock(&mutex1) == 0);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
+    }
+
+  do {
+    assert(pthread_cond_wait(&cv1,&mutex1) == 0);
+  } while ( NUMTHREADS > waiting );
+
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+
+  for (i = NUMTHREADS/3; i <= 2*NUMTHREADS/3; i++)
+    {
+//      assert(pthread_mutex_lock(&mutex) == 0);
+      assert(pthread_cond_signal(&cv) == 0);
+//      assert(pthread_mutex_unlock(&mutex) == 0);
+
+      signaled++;
+    }
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_join(t[i], (void **) &result) == 0);
+        assert(result == i);
+    }
+
+      fprintf(stderr, "awk = %d\n", awoken);
+      fprintf(stderr, "sig = %d\n", signaled);
+      fprintf(stderr, "tot = %d\n", timedout);
+
+  assert(signaled == awoken);
+  assert(timedout == NUMTHREADS - signaled);
+
+  assert(pthread_cond_destroy(&cv1) == 0);
+
+  {
+  int result = pthread_cond_destroy(&cv);
+  if (result != 0)
+    {
+      fprintf(stderr, "Result = %s\n", error_string[result]);
+        fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked);
+        fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone);
+        fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock);
+        fflush(stderr);
+    }
+  assert(result == 0);
+  }
+
+  assert(pthread_mutex_destroy(&mutex1) == 0);
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  return 0;
+}
diff --git a/tests/condvar3_2.c b/tests/condvar3_2.c
new file mode 100644
index 0000000..5ddcf57
--- /dev/null
+++ b/tests/condvar3_2.c
@@ -0,0 +1,193 @@
+/*
+ * File: condvar3_2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test timeout of multiple waits on a CV with remainder broadcast awoken.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Because some CVs are never signaled, we expect their waits to time out.
+ *   Some time out, the rest are broadcast signaled. Pthread_cond_destroy() will fail
+ *   unless all are accounted for, either signaled or timedout.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait does not return ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#define _WIN32_WINNT 0x400
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static pthread_cond_t cv;
+static pthread_mutex_t mutex;
+static struct timespec abstime = { 0, 0 };
+static struct timespec abstime2 = { 0, 0 };
+static int timedout = 0;
+static int awoken = 0;
+
+enum {
+  NUMTHREADS = 30
+};
+
+void *
+mythread(void * arg)
+{
+  int result;
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  abstime2.tv_sec = abstime.tv_sec;
+
+  if ((int) arg % 3 == 0)
+    {
+      abstime2.tv_sec += 2;
+    }
+
+  result = pthread_cond_timedwait(&cv, &mutex, &abstime2);
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  if (result == ETIMEDOUT)
+    {
+      InterlockedIncrement((LPLONG)&timedout);
+    }
+  else
+    {
+      InterlockedIncrement((LPLONG)&awoken);
+    }
+
+
+  return arg;
+}
+
+#include "../implement.h"
+
+int
+main()
+{
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+  int result = 0;
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert(pthread_cond_init(&cv, NULL) == 0);
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = abstime.tv_sec = currSysTime.time + 5;
+  abstime.tv_nsec = abstime2.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
+    }
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_join(t[i], (void **) &result) == 0);
+	assert(result == i);
+      /*
+       * Approximately 2/3rds of the threads are expected to time out.
+       * Signal the remainder after some threads have woken up and exited
+       * and while some are still waking up after timeout.
+       * Also tests that redundant broadcasts don't return errors.
+       */
+
+//      assert(pthread_mutex_lock(&mutex) == 0);
+
+      if (InterlockedExchangeAdd((LPLONG)&awoken, 0L) > NUMTHREADS/3)
+        {
+          assert(pthread_cond_broadcast(&cv) == 0);
+        }
+
+//      assert(pthread_mutex_unlock(&mutex) == 0);
+
+    }
+
+  assert(awoken == NUMTHREADS - timedout);
+
+  {
+  int result = pthread_cond_destroy(&cv);
+  if (result != 0)
+    {
+      fprintf(stderr, "Result = %s\n", error_string[result]);
+	fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked);
+	fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone);
+	fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock);
+	fflush(stderr);
+    }
+  assert(result == 0);
+  }
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  return 0;
+}
diff --git a/tests/condvar3_3.c b/tests/condvar3_3.c
new file mode 100644
index 0000000..fe67632
--- /dev/null
+++ b/tests/condvar3_3.c
@@ -0,0 +1,132 @@
+/*
+ * File: condvar3_3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test timeouts and lost signals on a CV.
+ *
+ * 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:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait does not return ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+/* Timur Aydin (taydin@snet.net) */
+
+#include "test.h"
+
+#include <sys/timeb.h>
+
+pthread_cond_t cnd;
+pthread_mutex_t mtx;
+
+int main()
+{
+   int rc;
+
+   struct timespec abstime = { 0, 0 };
+   struct _timeb currSysTime;
+   const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+   assert(pthread_cond_init(&cnd, 0) == 0);
+   assert(pthread_mutex_init(&mtx, 0) == 0);
+
+   /* get current system time */
+   _ftime(&currSysTime);
+
+   abstime.tv_sec = currSysTime.time;
+   abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+   abstime.tv_sec += 1;
+
+   /* Here pthread_cond_timedwait should time out after one second. */
+
+   assert(pthread_mutex_lock(&mtx) == 0);
+
+   assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT);
+
+   assert(pthread_mutex_unlock(&mtx) == 0);
+
+   /* Here, the condition variable is signaled, but there are no
+      threads waiting on it. The signal should be lost and
+      the next pthread_cond_timedwait should time out too. */
+
+//   assert(pthread_mutex_lock(&mtx) == 0);
+
+   assert((rc = pthread_cond_signal(&cnd)) == 0);
+
+//   assert(pthread_mutex_unlock(&mtx) == 0);
+
+   assert(pthread_mutex_lock(&mtx) == 0);
+
+   abstime.tv_sec = currSysTime.time;
+   abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+   abstime.tv_sec += 1;
+
+   assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT);
+
+   assert(pthread_mutex_unlock(&mtx) == 0);
+
+   return 0;
+}
diff --git a/tests/condvar4.c b/tests/condvar4.c
new file mode 100644
index 0000000..3babeea
--- /dev/null
+++ b/tests/condvar4.c
@@ -0,0 +1,169 @@
+/*
+ * File: condvar4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test PTHREAD_COND_INITIALIZER.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Test basic CV function but starting with a static initialised
+ *   CV.
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns 0.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+  pthread_cond_t notbusy;
+  pthread_mutex_t lock;
+  int shared;
+};
+
+static cvthing_t cvthing = {
+  PTHREAD_COND_INITIALIZER,
+  PTHREAD_MUTEX_INITIALIZER,
+  0
+};
+
+enum {
+  NUMTHREADS = 2
+};
+
+void *
+mythread(void * arg)
+{
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+  cvthing.shared++;
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  assert(pthread_cond_signal(&cvthing.notbusy) == 0);
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  pthread_t t[NUMTHREADS];
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  cvthing.shared = 0;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
+
+  assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+  assert(cvthing.lock != PTHREAD_MUTEX_INITIALIZER);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT);
+  
+  assert(cvthing.notbusy != PTHREAD_COND_INITIALIZER);
+
+  assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  while (! (cvthing.shared > 0))
+    assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+  assert(cvthing.shared > 0);
+
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  assert(pthread_join(t[1], NULL) == 0);
+
+  assert(pthread_mutex_destroy(&cvthing.lock) == 0);
+
+  assert(cvthing.lock == NULL);
+
+  assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+
+  assert(cvthing.notbusy == NULL);
+
+  return 0;
+}
diff --git a/tests/condvar5.c b/tests/condvar5.c
new file mode 100644
index 0000000..4d51f39
--- /dev/null
+++ b/tests/condvar5.c
@@ -0,0 +1,168 @@
+/*
+ * File: condvar5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test pthread_cond_broadcast.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Test broadcast with one waiting CV.
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns 0.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+  pthread_cond_t notbusy;
+  pthread_mutex_t lock;
+  int shared;
+};
+
+static cvthing_t cvthing = {
+  PTHREAD_COND_INITIALIZER,
+  PTHREAD_MUTEX_INITIALIZER,
+  0
+};
+
+enum {
+  NUMTHREADS = 2
+};
+
+void *
+mythread(void * arg)
+{
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+  cvthing.shared++;
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  pthread_t t[NUMTHREADS];
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  cvthing.shared = 0;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
+
+  assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+  assert(cvthing.lock != PTHREAD_MUTEX_INITIALIZER);
+
+  /* get current system time */
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT);
+  
+  assert(cvthing.notbusy != PTHREAD_COND_INITIALIZER);
+
+  assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  while (! (cvthing.shared > 0))
+    assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+  assert(cvthing.shared > 0);
+
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  assert(pthread_join(t[1], NULL) == 0);
+
+  assert(pthread_mutex_destroy(&cvthing.lock) == 0);
+
+  assert(cvthing.lock == NULL);
+
+  assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+
+  assert(cvthing.notbusy == NULL);
+
+  return 0;
+}
diff --git a/tests/condvar6.c b/tests/condvar6.c
new file mode 100644
index 0000000..e63132c
--- /dev/null
+++ b/tests/condvar6.c
@@ -0,0 +1,242 @@
+/*
+ * File: condvar6.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test pthread_cond_broadcast.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Test broadcast with NUMTHREADS (=5) waiting CVs.
+ *
+ * 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"
+#include <sys/timeb.h>
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 5
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+  pthread_cond_t notbusy;
+  pthread_mutex_t lock;
+  int shared;
+};
+
+static cvthing_t cvthing = {
+  PTHREAD_COND_INITIALIZER,
+  PTHREAD_MUTEX_INITIALIZER,
+  0
+};
+
+static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
+
+static struct timespec abstime = { 0, 0 };
+
+static int awoken;
+
+void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Wait for the start gun */
+  assert(pthread_mutex_lock(&start_flag) == 0);
+  assert(pthread_mutex_unlock(&start_flag) == 0);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+  while (! (cvthing.shared > 0))
+    assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+  assert(cvthing.shared > 0);
+
+  awoken++;
+
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  cvthing.shared = 0;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
+
+  assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&start_flag) == 0);
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  awoken = 0;
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+
+  assert(pthread_mutex_unlock(&start_flag) == 0);
+
+  /*
+   * Give threads time to start.
+   */
+  Sleep(1000);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+  cvthing.shared++;
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
+
+  /*
+   * Give threads time to complete.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      assert(pthread_join(t[i], NULL) == 0);
+    }
+
+  /* 
+   * Cleanup the CV.
+   */
+  
+  assert(pthread_mutex_destroy(&cvthing.lock) == 0);
+
+  assert(cvthing.lock == NULL);
+
+  assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+
+  assert(cvthing.notbusy == NULL);
+
+  /*
+   * 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);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here.
+   */
+
+  assert(awoken == NUMTHREADS);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+
diff --git a/tests/condvar7.c b/tests/condvar7.c
new file mode 100644
index 0000000..6d89f2e
--- /dev/null
+++ b/tests/condvar7.c
@@ -0,0 +1,257 @@
+/*
+ * File: condvar7.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test pthread_cond_broadcast with thread cancelation.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Test broadcast with NUMTHREADS (=5) waiting CVs, one is canceled while waiting.
+ *
+ * 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"
+#include <sys/timeb.h>
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 5
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+  pthread_cond_t notbusy;
+  pthread_mutex_t lock;
+  int shared;
+};
+
+static cvthing_t cvthing = {
+  PTHREAD_COND_INITIALIZER,
+  PTHREAD_MUTEX_INITIALIZER,
+  0
+};
+
+static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
+
+static struct timespec abstime = { 0, 0 };
+
+static int awoken;
+
+void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Wait for the start gun */
+  assert(pthread_mutex_lock(&start_flag) == 0);
+  assert(pthread_mutex_unlock(&start_flag) == 0);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock);
+
+  while (! (cvthing.shared > 0))
+    assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+  pthread_cleanup_pop(0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  assert(cvthing.shared > 0);
+
+  awoken++;
+
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  cvthing.shared = 0;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
+
+  assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&start_flag) == 0);
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 10;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  awoken = 0;
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+
+  assert(pthread_mutex_unlock(&start_flag) == 0);
+
+  /*
+   * Give threads time to start.
+   */
+  Sleep(1000);
+
+  /*
+   * Cancel one of the threads.
+   */
+  assert(pthread_cancel(t[1]) == 0);
+  assert(pthread_join(t[1], NULL) == 0);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+  cvthing.shared++;
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  /*
+   * Signal all remaining waiting threads.
+   */
+  assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
+
+  /*
+   * Wait for all threads to complete.
+   */
+  for (i = 2; i <= NUMTHREADS; i++)
+    assert(pthread_join(t[i], NULL) == 0);
+
+  /* 
+   * Cleanup the CV.
+   */
+  
+  assert(pthread_mutex_destroy(&cvthing.lock) == 0);
+
+  assert(cvthing.lock == NULL);
+
+  assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+
+  assert(cvthing.notbusy == NULL);
+
+  /*
+   * 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);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here.
+   */
+
+  assert(awoken == (NUMTHREADS - 1));
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/condvar8.c b/tests/condvar8.c
new file mode 100644
index 0000000..e384a1c
--- /dev/null
+++ b/tests/condvar8.c
@@ -0,0 +1,258 @@
+/*
+ * File: condvar8.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test multiple pthread_cond_broadcasts.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Make NUMTHREADS threads wait on CV, broadcast signal them, and then repeat.
+ *
+ * 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"
+#include <sys/timeb.h>
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 5
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+  pthread_cond_t notbusy;
+  pthread_mutex_t lock;
+  int shared;
+};
+
+static cvthing_t cvthing = {
+  PTHREAD_COND_INITIALIZER,
+  PTHREAD_MUTEX_INITIALIZER,
+  0
+};
+
+static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
+
+static struct timespec abstime = { 0, 0 };
+
+static int awoken;
+
+static void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Wait for the start gun */
+  assert(pthread_mutex_lock(&start_flag) == 0);
+  assert(pthread_mutex_unlock(&start_flag) == 0);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock);
+
+  while (! (cvthing.shared > 0))
+    assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+  pthread_cleanup_pop(0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  assert(cvthing.shared > 0);
+
+  awoken++;
+
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  int first, last;
+  pthread_t t[NUMTHREADS + 1];
+
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
+
+  assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 10;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  awoken = 0;
+
+  for (first = 1, last = NUMTHREADS / 2;
+       first < NUMTHREADS;
+       first = last + 1, last = NUMTHREADS)
+    {
+      assert(pthread_mutex_lock(&start_flag) == 0);
+
+      for (i = first; i <= last; i++)
+	{
+	  threadbag[i].started = 0;
+	  threadbag[i].threadnum = i;
+	  assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+	}
+
+      /*
+       * Code to control or munipulate child threads should probably go here.
+       */
+      cvthing.shared = 0;
+
+      assert(pthread_mutex_unlock(&start_flag) == 0);
+
+      /*
+       * Give threads time to start.
+       */
+      Sleep(100);
+
+      assert(pthread_mutex_lock(&cvthing.lock) == 0);
+      cvthing.shared++;
+      assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+      assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
+
+      /*
+       * Give threads time to complete.
+       */
+      for (i = first; i <= last; i++)
+	{
+	  assert(pthread_join(t[i], NULL) == 0);
+	}
+
+      assert(awoken == (i - 1));
+    }
+
+
+  /*
+   * 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);
+	}
+    }
+
+  /* 
+   * Cleanup the CV.
+   */
+  
+  assert(pthread_mutex_destroy(&cvthing.lock) == 0);
+
+  assert(cvthing.lock == NULL);
+
+  assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+
+  assert(cvthing.notbusy == NULL);
+
+  assert(!failed);
+
+  /*
+   * Check any results here.
+   */
+
+  assert(awoken == NUMTHREADS);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/condvar9.c b/tests/condvar9.c
new file mode 100644
index 0000000..c751271
--- /dev/null
+++ b/tests/condvar9.c
@@ -0,0 +1,267 @@
+/*
+ * File: condvar9.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test multiple pthread_cond_broadcasts with thread cancelation.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - 
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * - Make NUMTHREADS threads wait on CV, cancel one, broadcast signal them,
+ *   and then repeat.
+ *
+ * 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"
+#include <sys/timeb.h>
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 9
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  int finished;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+  pthread_cond_t notbusy;
+  pthread_mutex_t lock;
+  int shared;
+};
+
+static cvthing_t cvthing = {
+  PTHREAD_COND_INITIALIZER,
+  PTHREAD_MUTEX_INITIALIZER,
+  0
+};
+
+static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
+
+static struct timespec abstime = { 0, 0 };
+
+static int awoken;
+
+static void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /* Wait for the start gun */
+  assert(pthread_mutex_lock(&start_flag) == 0);
+  assert(pthread_mutex_unlock(&start_flag) == 0);
+
+  assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+  /*
+   * pthread_cond_timedwait is a cancelation point and we're
+   * going to cancel some threads deliberately.
+   */
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock);
+
+  while (! (cvthing.shared > 0))
+    assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+  pthread_cleanup_pop(0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  assert(cvthing.shared > 0);
+
+  awoken++;
+  bag->finished = 1;
+
+  assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  int first, last;
+  int canceledThreads = 0;
+  pthread_t t[NUMTHREADS + 1];
+
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
+
+  assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 5;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  awoken = 0;
+
+  for (first = 1, last = NUMTHREADS / 2;
+       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 = threadbag[i].finished = 0;
+	  threadbag[i].threadnum = i;
+	  assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+	}
+
+      /*
+       * Code to control or munipulate child threads should probably go here.
+       */
+      cvthing.shared = 0;
+
+      assert(pthread_mutex_unlock(&start_flag) == 0);
+
+      /*
+       * Give threads time to start.
+       */
+      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_mutex_unlock(&cvthing.lock) == 0);
+
+      assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
+
+      /*
+       * Standard check that all threads started - and wait for them to finish.
+       */
+      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_e(pthread_cond_destroy(&cvthing.notbusy), ==, 0);
+
+  assert(cvthing.notbusy == NULL);
+
+  assert(!failed);
+
+  /*
+   * Check any results here.
+   */
+
+  assert(awoken == NUMTHREADS - canceledThreads);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/context1.c b/tests/context1.c
new file mode 100644
index 0000000..090df9c
--- /dev/null
+++ b/tests/context1.c
@@ -0,0 +1,144 @@
+/*
+ * File: context1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test context switching method.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - pthread_create
+ *   pthread_exit
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#define _WIN32_WINNT 0x400
+
+#include "test.h"
+#include "../implement.h"
+
+static int washere = 0;
+
+static void * func(void * arg)
+{
+  washere = 1;
+
+  Sleep(1000);
+
+  return 0; 
+}
+
+static void
+anotherEnding ()
+{
+  /*
+   * Switched context
+   */
+  washere++;
+
+  pthread_exit(0);
+}
+
+int
+main()
+{
+  pthread_t t;
+  HANDLE hThread;
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  hThread = ((ptw32_thread_t *)t.p)->threadH;
+
+  Sleep(500);
+
+  SuspendThread(hThread);
+
+  if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT) 
+    {
+      /*
+       * Ok, thread did not exit before we got to it.
+       */
+      CONTEXT context;
+
+      context.ContextFlags = CONTEXT_CONTROL;
+
+      GetThreadContext(hThread, &context);
+      /*
+       *_x86 only!!!
+       */
+      context.Eip = (DWORD) anotherEnding;
+      SetThreadContext(hThread, &context);
+      ResumeThread(hThread);
+    }
+  else
+    {
+      printf("Exited early\n");
+      fflush(stdout);
+    }
+
+  Sleep(1000);
+
+  assert(washere == 2);
+
+  return 0;
+}
+
diff --git a/tests/count1.c b/tests/count1.c
new file mode 100644
index 0000000..c2386b0
--- /dev/null
+++ b/tests/count1.c
@@ -0,0 +1,90 @@
+/*
+ * count1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Description:
+ * Test some basic assertions about the number of threads at runtime.
+ */
+
+#include "test.h"
+
+#define NUMTHREADS (30)
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t threads[NUMTHREADS];
+static unsigned numThreads = 0;
+
+void *
+myfunc(void *arg)
+{
+  pthread_mutex_lock(&lock);
+  numThreads++;
+  pthread_mutex_unlock(&lock);
+
+  Sleep(1000);
+  return 0;
+}
+int
+main()
+{
+  int i;
+  int maxThreads = sizeof(threads) / sizeof(pthread_t);
+
+  /*
+   * Spawn NUMTHREADS threads. Each thread should increment the
+   * numThreads variable, sleep for one second.
+   */
+  for (i = 0; i < maxThreads; i++)
+    {
+      assert(pthread_create(&threads[i], NULL, myfunc, 0) == 0);
+    }
+  
+  /*
+   * Wait for all the threads to exit.
+   */
+  for (i = 0; i < maxThreads; i++)
+    {
+      assert(pthread_join(threads[i], NULL) == 0);
+    }
+
+  /* 
+   * Check the number of threads created.
+   */
+  assert((int) numThreads == maxThreads);
+  
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/create1.c b/tests/create1.c
new file mode 100644
index 0000000..8c630cb
--- /dev/null
+++ b/tests/create1.c
@@ -0,0 +1,66 @@
+/*
+ * create1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Description:
+ * Create a thread and check that it ran.
+ *
+ * Depends on API functions: None.
+ */
+
+#include "test.h"
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  washere = 1;
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  /* A dirty hack, but we cannot rely on pthread_join in this
+     primitive test. */
+  Sleep(2000);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/create2.c b/tests/create2.c
new file mode 100644
index 0000000..2ffb64e
--- /dev/null
+++ b/tests/create2.c
@@ -0,0 +1,108 @@
+/*
+ * File: create2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test that threads have a Win32 handle when started.
+ *
+ * Test Method (Validation or Falsification):
+ * - Statistical, not absolute (depends on sample size).
+ *
+ * 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"
+
+enum {
+  NUMTHREADS = 10000
+};
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  washere = 1;
+  return (void *) 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  pthread_attr_t attr;
+  void * result = NULL;
+  int i;
+
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      washere = 0;
+      assert(pthread_create(&t, &attr, func, NULL) == 0);
+      pthread_join(t, &result);
+      assert(washere == 1);
+    }
+
+  return 0;
+}
diff --git a/tests/create3.c b/tests/create3.c
new file mode 100644
index 0000000..98bd520
--- /dev/null
+++ b/tests/create3.c
@@ -0,0 +1,122 @@
+/*
+ * File: create3.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: Test passing NULL as thread id arg to pthread_create.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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.
+ */
+
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 1
+};
+
+
+void *
+threadFunc(void * arg)
+{
+  return (void *) 0;
+}
+
+int
+main(int argc, char * argv[])
+{
+  int i;
+  pthread_t mt;
+
+  if (argc <= 1)
+    {
+      int result;
+
+      printf("You should see an application memory write error message\n");
+      fflush(stdout);
+      result = system("create3.exe die");
+      exit(0);
+    }
+
+  assert((mt = pthread_self()).p != NULL);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      assert(pthread_create(NULL, NULL, threadFunc, NULL) == 0);
+    }
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
diff --git a/tests/delay1.c b/tests/delay1.c
new file mode 100644
index 0000000..83becd8
--- /dev/null
+++ b/tests/delay1.c
@@ -0,0 +1,51 @@
+/*
+ * delay1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions:
+ *    pthread_delay_np
+ */
+
+#include "test.h"
+
+int
+main(int argc, char * argv[])
+{
+  struct timespec interval = {1L, 500000000L};
+
+  assert(pthread_delay_np(&interval) == 0);
+
+  return 0;
+}
+
diff --git a/tests/delay2.c b/tests/delay2.c
new file mode 100644
index 0000000..8ecaf0b
--- /dev/null
+++ b/tests/delay2.c
@@ -0,0 +1,82 @@
+/*
+ * delay1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions:
+ *    pthread_delay_np
+ */
+
+#include "test.h"
+
+pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;
+
+void *
+func(void * arg)
+{
+  struct timespec interval = {5, 500000000L};
+
+  assert(pthread_mutex_lock(&mx) == 0);
+
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+  pthread_cleanup_push(pthread_mutex_unlock, &mx);
+  assert(pthread_delay_np(&interval) == 0);
+  pthread_cleanup_pop(1);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+  return (void *) 1;
+}
+
+int
+main(int argc, char * argv[])
+{
+  pthread_t t;
+  int result = 0;
+
+  assert(pthread_mutex_lock(&mx) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+  assert(pthread_cancel(t) == 0);
+
+  assert(pthread_mutex_unlock(&mx) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == (int) PTHREAD_CANCELED);
+
+  return 0;
+}
+
diff --git a/tests/detach1.c b/tests/detach1.c
new file mode 100644
index 0000000..165c8c1
--- /dev/null
+++ b/tests/detach1.c
@@ -0,0 +1,93 @@
+/*
+ * Test for pthread_detach().
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: pthread_create(), pthread_detach(), pthread_exit().
+ */
+
+#include "test.h"
+
+
+enum {
+  NUMTHREADS = 100
+};
+
+void *
+func(void * arg)
+{
+    int i = (int) arg;
+
+    Sleep(i * 10);
+
+    pthread_exit(arg);
+
+    /* Never reached. */
+    exit(1);
+}
+
+int
+main(int argc, char * argv[])
+{
+	pthread_t id[NUMTHREADS];
+	int i;
+
+	/* Create a few threads and then exit. */
+	for (i = 0; i < NUMTHREADS; i++)
+	  {
+	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
+	  }
+
+	/* Some threads will finish before they are detached, some after. */
+	Sleep(NUMTHREADS/2 * 10 + 50);
+
+	for (i = 0; i < NUMTHREADS; i++)
+	  {
+	    assert(pthread_detach(id[i]) == 0);
+	  }
+
+	Sleep(NUMTHREADS * 10 + 100);
+
+	/*
+	 * Check that all threads are now invalid.
+	 * This relies on unique thread IDs - e.g. works with
+	 * pthreads-w32 or Solaris, but may not work for Linux, BSD etc.
+	 */
+	for (i = 0; i < NUMTHREADS; i++)
+	  {
+	    assert(pthread_kill(id[i], 0) == ESRCH);
+	  }
+
+	/* Success. */
+	return 0;
+}
diff --git a/tests/equal1.c b/tests/equal1.c
new file mode 100644
index 0000000..8932bb2
--- /dev/null
+++ b/tests/equal1.c
@@ -0,0 +1,66 @@
+/*
+ * Test for pthread_equal.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on functions: pthread_create().
+ */
+
+#include "test.h"
+
+void * func(void * arg)
+{
+  Sleep(2000);
+  return 0;
+}
+
+int 
+main()
+{
+  pthread_t t1, t2;
+
+  assert(pthread_create(&t1, NULL, func, (void *) 1) == 0);
+
+  assert(pthread_create(&t2, NULL, func, (void *) 2) == 0);
+
+  assert(pthread_equal(t1, t2) == 0);
+
+  assert(pthread_equal(t1,t1) != 0);
+
+  /* This is a hack. We don't want to rely on pthread_join
+     yet if we can help it. */
+   Sleep(4000);
+
+  /* Success. */
+  return 0;
+}
diff --git a/tests/errno1.c b/tests/errno1.c
new file mode 100644
index 0000000..70ce928
--- /dev/null
+++ b/tests/errno1.c
@@ -0,0 +1,177 @@
+/*
+ * File: errno1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test thread-safety of errno
+ * - 
+ *
+ * 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"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 3
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+pthread_mutex_t stop_here = PTHREAD_MUTEX_INITIALIZER;
+
+void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  errno = bag->threadnum;
+
+  Sleep(1000);
+
+  pthread_mutex_lock(&stop_here);
+
+  assert(errno == bag->threadnum);
+
+  pthread_mutex_unlock(&stop_here);
+
+  Sleep(1000);
+
+  return 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t t[NUMTHREADS + 1];
+
+  pthread_mutex_lock(&stop_here);
+  errno = 0;
+
+  assert((t[0] = pthread_self()).p != NULL);
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+      assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(2000);
+  pthread_mutex_unlock(&stop_here);
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 1000);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      failed = !threadbag[i].started;
+
+      if (failed)
+	{
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print ouput on failure.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      /* ... */
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
diff --git a/tests/exception1.c b/tests/exception1.c
new file mode 100644
index 0000000..3f9f595
--- /dev/null
+++ b/tests/exception1.c
@@ -0,0 +1,263 @@
+/*
+ * File: exception1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test passing of exceptions back to the application.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+void *
+exceptionedThread(void * arg)
+{
+  int dummy = 0;
+  int result = ((int)PTHREAD_CANCELED + 1);
+  /* Set to async cancelable */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+  Sleep(100);
+
+#if defined(_MSC_VER) && !defined(__cplusplus)
+  __try
+  {
+    int zero = (int) arg; /* Passed in from arg to avoid compiler error */
+    int one = 1;
+    /*
+     * The deliberate exception condition (zero divide) is
+     * in an "if" to avoid being optimised out.
+     */
+    if (dummy == one/zero)
+      Sleep(0);
+  }
+  __except (EXCEPTION_EXECUTE_HANDLER)
+  {
+    /* Should get into here. */
+    result = ((int)PTHREAD_CANCELED + 2);
+  }
+#elif defined(__cplusplus)
+  try
+  {
+    /*
+     * I had a zero divide exception here but it
+     * wasn't being caught by the catch(...)
+     * below under Mingw32. That could be a problem.
+     */
+    throw dummy;
+  }
+#if defined(PtW32CatchAll)
+  PtW32CatchAll
+#else
+  catch (...)
+#endif
+  {
+    /* Should get into here. */
+    result = ((int)PTHREAD_CANCELED + 2);
+  }
+#endif
+
+  return (void *) result;
+}
+
+void *
+canceledThread(void * arg)
+{
+  int result = ((int)PTHREAD_CANCELED + 1);
+  int count;
+
+  /* Set to async cancelable */
+
+  assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
+
+  assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
+
+#if defined(_MSC_VER) && !defined(__cplusplus)
+  __try
+  {
+    /*
+     * We wait up to 10 seconds, waking every 0.1 seconds,
+     * for a cancelation to be applied to us.
+     */
+    for (count = 0; count < 100; count++)
+      Sleep(100);
+  }
+  __except (EXCEPTION_EXECUTE_HANDLER)
+  {
+    /* Should NOT get into here. */
+    result = ((int)PTHREAD_CANCELED + 2);
+  }
+#elif defined(__cplusplus)
+  try
+  {
+    /*
+     * We wait up to 10 seconds, waking every 0.1 seconds,
+     * for a cancelation to be applied to us.
+     */
+    for (count = 0; count < 100; count++)
+      Sleep(100);
+  }
+#if defined(PtW32CatchAll)
+  PtW32CatchAll
+#else
+  catch (...)
+#endif
+  {
+    /* Should NOT get into here. */
+    result = ((int)PTHREAD_CANCELED + 2);
+  }
+#endif
+
+  return (void *) result;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  pthread_t mt;
+  pthread_t et[NUMTHREADS];
+  pthread_t ct[NUMTHREADS];
+
+  assert((mt = pthread_self()).p != NULL);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      assert(pthread_create(&et[i], NULL, exceptionedThread, (void *) 0) == 0);
+      assert(pthread_create(&ct[i], NULL, canceledThread, NULL) == 0);
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(1000);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      assert(pthread_cancel(ct[i]) == 0);
+    }
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 1000);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+	/* Canceled thread */
+      assert(pthread_join(ct[i], (void **) &result) == 0);
+      assert(!(fail = (result != (int) PTHREAD_CANCELED)));
+
+      failed = (failed || fail);
+
+      /* Exceptioned thread */
+      assert(pthread_join(et[i], (void **) &result) == 0);
+      assert(!(fail = (result != ((int) PTHREAD_CANCELED + 2))));
+
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+#include <stdio.h>
+
+int
+main()
+{
+  fprintf(stderr, "Test N/A for this compiler environment.\n");
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/exception2.c b/tests/exception2.c
new file mode 100644
index 0000000..5c18568
--- /dev/null
+++ b/tests/exception2.c
@@ -0,0 +1,158 @@
+/*
+ * File: exception2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test passing of exceptions out of thread scope.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+
+#if defined(_MSC_VER) || defined(__cplusplus)
+
+#if defined(_MSC_VER) && defined(__cplusplus)
+#include <eh.h>
+#elif defined(__cplusplus)
+#include <exception>
+#endif
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#include "test.h"
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 1
+};
+
+
+void *
+exceptionedThread(void * arg)
+{
+  int dummy = 0x1;
+
+#if defined(_MSC_VER) && !defined(__cplusplus)
+
+  RaiseException(dummy, 0, 0, NULL);
+
+#elif defined(__cplusplus)
+
+  throw dummy;
+
+#endif
+
+  return (void *) 100;
+}
+
+int
+main(int argc, char argv[])
+{
+  int i;
+  pthread_t mt;
+  pthread_t et[NUMTHREADS];
+
+  if (argc <= 1)
+    {
+      int result;
+
+      printf("You should see an \"abnormal termination\" message\n");
+      fflush(stdout);
+      result = system("exception2.exe die");
+      exit(0);
+    }
+
+  assert((mt = pthread_self()).p != NULL);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      assert(pthread_create(&et[i], NULL, exceptionedThread, NULL) == 0);
+    }
+
+  Sleep(1000);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(_MSC_VER) || defined(__cplusplus) */
+
+#include <stdio.h>
+
+int
+main()
+{
+  fprintf(stderr, "Test N/A for this compiler environment.\n");
+  return 0;
+}
+
+#endif /* defined(_MSC_VER) || defined(__cplusplus) */
diff --git a/tests/exception3.c b/tests/exception3.c
new file mode 100644
index 0000000..9a70a40
--- /dev/null
+++ b/tests/exception3.c
@@ -0,0 +1,196 @@
+/*
+ * File: exception3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test running of user supplied terminate() function.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+#if defined(__cplusplus)
+
+#if defined(_MSC_VER)
+# include <eh.h>
+#else
+# if defined(__GNUC__) && __GNUC__ < 3
+#   include <new.h>
+# else
+#   include <new>
+    using std::set_terminate;
+# endif
+#endif
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 1
+};
+
+int caught = 0;
+pthread_mutex_t caughtLock;
+
+void
+terminateFunction ()
+{
+  assert(pthread_mutex_lock(&caughtLock) == 0);
+  caught++;
+#if 1
+  {
+     FILE * fp = fopen("pthread.log", "a");
+     fprintf(fp, "Caught = %d\n", caught);
+     fclose(fp);
+  }
+#endif
+  assert(pthread_mutex_unlock(&caughtLock) == 0);
+
+#if defined(__MINGW32__)
+  /*
+   * Seems to work. That is, threads exit and the process
+   * continues. Note: need to check correct POSIX behaviour.
+   * My guess is: this is because of the
+   * eh incompatibility between g++ and MSVC++. That is,
+   * an exception thrown in g++ code doesn't propogate
+   * through or to MSVC++ code, and vice versa.
+   * Applications should probably not depend on this.
+   */
+  pthread_exit((void *) 0);
+#else
+  /*
+   * 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).
+   */
+  exit(0);
+#endif
+}
+
+void *
+exceptionedThread(void * arg)
+{
+  int dummy = 0x1;
+
+  (void) set_terminate(&terminateFunction);
+
+  throw dummy;
+
+  return (void *) 0;
+}
+
+int
+main()
+{
+  int i;
+  pthread_t mt;
+  pthread_t et[NUMTHREADS];
+  pthread_mutexattr_t ma;
+
+  assert((mt = pthread_self()).p != NULL);
+
+  printf("See the notes inside of exception3.c re term_funcs.\n");
+
+  assert(pthread_mutexattr_init(&ma) == 0);
+  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK) == 0);
+  assert(pthread_mutex_init(&caughtLock, &ma) == 0);
+  assert(pthread_mutexattr_destroy(&ma) == 0);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      assert(pthread_create(&et[i], NULL, exceptionedThread, NULL) == 0);
+    }
+
+  Sleep(5000);
+
+  assert(caught == NUMTHREADS);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
+#else /* defined(__cplusplus) */
+
+#include <stdio.h>
+
+int
+main()
+{
+  fprintf(stderr, "Test N/A for this compiler environment.\n");
+  return 0;
+}
+
+#endif /* defined(__cplusplus) */
diff --git a/tests/exit1.c b/tests/exit1.c
new file mode 100644
index 0000000..38f2182
--- /dev/null
+++ b/tests/exit1.c
@@ -0,0 +1,50 @@
+/*
+ * Test for pthread_exit().
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: None.
+ */
+
+#include "test.h"
+
+int
+main(int argc, char * argv[])
+{
+	/* A simple test first. */
+	pthread_exit((void *) 0);
+
+	/* Not reached */
+	assert(0);
+	return 0;
+}
diff --git a/tests/exit2.c b/tests/exit2.c
new file mode 100644
index 0000000..196139a
--- /dev/null
+++ b/tests/exit2.c
@@ -0,0 +1,64 @@
+/*
+ * Test for pthread_exit().
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions:
+ *	pthread_create()
+ *	pthread_exit()
+ */
+
+#include "test.h"
+
+void *
+func(void * arg)
+{
+	pthread_exit(arg);
+
+	/* Never reached. */
+	assert(0);
+
+	return NULL;
+}
+
+int
+main(int argc, char * argv[])
+{
+  pthread_t t;
+
+  assert(pthread_create(&t, NULL, func, (void *) NULL) == 0);
+
+  Sleep(1000);
+
+  return 0;
+}
diff --git a/tests/exit3.c b/tests/exit3.c
new file mode 100644
index 0000000..574a92d
--- /dev/null
+++ b/tests/exit3.c
@@ -0,0 +1,68 @@
+/*
+ * Test for pthread_exit().
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: pthread_create().
+ */
+
+#include "test.h"
+
+void *
+func(void * arg)
+{
+	pthread_exit(arg);
+
+	/* Never reached. */
+	assert(0);
+
+	return NULL;
+}
+
+int
+main(int argc, char * argv[])
+{
+	pthread_t id[4];
+	int i;
+
+	/* Create a few threads and then exit. */
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
+	  }
+
+	Sleep(1000);
+
+	/* Success. */
+	return 0;
+}
diff --git a/tests/exit4.c b/tests/exit4.c
new file mode 100644
index 0000000..1ceca4e
--- /dev/null
+++ b/tests/exit4.c
@@ -0,0 +1,199 @@
+/*
+ * File: exit4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test calling pthread_exit from a Win32 thread
+ *                without having created an implicit POSIX handle for it.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#ifndef _UWIN
+#include <process.h>
+#endif
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+unsigned __stdcall
+#else
+void
+#endif
+Win32thread(void * arg)
+{
+  int result = 1;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  /*
+   * Doesn't return and doesn't create an implicit POSIX handle.
+   */
+  pthread_exit((void *) result);
+
+  return 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  HANDLE h[NUMTHREADS + 1];
+  unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr);
+#else
+      h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]);
+#endif
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE);
+#else
+      /*
+       * Can't get a result code.
+       */
+      result = 1;
+#endif
+
+      fail = (result != 1);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
diff --git a/tests/exit5.c b/tests/exit5.c
new file mode 100644
index 0000000..450ed3b
--- /dev/null
+++ b/tests/exit5.c
@@ -0,0 +1,205 @@
+/*
+ * File: exit5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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: Test calling pthread_exit from a Win32 thread
+ *                having created an implicit POSIX handle for it.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validate return value and that POSIX handle is created and destroyed.
+ *
+ * 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:
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
+ *   pthread_testcancel, pthread_cancel, pthread_join
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#ifndef _UWIN
+#include <process.h>
+#endif
+
+/*
+ * Create NUMTHREADS threads in addition to the Main thread.
+ */
+enum {
+  NUMTHREADS = 4
+};
+
+typedef struct bag_t_ bag_t;
+struct bag_t_ {
+  int threadnum;
+  int started;
+  /* Add more per-thread state variables here */
+  int count;
+  pthread_t self;
+};
+
+static bag_t threadbag[NUMTHREADS + 1];
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+unsigned __stdcall
+#else
+void
+#endif
+Win32thread(void * arg)
+{
+  int result = 1;
+  bag_t * bag = (bag_t *) arg;
+
+  assert(bag == &threadbag[bag->threadnum]);
+  assert(bag->started == 0);
+  bag->started = 1;
+
+  assert((bag->self = pthread_self()).p != NULL);
+  assert(pthread_kill(bag->self, 0) == 0);
+
+  /*
+   * Doesn't return.
+   */
+  pthread_exit((void *) result);
+
+  return 0;
+}
+
+int
+main()
+{
+  int failed = 0;
+  int i;
+  HANDLE h[NUMTHREADS + 1];
+  unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */
+
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      threadbag[i].started = 0;
+      threadbag[i].threadnum = i;
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr);
+#else
+      h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]);
+#endif
+    }
+
+  /*
+   * Code to control or munipulate child threads should probably go here.
+   */
+  Sleep(500);
+
+  /*
+   * Give threads time to run.
+   */
+  Sleep(NUMTHREADS * 100);
+
+  /*
+   * Standard check that all threads started.
+   */
+  for (i = 1; i <= NUMTHREADS; i++)
+    { 
+      if (!threadbag[i].started)
+	{
+	  failed |= !threadbag[i].started;
+	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
+	}
+    }
+
+  assert(!failed);
+
+  /*
+   * Check any results here. Set "failed" and only print output on failure.
+   */
+  failed = 0;
+  for (i = 1; i <= NUMTHREADS; i++)
+    {
+      int fail = 0;
+      int result = 0;
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+      assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE);
+#else
+      /*
+       * Can't get a result code.
+       */
+      result = 1;
+#endif
+
+      assert(threadbag[i].self.p != NULL && pthread_kill(threadbag[i].self, 0) == ESRCH);
+
+      fail = (result != 1);
+
+      if (fail)
+	{
+	  fprintf(stderr, "Thread %d: started %d: count %d\n",
+		  i,
+		  threadbag[i].started,
+		  threadbag[i].count);
+	}
+      failed = (failed || fail);
+    }
+
+  assert(!failed);
+
+  /*
+   * Success.
+   */
+  return 0;
+}
+
diff --git a/tests/eyal1.c b/tests/eyal1.c
new file mode 100644
index 0000000..72b5697
--- /dev/null
+++ b/tests/eyal1.c
@@ -0,0 +1,367 @@
+/* Simple POSIX threads program.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Author: Eyal Lebedinsky eyal@eyal.emu.id.au
+ * Written: Sep 1998.
+ * Version Date: 12 Sep 1998
+ *
+ * Do we need to lock stdout or is it thread safe?
+ *
+ * Used:
+ *	pthread_t
+ *	pthread_attr_t
+ *	pthread_create()
+ *	pthread_join()
+ *	pthread_mutex_t
+ *	PTHREAD_MUTEX_INITIALIZER
+ *	pthread_mutex_init() [not used now]
+ *	pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ *
+ * What this program does is establish a work queue (implemented using
+ * four mutexes for each thread). It then schedules work (by storing
+ * a number in 'todo') and releases the threads. When the work is done
+ * the threads will block. The program then repeats the same thing once
+ * more (just to test the logic) and when the work is done it destroyes
+ * the threads.
+ *
+ * The 'work' we do is simply burning CPU cycles in a loop.
+ * The 'todo' work queue is trivial - each threads pops one element
+ * off it by incrementing it, the poped number is the 'work' to do.
+ * When 'todo' reaches the limit (nwork) the queue is considered
+ * empty.
+ *
+ * The number displayed at the end is the amount of work each thread
+ * did, so we can see if the load was properly distributed.
+ *
+ * The program was written to test a threading setup (not seen here)
+ * rather than to demonstrate correct usage of the pthread facilities.
+ *
+ * Note how each thread is given access to a thread control structure
+ * (TC) which is used for communicating to/from the main program (e.g.
+ * the threads knows its 'id' and also filles in the 'work' done).
+*/
+
+#include "test.h"
+
+#include <stdlib.h>
+#include <math.h>
+
+struct thread_control {
+  int		id;
+  pthread_t	thread;		/* thread id */
+  pthread_mutex_t	mutex_start;
+  pthread_mutex_t	mutex_started;
+  pthread_mutex_t	mutex_end;
+  pthread_mutex_t	mutex_ended;
+  long		work;		/* work done */
+  int		stat;		/* pthread_init status */
+};
+
+typedef struct thread_control	TC;
+
+static TC		*tcs = NULL;
+static int		nthreads = 10;
+static int		nwork = 100;
+static int		quiet = 0;
+
+static int		todo = -1;
+
+static pthread_mutex_t	mutex_todo = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t	mutex_stdout = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+die (int ret)
+{
+  if (NULL != tcs)
+    {
+      free (tcs);
+      tcs = NULL;
+    }
+
+  if (ret)
+    exit (ret);
+}
+
+
+static double
+waste_time (int n)
+{
+  int		i;
+  double	f, g, h, s;
+
+  s = 0.0;
+
+  /*
+   * Useless work.
+   */
+  for (i = n*100; i > 0; --i)
+    {
+      f = rand ();
+      g = rand ();
+      h = rand ();
+      s += 2.0 * f * g / (h != 0.0 ? (h * h) : 1.0);
+    }
+  return s;
+}
+
+static int
+do_work_unit (int who, int n)
+{
+  int		i;
+  static int	nchars = 0;
+  double	f = 0.0;
+
+  if (quiet)
+    i = 0;
+  else {
+    /*
+     * get lock on stdout
+     */
+    assert(pthread_mutex_lock (&mutex_stdout) == 0);
+
+    /*
+     * do our job
+     */
+    i = printf ("%c", "0123456789abcdefghijklmnopqrstuvwxyz"[who]);
+
+    if (!(++nchars % 50))
+      printf ("\n");
+
+    fflush (stdout);
+
+    /*
+     * release lock on stdout
+     */
+    assert(pthread_mutex_unlock (&mutex_stdout) == 0);
+  }
+
+  n = rand () % 10000;	/* ignore incoming 'n' */
+  f = waste_time (n);
+
+  /* This prevents the statement above from being optimised out */
+  if (f > 0.0)
+    return(n);
+
+  return (n);
+}
+
+static int
+print_server (void *ptr)
+{
+  int		mywork;
+  int		n;
+  TC		*tc = (TC *)ptr;
+
+  assert(pthread_mutex_lock (&tc->mutex_started) == 0);
+
+  for (;;)
+    {
+      assert(pthread_mutex_lock (&tc->mutex_start) == 0);
+      assert(pthread_mutex_unlock (&tc->mutex_start) == 0);
+      assert(pthread_mutex_lock (&tc->mutex_ended) == 0);
+      assert(pthread_mutex_unlock (&tc->mutex_started) == 0);
+
+      for (;;)
+	{
+
+	  /*
+	   * get lock on todo list
+	   */
+	  assert(pthread_mutex_lock (&mutex_todo) == 0);
+
+	  mywork = todo;
+	  if (todo >= 0)
+	    {
+	      ++todo;
+	      if (todo >= nwork)
+		todo = -1;
+	    }
+	  assert(pthread_mutex_unlock (&mutex_todo) == 0);
+
+	  if (mywork < 0)
+	    break;
+
+	  assert((n = do_work_unit (tc->id, mywork)) >= 0);
+	  tc->work += n;
+	}
+
+      assert(pthread_mutex_lock (&tc->mutex_end) == 0);
+      assert(pthread_mutex_unlock (&tc->mutex_end) == 0);
+      assert(pthread_mutex_lock (&tc->mutex_started) == 0);
+      assert(pthread_mutex_unlock (&tc->mutex_ended) == 0);
+
+      if (-2 == mywork)
+	break;
+    }
+
+  assert(pthread_mutex_unlock (&tc->mutex_started) == 0);
+
+  return (0);
+}
+
+static void
+dosync (void)
+{
+  int		i;
+
+  for (i = 0; i < nthreads; ++i)
+    {
+      assert(pthread_mutex_lock (&tcs[i].mutex_end) == 0);
+      assert(pthread_mutex_unlock (&tcs[i].mutex_start) == 0);
+      assert(pthread_mutex_lock (&tcs[i].mutex_started) == 0);
+      assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);
+    }
+
+  /*
+   * Now threads do their work
+   */
+  for (i = 0; i < nthreads; ++i)
+    {
+      assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0);
+      assert(pthread_mutex_unlock (&tcs[i].mutex_end) == 0);
+      assert(pthread_mutex_lock (&tcs[i].mutex_ended) == 0);
+      assert(pthread_mutex_unlock (&tcs[i].mutex_ended) == 0);
+    }
+}
+
+static void
+dowork (void)
+{
+  todo = 0;
+  dosync();
+
+  todo = 0;
+  dosync();
+}
+
+int
+main (int argc, char *argv[])
+{
+  int		i;
+
+  assert(NULL != (tcs = (TC *) calloc (nthreads, sizeof (*tcs))));
+
+  /* 
+   * Launch threads
+   */
+  for (i = 0; i < nthreads; ++i)
+    {
+      tcs[i].id = i;
+
+      assert(pthread_mutex_init (&tcs[i].mutex_start, NULL) == 0);
+      assert(pthread_mutex_init (&tcs[i].mutex_started, NULL) == 0);
+      assert(pthread_mutex_init (&tcs[i].mutex_end, NULL) == 0);
+      assert(pthread_mutex_init (&tcs[i].mutex_ended, NULL) == 0);
+
+      tcs[i].work = 0;  
+
+      assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0);
+      assert((tcs[i].stat = 
+	      pthread_create (&tcs[i].thread,
+			      NULL,
+                  (void *(*)(void *))print_server,
+                (void *) &tcs[i])
+	      ) == 0);
+
+      /* 
+       * Wait for thread initialisation
+       */
+      {
+	int trylock = 0;
+
+	while (trylock == 0)
+	  {
+	    trylock = pthread_mutex_trylock(&tcs[i].mutex_started);
+	    assert(trylock == 0 || trylock == EBUSY);
+
+	    if (trylock == 0)
+	      {
+		assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);
+	      }
+	  }
+      }
+    }
+
+  dowork ();
+
+  /*
+   * Terminate threads
+   */
+  todo = -2;	/* please terminate */
+  dosync();
+
+  for (i = 0; i < nthreads; ++i)
+    {
+      if (0 == tcs[i].stat)
+	assert(pthread_join (tcs[i].thread, NULL) == 0);
+    }
+
+  /* 
+   * destroy locks
+   */
+  assert(pthread_mutex_destroy (&mutex_stdout) == 0);
+  assert(pthread_mutex_destroy (&mutex_todo) == 0);
+
+  /*
+   * Cleanup
+   */
+  printf ("\n");
+
+  /*
+   * Show results
+   */
+  for (i = 0; i < nthreads; ++i)
+    {
+      printf ("%2d ", i);
+      if (0 == tcs[i].stat)
+	printf ("%10ld\n", tcs[i].work);
+      else
+	printf ("failed %d\n", tcs[i].stat);
+
+      assert(pthread_mutex_unlock(&tcs[i].mutex_start) == 0);
+
+      assert(pthread_mutex_destroy (&tcs[i].mutex_start) == 0);
+      assert(pthread_mutex_destroy (&tcs[i].mutex_started) == 0);
+      assert(pthread_mutex_destroy (&tcs[i].mutex_end) == 0);
+      assert(pthread_mutex_destroy (&tcs[i].mutex_ended) == 0);
+    }
+
+  die (0);
+
+  return (0);
+}
diff --git a/tests/inherit1.c b/tests/inherit1.c
new file mode 100644
index 0000000..482a5a8
--- /dev/null
+++ b/tests/inherit1.c
@@ -0,0 +1,177 @@
+/*
+ * File: inherit1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test thread priority inheritance.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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"
+
+enum {
+  PTW32TEST_THREAD_INIT_PRIO = 0,
+  PTW32TEST_MAXPRIORITIES = 512
+};
+
+int minPrio;
+int maxPrio;
+int validPriorities[PTW32TEST_MAXPRIORITIES];
+
+
+void * func(void * arg)
+{
+  int policy;
+  struct sched_param param;
+
+  assert(pthread_getschedparam(pthread_self(), &policy, &param) == 0);
+  return (void *) param.sched_priority;
+}
+
+
+void *
+getValidPriorities(void * arg)
+{
+  int prioSet;
+  pthread_t thread = pthread_self();
+  HANDLE threadH = pthread_getw32threadhandle_np(thread);
+  struct sched_param param;
+
+  for (prioSet = minPrio;
+       prioSet <= maxPrio;
+       prioSet++)
+    {
+        /*
+       * If prioSet is invalid then the threads priority is unchanged
+       * from the previous value. Make the previous value a known
+       * one so that we can check later.
+       */
+        param.sched_priority = prioSet;
+        assert(pthread_setschedparam(thread, SCHED_OTHER, &param) == 0);
+        validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)] = GetThreadPriority(threadH);
+    }
+
+  return (void *) 0;
+}
+
+
+int
+main()
+{
+  pthread_t t;
+  pthread_t mainThread = pthread_self();
+  pthread_attr_t attr;
+  void * result = NULL;
+  struct sched_param param;
+  struct sched_param mainParam;
+  int prio;
+  int policy;
+  int inheritsched = -1;
+  pthread_t threadID = pthread_self();
+  HANDLE threadH = pthread_getw32threadhandle_np(threadID);
+
+  assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1);
+  assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1);
+
+  assert(pthread_create(&t, NULL, getValidPriorities, NULL) == 0);
+  assert(pthread_join(t, &result) == 0);
+
+  assert(pthread_attr_init(&attr) == 0);
+  assert(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) == 0);
+  assert(pthread_attr_getinheritsched(&attr, &inheritsched) == 0);
+  assert(inheritsched == PTHREAD_INHERIT_SCHED);
+
+  for (prio = minPrio; prio <= maxPrio; prio++)
+    {
+      mainParam.sched_priority = prio;
+
+      /* Set the thread's priority to a known initial value. */
+      SetThreadPriority(threadH, PTW32TEST_THREAD_INIT_PRIO);
+
+      /* Change the main thread priority */
+      assert(pthread_setschedparam(mainThread, SCHED_OTHER, &mainParam) == 0);
+      assert(pthread_getschedparam(mainThread, &policy, &mainParam) == 0);
+      assert(policy == SCHED_OTHER);
+      /* Priority returned below should be the level set by pthread_setschedparam(). */
+      assert(mainParam.sched_priority == prio);
+      assert(GetThreadPriority(threadH) ==
+               validPriorities[prio+(PTW32TEST_MAXPRIORITIES/2)]);
+
+      for (param.sched_priority = prio;
+           param.sched_priority <= maxPrio;
+           param.sched_priority++)
+        {
+          /* The new thread create should ignore this new priority */
+          assert(pthread_attr_setschedparam(&attr, &param) == 0);
+          assert(pthread_create(&t, &attr, func, NULL) == 0);
+          pthread_join(t, &result);
+          assert((int) result == mainParam.sched_priority);
+        }
+    }
+
+  return 0;
+}
diff --git a/tests/join0.c b/tests/join0.c
new file mode 100644
index 0000000..a6cb25d
--- /dev/null
+++ b/tests/join0.c
@@ -0,0 +1,67 @@
+/*
+ * Test for pthread_join().
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: pthread_create(), pthread_exit().
+ */
+
+#include "test.h"
+
+void *
+func(void * arg)
+{
+  Sleep(2000);
+
+  pthread_exit(arg);
+
+  /* Never reached. */
+  exit(1);
+}
+
+int
+main(int argc, char * argv[])
+{
+  pthread_t id;
+  int result;
+
+  /* Create a single thread and wait for it to exit. */
+  assert(pthread_create(&id, NULL, func, (void *) 123) == 0);
+
+  assert(pthread_join(id, (void **) &result) == 0);
+
+  assert(result == 123);
+
+  /* Success. */
+  return 0;
+}
diff --git a/tests/join1.c b/tests/join1.c
new file mode 100644
index 0000000..8b11e95
--- /dev/null
+++ b/tests/join1.c
@@ -0,0 +1,78 @@
+/*
+ * Test for pthread_join().
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: pthread_create(), pthread_join(), pthread_exit().
+ */
+
+#include "test.h"
+
+void *
+func(void * arg)
+{
+    int i = (int) arg;
+
+    Sleep(i * 100);
+
+    pthread_exit(arg);
+
+    /* Never reached. */
+    exit(1);
+}
+
+int
+main(int argc, char * argv[])
+{
+	pthread_t id[4];
+	int i;
+	int result;
+
+	/* Create a few threads and then exit. */
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
+	  }
+
+	/* Some threads will finish before they are joined, some after. */
+	Sleep(2 * 100 + 50);
+
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_join(id[i], (void **) &result) == 0);
+	    assert(result == i);
+	  }
+
+	/* Success. */
+	return 0;
+}
diff --git a/tests/join2.c b/tests/join2.c
new file mode 100644
index 0000000..4fa3012
--- /dev/null
+++ b/tests/join2.c
@@ -0,0 +1,69 @@
+/*
+ * Test for pthread_join() returning return value from threads.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: pthread_create().
+ */
+
+#include "test.h"
+
+void *
+func(void * arg)
+{
+	Sleep(1000);
+	return arg;
+}
+
+int
+main(int argc, char * argv[])
+{
+	pthread_t id[4];
+	int i;
+	int result;
+
+	/* Create a few threads and then exit. */
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
+	  }
+
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_join(id[i], (void **) &result) == 0);
+	    assert(result == i);
+	  }
+
+	/* Success. */
+	return 0;
+}
diff --git a/tests/join3.c b/tests/join3.c
new file mode 100644
index 0000000..70cf3e9
--- /dev/null
+++ b/tests/join3.c
@@ -0,0 +1,75 @@
+/*
+ * Test for pthread_join() returning return value from threads.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Depends on API functions: pthread_create().
+ */
+
+#include "test.h"
+
+void *
+func(void * arg)
+{
+	sched_yield();
+	return arg;
+}
+
+int
+main(int argc, char * argv[])
+{
+	pthread_t id[4];
+	int i;
+	int result;
+
+	/* Create a few threads and then exit. */
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
+	  }
+
+	/*
+	 * Let threads exit before we join them.
+	 * We should still retrieve the exit code for the threads.
+	 */
+	Sleep(1000);
+
+	for (i = 0; i < 4; i++)
+	  {
+	    assert(pthread_join(id[i], (void **) &result) == 0);
+	    assert(result == i);
+	  }
+
+	/* Success. */
+	return 0;
+}
diff --git a/tests/kill1.c b/tests/kill1.c
new file mode 100644
index 0000000..fd1eaee
--- /dev/null
+++ b/tests/kill1.c
@@ -0,0 +1,83 @@
+/*
+ * File: kill1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - pthread_kill() does not support non zero signals..
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * 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"
+
+
+int
+main()
+{
+  assert(pthread_kill(pthread_self(), 1) == EINVAL);
+
+  return 0;
+}
diff --git a/tests/loadfree.c b/tests/loadfree.c
new file mode 100644
index 0000000..65bb15c
--- /dev/null
+++ b/tests/loadfree.c
@@ -0,0 +1,70 @@
+/*
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ * From: Todd Owen <towen@lucidcalm.dropbear.id.au>
+ * To: pthreads-win32@sourceware.cygnus.com
+ * Subject: invalid page fault when using LoadLibrary/FreeLibrary
+ * 
+ * hi,
+ * for me, pthread.dll consistently causes an "invalid page fault in
+ * kernel32.dll" when I load it "explicitly"...to be precise, loading (with
+ * LoadLibrary) isn't a problem, it gives the error when I call FreeLibrary.
+ * I guess that the dll's cleanup must be causing the error.
+ * 
+ * Implicit linkage of the dll has never given me this problem.  Here's a
+ * program (console application) that gives me the error.
+ * 
+ * I compile with: mingw32 (gcc-2.95 release), with the MSVCRT add-on (not
+ * that the compiler should make much difference in this case).
+ * PTHREAD.DLL: is the precompiled 1999-11-02 one (I tried an older one as
+ * well, with the same result).
+ * 
+ * Fascinatingly, if you have your own dll (mycode.dll) which implicitly
+ * loads pthread.dll, and then do LoadLibrary/FreeLibrary on _this_ dll, the
+ * same thing happens.
+ * 
+ */
+
+#include "test.h"
+
+int main() {
+  HINSTANCE hinst;
+
+  assert((hinst = LoadLibrary("pthread")) != (HINSTANCE) 0);
+
+  Sleep(100);
+
+  FreeLibrary(hinst);
+  return 0;
+}
+
diff --git a/tests/mutex1.c b/tests/mutex1.c
new file mode 100644
index 0000000..918c903
--- /dev/null
+++ b/tests/mutex1.c
@@ -0,0 +1,68 @@
+/* 
+ * mutex1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create a simple mutex object, lock it, and then unlock it again.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ * 	pthread_mutex_init()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ *	pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+
+int
+main()
+{
+  assert(mutex == NULL);
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex1e.c b/tests/mutex1e.c
new file mode 100644
index 0000000..e528107
--- /dev/null
+++ b/tests/mutex1e.c
@@ -0,0 +1,74 @@
+/* 
+ * mutex1e.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * As for mutex1.c but with type set to PTHREAD_MUTEX_ERRORCHECK.
+ *
+ * Create a simple mutex object, lock it, unlock it, then destroy it.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ *	pthread_mutexattr_settype()
+ * 	pthread_mutex_init()
+ *	pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0);
+
+  assert(mutex == NULL);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex1n.c b/tests/mutex1n.c
new file mode 100644
index 0000000..74850d6
--- /dev/null
+++ b/tests/mutex1n.c
@@ -0,0 +1,74 @@
+/* 
+ * mutex1n.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * As for mutex1.c but with type set to PTHREAD_MUTEX_NORMAL.
+ *
+ * Create a simple mutex object, lock it, unlock it, then destroy it.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ *	pthread_mutexattr_settype()
+ * 	pthread_mutex_init()
+ *	pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0);
+
+  assert(mutex == NULL);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex1r.c b/tests/mutex1r.c
new file mode 100644
index 0000000..0666dec
--- /dev/null
+++ b/tests/mutex1r.c
@@ -0,0 +1,74 @@
+/* 
+ * mutex1r.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * As for mutex1.c but with type set to PTHREAD_MUTEX_RECURSIVE.
+ *
+ * Create a simple mutex object, lock it, unlock it, then destroy it.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ * Depends on API functions:
+ *	pthread_mutexattr_settype()
+ * 	pthread_mutex_init()
+ *	pthread_mutex_destroy()
+ */
+
+#include "test.h"
+
+pthread_mutex_t mutex = NULL;
+pthread_mutexattr_t mxAttr;
+
+int
+main()
+{
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
+
+  assert(mutex == NULL);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex2.c b/tests/mutex2.c
new file mode 100644
index 0000000..377468e
--- /dev/null
+++ b/tests/mutex2.c
@@ -0,0 +1,66 @@
+/* 
+ * mutex2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static mutex object, lock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int
+main()
+{
+  assert(mutex == PTHREAD_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(mutex != PTHREAD_MUTEX_INITIALIZER);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex2e.c b/tests/mutex2e.c
new file mode 100644
index 0000000..7df6073
--- /dev/null
+++ b/tests/mutex2e.c
@@ -0,0 +1,66 @@
+/* 
+ * mutex2e.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static mutex object, lock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+
+int
+main()
+{
+  assert(mutex == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(mutex != PTHREAD_ERRORCHECK_MUTEX_INITIALIZER);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex2r.c b/tests/mutex2r.c
new file mode 100644
index 0000000..c96e366
--- /dev/null
+++ b/tests/mutex2r.c
@@ -0,0 +1,66 @@
+/* 
+ * mutex2r.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static mutex object, lock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+
+int
+main()
+{
+  assert(mutex == PTHREAD_RECURSIVE_MUTEX_INITIALIZER);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(mutex != PTHREAD_RECURSIVE_MUTEX_INITIALIZER);
+
+  assert(mutex != NULL);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  assert(mutex == NULL);
+
+  return 0;
+}
diff --git a/tests/mutex3.c b/tests/mutex3.c
new file mode 100644
index 0000000..bc1429e
--- /dev/null
+++ b/tests/mutex3.c
@@ -0,0 +1,75 @@
+/* 
+ * mutex3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static mutex object, lock it, trylock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_mutex_trylock(&mutex1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_mutex_lock(&mutex1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+  assert(pthread_join(t, NULL) == 0);
+
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/mutex3e.c b/tests/mutex3e.c
new file mode 100644
index 0000000..66cfcb7
--- /dev/null
+++ b/tests/mutex3e.c
@@ -0,0 +1,75 @@
+/* 
+ * mutex3e.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static mutex object, lock it, trylock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_mutex_t mutex1 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_mutex_trylock(&mutex1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_mutex_lock(&mutex1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+  assert(pthread_join(t, NULL) == 0);
+
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/mutex3r.c b/tests/mutex3r.c
new file mode 100644
index 0000000..8fa7f25
--- /dev/null
+++ b/tests/mutex3r.c
@@ -0,0 +1,75 @@
+/* 
+ * mutex3r.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static mutex object, lock it, trylock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_mutex_t mutex1 = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_mutex_trylock(&mutex1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_mutex_lock(&mutex1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+  assert(pthread_join(t, NULL) == 0);
+
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/mutex4.c b/tests/mutex4.c
new file mode 100644
index 0000000..547d9cb
--- /dev/null
+++ b/tests/mutex4.c
@@ -0,0 +1,111 @@
+/* 
+ * mutex4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Thread A locks mutex - thread B tries to unlock.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int wasHere = 0;
+
+static pthread_mutex_t mutex1;
+ 
+void * unlocker(void * arg)
+{
+  int expectedResult = (int) arg;
+
+  wasHere++;
+  assert(pthread_mutex_unlock(&mutex1) == expectedResult);
+  wasHere++;
+  return NULL;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  pthread_mutexattr_t ma;
+
+  assert(pthread_mutexattr_init(&ma) == 0);
+
+  wasHere = 0;
+  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_DEFAULT) == 0);
+  assert(pthread_mutex_init(&mutex1, &ma) == 0);
+  assert(pthread_mutex_lock(&mutex1) == 0);
+  /*
+   * NORMAL (fast) mutexes don't check ownership.
+   */
+  assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_mutex_unlock(&mutex1) == EPERM);
+  assert(wasHere == 2);
+
+  wasHere = 0;
+  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_NORMAL) == 0);
+  assert(pthread_mutex_init(&mutex1, &ma) == 0);
+  assert(pthread_mutex_lock(&mutex1) == 0);
+  /*
+   * NORMAL (fast) mutexes don't check ownership.
+   */
+  assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_mutex_unlock(&mutex1) == EPERM);
+  assert(wasHere == 2);
+
+  wasHere = 0;
+  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK) == 0);
+  assert(pthread_mutex_init(&mutex1, &ma) == 0);
+  assert(pthread_mutex_lock(&mutex1) == 0);
+  assert(pthread_create(&t, NULL, unlocker, (void *) EPERM) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+  assert(wasHere == 2);
+
+  wasHere = 0;
+  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE) == 0);
+  assert(pthread_mutex_init(&mutex1, &ma) == 0);
+  assert(pthread_mutex_lock(&mutex1) == 0);
+  assert(pthread_create(&t, NULL, unlocker, (void *) EPERM) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_mutex_unlock(&mutex1) == 0);
+  assert(wasHere == 2);
+
+  return 0;
+}
diff --git a/tests/mutex5.c b/tests/mutex5.c
new file mode 100644
index 0000000..a71f9d8
--- /dev/null
+++ b/tests/mutex5.c
@@ -0,0 +1,67 @@
+/* 
+ * mutex5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Confirm the equality/inequality of the various mutex types,
+ * and the default not-set value.
+ */
+
+#include "test.h"
+
+static pthread_mutexattr_t mxAttr;
+
+/* Prevent optimiser from removing dead or obvious asserts. */
+int _optimiseFoil;
+#define FOIL(x) (_optimiseFoil = x)
+
+int
+main()
+{
+  int mxType = -1;
+
+  assert(FOIL(PTHREAD_MUTEX_DEFAULT) == PTHREAD_MUTEX_NORMAL);
+  assert(FOIL(PTHREAD_MUTEX_DEFAULT) != PTHREAD_MUTEX_ERRORCHECK);
+  assert(FOIL(PTHREAD_MUTEX_DEFAULT) != PTHREAD_MUTEX_RECURSIVE);
+  assert(FOIL(PTHREAD_MUTEX_RECURSIVE) != PTHREAD_MUTEX_ERRORCHECK);
+
+  assert(FOIL(PTHREAD_MUTEX_NORMAL) == PTHREAD_MUTEX_FAST_NP);
+  assert(FOIL(PTHREAD_MUTEX_RECURSIVE) == PTHREAD_MUTEX_RECURSIVE_NP);
+  assert(FOIL(PTHREAD_MUTEX_ERRORCHECK) == PTHREAD_MUTEX_ERRORCHECK_NP);
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_NORMAL);
+
+  return 0;
+}
diff --git a/tests/mutex6.c b/tests/mutex6.c
new file mode 100644
index 0000000..15649fc
--- /dev/null
+++ b/tests/mutex6.c
@@ -0,0 +1,93 @@
+/* 
+ * mutex6.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 the default (type not set) mutex type.
+ * Should be the same as PTHREAD_MUTEX_NORMAL.
+ * Thread locks mutex twice (recursive lock).
+ * Locking thread should deadlock on second attempt.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+
+  /* Should wait here (deadlocked) */
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return 0;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(1000);
+
+  assert(lockCount == 1);
+
+  /*
+   * Should succeed even though we don't own the lock
+   * because FAST mutexes don't check ownership.
+   */
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  Sleep (1000);
+
+  assert(lockCount == 2);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
diff --git a/tests/mutex6e.c b/tests/mutex6e.c
new file mode 100644
index 0000000..8af9274
--- /dev/null
+++ b/tests/mutex6e.c
@@ -0,0 +1,102 @@
+/* 
+ * mutex6e.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_ERRORCHECK mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * This should fail with an EDEADLK error.
+ * The second unlock attempt should fail with an EPERM error.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_join()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_destroy()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *      pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_lock(&mutex) == EDEADLK);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == EPERM);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int result = 0;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_ERRORCHECK);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == 555);
+
+  assert(lockCount == 2);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+  assert(pthread_mutexattr_destroy(&mxAttr) == 0);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
+
diff --git a/tests/mutex6es.c b/tests/mutex6es.c
new file mode 100644
index 0000000..0d879c4
--- /dev/null
+++ b/tests/mutex6es.c
@@ -0,0 +1,94 @@
+/* 
+ * mutex6es.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_ERRORCHECK static mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * This should fail with an EDEADLK error.
+ * The second unlock attempt should fail with an EPERM error.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_join()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_destroy()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *      pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_lock(&mutex) == EDEADLK);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == EPERM);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int result = 0;
+
+  assert(mutex == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == 555);
+
+  assert(lockCount == 2);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
+
diff --git a/tests/mutex6n.c b/tests/mutex6n.c
new file mode 100644
index 0000000..9b4bbb9
--- /dev/null
+++ b/tests/mutex6n.c
@@ -0,0 +1,104 @@
+/* 
+ * mutex6n.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_NORMAL mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * The thread should deadlock.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+
+  /* Should wait here (deadlocked) */
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_NORMAL);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(1000);
+
+  assert(lockCount == 1);
+
+  /*
+   * Should succeed even though we don't own the lock
+   * because FAST mutexes don't check ownership.
+   */
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  Sleep (1000);
+
+  assert(lockCount == 2);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
+
diff --git a/tests/mutex6r.c b/tests/mutex6r.c
new file mode 100644
index 0000000..4bf853f
--- /dev/null
+++ b/tests/mutex6r.c
@@ -0,0 +1,100 @@
+/* 
+ * mutex6r.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_RECURSIVE mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * Both locks and unlocks should succeed.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_join()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_destroy()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *      pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int result = 0;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_RECURSIVE);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == 555);
+
+  assert(lockCount == 2);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+  assert(pthread_mutexattr_destroy(&mxAttr) == 0);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
diff --git a/tests/mutex6rs.c b/tests/mutex6rs.c
new file mode 100644
index 0000000..4ebe44e
--- /dev/null
+++ b/tests/mutex6rs.c
@@ -0,0 +1,92 @@
+/* 
+ * mutex6rs.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_RECURSIVE static mutex type.
+ * Thread locks mutex twice (recursive lock).
+ * Both locks and unlocks should succeed.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_join()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_destroy()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *      pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int result = 0;
+
+  assert(mutex == PTHREAD_RECURSIVE_MUTEX_INITIALIZER);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == 555);
+
+  assert(lockCount == 2);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
diff --git a/tests/mutex6s.c b/tests/mutex6s.c
new file mode 100644
index 0000000..8b82dc3
--- /dev/null
+++ b/tests/mutex6s.c
@@ -0,0 +1,93 @@
+/* 
+ * mutex6s.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 the default (type not set) static mutex type.
+ * Should be the same as PTHREAD_MUTEX_NORMAL.
+ * Thread locks mutex twice (recursive lock).
+ * Locking thread should deadlock on second attempt.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+
+  /* Should wait here (deadlocked) */
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return 0;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(mutex == PTHREAD_MUTEX_INITIALIZER);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(1000);
+
+  assert(lockCount == 1);
+
+  /*
+   * Should succeed even though we don't own the lock
+   * because FAST mutexes don't check ownership.
+   */
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  Sleep (1000);
+
+  assert(lockCount == 2);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
diff --git a/tests/mutex7.c b/tests/mutex7.c
new file mode 100644
index 0000000..8772b97
--- /dev/null
+++ b/tests/mutex7.c
@@ -0,0 +1,82 @@
+/* 
+ * mutex7.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 the default (type not set) mutex type.
+ * Should be the same as PTHREAD_MUTEX_NORMAL.
+ * Thread locks then trylocks mutex (attempted recursive lock).
+ * The thread should lock first time and EBUSY second time.
+ *
+ * Depends on API functions: 
+ *	pthread_mutex_lock()
+ *	pthread_mutex_trylock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_trylock(&mutex) == EBUSY);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == EPERM);
+
+  return 0;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(1000);
+
+  assert(lockCount == 2);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
diff --git a/tests/mutex7e.c b/tests/mutex7e.c
new file mode 100644
index 0000000..854789b
--- /dev/null
+++ b/tests/mutex7e.c
@@ -0,0 +1,102 @@
+/* 
+ * mutex7e.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_ERRORCHECK mutex type.
+ * Thread locks and then trylocks mutex (attempted recursive lock).
+ * Trylock should fail with an EBUSY error.
+ * The second unlock attempt should fail with an EPERM error.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_join()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_destroy()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *      pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_trylock(&mutex) == EBUSY);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == EPERM);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int result = 0;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_ERRORCHECK);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == 555);
+
+  assert(lockCount == 2);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+  assert(pthread_mutexattr_destroy(&mxAttr) == 0);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
+
diff --git a/tests/mutex7n.c b/tests/mutex7n.c
new file mode 100644
index 0000000..174355f
--- /dev/null
+++ b/tests/mutex7n.c
@@ -0,0 +1,93 @@
+/* 
+ * mutex7n.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_NORMAL mutex type.
+ * Thread locks then trylocks mutex (attempted recursive lock).
+ * The thread should lock first time and EBUSY second time.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_trylock(&mutex) == EBUSY);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == EPERM);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_NORMAL);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(1000);
+
+  assert(lockCount == 2);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
+
diff --git a/tests/mutex7r.c b/tests/mutex7r.c
new file mode 100644
index 0000000..f9e5ff0
--- /dev/null
+++ b/tests/mutex7r.c
@@ -0,0 +1,100 @@
+/* 
+ * mutex7r.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_RECURSIVE mutex type.
+ * Thread locks mutex then trylocks mutex (recursive lock twice).
+ * Both locks and unlocks should succeed.
+ *
+ * Depends on API functions: 
+ *      pthread_create()
+ *      pthread_join()
+ *      pthread_mutexattr_init()
+ *      pthread_mutexattr_destroy()
+ *      pthread_mutexattr_settype()
+ *      pthread_mutexattr_gettype()
+ *      pthread_mutex_init()
+ *      pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  assert(pthread_mutex_lock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_trylock(&mutex) == 0);
+  lockCount++;
+  assert(pthread_mutex_unlock(&mutex) == 0);
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return (void *) 555;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  int result = 0;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_RECURSIVE);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result == 555);
+
+  assert(lockCount == 2);
+
+  assert(pthread_mutex_destroy(&mutex) == 0);
+  assert(pthread_mutexattr_destroy(&mxAttr) == 0);
+
+  exit(0);
+
+  /* Never reached */
+  return 0;
+}
diff --git a/tests/mutex8.c b/tests/mutex8.c
new file mode 100644
index 0000000..5ca9982
--- /dev/null
+++ b/tests/mutex8.c
@@ -0,0 +1,82 @@
+/* 
+ * mutex8.c
+ *
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998 Ben Elliston and Ross Johnson
+ * Copyright (C) 1999,2000,2001 Ross Johnson
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * 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.1 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test the default (type not set) mutex type exercising timedlock.
+ * Thread locks mutex, another thread timedlocks the mutex.
+ * Timed thread should timeout.
+ *
+ * Depends on API functions:
+ *	pthread_mutex_lock()
+ *	pthread_mutex_timedlock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+
+void * locker(void * arg)
+{
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT);
+
+  lockCount++;
+
+  return 0;
+}
+
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(lockCount == 1);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return 0;
+}
diff --git a/tests/mutex8e.c b/tests/mutex8e.c
new file mode 100644
index 0000000..b99d24e
--- /dev/null
+++ b/tests/mutex8e.c
@@ -0,0 +1,97 @@
+/* 
+ * mutex8e.c
+ *
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998 Ben Elliston and Ross Johnson
+ * Copyright (C) 1999,2000,2001 Ross Johnson
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * 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.1 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_ERRORCHECK mutex type exercising timedlock.
+ * Thread locks mutex, another thread timedlocks the mutex.
+ * Timed thread should timeout.
+ *
+ * Depends on API functions:
+ *	pthread_create()
+ *	pthread_mutexattr_init()
+ *	pthread_mutexattr_destroy()
+ *	pthread_mutexattr_settype()
+ *	pthread_mutexattr_gettype()
+ *	pthread_mutex_init()
+ *	pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_timedlock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT);
+
+  lockCount++;
+
+  return 0;
+}
+
+int
+main()
+{
+  pthread_t t;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_ERRORCHECK);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(lockCount == 1);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return 0;
+}
+
diff --git a/tests/mutex8n.c b/tests/mutex8n.c
new file mode 100644
index 0000000..3cfdae6
--- /dev/null
+++ b/tests/mutex8n.c
@@ -0,0 +1,97 @@
+/*
+ * mutex8n.c
+ *
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998 Ben Elliston and Ross Johnson
+ * Copyright (C) 1999,2000,2001 Ross Johnson
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * 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.1 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_NORMAL mutex type exercising timedlock.
+ * Thread locks mutex, another thread timedlocks the mutex.
+ * Timed thread should timeout.
+ *
+ * Depends on API functions:
+ *	pthread_create()
+ *	pthread_mutexattr_init()
+ *	pthread_mutexattr_destroy()
+ *	pthread_mutexattr_settype()
+ *	pthread_mutexattr_gettype()
+ *	pthread_mutex_init()
+ *	pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_timedlock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT);
+
+  lockCount++;
+
+  return 0;
+}
+
+int
+main()
+{
+  pthread_t t;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_NORMAL);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(lockCount == 1);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return 0;
+}
+
diff --git a/tests/mutex8r.c b/tests/mutex8r.c
new file mode 100644
index 0000000..d1328ca
--- /dev/null
+++ b/tests/mutex8r.c
@@ -0,0 +1,97 @@
+/* 
+ * mutex8r.c
+ *
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998 Ben Elliston and Ross Johnson
+ * Copyright (C) 1999,2000,2001 Ross Johnson
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * 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.1 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Tests PTHREAD_MUTEX_RECURSIVE mutex type exercising timedlock.
+ * Thread locks mutex, another thread timedlocks the mutex.
+ * Timed thread should timeout.
+ *
+ * Depends on API functions:
+ *	pthread_create()
+ *	pthread_mutexattr_init()
+ *	pthread_mutexattr_destroy()
+ *	pthread_mutexattr_settype()
+ *	pthread_mutexattr_gettype()
+ *	pthread_mutex_init()
+ *	pthread_mutex_destroy()
+ *	pthread_mutex_lock()
+ *	pthread_mutex_timedlock()
+ *	pthread_mutex_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static int lockCount = 0;
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mxAttr;
+
+void * locker(void * arg)
+{
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT);
+
+  lockCount++;
+
+  return 0;
+}
+
+int
+main()
+{
+  pthread_t t;
+  int mxType = -1;
+
+  assert(pthread_mutexattr_init(&mxAttr) == 0);
+  assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
+  assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
+  assert(mxType == PTHREAD_MUTEX_RECURSIVE);
+
+  assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
+
+  assert(pthread_mutex_lock(&mutex) == 0);
+
+  assert(pthread_create(&t, NULL, locker, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(lockCount == 1);
+
+  assert(pthread_mutex_unlock(&mutex) == 0);
+
+  return 0;
+}
+
diff --git a/tests/once1.c b/tests/once1.c
new file mode 100644
index 0000000..daec112
--- /dev/null
+++ b/tests/once1.c
@@ -0,0 +1,77 @@
+/*
+ * once1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create a static pthread_once and test that it calls myfunc once.
+ *
+ * Depends on API functions:
+ *	pthread_once()
+ *	pthread_create()
+ */
+
+#include "test.h"
+
+pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int washere = 0;
+
+void
+myfunc(void)
+{
+  washere++;
+}
+
+void *
+mythread(void * arg)
+{
+   assert(pthread_once(&once, myfunc) == 0);
+
+   return 0;
+}
+
+int
+main()
+{
+  pthread_t t1, t2;
+  
+  assert(pthread_create(&t1, NULL, mythread, NULL) == 0);
+
+  assert(pthread_create(&t2, NULL, mythread, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/once2.c b/tests/once2.c
new file mode 100644
index 0000000..248ccb1
--- /dev/null
+++ b/tests/once2.c
@@ -0,0 +1,109 @@
+/*
+ * once2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create several static pthread_once objects and channel several threads
+ * through each.
+ *
+ * Depends on API functions:
+ *	pthread_once()
+ *	pthread_create()
+ */
+
+#include "test.h"
+
+#define NUM_THREADS 100 /* Targeting each once control */
+#define NUM_ONCE    10
+
+pthread_once_t o = PTHREAD_ONCE_INIT;
+pthread_once_t once[NUM_ONCE];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t numOnce = {0, {0}};
+static sharedInt_t numThreads = {0, {0}};
+
+void
+myfunc(void)
+{
+  EnterCriticalSection(&numOnce.cs);
+  numOnce.i++;
+  LeaveCriticalSection(&numOnce.cs);
+  /* Simulate slow once routine so that following threads pile up behind it */
+  Sleep(100);
+}
+
+void *
+mythread(void * arg)
+{
+   assert(pthread_once(&once[(int) arg], myfunc) == 0);
+   EnterCriticalSection(&numThreads.cs);
+   numThreads.i++;   
+   LeaveCriticalSection(&numThreads.cs);
+   return 0;
+}
+
+int
+main()
+{
+  pthread_t t[NUM_THREADS][NUM_ONCE];
+  int i, j;
+  
+  InitializeCriticalSection(&numThreads.cs);
+  InitializeCriticalSection(&numOnce.cs);
+
+  for (j = 0; j < NUM_ONCE; j++)
+    {
+      once[j] = o;
+
+      for (i = 0; i < NUM_THREADS; i++)
+        assert(pthread_create(&t[i][j], NULL, mythread, (void *) j) == 0);
+    }
+
+  for (j = 0; j < NUM_ONCE; j++)
+    for (i = 0; i < NUM_THREADS; i++)
+      if (pthread_join(t[i][j], NULL) != 0)
+        printf("Join failed for [thread,once] = [%d,%d]\n", i, j);
+
+  assert(numOnce.i == NUM_ONCE);
+  assert(numThreads.i == NUM_THREADS * NUM_ONCE);
+
+  DeleteCriticalSection(&numOnce.cs);
+  DeleteCriticalSection(&numThreads.cs);
+
+  return 0;
+}
diff --git a/tests/once3.c b/tests/once3.c
new file mode 100644
index 0000000..981bbf7
--- /dev/null
+++ b/tests/once3.c
@@ -0,0 +1,132 @@
+/*
+ * once3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create several pthread_once objects and channel several threads
+ * through each. Make the init_routine cancelable and cancel them with
+ * waiters waiting.
+ *
+ * Depends on API functions:
+ *	pthread_once()
+ *	pthread_create()
+ *      pthread_testcancel()
+ *      pthread_cancel()
+ *      pthread_once()
+ */
+
+#define ASSERT_TRACE
+
+#include "test.h"
+
+#define NUM_THREADS 100 /* Targeting each once control */
+#define NUM_ONCE    10
+
+pthread_once_t o = PTHREAD_ONCE_INIT;
+pthread_once_t once[NUM_ONCE];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t numOnce = {0, {0}};
+static sharedInt_t numThreads = {0, {0}};
+
+void
+myfunc(void)
+{
+  EnterCriticalSection(&numOnce.cs);
+  numOnce.i++;
+  assert(numOnce.i > 0);
+  LeaveCriticalSection(&numOnce.cs);
+  /* Simulate slow once routine so that following threads pile up behind it */
+  Sleep(10);
+  /* test for cancelation late so we're sure to have waiters. */
+  pthread_testcancel();
+}
+
+void *
+mythread(void * arg)
+{
+  /*
+   * Cancel every thread. These threads are deferred cancelable only, so
+   * only the thread performing the once routine (my_func) will see it (there are
+   * no other cancelation points here). The result will be that every thread
+   * eventually cancels only when it becomes the new once thread.
+   */
+  assert(pthread_cancel(pthread_self()) == 0);
+  assert(pthread_once(&once[(int) arg], myfunc) == 0);
+  EnterCriticalSection(&numThreads.cs);
+  numThreads.i++;
+  LeaveCriticalSection(&numThreads.cs);
+  return 0;
+}
+
+int
+main()
+{
+  pthread_t t[NUM_THREADS][NUM_ONCE];
+  int i, j;
+  
+  InitializeCriticalSection(&numThreads.cs);
+  InitializeCriticalSection(&numOnce.cs);
+
+  for (j = 0; j < NUM_ONCE; j++)
+    {
+      once[j] = o;
+
+      for (i = 0; i < NUM_THREADS; i++)
+        {
+          assert(pthread_create(&t[i][j], NULL, mythread, (void *) j) == 0);
+        }
+    }
+
+  for (j = 0; j < NUM_ONCE; j++)
+    for (i = 0; i < NUM_THREADS; i++)
+      if (pthread_join(t[i][j], NULL) != 0)
+        printf("Join failed for [thread,once] = [%d,%d]\n", i, j);
+
+  /*
+   * All threads will cancel, none will return normally from
+   * pthread_once and so numThreads should never be incremented. However,
+   * numOnce should be incremented by every thread (NUM_THREADS*NUM_ONCE).
+   */
+  assert(numOnce.i == NUM_ONCE * NUM_THREADS);
+  assert(numThreads.i == 0);
+
+  DeleteCriticalSection(&numOnce.cs);
+  DeleteCriticalSection(&numThreads.cs);
+
+  return 0;
+}
diff --git a/tests/once4.c b/tests/once4.c
new file mode 100644
index 0000000..f5be644
--- /dev/null
+++ b/tests/once4.c
@@ -0,0 +1,191 @@
+/*
+ * once4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create several pthread_once objects and channel several threads
+ * through each. Make the init_routine cancelable and cancel them
+ * waiters waiting. Vary the priorities.
+ *
+ * Depends on API functions:
+ *	pthread_once()
+ *	pthread_create()
+ *      pthread_testcancel()
+ *      pthread_cancel()
+ *      pthread_once()
+ */
+
+#include "test.h"
+
+#define NUM_THREADS 100 /* Targeting each once control */
+#define NUM_ONCE    10
+
+pthread_once_t o = PTHREAD_ONCE_INIT;
+pthread_once_t once[NUM_ONCE];
+
+typedef struct {
+  int i;
+  CRITICAL_SECTION cs;
+} sharedInt_t;
+
+static sharedInt_t numOnce = {0, {0}};
+static sharedInt_t numThreads = {0, {0}};
+
+typedef struct {
+  int threadnum;
+  int oncenum;
+  int myPrio;
+  HANDLE w32Thread;
+} bag_t;
+
+static bag_t threadbag[NUM_THREADS][NUM_ONCE];
+
+CRITICAL_SECTION print_lock;
+
+void
+mycleanupfunc(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+  EnterCriticalSection(&print_lock);
+  /*      once thrd  prio error */
+  printf("%4d %4d %4d %4d\n",
+	 bag->oncenum,
+	 bag->threadnum,
+	 bag->myPrio,
+	 bag->myPrio - GetThreadPriority(bag->w32Thread));
+  LeaveCriticalSection(&print_lock);
+}
+
+void
+myinitfunc(void)
+{
+  EnterCriticalSection(&numOnce.cs);
+  numOnce.i++;
+  LeaveCriticalSection(&numOnce.cs);
+  /* Simulate slow once routine so that following threads pile up behind it */
+  Sleep(10);
+  /* test for cancelation late so we're sure to have waiters. */
+  pthread_testcancel();
+}
+
+void *
+mythread(void * arg)
+{
+  bag_t * bag = (bag_t *) arg;
+  struct sched_param param;
+
+  /*
+   * Cancel every thread. These threads are deferred cancelable only, so
+   * only the thread performing the init_routine will see it (there are
+   * no other cancelation points here). The result will be that every thread
+   * eventually cancels only when it becomes the new initter.
+   */
+  pthread_t self = pthread_self();
+  bag->w32Thread = pthread_getw32threadhandle_np(self);
+  /*
+   * Set priority between -2 and 2 inclusive.
+   */
+  bag->myPrio = (bag->threadnum % 5) - 2;
+  param.sched_priority = bag->myPrio;
+  pthread_setschedparam(self, SCHED_OTHER, &param);
+
+  /* Trigger a cancellation at the next cancellation point in this thread */
+  pthread_cancel(self);
+#if 0
+  pthread_cleanup_push(mycleanupfunc, arg);
+  assert(pthread_once(&once[bag->oncenum], myinitfunc) == 0);
+  pthread_cleanup_pop(1);
+#else
+  assert(pthread_once(&once[bag->oncenum], myinitfunc) == 0);
+#endif
+  EnterCriticalSection(&numThreads.cs);
+  numThreads.i++;
+  LeaveCriticalSection(&numThreads.cs);
+  return 0;
+}
+
+int
+main()
+{
+  pthread_t t[NUM_THREADS][NUM_ONCE];
+  int i, j;
+  
+  InitializeCriticalSection(&print_lock);
+  InitializeCriticalSection(&numThreads.cs);
+  InitializeCriticalSection(&numOnce.cs);
+
+#if 0
+  /*       once thrd  prio change */
+  printf("once thrd  prio  error\n");
+#endif
+
+  /*
+   * Set the priority class to realtime - otherwise normal
+   * Windows random priority boosting will obscure any problems.
+   */
+  SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
+  /* Set main thread to lower prio than threads */
+  SetThreadPriority(GetCurrentThread(), -2);
+
+  for (j = 0; j < NUM_ONCE; j++)
+    {
+      once[j] = o;
+
+      for (i = 0; i < NUM_THREADS; i++)
+        {
+	  bag_t * bag = &threadbag[i][j];
+	  bag->threadnum = i;
+	  bag->oncenum = j;
+          assert(pthread_create(&t[i][j], NULL, mythread, (void *) bag) == 0);
+        }
+    }
+
+  for (j = 0; j < NUM_ONCE; j++)
+    for (i = 0; i < NUM_THREADS; i++)
+      if (pthread_join(t[i][j], NULL) != 0)
+        printf("Join failed for [thread,once] = [%d,%d]\n", i, j);
+
+  /*
+   * All threads will cancel, none will return normally from
+   * pthread_once and so numThreads should never be incremented. However,
+   * numOnce should be incremented by every thread (NUM_THREADS*NUM_ONCE).
+   */
+  assert(numOnce.i == NUM_ONCE * NUM_THREADS);
+  assert(numThreads.i == 0);
+
+  DeleteCriticalSection(&numOnce.cs);
+  DeleteCriticalSection(&numThreads.cs);
+  DeleteCriticalSection(&print_lock);
+
+  return 0;
+}
diff --git a/tests/priority1.c b/tests/priority1.c
new file mode 100644
index 0000000..c270e99
--- /dev/null
+++ b/tests/priority1.c
@@ -0,0 +1,172 @@
+/*
+ * File: priority1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test thread priority explicit setting using thread attribute.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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"
+
+enum {
+  PTW32TEST_THREAD_INIT_PRIO = 0,
+  PTW32TEST_MAXPRIORITIES = 512
+};
+
+int minPrio;
+int maxPrio;
+int validPriorities[PTW32TEST_MAXPRIORITIES];
+
+void *
+func(void * arg)
+{
+  int policy;
+  struct sched_param param;
+  pthread_t threadID = pthread_self();
+
+  assert(pthread_getschedparam(threadID, &policy, &param) == 0);
+  assert(policy == SCHED_OTHER);
+  return (void *) (param.sched_priority);
+}
+
+void *
+getValidPriorities(void * arg)
+{
+  int prioSet;
+  pthread_t threadID = pthread_self();
+  HANDLE threadH = pthread_getw32threadhandle_np(threadID);
+
+  printf("Using GetThreadPriority\n");
+  printf("%10s %10s\n", "Set value", "Get value");
+
+  for (prioSet = minPrio;
+       prioSet <= maxPrio;
+       prioSet++)
+    {
+	/*
+       * If prioSet is invalid then the threads priority is unchanged
+       * from the previous value. Make the previous value a known
+       * one so that we can check later.
+       */
+        if (prioSet < 0)
+	  SetThreadPriority(threadH, THREAD_PRIORITY_LOWEST);
+        else
+	  SetThreadPriority(threadH, THREAD_PRIORITY_HIGHEST);
+	SetThreadPriority(threadH, prioSet);
+	validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)] = GetThreadPriority(threadH);
+	printf("%10d %10d\n", prioSet, validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)]);
+    }
+
+  return (void *) 0;
+}
+
+
+int
+main()
+{
+  pthread_t t;
+  pthread_attr_t attr;
+  void * result = NULL;
+  struct sched_param param;
+
+  assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1);
+  assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1);
+
+  assert(pthread_create(&t, NULL, getValidPriorities, NULL) == 0);
+  assert(pthread_join(t, &result) == 0);
+
+  assert(pthread_attr_init(&attr) == 0);
+  assert(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0);
+
+  /* Set the thread's priority to a known initial value. */
+  SetThreadPriority(pthread_getw32threadhandle_np(pthread_self()),
+                    PTW32TEST_THREAD_INIT_PRIO);
+
+  printf("Using pthread_getschedparam\n");
+  printf("%10s %10s %10s\n", "Set value", "Get value", "Win priority");
+
+  for (param.sched_priority = minPrio;
+       param.sched_priority <= maxPrio;
+       param.sched_priority++)
+    {
+      int prio;
+
+      assert(pthread_attr_setschedparam(&attr, &param) == 0);
+      assert(pthread_create(&t, &attr, func, (void *) &attr) == 0);
+
+      assert((prio = GetThreadPriority(pthread_getw32threadhandle_np(t)))
+             == validPriorities[param.sched_priority+(PTW32TEST_MAXPRIORITIES/2)]);
+
+      assert(pthread_join(t, &result) == 0);
+
+      assert(param.sched_priority == (int) result);
+      printf("%10d %10d %10d\n", param.sched_priority, (int) result, prio);
+    }
+
+  return 0;
+}
diff --git a/tests/priority2.c b/tests/priority2.c
new file mode 100644
index 0000000..a5575ab
--- /dev/null
+++ b/tests/priority2.c
@@ -0,0 +1,169 @@
+/*
+ * File: priority2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test thread priority setting after creation.
+ *
+ * Test Method (Validation or Falsification):
+ * - 
+ *
+ * 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"
+
+enum {
+  PTW32TEST_THREAD_INIT_PRIO = 0,
+  PTW32TEST_MAXPRIORITIES = 512
+};
+
+int minPrio;
+int maxPrio;
+int validPriorities[PTW32TEST_MAXPRIORITIES];
+pthread_barrier_t startBarrier, endBarrier;
+
+void * func(void * arg)
+{
+  int policy;
+  int result;
+  struct sched_param param;
+
+  result = pthread_barrier_wait(&startBarrier);
+  assert(result == 0 || result == PTHREAD_BARRIER_SERIAL_THREAD);
+  assert(pthread_getschedparam(pthread_self(), &policy, &param) == 0);
+  assert(policy == SCHED_OTHER);
+  result = pthread_barrier_wait(&endBarrier);
+  assert(result == 0 || result == PTHREAD_BARRIER_SERIAL_THREAD);
+  return (void *) param.sched_priority;
+}
+
+
+void *
+getValidPriorities(void * arg)
+{
+  int prioSet;
+  pthread_t thread = pthread_self();
+  HANDLE threadH = pthread_getw32threadhandle_np(thread);
+  struct sched_param param;
+
+  for (prioSet = minPrio;
+       prioSet <= maxPrio;
+       prioSet++)
+    {
+	/*
+       * If prioSet is invalid then the threads priority is unchanged
+       * from the previous value. Make the previous value a known
+       * one so that we can check later.
+       */
+        param.sched_priority = prioSet;
+	assert(pthread_setschedparam(thread, SCHED_OTHER, &param) == 0);
+	validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)] = GetThreadPriority(threadH);
+    }
+
+  return (void *) 0;
+}
+
+
+int
+main()
+{
+  pthread_t t;
+  void * result = NULL;
+  int result2;
+  struct sched_param param;
+
+  assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1);
+  assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1);
+
+  assert(pthread_create(&t, NULL, getValidPriorities, NULL) == 0);
+  assert(pthread_join(t, &result) == 0);
+
+  assert(pthread_barrier_init(&startBarrier, NULL, 2) == 0);
+  assert(pthread_barrier_init(&endBarrier, NULL, 2) == 0);
+
+  /* Set the thread's priority to a known initial value.
+   * If the new priority is invalid then the threads priority
+   * is unchanged from the previous value.
+   */
+  SetThreadPriority(pthread_getw32threadhandle_np(pthread_self()),
+                    PTW32TEST_THREAD_INIT_PRIO);
+
+  for (param.sched_priority = minPrio;
+       param.sched_priority <= maxPrio;
+       param.sched_priority++)
+    {
+      assert(pthread_create(&t, NULL, func, NULL) == 0);
+      assert(pthread_setschedparam(t, SCHED_OTHER, &param) == 0);
+      result2 = pthread_barrier_wait(&startBarrier);
+      assert(result2 == 0 || result2 == PTHREAD_BARRIER_SERIAL_THREAD);
+      result2 = pthread_barrier_wait(&endBarrier);
+      assert(result2 == 0 || result2 == PTHREAD_BARRIER_SERIAL_THREAD);
+      assert(GetThreadPriority(pthread_getw32threadhandle_np(t)) ==
+	  validPriorities[param.sched_priority+(PTW32TEST_MAXPRIORITIES/2)]);
+      pthread_join(t, &result);
+      assert(param.sched_priority == (int)result);
+    }
+
+  return 0;
+}
diff --git a/tests/reuse1.c b/tests/reuse1.c
new file mode 100644
index 0000000..ae9efe4
--- /dev/null
+++ b/tests/reuse1.c
@@ -0,0 +1,124 @@
+/*
+ * File: reuse1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Confirm that thread reuse works for joined threads.
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * 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"
+
+enum {
+	NUMTHREADS = 100
+};
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  washere = 1;
+  return arg; 
+}
+ 
+int
+main()
+{
+  pthread_t t,
+            last_t;
+  pthread_attr_t attr;
+  void * result = NULL;
+  int i;
+
+  assert(pthread_attr_init(&attr) == 0);;
+  assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) == 0);
+
+  washere = 0;
+  assert(pthread_create(&t, &attr, func, NULL) == 0);
+  assert(pthread_join(t, &result) == 0);;
+  assert(result == 0);
+  assert(washere == 1);
+  last_t = t;
+
+  for (i = 1; i < NUMTHREADS; i++)
+    {
+      washere = 0;
+      assert(pthread_create(&t, &attr, func, (void *) i) == 0);
+      pthread_join(t, &result);
+      assert((int) result == i);
+      assert(washere == 1);
+      /* 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;
+    }
+
+  return 0;
+}
diff --git a/tests/reuse2.c b/tests/reuse2.c
new file mode 100644
index 0000000..c4db811
--- /dev/null
+++ b/tests/reuse2.c
@@ -0,0 +1,167 @@
+/*
+ * File: reuse2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test that thread reuse works for detached threads.
+ * - Analyse thread struct reuse.
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * Requirements Tested:
+ * -
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * -
+ *
+ * Environment:
+ * - This test is implementation specific
+ * because it uses knowledge of internals that should be
+ * opaque to an application.
+ *
+ * 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"
+
+/*
+ */
+
+enum {
+	NUMTHREADS = 10000
+};
+
+
+static long done = 0;
+
+void * func(void * arg)
+{
+  sched_yield();
+
+  InterlockedIncrement(&done);
+
+  return (void *) 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t[NUMTHREADS];
+  pthread_attr_t attr;
+  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);
+
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      assert(pthread_create(&t[i], &attr, func, NULL) == 0);
+    }
+
+  while (NUMTHREADS > InterlockedExchangeAdd((LPLONG)&done, 0L))
+    Sleep(100);
+
+  Sleep(100);
+
+  /*
+   * Analyse reuse by computing min and max number of times pthread_create()
+   * returned the same pthread_t value.
+   */
+  for (i = 0; i < NUMTHREADS; i++)
+    {
+      if (t[i].p != NULL)
+        {
+          unsigned int j, thisMax;
+
+          thisMax = t[i].x;
+
+          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;
+        }
+    }
+
+  for (i = 0; i < NUMTHREADS; i++)
+    if (t[i].p != NULL)
+      totalHandles++;
+
+  /*
+   * pthread_t reuse counts start at 0, so we need to add 1
+   * to the max and min values derived above.
+   */
+  printf("For %d total threads:\n", NUMTHREADS);
+  printf("Non-unique IDs = %d\n", notUnique);
+  printf("Reuse maximum  = %d\n", reuseMax + 1);
+  printf("Reuse minimum  = %d\n", reuseMin + 1);
+  printf("Total handles  = %d\n", totalHandles);
+
+  return 0;
+}
diff --git a/tests/rwlock1.c b/tests/rwlock1.c
new file mode 100644
index 0000000..3d08ac9
--- /dev/null
+++ b/tests/rwlock1.c
@@ -0,0 +1,61 @@
+/* 
+ * rwlock1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create a simple rwlock object and then destroy it.
+ *
+ * Depends on API functions:
+ * 	pthread_rwlock_init()
+ *	pthread_rwlock_destroy()
+ */
+
+#include "test.h"
+
+pthread_rwlock_t rwlock = NULL;
+
+int
+main()
+{
+  assert(rwlock == NULL);
+
+  assert(pthread_rwlock_init(&rwlock, NULL) == 0);
+
+  assert(rwlock != NULL);
+
+  assert(pthread_rwlock_destroy(&rwlock) == 0);
+
+  assert(rwlock == NULL);
+
+  return 0;
+}
diff --git a/tests/rwlock2.c b/tests/rwlock2.c
new file mode 100644
index 0000000..07518eb
--- /dev/null
+++ b/tests/rwlock2.c
@@ -0,0 +1,66 @@
+/* 
+ * rwlock2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, lock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_rdlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+int
+main()
+{
+  assert(rwlock == PTHREAD_RWLOCK_INITIALIZER);
+
+  assert(pthread_rwlock_rdlock(&rwlock) == 0);
+
+  assert(rwlock != PTHREAD_RWLOCK_INITIALIZER);
+
+  assert(rwlock != NULL);
+
+  assert(pthread_rwlock_unlock(&rwlock) == 0);
+
+  assert(pthread_rwlock_destroy(&rwlock) == 0);
+
+  assert(rwlock == NULL);
+
+  return 0;
+}
diff --git a/tests/rwlock2_t.c b/tests/rwlock2_t.c
new file mode 100644
index 0000000..8e6ab6d
--- /dev/null
+++ b/tests/rwlock2_t.c
@@ -0,0 +1,78 @@
+/* 
+ * rwlock2_t.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, timed-lock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions:
+ *	pthread_rwlock_timedrdlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+int
+main()
+{
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(rwlock == PTHREAD_RWLOCK_INITIALIZER);
+
+  assert(pthread_rwlock_timedrdlock(&rwlock, &abstime) == 0);
+
+  assert(rwlock != PTHREAD_RWLOCK_INITIALIZER);
+
+  assert(rwlock != NULL);
+
+  assert(pthread_rwlock_unlock(&rwlock) == 0);
+
+  assert(pthread_rwlock_destroy(&rwlock) == 0);
+
+  assert(rwlock == NULL);
+
+  return 0;
+}
diff --git a/tests/rwlock3.c b/tests/rwlock3.c
new file mode 100644
index 0000000..4b22c5a
--- /dev/null
+++ b/tests/rwlock3.c
@@ -0,0 +1,76 @@
+/* 
+ * rwlock3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, wrlock it, trywrlock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_wrlock()
+ *	pthread_rwlock_trywrlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_rwlock_wrlock(&rwlock1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/rwlock3_t.c b/tests/rwlock3_t.c
new file mode 100644
index 0000000..bc45abc
--- /dev/null
+++ b/tests/rwlock3_t.c
@@ -0,0 +1,87 @@
+/* 
+ * rwlock3_t.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, timed-wrlock it, trywrlock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_timedwrlock()
+ *	pthread_rwlock_trywrlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_rwlock_timedwrlock(&rwlock1, &abstime) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/rwlock4.c b/tests/rwlock4.c
new file mode 100644
index 0000000..edd9dc2
--- /dev/null
+++ b/tests/rwlock4.c
@@ -0,0 +1,76 @@
+/* 
+ * rwlock4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, rdlock it, trywrlock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_rdlock()
+ *	pthread_rwlock_trywrlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_rwlock_rdlock(&rwlock1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/rwlock4_t.c b/tests/rwlock4_t.c
new file mode 100644
index 0000000..37ec34f
--- /dev/null
+++ b/tests/rwlock4_t.c
@@ -0,0 +1,87 @@
+/* 
+ * rwlock4_t.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, timed-rdlock it, trywrlock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_timedrdlock()
+ *	pthread_rwlock_trywrlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/rwlock5.c b/tests/rwlock5.c
new file mode 100644
index 0000000..75b82f3
--- /dev/null
+++ b/tests/rwlock5.c
@@ -0,0 +1,78 @@
+/* 
+ * rwlock5.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, rdlock it, tryrdlock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_rdlock()
+ *	pthread_rwlock_tryrdlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+ 
+pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_rwlock_tryrdlock(&rwlock1) == 0);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_rwlock_rdlock(&rwlock1) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/rwlock5_t.c b/tests/rwlock5_t.c
new file mode 100644
index 0000000..bf473a4
--- /dev/null
+++ b/tests/rwlock5_t.c
@@ -0,0 +1,89 @@
+/* 
+ * rwlock5_t.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static rwlock object, timed-rdlock it, tryrdlock it, 
+ * and then unlock it again.
+ *
+ * Depends on API functions: 
+ *	pthread_rwlock_timedrdlock()
+ *	pthread_rwlock_tryrdlock()
+ *	pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_rwlock_tryrdlock(&rwlock1) == 0);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  Sleep(2000);
+
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/rwlock6.c b/tests/rwlock6.c
new file mode 100644
index 0000000..22d10db
--- /dev/null
+++ b/tests/rwlock6.c
@@ -0,0 +1,101 @@
+/*
+ * rwlock6.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Check writer and reader locking
+ *
+ * Depends on API functions:
+ *      pthread_rwlock_rdlock()
+ *      pthread_rwlock_wrlock()
+ *      pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+
+static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int bankAccount = 0;
+
+void * wrfunc(void * arg)
+{
+  int ba;
+
+  assert(pthread_rwlock_wrlock(&rwlock1) == 0);
+  Sleep(2000);
+  bankAccount += 10;
+  ba = bankAccount;
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  return ((void *) ba);
+}
+
+void * rdfunc(void * arg)
+{
+  int ba;
+
+  assert(pthread_rwlock_rdlock(&rwlock1) == 0);
+  ba = bankAccount;
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  return ((void *) ba);
+}
+
+int
+main()
+{
+  pthread_t wrt1;
+  pthread_t wrt2;
+  pthread_t rdt;
+  int wr1Result = 0;
+  int wr2Result = 0;
+  int rdResult = 0;
+
+  bankAccount = 0;
+
+  assert(pthread_create(&wrt1, NULL, wrfunc, NULL) == 0);
+  Sleep(500);
+  assert(pthread_create(&rdt, NULL, rdfunc, NULL) == 0);
+  Sleep(500);
+  assert(pthread_create(&wrt2, NULL, wrfunc, NULL) == 0);
+
+  assert(pthread_join(wrt1, (void **) &wr1Result) == 0);
+  assert(pthread_join(rdt, (void **) &rdResult) == 0);
+  assert(pthread_join(wrt2, (void **) &wr2Result) == 0);
+
+  assert(wr1Result == 10);
+  assert(rdResult == 10);
+  assert(wr2Result == 20);
+
+  return 0;
+}
diff --git a/tests/rwlock6_t.c b/tests/rwlock6_t.c
new file mode 100644
index 0000000..aa38bf5
--- /dev/null
+++ b/tests/rwlock6_t.c
@@ -0,0 +1,126 @@
+/*
+ * rwlock6_t.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Check writer and reader locking with reader timeouts
+ *
+ * Depends on API functions: 
+ *      pthread_rwlock_timedrdlock()
+ *      pthread_rwlock_wrlock()
+ *      pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int bankAccount = 0;
+
+void * wrfunc(void * arg)
+{
+  assert(pthread_rwlock_wrlock(&rwlock1) == 0);
+  Sleep(2000);
+  bankAccount += 10;
+  assert(pthread_rwlock_unlock(&rwlock1) == 0);
+
+  return ((void *) bankAccount);
+}
+
+void * rdfunc(void * arg)
+{
+  int ba = -1;
+  struct timespec abstime = { 0, 0 };
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+
+  if ((int) arg == 1)
+    {
+      abstime.tv_sec += 1;
+      assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == ETIMEDOUT);
+      ba = 0;
+    }
+  else if ((int) arg == 2)
+    {
+      abstime.tv_sec += 3;
+      assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == 0);
+      ba = bankAccount;
+      assert(pthread_rwlock_unlock(&rwlock1) == 0);
+    }
+
+  return ((void *) ba);
+}
+
+int
+main()
+{
+  pthread_t wrt1;
+  pthread_t wrt2;
+  pthread_t rdt1;
+  pthread_t rdt2;
+  int wr1Result = 0;
+  int wr2Result = 0;
+  int rd1Result = 0;
+  int rd2Result = 0;
+
+  bankAccount = 0;
+
+  assert(pthread_create(&wrt1, NULL, wrfunc, NULL) == 0);
+  Sleep(500);
+  assert(pthread_create(&rdt1, NULL, rdfunc, (void *) 1) == 0);
+  Sleep(500);
+  assert(pthread_create(&wrt2, NULL, wrfunc, NULL) == 0);
+  Sleep(500);
+  assert(pthread_create(&rdt2, NULL, rdfunc, (void *) 2) == 0);
+
+  assert(pthread_join(wrt1, (void **) &wr1Result) == 0);
+  assert(pthread_join(rdt1, (void **) &rd1Result) == 0);
+  assert(pthread_join(wrt2, (void **) &wr2Result) == 0);
+  assert(pthread_join(rdt2, (void **) &rd2Result) == 0);
+
+  assert(wr1Result == 10);
+  assert(rd1Result == 0);
+  assert(wr2Result == 20);
+  assert(rd2Result == 20);
+
+  return 0;
+}
+
+
diff --git a/tests/rwlock6_t2.c b/tests/rwlock6_t2.c
new file mode 100644
index 0000000..58bfc3d
--- /dev/null
+++ b/tests/rwlock6_t2.c
@@ -0,0 +1,119 @@
+/*
+ * rwlock6_t2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Check writer and reader timeouts.
+ *
+ * Depends on API functions: 
+ *      pthread_rwlock_timedrdlock()
+ *      pthread_rwlock_timedwrlock()
+ *      pthread_rwlock_unlock()
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
+
+static int bankAccount = 0;
+struct timespec abstime = { 0, 0 };
+
+void * wrfunc(void * arg)
+{
+  int result;
+
+  result = pthread_rwlock_timedwrlock(&rwlock1, &abstime);
+  if ((int) arg == 1)
+    {
+      assert(result == 0);
+      Sleep(2000);
+      bankAccount += 10;
+      assert(pthread_rwlock_unlock(&rwlock1) == 0);
+      return ((void *) bankAccount);
+    }
+  else if ((int) arg == 2)
+    {
+      assert(result == ETIMEDOUT);
+      return ((void *) 100);
+    }
+
+  return ((void *) -1);
+}
+
+void * rdfunc(void * arg)
+{
+  int ba = 0;
+
+  assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == ETIMEDOUT);
+
+  return ((void *) ba);
+}
+
+int
+main()
+{
+  pthread_t wrt1;
+  pthread_t wrt2;
+  pthread_t rdt;
+  int wr1Result = 0;
+  int wr2Result = 0;
+  int rdResult = 0;
+  struct _timeb currSysTime;
+  const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+  _ftime(&currSysTime);
+
+  abstime.tv_sec = currSysTime.time;
+  abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+  abstime.tv_sec += 1;
+
+  bankAccount = 0;
+
+  assert(pthread_create(&wrt1, NULL, wrfunc, (void *) 1) == 0);
+  Sleep(100);
+  assert(pthread_create(&rdt, NULL, rdfunc, NULL) == 0);
+  Sleep(100);
+  assert(pthread_create(&wrt2, NULL, wrfunc, (void *) 2) == 0);
+
+  assert(pthread_join(wrt1, (void **) &wr1Result) == 0);
+  assert(pthread_join(rdt, (void **) &rdResult) == 0);
+  assert(pthread_join(wrt2, (void **) &wr2Result) == 0);
+
+  assert(wr1Result == 10);
+  assert(rdResult == 0);
+  assert(wr2Result == 100);
+
+  return 0;
+}
diff --git a/tests/rwlock7.c b/tests/rwlock7.c
new file mode 100644
index 0000000..91466e4
--- /dev/null
+++ b/tests/rwlock7.c
@@ -0,0 +1,199 @@
+/*
+ * rwlock7.c
+ *
+ * Hammer on a bunch of rwlocks to test robustness and fairness.
+ * Printed stats should be roughly even for each thread.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#define THREADS         5
+#define DATASIZE        7
+#define ITERATIONS      1000000
+
+/*
+ * Keep statistics for each thread.
+ */
+typedef struct thread_tag {
+  int         thread_num;
+  pthread_t   thread_id;
+  int         updates;
+  int         reads;
+  int         changed;
+  int         seed;
+} thread_t;
+
+/*
+ * Read-write lock and shared data
+ */
+typedef struct data_tag {
+  pthread_rwlock_t    lock;
+  int                 data;
+  int                 updates;
+} data_t;
+
+static thread_t threads[THREADS];
+static data_t data[DATASIZE];
+
+/*
+ * Thread start routine that uses read-write locks
+ */
+void *thread_routine (void *arg)
+{
+  thread_t *self = (thread_t*)arg;
+  int iteration;
+  int element = 0;
+  int seed = self->seed;
+  int interval = 1 + rand_r (&seed) % 71;
+
+  self->changed = 0;
+
+  for (iteration = 0; iteration < ITERATIONS; iteration++)
+    {
+      if (iteration % (ITERATIONS / 10) == 0)
+        {
+          putchar('.');
+          fflush(stdout);
+        }
+      /*
+       * Each "self->interval" iterations, perform an
+       * update operation (write lock instead of read
+       * lock).
+       */
+      if ((iteration % interval) == 0)
+        {
+          assert(pthread_rwlock_wrlock (&data[element].lock) == 0);
+          data[element].data = self->thread_num;
+          data[element].updates++;
+          self->updates++;
+	  interval = 1 + rand_r (&seed) % 71;
+          assert(pthread_rwlock_unlock (&data[element].lock) == 0);
+        } else {
+          /*
+           * Look at the current data element to see whether
+           * the current thread last updated it. Count the
+           * times, to report later.
+           */
+          assert(pthread_rwlock_rdlock (&data[element].lock) == 0);
+
+          self->reads++;
+
+          if (data[element].data != self->thread_num)
+            {
+              self->changed++;
+	      interval = 1 + self->changed % 71;
+            }
+
+          assert(pthread_rwlock_unlock (&data[element].lock) == 0);
+        }
+
+      element = (element + 1) % DATASIZE;
+
+    }
+
+  return NULL;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int count;
+  int data_count;
+  int thread_updates = 0;
+  int data_updates = 0;
+  int seed = 1;
+
+  struct _timeb currSysTime1;
+  struct _timeb currSysTime2;
+
+  /*
+   * Initialize the shared data.
+   */
+  for (data_count = 0; data_count < DATASIZE; data_count++)
+    {
+      data[data_count].data = 0;
+      data[data_count].updates = 0;
+
+      assert(pthread_rwlock_init (&data[data_count].lock, NULL) == 0);
+    }
+
+  _ftime(&currSysTime1);
+
+  /*
+   * Create THREADS threads to access shared data.
+   */
+  for (count = 0; count < THREADS; count++)
+    {
+      threads[count].thread_num = count;
+      threads[count].updates = 0;
+      threads[count].reads = 0;
+      threads[count].seed = 1 + rand_r (&seed) % 71;
+
+      assert(pthread_create (&threads[count].thread_id,
+                             NULL, thread_routine, (void*)&threads[count]) == 0);
+    }
+
+  /*
+   * Wait for all threads to complete, and collect
+   * statistics.
+   */
+  for (count = 0; count < THREADS; count++)
+    {
+      assert(pthread_join (threads[count].thread_id, NULL) == 0);
+    }
+
+  putchar('\n');
+  fflush(stdout);
+
+  for (count = 0; count < THREADS; count++)
+    {
+      if (threads[count].changed > 0)
+        {
+          printf ("Thread %d found changed elements %d times\n",
+                  count, threads[count].changed);
+        }
+    }
+
+  putchar('\n');
+  fflush(stdout);
+
+  for (count = 0; count < THREADS; count++)
+    {
+      thread_updates += threads[count].updates;
+      printf ("%02d: seed %d, updates %d, reads %d\n",
+              count, threads[count].seed,
+              threads[count].updates, threads[count].reads);
+    }
+
+  putchar('\n');
+  fflush(stdout);
+
+  /*
+   * Collect statistics for the data.
+   */
+  for (data_count = 0; data_count < DATASIZE; data_count++)
+    {
+      data_updates += data[data_count].updates;
+      printf ("data %02d: value %d, %d updates\n",
+              data_count, data[data_count].data, data[data_count].updates);
+      assert(pthread_rwlock_destroy (&data[data_count].lock) == 0);
+    }
+
+  printf ("%d thread updates, %d data updates\n",
+          thread_updates, data_updates);
+
+  _ftime(&currSysTime2);
+
+  printf( "\nstart: %ld/%d, stop: %ld/%d, duration:%ld\n",
+          currSysTime1.time,currSysTime1.millitm,
+          currSysTime2.time,currSysTime2.millitm,
+          (currSysTime2.time*1000+currSysTime2.millitm) -
+          (currSysTime1.time*1000+currSysTime1.millitm));
+
+  return 0;
+}
diff --git a/tests/rwlock8.c b/tests/rwlock8.c
new file mode 100644
index 0000000..c83a775
--- /dev/null
+++ b/tests/rwlock8.c
@@ -0,0 +1,205 @@
+/*
+ * rwlock8.c
+ *
+ * Hammer on a bunch of rwlocks to test robustness and fairness.
+ * Printed stats should be roughly even for each thread.
+ *
+ * Yield during each access to exercise lock contention code paths
+ * more than rwlock7.c does (particularly on uni-processor systems).
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+#ifdef __GNUC__
+#include <stdlib.h>
+#endif
+
+#define THREADS         5
+#define DATASIZE        7
+#define ITERATIONS      100000
+
+/*
+ * Keep statistics for each thread.
+ */
+typedef struct thread_tag {
+  int         thread_num;
+  pthread_t   thread_id;
+  int         updates;
+  int         reads;
+  int         changed;
+  int         seed;
+} thread_t;
+
+/*
+ * Read-write lock and shared data
+ */
+typedef struct data_tag {
+  pthread_rwlock_t    lock;
+  int                 data;
+  int                 updates;
+} data_t;
+
+static thread_t threads[THREADS];
+static data_t data[DATASIZE];
+
+/*
+ * Thread start routine that uses read-write locks
+ */
+void *thread_routine (void *arg)
+{
+  thread_t *self = (thread_t*)arg;
+  int iteration;
+  int element = 0;
+  int seed = self->seed;
+  int interval = 1 + rand_r (&seed) % 71;
+
+  self->changed = 0;
+
+  for (iteration = 0; iteration < ITERATIONS; iteration++)
+    {
+      if (iteration % (ITERATIONS / 10) == 0)
+        {
+          putchar('.');
+          fflush(stdout);
+        }
+      /*
+       * Each "self->interval" iterations, perform an
+       * update operation (write lock instead of read
+       * lock).
+       */
+      if ((iteration % interval) == 0)
+        {
+          assert(pthread_rwlock_wrlock (&data[element].lock) == 0);
+          data[element].data = self->thread_num;
+          data[element].updates++;
+          self->updates++;
+	  interval = 1 + rand_r (&seed) % 71;
+	  sched_yield();
+          assert(pthread_rwlock_unlock (&data[element].lock) == 0);
+        } else {
+          /*
+           * Look at the current data element to see whether
+           * the current thread last updated it. Count the
+           * times, to report later.
+           */
+          assert(pthread_rwlock_rdlock (&data[element].lock) == 0);
+
+          self->reads++;
+
+          if (data[element].data != self->thread_num)
+            {
+              self->changed++;
+	      interval = 1 + self->changed % 71;
+            }
+
+	  sched_yield();
+
+          assert(pthread_rwlock_unlock (&data[element].lock) == 0);
+        }
+
+      element = (element + 1) % DATASIZE;
+
+    }
+
+  return NULL;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int count;
+  int data_count;
+  int thread_updates = 0;
+  int data_updates = 0;
+  int seed = 1;
+
+  struct _timeb currSysTime1;
+  struct _timeb currSysTime2;
+
+  /*
+   * Initialize the shared data.
+   */
+  for (data_count = 0; data_count < DATASIZE; data_count++)
+    {
+      data[data_count].data = 0;
+      data[data_count].updates = 0;
+
+      assert(pthread_rwlock_init (&data[data_count].lock, NULL) == 0);
+    }
+
+  _ftime(&currSysTime1);
+
+  /*
+   * Create THREADS threads to access shared data.
+   */
+  for (count = 0; count < THREADS; count++)
+    {
+      threads[count].thread_num = count;
+      threads[count].updates = 0;
+      threads[count].reads = 0;
+      threads[count].seed = 1 + rand_r (&seed) % 71;
+
+      assert(pthread_create (&threads[count].thread_id,
+                             NULL, thread_routine, (void*)&threads[count]) == 0);
+    }
+
+  /*
+   * Wait for all threads to complete, and collect
+   * statistics.
+   */
+  for (count = 0; count < THREADS; count++)
+    {
+      assert(pthread_join (threads[count].thread_id, NULL) == 0);
+    }
+
+  putchar('\n');
+  fflush(stdout);
+
+  for (count = 0; count < THREADS; count++)
+    {
+      if (threads[count].changed > 0)
+        {
+          printf ("Thread %d found changed elements %d times\n",
+                  count, threads[count].changed);
+        }
+    }
+
+  putchar('\n');
+  fflush(stdout);
+
+  for (count = 0; count < THREADS; count++)
+    {
+      thread_updates += threads[count].updates;
+      printf ("%02d: seed %d, updates %d, reads %d\n",
+              count, threads[count].seed,
+              threads[count].updates, threads[count].reads);
+    }
+
+  putchar('\n');
+  fflush(stdout);
+
+  /*
+   * Collect statistics for the data.
+   */
+  for (data_count = 0; data_count < DATASIZE; data_count++)
+    {
+      data_updates += data[data_count].updates;
+      printf ("data %02d: value %d, %d updates\n",
+              data_count, data[data_count].data, data[data_count].updates);
+      assert(pthread_rwlock_destroy (&data[data_count].lock) == 0);
+    }
+
+  printf ("%d thread updates, %d data updates\n",
+          thread_updates, data_updates);
+
+  _ftime(&currSysTime2);
+
+  printf( "\nstart: %ld/%d, stop: %ld/%d, duration:%ld\n",
+          currSysTime1.time,currSysTime1.millitm,
+          currSysTime2.time,currSysTime2.millitm,
+          (currSysTime2.time*1000+currSysTime2.millitm) -
+          (currSysTime1.time*1000+currSysTime1.millitm));
+
+  return 0;
+}
diff --git a/tests/self1.c b/tests/self1.c
new file mode 100644
index 0000000..59498d9
--- /dev/null
+++ b/tests/self1.c
@@ -0,0 +1,69 @@
+/*
+ * self1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 for pthread_self().
+ *
+ * Depends on API functions:
+ *	pthread_self()
+ *
+ * Implicitly depends on:
+ *	pthread_getspecific()
+ *	pthread_setspecific()
+ */
+
+#include "test.h"
+
+int
+main(int argc, char * argv[])
+{
+	/*
+	 * This should always succeed unless the system has no
+	 * resources (memory) left.
+	 */
+	pthread_t self;
+
+#ifdef PTW32_STATIC_LIB
+	pthread_win32_process_attach_np();
+#endif
+
+	self = pthread_self();
+
+	assert(self.p != NULL);
+
+#ifdef PTW32_STATIC_LIB
+	pthread_win32_process_detach_np();
+#endif
+	return 0;
+}
diff --git a/tests/self2.c b/tests/self2.c
new file mode 100644
index 0000000..28e5725
--- /dev/null
+++ b/tests/self2.c
@@ -0,0 +1,73 @@
+/*
+ * self2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 for pthread_self().
+ *
+ * Depends on API functions:
+ *	pthread_create()
+ *	pthread_self()
+ *
+ * Implicitly depends on:
+ *	pthread_getspecific()
+ *	pthread_setspecific()
+ */
+
+#include "test.h"
+#include <string.h>
+
+static pthread_t me;
+
+void *
+entry(void * arg)
+{
+  me = pthread_self();
+
+  return arg;
+}
+
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_create(&t, NULL, entry, NULL) == 0);
+
+  Sleep(100);
+
+  assert(pthread_equal(t, me) != 0);
+
+  /* Success. */
+  return 0;
+}
diff --git a/tests/semaphore1.c b/tests/semaphore1.c
new file mode 100644
index 0000000..f89a430
--- /dev/null
+++ b/tests/semaphore1.c
@@ -0,0 +1,161 @@
+/*
+ * File: semaphore1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 trywait() returns -1 and sets EAGAIN.
+ * - 
+ *
+ * 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"
+
+void *
+thr(void * arg)
+{
+  sem_t s;
+  int result;
+
+  assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0);
+
+  assert((result = sem_trywait(&s)) == -1);
+
+  if ( result == -1 )
+  {
+    int err = errno;
+    printf("thread: sem_trywait 1: expecting error %s: got %s\n",
+	   error_string[EAGAIN], error_string[err]); fflush(stdout);
+    assert(err == EAGAIN);
+  }
+  else
+  {
+    printf("thread: ok 1\n");
+  }
+
+  assert((result = sem_post(&s)) == 0);
+
+  assert((result = sem_trywait(&s)) == 0);
+
+  if ( result == -1 )
+  {
+    perror("thread: sem_trywait 2");
+  }
+  else
+  {
+    printf("thread: ok 2\n");
+  }
+
+  assert(sem_post(&s) == 0);
+
+  return 0;
+}
+
+
+int
+main()
+{
+  pthread_t t;
+  sem_t s;
+  int result;
+
+  assert(pthread_create(&t, NULL, thr, NULL) == 0);
+  assert(pthread_join(t, (void **)&result) == 0);
+  assert(result == 0);
+
+  assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0);
+
+  assert((result = sem_trywait(&s)) == -1);
+
+  if ( result == -1 )
+  {
+    int err = errno;
+    printf("main: sem_trywait 1: expecting error %s: got %s\n",
+	   error_string[EAGAIN], error_string[err]); fflush(stdout);
+    assert(err == EAGAIN);
+  }
+  else
+  {
+    printf("main: ok 1\n");
+  }
+
+  assert((result = sem_post(&s)) == 0);
+
+  assert((result = sem_trywait(&s)) == 0);
+
+  if ( result == -1 )
+  {
+    perror("main: sem_trywait 2");
+  }
+  else
+  {
+    printf("main: ok 2\n");
+  }
+
+  assert(sem_post(&s) == 0);
+
+  return 0;
+}
+
diff --git a/tests/semaphore2.c b/tests/semaphore2.c
new file mode 100644
index 0000000..af4d0ea
--- /dev/null
+++ b/tests/semaphore2.c
@@ -0,0 +1,108 @@
+/*
+ * File: semaphore2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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 value.
+ * - 
+ *
+ * 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
+
+int
+main()
+{
+  sem_t s;
+	int value = 0;
+	int i;
+
+  assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, MAX_COUNT) == 0);
+	assert(sem_getvalue(&s, &value) == 0);
+	assert(value == MAX_COUNT);
+//	  printf("Value = %ld\n", value);
+
+	for (i = MAX_COUNT - 1; i >= 0; i--)
+		{
+			assert(sem_wait(&s) == 0);
+			assert(sem_getvalue(&s, &value) == 0);
+//			  printf("Value = %ld\n", value);
+			assert(value == i);
+		}
+
+	for (i = 1; i <= MAX_COUNT; i++)
+		{
+			assert(sem_post(&s) == 0);
+			assert(sem_getvalue(&s, &value) == 0);
+//			  printf("Value = %ld\n", value);
+			assert(value == i);
+		}
+
+  return 0;
+}
+
diff --git a/tests/semaphore3.c b/tests/semaphore3.c
new file mode 100644
index 0000000..a0dfcb6
--- /dev/null
+++ b/tests/semaphore3.c
@@ -0,0 +1,121 @@
+/*
+ * File: semaphore3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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.
+ * - 
+ *
+ * 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);
+  assert(pthread_detach(pthread_self()) == 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);
+		}
+
+	for (i = MAX_COUNT - 1; i >= 0; i--)
+		{
+			assert(sem_post(&s) == 0);
+			assert(sem_getvalue(&s, &value) == 0);
+//			printf("Value = %d\n", value);	fflush(stdout);
+			assert(-value == i);
+		}
+
+  return 0;
+}
+
diff --git a/tests/semaphore4.c b/tests/semaphore4.c
new file mode 100644
index 0000000..37613ac
--- /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,2005 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..14a4669
--- /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,2005 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
new file mode 100644
index 0000000..73c7261
--- /dev/null
+++ b/tests/sizes.c
@@ -0,0 +1,32 @@
+#define _WIN32_WINNT 0x400
+
+#include "test.h"
+#include "../implement.h"
+
+int
+main()
+{
+  printf("Sizes of pthreads-win32 structs\n");
+  printf("-------------------------------\n");
+  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_));
+  printf("%30s %4d\n", "pthread_mutexattr_t_", sizeof(struct pthread_mutexattr_t_));
+  printf("%30s %4d\n", "pthread_spinlock_t_", sizeof(struct pthread_spinlock_t_));
+  printf("%30s %4d\n", "pthread_barrier_t_", sizeof(struct pthread_barrier_t_));
+  printf("%30s %4d\n", "pthread_barrierattr_t_", sizeof(struct pthread_barrierattr_t_));
+  printf("%30s %4d\n", "pthread_key_t_", sizeof(struct pthread_key_t_));
+  printf("%30s %4d\n", "pthread_cond_t_", sizeof(struct pthread_cond_t_));
+  printf("%30s %4d\n", "pthread_condattr_t_", sizeof(struct pthread_condattr_t_));
+  printf("%30s %4d\n", "pthread_rwlock_t_", sizeof(struct pthread_rwlock_t_));
+  printf("%30s %4d\n", "pthread_rwlockattr_t_", sizeof(struct pthread_rwlockattr_t_));
+  printf("%30s %4d\n", "pthread_once_t_", sizeof(struct pthread_once_t_));
+  printf("%30s %4d\n", "ptw32_cleanup_t", sizeof(struct ptw32_cleanup_t));
+  printf("%30s %4d\n", "ptw32_mcs_node_t_", sizeof(struct ptw32_mcs_node_t_));
+  printf("%30s %4d\n", "sched_param", sizeof(struct sched_param));
+  printf("-------------------------------\n");
+
+  return 0;
+}
diff --git a/tests/spin1.c b/tests/spin1.c
new file mode 100644
index 0000000..00ecd11
--- /dev/null
+++ b/tests/spin1.c
@@ -0,0 +1,59 @@
+/* 
+ * spin1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Create a simple spinlock object, lock it, and then unlock it again.
+ * This is the simplest test of the pthread mutex family that we can do.
+ *
+ */
+
+#include "test.h"
+
+pthread_spinlock_t lock;
+
+int
+main()
+{
+  assert(pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE) == 0);
+
+  assert(pthread_spin_lock(&lock) == 0);
+
+  assert(pthread_spin_unlock(&lock) == 0);
+
+  assert(pthread_spin_destroy(&lock) == 0);
+
+  assert(pthread_spin_lock(&lock) == EINVAL);
+
+  return 0;
+}
diff --git a/tests/spin2.c b/tests/spin2.c
new file mode 100644
index 0000000..b13c29c
--- /dev/null
+++ b/tests/spin2.c
@@ -0,0 +1,75 @@
+/* 
+ * spin2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a spinlock object, lock it, trylock it, 
+ * and then unlock it again.
+ *
+ */
+
+#include "test.h"
+ 
+pthread_spinlock_t lock = NULL;
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  assert(pthread_spin_trylock(&lock) == EBUSY);
+
+  washere = 1;
+
+  return 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  assert(pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE) == 0);
+
+  assert(pthread_spin_lock(&lock) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+  assert(pthread_join(t, NULL) == 0);
+
+  assert(pthread_spin_unlock(&lock) == 0);
+
+  assert(pthread_spin_destroy(&lock) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/spin3.c b/tests/spin3.c
new file mode 100644
index 0000000..8c0dae6
--- /dev/null
+++ b/tests/spin3.c
@@ -0,0 +1,72 @@
+/* 
+ * spin3.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Thread A locks spin - thread B tries to unlock.
+ * This should succeed, but it's undefined behaviour.
+ *
+ */
+
+#include "test.h"
+
+static int wasHere = 0;
+
+static pthread_spinlock_t spin;
+ 
+void * unlocker(void * arg)
+{
+  int expectedResult = (int) arg;
+
+  wasHere++;
+  assert(pthread_spin_unlock(&spin) == expectedResult);
+  wasHere++;
+  return NULL;
+}
+ 
+int
+main()
+{
+  pthread_t t;
+
+  wasHere = 0;
+  assert(pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE) == 0);
+  assert(pthread_spin_lock(&spin) == 0);
+  assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0);
+  assert(pthread_join(t, NULL) == 0);
+  assert(pthread_spin_unlock(&spin) == EPERM);
+  assert(pthread_spin_destroy(&spin) == 0);
+  assert(wasHere == 2);
+
+  return 0;
+}
diff --git a/tests/spin4.c b/tests/spin4.c
new file mode 100644
index 0000000..8386d09
--- /dev/null
+++ b/tests/spin4.c
@@ -0,0 +1,103 @@
+/* 
+ * spin4.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Declare a static spinlock object, lock it, spin on it, 
+ * and then unlock it again.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+ 
+pthread_spinlock_t lock = PTHREAD_SPINLOCK_INITIALIZER;
+struct _timeb currSysTimeStart;
+struct _timeb currSysTimeStop;
+
+#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \
+					       - (_TStart.time*1000+_TStart.millitm))
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  _ftime(&currSysTimeStart);
+  washere = 1;
+  assert(pthread_spin_lock(&lock) == 0);
+  assert(pthread_spin_unlock(&lock) == 0);
+  _ftime(&currSysTimeStop);
+
+  return (void *) GetDurationMilliSecs(currSysTimeStart, currSysTimeStop);
+}
+ 
+int
+main()
+{
+  long result = 0;
+  pthread_t t;
+  int CPUs;
+  struct _timeb sysTime;
+
+  if ((CPUs = pthread_num_processors_np()) == 1)
+    {
+      printf("Test not run - it requires multiple CPUs.\n");
+	exit(0);
+    }
+
+  assert(pthread_spin_lock(&lock) == 0);
+
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+
+  while (washere == 0)
+    {
+      sched_yield();
+    }
+
+  do
+    {
+      sched_yield();
+      _ftime(&sysTime);
+    }
+  while (GetDurationMilliSecs(currSysTimeStart, sysTime) <= 1000);
+
+  assert(pthread_spin_unlock(&lock) == 0);
+
+  assert(pthread_join(t, (void **) &result) == 0);
+  assert(result > 1000);
+
+  assert(pthread_spin_destroy(&lock) == 0);
+
+  assert(washere == 1);
+
+  return 0;
+}
diff --git a/tests/stress1.c b/tests/stress1.c
new file mode 100644
index 0000000..34dca56
--- /dev/null
+++ b/tests/stress1.c
@@ -0,0 +1,279 @@
+/*
+ * stress1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Stress test condition variables, mutexes, semaphores.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * - Correct accounting of semaphore and condition variable waiters.
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Description:
+ * Attempting to expose race conditions in cond vars, semaphores etc.
+ * - Master attempts to signal slave close to when timeout is due.
+ * - Master and slave do battle continuously until main tells them to stop.
+ * - Afterwards, the CV must be successfully destroyed (will return an
+ * error if there are waiters (including any internal semaphore waiters,
+ * which, if there are, cannot not be real waiters).
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * - 
+ *
+ * Pass Criteria:
+ * - CV is successfully destroyed.
+ *
+ * Fail Criteria:
+ * - CV destroy fails.
+ */
+
+#include "test.h"
+#include <string.h>
+#include <sys/timeb.h>
+
+
+const unsigned int ITERATIONS = 1000;
+
+static pthread_t master, slave;
+typedef struct {
+  int value;
+  pthread_cond_t cv;
+  pthread_mutex_t mx;
+} mysig_t;
+
+static int allExit;
+static mysig_t control = {0, PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
+static pthread_barrier_t startBarrier, readyBarrier, holdBarrier;
+static int timeoutCount = 0;
+static int signalsTakenCount = 0;
+static int signalsSent = 0;
+static int bias = 0;
+static int timeout = 10;
+ // Must be > 0
+
+enum {
+  CTL_STOP     = -1
+};
+
+/*
+ * Returns abstime 'milliseconds' from 'now'.
+ *
+ * Works for: -INT_MAX <= millisecs <= INT_MAX
+ */
+struct timespec *
+millisecondsFromNow (struct timespec * time, int millisecs)
+{
+  struct _timeb currSysTime;
+  int64_t nanosecs, secs;
+  const int64_t NANOSEC_PER_MILLISEC = 1000000;
+  const int64_t NANOSEC_PER_SEC = 1000000000;
+
+  /* get current system time and add millisecs */
+  _ftime(&currSysTime);
+
+  secs = (int64_t)(currSysTime.time) + (millisecs / 1000);
+  nanosecs = ((int64_t) (millisecs%1000 + currSysTime.millitm)) * NANOSEC_PER_MILLISEC;
+  if (nanosecs >= NANOSEC_PER_SEC)
+    {
+      secs++;
+      nanosecs -= NANOSEC_PER_SEC;
+    }
+  else if (nanosecs < 0)
+    {
+      secs--;
+      nanosecs += NANOSEC_PER_SEC;
+    }
+
+  time->tv_nsec = (long)nanosecs;
+  time->tv_sec = (long)secs;
+
+  return time;
+}
+
+void *
+masterThread (void * arg)
+{
+  int dither = (int) arg;
+
+  timeout = (int) arg;
+
+  pthread_barrier_wait(&startBarrier);
+
+  do
+    {
+      int sleepTime;
+
+      assert(pthread_mutex_lock(&control.mx) == 0);
+      control.value = timeout;
+      assert(pthread_mutex_unlock(&control.mx) == 0);
+
+      /*
+       * We are attempting to send the signal close to when the slave
+       * is due to timeout. We feel around by adding some [non-random] dither.
+       *
+       * dither is in the range 2*timeout peak-to-peak
+       * sleep time is the average of timeout plus dither.
+       * e.g.
+       * if timeout = 10 then dither = 20 and
+       * sleep millisecs is: 5 <= ms <= 15
+       *
+       * The bias value attempts to apply some negative feedback to keep
+       * the ratio of timeouts to signals taken close to 1:1.
+       * bias changes more slowly than dither so as to average more.
+       *
+       * Finally, if abs(bias) exceeds timeout then timeout is incremented.
+       */
+      if (signalsSent % timeout == 0)
+	{
+          if (timeoutCount > signalsTakenCount)
+	    {
+	      bias++;
+	    }
+          else if (timeoutCount < signalsTakenCount)
+	    {
+	      bias--;
+	    }
+	  if (bias < -timeout || bias > timeout)
+	    {
+	      timeout++;
+	    }
+	}
+      dither = (dither + 1 ) % (timeout * 2);
+      sleepTime = (timeout - bias + dither) / 2;
+      Sleep(sleepTime);
+      assert(pthread_cond_signal(&control.cv) == 0);
+      signalsSent++;
+
+      pthread_barrier_wait(&holdBarrier);
+      pthread_barrier_wait(&readyBarrier);
+    }
+  while (!allExit);
+
+  return NULL;
+}
+
+void *
+slaveThread (void * arg)
+{
+  struct timespec time;
+
+  pthread_barrier_wait(&startBarrier);
+
+  do
+    {
+      assert(pthread_mutex_lock(&control.mx) == 0);
+      if (pthread_cond_timedwait(&control.cv,
+				 &control.mx,
+				 millisecondsFromNow(&time, control.value)) == ETIMEDOUT)
+	{
+	  timeoutCount++;
+	}
+      else
+	{
+	  signalsTakenCount++;
+	}
+      assert(pthread_mutex_unlock(&control.mx) == 0);
+
+      pthread_barrier_wait(&holdBarrier);
+      pthread_barrier_wait(&readyBarrier);
+    }
+  while (!allExit);
+
+  return NULL;
+}
+
+int
+main ()
+{
+  unsigned int i;
+
+  assert(pthread_barrier_init(&startBarrier, NULL, 3) == 0);
+  assert(pthread_barrier_init(&readyBarrier, NULL, 3) == 0);
+  assert(pthread_barrier_init(&holdBarrier, NULL, 3) == 0);
+
+  assert(pthread_create(&master, NULL, masterThread, (void *) timeout) == 0);
+  assert(pthread_create(&slave, NULL, slaveThread, NULL) == 0);
+
+  allExit = FALSE;
+
+  pthread_barrier_wait(&startBarrier);
+
+  for (i = 1; !allExit; i++)
+    {
+      pthread_barrier_wait(&holdBarrier);
+      if (i >= ITERATIONS)
+	{
+	  allExit = TRUE;
+	}
+      pthread_barrier_wait(&readyBarrier);
+    }
+
+  assert(pthread_join(slave, NULL) == 0);
+  assert(pthread_join(master, NULL) == 0);
+
+  printf("Signals sent = %d\nWait timeouts = %d\nSignals taken = %d\nBias = %d\nTimeout = %d\n",
+	 signalsSent,
+	 timeoutCount,
+	 signalsTakenCount,
+	 (int) bias,
+	 timeout);
+
+  /* Cleanup */
+  assert(pthread_barrier_destroy(&holdBarrier) == 0);
+  assert(pthread_barrier_destroy(&readyBarrier) == 0);
+  assert(pthread_barrier_destroy(&startBarrier) == 0);
+  assert(pthread_cond_destroy(&control.cv) == 0);
+  assert(pthread_mutex_destroy(&control.mx) == 0);
+
+  /* Success. */
+  return 0;
+}
diff --git a/tests/test.h b/tests/test.h
new file mode 100644
index 0000000..3132c69
--- /dev/null
+++ b/tests/test.h
@@ -0,0 +1,140 @@
+/* 
+ * test.h
+ *
+ * Useful definitions and declarations for tests.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ */
+
+#ifndef _PTHREAD_TEST_H_
+#define _PTHREAD_TEST_H_
+
+#include "pthread.h"
+#include "sched.h"
+#include "semaphore.h"
+
+#include <windows.h>
+#include <stdio.h>
+
+#define PTW32_THREAD_NULL_ID {NULL,0}
+
+#if defined(__MINGW32__)
+#include <stdint.h>
+#elif defined(__BORLANDC__)
+#define int64_t ULONGLONG
+#else
+#define int64_t _int64
+#endif
+
+
+char * error_string[] = {
+  "ZERO_or_EOK",
+  "EPERM",
+  "ENOFILE_or_ENOENT",
+  "ESRCH",
+  "EINTR",
+  "EIO",
+  "ENXIO",
+  "E2BIG",
+  "ENOEXEC",
+  "EBADF",
+  "ECHILD",
+  "EAGAIN",
+  "ENOMEM",
+  "EACCES",
+  "EFAULT",
+  "UNKNOWN_15",
+  "EBUSY",
+  "EEXIST",
+  "EXDEV",
+  "ENODEV",
+  "ENOTDIR",
+  "EISDIR",
+  "EINVAL",
+  "ENFILE",
+  "EMFILE",
+  "ENOTTY",
+  "UNKNOWN_26",
+  "EFBIG",
+  "ENOSPC",
+  "ESPIPE",
+  "EROFS",
+  "EMLINK",
+  "EPIPE",
+  "EDOM",
+  "ERANGE",
+  "UNKNOWN_35",
+  "EDEADLOCK_or_EDEADLK",
+  "UNKNOWN_37",
+  "ENAMETOOLONG",
+  "ENOLCK",
+  "ENOSYS",
+  "ENOTEMPTY",
+  "EILSEQ",
+};
+
+/*
+ * The Mingw32 assert macro calls the CRTDLL _assert function
+ * which pops up a dialog. We want to run in batch mode so
+ * we define our own assert macro.
+ */
+#ifdef assert
+# undef assert
+#endif
+
+#ifndef ASSERT_TRACE
+# define ASSERT_TRACE 0
+#else
+# undef ASSERT_TRACE
+# define ASSERT_TRACE 1
+#endif
+
+# define assert(e) \
+   ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \
+                                    "Assertion succeeded: (%s), file %s, line %d\n", \
+			            #e, __FILE__, (int) __LINE__), \
+	                            fflush(stderr) : \
+                             0) : \
+          (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
diff --git a/tests/tryentercs.c b/tests/tryentercs.c
new file mode 100644
index 0000000..13a6e09
--- /dev/null
+++ b/tests/tryentercs.c
@@ -0,0 +1,103 @@
+/*
+ * tryentercs.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * See if we have the TryEnterCriticalSection function.
+ * Does not use any part of pthreads.
+ */
+
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+
+/*
+ * Function pointer to TryEnterCriticalSection if it exists
+ * - otherwise NULL
+ */
+BOOL (WINAPI *_try_enter_critical_section)(LPCRITICAL_SECTION) =
+NULL;
+
+/*
+ * Handle to kernel32.dll
+ */
+static HINSTANCE _h_kernel32;
+
+
+int
+main()
+{
+  CRITICAL_SECTION cs;
+
+  SetLastError(0);
+
+  printf("Last Error [main enter] %ld\n", (long) GetLastError());
+
+  /*
+   * Load KERNEL32 and try to get address of TryEnterCriticalSection
+   */
+  _h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));
+  _try_enter_critical_section =
+        (BOOL (PT_STDCALL *)(LPCRITICAL_SECTION))
+        GetProcAddress(_h_kernel32,
+                         (LPCSTR) "TryEnterCriticalSection");
+
+  if (_try_enter_critical_section != NULL)
+    {
+      InitializeCriticalSection(&cs);
+
+      SetLastError(0);
+
+      if ((*_try_enter_critical_section)(&cs) != 0)
+        {
+          LeaveCriticalSection(&cs);
+        }
+	else
+	  {
+	    printf("Last Error [try enter] %ld\n", (long) GetLastError());
+
+	    _try_enter_critical_section = NULL;
+	  }
+      DeleteCriticalSection(&cs);
+    }
+
+  (void) FreeLibrary(_h_kernel32);
+
+  printf("This system %s TryEnterCriticalSection.\n",
+         (_try_enter_critical_section == NULL) ? "DOES NOT SUPPORT" : "SUPPORTS");
+  printf("POSIX Mutexes will be based on Win32 %s.\n",
+         (_try_enter_critical_section == NULL) ? "Mutexes" : "Critical Sections");
+
+  return(0);
+}
+
diff --git a/tests/tryentercs2.c b/tests/tryentercs2.c
new file mode 100644
index 0000000..a1c4d97
--- /dev/null
+++ b/tests/tryentercs2.c
@@ -0,0 +1,92 @@
+/*
+ * tryentercs.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * See if we have the TryEnterCriticalSection function.
+ * Does not use any part of pthreads.
+ */
+
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+
+/*
+ * Function pointer to TryEnterCriticalSection if it exists
+ * - otherwise NULL
+ */
+BOOL (WINAPI *_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL;
+
+/*
+ * Handle to kernel32.dll
+ */
+static HINSTANCE _h_kernel32;
+
+
+int
+main()
+{
+  LPCRITICAL_SECTION lpcs = NULL;
+
+  SetLastError(0);
+
+  printf("Last Error [main enter] %ld\n", (long) GetLastError());
+
+  /*
+   * Load KERNEL32 and try to get address of TryEnterCriticalSection
+   */
+  _h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));
+  _try_enter_critical_section =
+        (BOOL (PT_STDCALL *)(LPCRITICAL_SECTION))
+        GetProcAddress(_h_kernel32,
+                         (LPCSTR) "TryEnterCriticalSection");
+
+  if (_try_enter_critical_section != NULL)
+    {
+      SetLastError(0);
+
+      (*_try_enter_critical_section)(lpcs);
+
+      printf("Last Error [try enter] %ld\n", (long) GetLastError());
+    }
+
+  (void) FreeLibrary(_h_kernel32);
+
+  printf("This system %s TryEnterCriticalSection.\n",
+         (_try_enter_critical_section == NULL) ? "DOES NOT SUPPORT" : "SUPPORTS");
+  printf("POSIX Mutexes will be based on Win32 %s.\n",
+         (_try_enter_critical_section == NULL) ? "Mutexes" : "Critical Sections");
+
+  return(0);
+}
+
diff --git a/tests/tsd1.c b/tests/tsd1.c
new file mode 100644
index 0000000..c28e4c5
--- /dev/null
+++ b/tests/tsd1.c
@@ -0,0 +1,211 @@
+/*
+ * tsd1.c
+ *
+ * Test Thread Specific Data (TSD) key creation and destruction.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Description:
+ * - 
+ *
+ * Test Method (validation or falsification):
+ * - validation
+ *
+ * Requirements Tested:
+ * - keys are created for each existing thread including the main thread
+ * - keys are created for newly created threads
+ * - keys are thread specific
+ * - destroy routine is called on each thread exit including the main thread
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - none
+ *
+ * Output:
+ * - text to stdout
+ *
+ * Assumptions:
+ * - already validated:     pthread_create()
+ *                          pthread_once()
+ * - main thread also has a POSIX thread identity
+ *
+ * Pass Criteria:
+ * - stdout matches file reference/tsd1.out
+ *
+ * Fail Criteria:
+ * - fails to match file reference/tsd1.out
+ * - output identifies failed component
+ */
+
+#include <sched.h>
+#include "test.h"
+
+enum {
+  NUM_THREADS = 100
+};
+
+static pthread_key_t key = NULL;
+static int accesscount[NUM_THREADS];
+static int thread_set[NUM_THREADS];
+static int thread_destroyed[NUM_THREADS];
+static pthread_barrier_t startBarrier;
+
+static void
+destroy_key(void * arg)
+{
+  int * j = (int *) arg;
+
+  (*j)++;
+
+  assert(*j == 2);
+
+  thread_destroyed[j - accesscount] = 1;
+}
+
+static void
+setkey(void * arg)
+{
+  int * j = (int *) arg;
+
+  thread_set[j - accesscount] = 1;
+
+  assert(*j == 0);
+
+  assert(pthread_getspecific(key) == NULL);
+
+  assert(pthread_setspecific(key, arg) == 0);
+  assert(pthread_setspecific(key, arg) == 0);
+  assert(pthread_setspecific(key, arg) == 0);
+
+  assert(pthread_getspecific(key) == arg);
+
+  (*j)++;
+
+  assert(*j == 1);
+}
+
+static void *
+mythread(void * arg)
+{
+  (void) pthread_barrier_wait(&startBarrier);
+
+  setkey(arg);
+
+  return 0;
+
+  /* Exiting the thread will call the key destructor. */
+}
+
+int
+main()
+{
+  int i;
+  int fail = 0;
+  pthread_t thread[NUM_THREADS];
+
+  assert(pthread_barrier_init(&startBarrier, NULL, NUM_THREADS/2) == 0);
+
+  for (i = 1; i < NUM_THREADS/2; i++)
+    {
+      accesscount[i] = thread_set[i] = thread_destroyed[i] = 0;
+      assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);
+    }
+
+  /*
+   * Here we test that existing threads will get a key created
+   * for them.
+   */
+  assert(pthread_key_create(&key, destroy_key) == 0);
+
+  (void) pthread_barrier_wait(&startBarrier);
+
+  /*
+   * Test main thread key.
+   */
+  accesscount[0] = 0;
+  setkey((void *) &accesscount[0]);
+
+  /*
+   * Here we test that new threads will get a key created
+   * for them.
+   */
+  for (i = NUM_THREADS/2; i < NUM_THREADS; i++)
+    {
+      accesscount[i] = thread_set[i] = thread_destroyed[i] = 0;
+      assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);
+    }
+
+  /*
+   * Wait for all threads to complete.
+   */
+  for (i = 1; i < NUM_THREADS; i++)
+    {
+	int result = 0;
+
+	assert(pthread_join(thread[i], (void **) &result) == 0);
+    }
+
+  assert(pthread_key_delete(key) == 0);
+
+  assert(pthread_barrier_destroy(&startBarrier) == 0);
+
+  for (i = 1; i < NUM_THREADS; i++)
+    {
+	/*
+	 * The counter is incremented once when the key is set to
+	 * a value, and again when the key is destroyed. If the key
+	 * doesn't get set for some reason then it will still be
+	 * NULL and the destroy function will not be called, and
+	 * hence accesscount will not equal 2.
+	 */
+	if (accesscount[i] != 2)
+	  {
+	    fail++;
+	    fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n",
+			i, thread_set[i], thread_destroyed[i]);
+	  }
+    }
+
+  fflush(stderr);
+
+  return (fail);
+}
diff --git a/tests/tsd2.c b/tests/tsd2.c
new file mode 100644
index 0000000..d1f50cd
--- /dev/null
+++ b/tests/tsd2.c
@@ -0,0 +1,215 @@
+/*
+ * tsd2.c
+ *
+ * Test Thread Specific Data (TSD) key creation and destruction.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Description:
+ * - 
+ *
+ * Test Method (validation or falsification):
+ * - validation
+ *
+ * Requirements Tested:
+ * - keys are created for each existing thread including the main thread
+ * - keys are created for newly created threads
+ * - keys are thread specific
+ * - destroy routine is called on each thread exit including the main thread
+ *
+ * Features Tested:
+ * - 
+ *
+ * Cases Tested:
+ * - 
+ *
+ * Environment:
+ * - 
+ *
+ * Input:
+ * - none
+ *
+ * Output:
+ * - text to stdout
+ *
+ * Assumptions:
+ * - already validated:     pthread_create()
+ *                          pthread_once()
+ * - main thread also has a POSIX thread identity
+ *
+ * Pass Criteria:
+ * - stdout matches file reference/tsd1.out
+ *
+ * Fail Criteria:
+ * - fails to match file reference/tsd1.out
+ * - output identifies failed component
+ */
+
+#include <sched.h>
+#include "test.h"
+
+enum {
+  NUM_THREADS = 100
+};
+
+static pthread_key_t key = NULL;
+static int accesscount[NUM_THREADS];
+static int thread_set[NUM_THREADS];
+static int thread_destroyed[NUM_THREADS];
+static pthread_barrier_t startBarrier;
+
+static void
+destroy_key(void * arg)
+{
+  int * j = (int *) arg;
+
+  (*j)++;
+
+  /* Set TSD key from the destructor to test destructor iteration */
+  if (*j == 2)
+    assert(pthread_setspecific(key, arg) == 0);
+  else
+    assert(*j == 3);
+
+  thread_destroyed[j - accesscount] = 1;
+}
+
+static void
+setkey(void * arg)
+{
+  int * j = (int *) arg;
+
+  thread_set[j - accesscount] = 1;
+
+  assert(*j == 0);
+
+  assert(pthread_getspecific(key) == NULL);
+
+  assert(pthread_setspecific(key, arg) == 0);
+  assert(pthread_setspecific(key, arg) == 0);
+  assert(pthread_setspecific(key, arg) == 0);
+
+  assert(pthread_getspecific(key) == arg);
+
+  (*j)++;
+
+  assert(*j == 1);
+}
+
+static void *
+mythread(void * arg)
+{
+  (void) pthread_barrier_wait(&startBarrier);
+
+  setkey(arg);
+
+  return 0;
+
+  /* Exiting the thread will call the key destructor. */
+}
+
+int
+main()
+{
+  int i;
+  int fail = 0;
+  pthread_t thread[NUM_THREADS];
+
+  assert(pthread_barrier_init(&startBarrier, NULL, NUM_THREADS/2) == 0);
+
+  for (i = 1; i < NUM_THREADS/2; i++)
+    {
+      accesscount[i] = thread_set[i] = thread_destroyed[i] = 0;
+      assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);
+    }
+
+  /*
+   * Here we test that existing threads will get a key created
+   * for them.
+   */
+  assert(pthread_key_create(&key, destroy_key) == 0);
+
+  (void) pthread_barrier_wait(&startBarrier);
+
+  /*
+   * Test main thread key.
+   */
+  accesscount[0] = 0;
+  setkey((void *) &accesscount[0]);
+
+  /*
+   * Here we test that new threads will get a key created
+   * for them.
+   */
+  for (i = NUM_THREADS/2; i < NUM_THREADS; i++)
+    {
+      accesscount[i] = thread_set[i] = thread_destroyed[i] = 0;
+      assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);
+    }
+
+  /*
+   * Wait for all threads to complete.
+   */
+  for (i = 1; i < NUM_THREADS; i++)
+    {
+	int result = 0;
+
+	assert(pthread_join(thread[i], (void **) &result) == 0);
+    }
+
+  assert(pthread_key_delete(key) == 0);
+
+  assert(pthread_barrier_destroy(&startBarrier) == 0);
+
+  for (i = 1; i < NUM_THREADS; i++)
+    {
+	/*
+	 * The counter is incremented once when the key is set to
+	 * a value, and again when the key is destroyed. If the key
+	 * doesn't get set for some reason then it will still be
+	 * NULL and the destroy function will not be called, and
+	 * hence accesscount will not equal 2.
+	 */
+	if (accesscount[i] != 3)
+	  {
+	    fail++;
+	    fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n",
+			i, thread_set[i], thread_destroyed[i]);
+	  }
+    }
+
+  fflush(stderr);
+
+  return (fail);
+}
diff --git a/tests/valid1.c b/tests/valid1.c
new file mode 100644
index 0000000..4d5cab5
--- /dev/null
+++ b/tests/valid1.c
@@ -0,0 +1,103 @@
+/*
+ * File: valid1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Test that thread validation works.
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * 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"
+
+enum {
+	NUMTHREADS = 1
+};
+
+static int washere = 0;
+
+void * func(void * arg)
+{
+  washere = 1;
+  return (void *) 0; 
+}
+ 
+int
+main()
+{
+  pthread_t t;
+  void * result = NULL;
+
+  washere = 0;
+  assert(pthread_create(&t, NULL, func, NULL) == 0);
+  assert(pthread_join(t, &result) == 0);
+  assert(result == 0);
+  assert(washere == 1);
+  sched_yield();
+  assert(pthread_kill(t, 0) == ESRCH);
+
+  return 0;
+}
diff --git a/tests/valid2.c b/tests/valid2.c
new file mode 100644
index 0000000..b967179
--- /dev/null
+++ b/tests/valid2.c
@@ -0,0 +1,84 @@
+/*
+ * File: valid2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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:
+ * - Confirm that thread validation fails for garbage thread ID.
+ *
+ * Test Method (Validation or Falsification):
+ * -
+ *
+ * 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"
+ 
+int
+main()
+{
+  pthread_t NullThread = PTW32_THREAD_NULL_ID;
+
+  assert(pthread_kill(NullThread, 0) == ESRCH);
+
+  return 0;
+}
diff --git a/tsd.c b/tsd.c
new file mode 100644
index 0000000..ed44fe6
--- /dev/null
+++ b/tsd.c
@@ -0,0 +1,44 @@
+/*
+ * tsd.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_key_create.c"
+#include "pthread_key_delete.c"
+#include "pthread_setspecific.c"
+#include "pthread_getspecific.c"
diff --git a/version.rc b/version.rc
new file mode 100644
index 0000000..a6c22a2
--- /dev/null
+++ b/version.rc
@@ -0,0 +1,384 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include <winver.h>
+#include "pthread.h"
+
+/*
+ * Note: the correct __CLEANUP_* macro must be defined corresponding to
+ * the definition used for the object file builds. This is done in the
+ * relevent makefiles for the command line builds, but users should ensure
+ * that their resource compiler knows what it is too.
+ * If using the default (no __CLEANUP_* defined), pthread.h will define it
+ * as __CLEANUP_C.
+ */
+
+#ifdef PTW32_RC_MSC
+#  if defined(__CLEANUP_C)
+#    define PTW32_VERSIONINFO_NAME "pthreadVC\0"
+#    define PTW32_VERSIONINFO_COMMENT "MS C build -- longjmp thread exiting\0"
+#  elif defined(__CLEANUP_CXX)
+#    define PTW32_VERSIONINFO_NAME "pthreadVCE\0"
+#    define PTW32_VERSIONINFO_COMMENT "MS C++ build -- C++ exception thread exiting\0"
+#  elif defined(__CLEANUP_SEH)
+#    define PTW32_VERSIONINFO_NAME "pthreadVSE\0"
+#    define PTW32_VERSIONINFO_COMMENT "MS C build -- structured exception thread exiting\0"
+#  else
+#    error Resource compiler doesn't know which cleanup style you're using - see version.rc
+#  endif
+#elif defined(__GNUC__)
+#  if defined(__CLEANUP_C)
+#    define PTW32_VERSIONINFO_NAME "pthreadGC\0"
+#    define PTW32_VERSIONINFO_COMMENT "GNU C build -- longjmp thread exiting\0"
+#  elif defined(__CLEANUP_CXX)
+#    define PTW32_VERSIONINFO_NAME "pthreadGCE\0"
+#    define PTW32_VERSIONINFO_COMMENT "GNU C++ build -- C++ exception thread exiting\0"
+#  else
+#    error Resource compiler doesn't know which cleanup style you're using - see version.rc
+#  endif
+#elif defined(__BORLANDC__)
+#  if defined(__CLEANUP_C)
+#    define PTW32_VERSIONINFO_NAME "pthreadBC\0"
+#    define PTW32_VERSIONINFO_COMMENT "BORLAND C build -- longjmp thread exiting\0"
+#  elif defined(__CLEANUP_CXX)
+#    define PTW32_VERSIONINFO_NAME "pthreadBCE\0"
+#    define PTW32_VERSIONINFO_COMMENT "BORLAND C++ build -- C++ exception thread exiting\0"
+#  else
+#    error Resource compiler doesn't know which cleanup style you're using - see version.rc
+#  endif
+#elif defined(__WATCOMC__)
+#  if defined(__CLEANUP_C)
+#    define PTW32_VERSIONINFO_NAME "pthreadWC\0"
+#    define PTW32_VERSIONINFO_COMMENT "WATCOM C build -- longjmp thread exiting\0"
+#  elif defined(__CLEANUP_CXX)
+#    define PTW32_VERSIONINFO_NAME "pthreadWCE\0"
+#    define PTW32_VERSIONINFO_COMMENT "WATCOM C++ build -- C++ exception thread exiting\0"
+#  else
+#    error Resource compiler doesn't know which cleanup style you're using - see version.rc
+#  endif
+#else
+#  error Resource compiler doesn't know which compiler you're using - see version.rc
+#endif
+
+
+VS_VERSION_INFO VERSIONINFO
+  FILEVERSION    PTW32_VERSION
+  PRODUCTVERSION PTW32_VERSION
+  FILEFLAGSMASK  VS_FFI_FILEFLAGSMASK
+  FILEFLAGS      0
+  FILEOS         VOS__WINDOWS32
+  FILETYPE       VFT_DLL
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "POSIX Threads for Windows32 Library\0"
+            VALUE "ProductVersion", PTW32_VERSION_STRING
+            VALUE "FileVersion", PTW32_VERSION_STRING
+            VALUE "InternalName", PTW32_VERSIONINFO_NAME
+            VALUE "OriginalFilename", PTW32_VERSIONINFO_NAME
+            VALUE "CompanyName", "Open Source Software community project\0"
+            VALUE "LegalCopyright", "Copyright (C) Project contributors 1998-2004\0"
+            VALUE "Licence", "LGPL\0"
+            VALUE "Info", "http://sources.redhat.com/pthreads-win32/\0"
+	    VALUE "Comment", PTW32_VERSIONINFO_COMMENT
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+/*
+VERSIONINFO Resource
+
+The VERSIONINFO resource-definition statement creates a version-information
+resource. The resource contains such information about the file as its
+version number, its intended operating system, and its original filename.
+The resource is intended to be used with the Version Information functions.
+
+versionID VERSIONINFO fixed-info  { block-statement...}
+
+versionID
+    Version-information resource identifier. This value must be 1.
+
+fixed-info
+    Version information, such as the file version and the intended operating
+    system. This parameter consists of the following statements.
+
+
+    Statement 		Description
+    --------------------------------------------------------------------------
+    FILEVERSION
+    version 		Binary version number for the file. The version
+			consists of two 32-bit integers, defined by four
+			16-bit integers. For example, "FILEVERSION 3,10,0,61"
+			is translated into two doublewords: 0x0003000a and
+			0x0000003d, in that order. Therefore, if version is
+			defined by the DWORD values dw1 and dw2, they need
+			to appear in the FILEVERSION statement as follows:
+			HIWORD(dw1), LOWORD(dw1), HIWORD(dw2), LOWORD(dw2).
+    PRODUCTVERSION
+    version 		Binary version number for the product with which the
+			file is distributed. The version parameter is two
+			32-bit integers, defined by four 16-bit integers.
+			For more information about version, see the
+			FILEVERSION description.
+    FILEFLAGSMASK
+    fileflagsmask 	Bits in the FILEFLAGS statement are valid. If a bit
+			is set, the corresponding bit in FILEFLAGS is valid.
+    FILEFLAGSfileflags 	Attributes of the file. The fileflags parameter must
+			be the combination of all the file flags that are
+			valid at compile time. For 16-bit Windows, this
+			value is 0x3f.
+    FILEOSfileos 	Operating system for which this file was designed.
+			The fileos parameter can be one of the operating
+			system values given in the Remarks section.
+    FILETYPEfiletype 	General type of file. The filetype parameter can be
+			one of the file type values listed in the Remarks
+			section.
+    FILESUBTYPE
+    subtype 		Function of the file. The subtype parameter is zero
+			unless the type parameter in the FILETYPE statement
+			is VFT_DRV, VFT_FONT, or VFT_VXD. For a list of file
+			subtype values, see the Remarks section.
+
+block-statement
+    Specifies one or more version-information blocks. A block can contain
+    string information or variable information. For more information, see
+    StringFileInfo Block or VarFileInfo Block.
+
+Remarks
+
+To use the constants specified with the VERSIONINFO statement, you must
+include the Winver.h or Windows.h header file in the resource-definition file.
+
+The following list describes the parameters used in the VERSIONINFO statement:
+
+fileflags
+    A combination of the following values.
+
+    Value 		Description
+
+    VS_FF_DEBUG 	File contains debugging information or is compiled
+			with debugging features enabled.
+    VS_FF_PATCHED 	File has been modified and is not identical to the
+			original shipping file of the same version number.
+    VS_FF_PRERELEASE 	File is a development version, not a commercially
+			released product.
+    VS_FF_PRIVATEBUILD 	File was not built using standard release procedures.
+			If this value is given, the StringFileInfo block must
+			contain a PrivateBuild string.
+    VS_FF_SPECIALBUILD 	File was built by the original company using standard
+			release procedures but is a variation of the standard
+			file of the same version number. If this value is
+			given, the StringFileInfo block must contain a
+			SpecialBuild string.
+
+fileos
+    One of the following values.
+
+    Value 		Description
+
+    VOS_UNKNOWN 	The operating system for which the file was designed
+			is unknown.
+    VOS_DOS 		File was designed for MS-DOS.
+    VOS_NT 		File was designed for Windows Server 2003 family,
+			Windows XP, Windows 2000, or Windows NT.
+    VOS__WINDOWS16 	File was designed for 16-bit Windows.
+    VOS__WINDOWS32 	File was designed for 32-bit Windows.
+    VOS_DOS_WINDOWS16 	File was designed for 16-bit Windows running with
+			MS-DOS.
+    VOS_DOS_WINDOWS32 	File was designed for 32-bit Windows running with
+			MS-DOS.
+    VOS_NT_WINDOWS32 	File was designed for Windows Server 2003 family,
+			Windows XP, Windows 2000, or Windows NT.
+
+    The values 0x00002L, 0x00003L, 0x20000L and 0x30000L are reserved.
+
+filetype
+    One of the following values.
+
+    Value 		Description
+
+    VFT_UNKNOWN 	File type is unknown.
+    VFT_APP 		File contains an application.
+    VFT_DLL 		File contains a dynamic-link library (DLL).
+    VFT_DRV 		File contains a device driver. If filetype is
+			VFT_DRV, subtype contains a more specific
+			description of the driver.
+    VFT_FONT 		File contains a font. If filetype is VFT_FONT,
+			subtype contains a more specific description of the
+			font.
+    VFT_VXD 		File contains a virtual device.
+    VFT_STATIC_LIB 	File contains a static-link library.
+
+    All other values are reserved for use by Microsoft.
+
+subtype
+    Additional information about the file type.
+
+    If filetype specifies VFT_DRV, this parameter can be one of the
+    following values.
+
+    Value 			Description
+
+    VFT2_UNKNOWN 		Driver type is unknown.
+    VFT2_DRV_COMM 		File contains a communications driver.
+    VFT2_DRV_PRINTER 		File contains a printer driver.
+    VFT2_DRV_KEYBOARD 		File contains a keyboard driver.
+    VFT2_DRV_LANGUAGE 		File contains a language driver.
+    VFT2_DRV_DISPLAY 		File contains a display driver.
+    VFT2_DRV_MOUSE 		File contains a mouse driver.
+    VFT2_DRV_NETWORK 		File contains a network driver.
+    VFT2_DRV_SYSTEM 		File contains a system driver.
+    VFT2_DRV_INSTALLABLE 	File contains an installable driver.
+    VFT2_DRV_SOUND 		File contains a sound driver.
+    VFT2_DRV_VERSIONED_PRINTER 	File contains a versioned printer driver.
+
+    If filetype specifies VFT_FONT, this parameter can be one of the
+    following values.
+
+    Value 		Description
+
+    VFT2_UNKNOWN 	Font type is unknown.
+    VFT2_FONT_RASTER 	File contains a raster font.
+    VFT2_FONT_VECTOR 	File contains a vector font.
+    VFT2_FONT_TRUETYPE 	File contains a TrueType font.
+
+    If filetype specifies VFT_VXD, this parameter must be the virtual-device
+    identifier included in the virtual-device control block.
+
+    All subtype values not listed here are reserved for use by Microsoft.
+
+langID
+    One of the following language codes.
+
+    Code 	Language 		Code 	Language
+
+    0x0401 	Arabic 			0x0415 	Polish
+    0x0402 	Bulgarian 		0x0416 	Portuguese (Brazil)
+    0x0403 	Catalan 		0x0417 	Rhaeto-Romanic
+    0x0404 	Traditional Chinese 	0x0418 	Romanian
+    0x0405 	Czech 			0x0419 	Russian
+    0x0406 	Danish 			0x041A 	Croato-Serbian (Latin)
+    0x0407 	German 			0x041B 	Slovak
+    0x0408 	Greek 			0x041C 	Albanian
+    0x0409 	U.S. English 		0x041D 	Swedish
+    0x040A 	Castilian Spanish 	0x041E 	Thai
+    0x040B 	Finnish 		0x041F 	Turkish
+    0x040C 	French 			0x0420 	Urdu
+    0x040D 	Hebrew 			0x0421 	Bahasa
+    0x040E 	Hungarian 		0x0804 	Simplified Chinese
+    0x040F 	Icelandic 		0x0807 	Swiss German
+    0x0410 	Italian 		0x0809 	U.K. English
+    0x0411 	Japanese 		0x080A 	Mexican Spanish
+    0x0412 	Korean 			0x080C 	Belgian French
+    0x0413 	Dutch 			0x0C0C 	Canadian French
+    0x0414 	Norwegian – Bokmal 	0x100C 	Swiss French
+    0x0810 	Swiss Italian 		0x0816 	Portuguese (Portugal)
+    0x0813 	Belgian Dutch 		0x081A 	Serbo-Croatian (Cyrillic)
+    0x0814 	Norwegian – Nynorsk 	  	 
+
+charsetID
+    One of the following character-set identifiers.
+
+    Identifier 	Character Set
+
+    0 		7-bit ASCII
+    932 	Japan (Shift %G–%@ JIS X-0208)
+    949 	Korea (Shift %G–%@ KSC 5601)
+    950 	Taiwan (Big5)
+    1200 	Unicode
+    1250 	Latin-2 (Eastern European)
+    1251 	Cyrillic
+    1252 	Multilingual
+    1253 	Greek
+    1254 	Turkish
+    1255 	Hebrew
+    1256 	Arabic
+
+string-name
+    One of the following predefined names.
+
+    Name 		Description
+
+    Comments 		Additional information that should be displayed for
+			diagnostic purposes.
+    CompanyName 	Company that produced the file%G—%@for example,
+			"Microsoft Corporation" or "Standard Microsystems
+			Corporation, Inc." This string is required.
+    FileDescription 	File description to be presented to users. This
+			string may be displayed in a list box when the user
+			is choosing files to install%G—%@for example,
+			"Keyboard Driver for AT-Style Keyboards". This
+			string is required.
+    FileVersion 	Version number of the file%G—%@for example,
+			"3.10" or "5.00.RC2". This string is required.
+    InternalName 	Internal name of the file, if one exists — for
+			example, a module name if the file is a dynamic-link
+			library. If the file has no internal name, this
+			string should be the original filename, without
+			extension. This string is required.
+    LegalCopyright 	Copyright notices that apply to the file. This
+			should include the full text of all notices, legal
+			symbols, copyright dates, and so on — for example,
+			"Copyright (C) Microsoft Corporation 1990–1999".
+			This string is optional.
+    LegalTrademarks 	Trademarks and registered trademarks that apply to
+			the file. This should include the full text of all
+			notices, legal symbols, trademark numbers, and so on.
+			This string is optional.
+    OriginalFilename 	Original name of the file, not including a path.
+			This information enables an application to determine
+			whether a file has been renamed by a user. The
+			format of the name depends on the file system for
+			which the file was created. This string is required.
+    PrivateBuild 	Information about a private version of the file — for
+			example, "Built by TESTER1 on \TESTBED". This string
+			should be present only if VS_FF_PRIVATEBUILD is
+			specified in the fileflags parameter of the root
+			block.
+    ProductName 	Name of the product with which the file is
+			distributed. This string is required.
+    ProductVersion 	Version of the product with which the file is
+			distributed — for example, "3.10" or "5.00.RC2".
+			This string is required.
+    SpecialBuild 	Text that indicates how this version of the file
+			differs from the standard version — for example,
+			"Private build for TESTER1 solving mouse problems
+			on M250 and M250E computers". This string should be
+			present only if VS_FF_SPECIALBUILD is specified in
+			the fileflags parameter of the root block.
+ */
diff --git a/w32_CancelableWait.c b/w32_CancelableWait.c
new file mode 100644
index 0000000..97e15aa
--- /dev/null
+++ b/w32_CancelableWait.c
@@ -0,0 +1,160 @@
+/*
+ * w32_CancelableWait.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+static INLINE int
+ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)
+     /*
+      * -------------------------------------------------------------------
+      * This provides an extra hook into the pthread_cancel
+      * mechanism that will allow you to wait on a Windows handle and make it a
+      * cancellation point. This function blocks until the given WIN32 handle is
+      * signaled or pthread_cancel has been called. It is implemented using
+      * WaitForMultipleObjects on 'waitHandle' and a manually reset WIN32
+      * event used to implement pthread_cancel.
+      * 
+      * Given this hook it would be possible to implement more of the cancellation
+      * points.
+      * -------------------------------------------------------------------
+      */
+{
+  int result;
+  pthread_t self;
+  ptw32_thread_t * sp;
+  HANDLE handles[2];
+  DWORD nHandles = 1;
+  DWORD status;
+
+  handles[0] = waitHandle;
+
+  self = pthread_self();
+  sp = (ptw32_thread_t *) self.p;
+
+  if (sp != NULL)
+    {
+      /*
+       * Get cancelEvent handle
+       */
+      if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
+	{
+
+	  if ((handles[1] = sp->cancelEvent) != NULL)
+	    {
+	      nHandles++;
+	    }
+	}
+    }
+  else
+    {
+      handles[1] = NULL;
+    }
+
+  status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout);
+
+  switch (status - WAIT_OBJECT_0)
+    {
+    case 0:
+      /*
+       * Got the handle.
+       * In the event that both handles are signalled, the smallest index
+       * value (us) is returned. As it has been arranged, this ensures that
+       * we don't drop a signal that we should act on (i.e. semaphore,
+       * mutex, or condition variable etc).
+       */
+      result = 0;
+      break;
+
+    case 1:
+      /*
+       * Got cancel request.
+       * In the event that both handles are signaled, the cancel will
+       * be ignored (see case 0 comment).
+       */
+      ResetEvent (handles[1]);
+
+      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 (&sp->cancelLock);
+	  if (sp->state < PThreadStateCanceling)
+	    {
+	      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 (&sp->cancelLock);
+	}
+
+      /* Should never get to here. */
+      result = EINVAL;
+      break;
+
+    default:
+      if (status == WAIT_TIMEOUT)
+	{
+	  result = ETIMEDOUT;
+	}
+      else
+	{
+	  result = EINVAL;
+	}
+      break;
+    }
+
+  return (result);
+
+}				/* CancelableWait */
+
+int
+pthreadCancelableWait (HANDLE waitHandle)
+{
+  return (ptw32_cancelable_wait (waitHandle, INFINITE));
+}
+
+int
+pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout)
+{
+  return (ptw32_cancelable_wait (waitHandle, timeout));
+}