diff -urp src.old/winsup/cygwin/include/pthread.h src/winsup/cygwin/include/pthread.h
--- src.old/winsup/cygwin/include/pthread.h	Thu Apr 25 10:11:30 2002
+++ src/winsup/cygwin/include/pthread.h	Thu Apr 25 17:33:27 2002
@@ -42,7 +42,7 @@ extern "C"
 #define PTHREAD_CANCEL_ENABLE 0
 #define PTHREAD_CANCEL_DEFERRED 0
 #define PTHREAD_CANCEL_DISABLE 1
-#define PTHREAD_CANCELED
+#define PTHREAD_CANCELED ((void *)-1)
 /* this should be a value that can never be a valid address */
 #define PTHREAD_COND_INITIALIZER (void *)21
 #define PTHREAD_CREATE_DETACHED 1
diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc
--- src.old/winsup/cygwin/thread.cc	Fri Apr 26 08:22:57 2002
+++ src/winsup/cygwin/thread.cc	Fri Apr 26 09:42:36 2002
@@ -48,6 +48,26 @@ details. */
 
 extern int threadsafe;
 
+#if defined(_M_IX86) || defined(_X86_)
+#define PROGCTR(Context)  ((Context).Eip)
+#endif
+ 
+#if defined(_MIPS_)
+#define PROGCTR(Context)  ((Context).Fir)
+#endif
+ 
+#if defined(_ALPHA_)
+#define PROGCTR(Context)  ((Context).Fir)
+#endif
+ 
+#if defined(_PPC_)
+#define PROGCTR(Context)  ((Context).Iar)
+#endif
+ 
+#if !defined(PROGCTR)
+#error Module contains CPU-specific code; modify and recompile.
+#endif                                                                          
+
 /*pthread_key_destructor_list class: to-be threadsafe single linked list
  *FIXME: Put me in a dedicated file, or a least a tools area !
  */
@@ -346,13 +366,16 @@ MTinterface::fixup_after_fork (void)
 }
 
 pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
-                    cancelstate (0), canceltype (0), mutex(NULL),
+                    cancelstate (0), canceltype (0), cancel_event (0),
+                    mutex ((pthread_mutex *)PTHREAD_MUTEX_INITIALIZER),
                     cleanup_handlers(NULL), joiner(NULL)
 {
 }
 
 pthread::~pthread ()
 {
+  if (cancel_event)
+    CloseHandle (cancel_event);
   if (win32_obj_id)
     CloseHandle (win32_obj_id);
   __pthread_mutex_destroy(&mutex);
@@ -387,6 +410,16 @@ pthread::create (void *(*func) (void *),
       return;
     }
 
+  cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL);
+  if (!cancel_event)
+    {
+      system_printf ("couldn't create cancel event, this %p LastError %d", this, GetLastError () );
+      /*we need the event for correct behaviour */
+      magic = 0;
+      return;
+    }
+
+
   win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
 				(LPTHREAD_START_ROUTINE) thread_init_wrapper,
 				this, CREATE_SUSPENDED, &thread_id);
@@ -1000,33 +1033,44 @@ __pthread_cleanup (pthread_t thread)
 int
 __pthread_cancel (pthread_t thread)
 {
+  pthread_t self = __pthread_self ();
+
   if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
     return ESRCH;
-  if (thread->cancelstate == PTHREAD_CANCEL_ENABLE)
+
+  if( __pthread_equal(&thread, &self ) )
     {
-#if 0
-      /*once all the functions call testcancel (), we will do this */
-      if (thread->canceltype == PTHREAD_CANCEL_DEFERRED)
-	{
-	}
-      else
+      __pthread_cancel_self ();
+    }
+
+  __pthread_mutex_lock (&thread->mutex);
+
+  if (thread->canceltype == PTHREAD_CANCEL_DEFERRED ||
+      thread->cancelstate == PTHREAD_CANCEL_DISABLE)
 	{
-	  /*possible FIXME: this function is meant to return asynchronously
-	   *from the cancellation routine actually firing. So we may need some sort
-	   *of signal to be sent that is immediately recieved and acted on.
-	   */
-	  __pthread_cleanup (thread);
+      // cancel deferred
+      SetEvent (thread->cancel_event);
+      __pthread_mutex_unlock (&thread->mutex);
+      return 0;
 	}
-#endif
+
+  // cancel asynchronous
+  SuspendThread (thread->win32_obj_id);
+  if (WaitForSingleObject (thread->win32_obj_id, 0) == WAIT_TIMEOUT)
+    {
+      CONTEXT context;
+      context.ContextFlags = CONTEXT_CONTROL;
+      GetThreadContext (thread->win32_obj_id, &context);
+      PROGCTR(context) = (DWORD) __pthread_cancel_self;
+      SetThreadContext (thread->win32_obj_id, &context);
     }
-/* return 0;
-*/
+  ResumeThread (thread->win32_obj_id);
 
-  return ESRCH;
-/*
-  we return ESRCH until all the required functions call testcancel ();
-  this will give applications predictable behaviour.
+  __pthread_mutex_unlock (&thread->mutex);
 
+  return 0;
+/*
+  TODO: insert  pthread_testcancel into the required functions
   the required function list is: *indicates done, X indicates not present in cygwin.
 aio_suspend ()
 *close ()
@@ -1200,27 +1244,54 @@ opengroup specs.
  */
 }
 
-/*no races in these three functions: they are all current-thread-only */
+void
+__pthread_cancel_self (void)
+{
+   __pthread_exit (PTHREAD_CANCELED);
+}
+
 int
 __pthread_setcancelstate (int state, int *oldstate)
 {
+  int result = 0;
   class pthread *thread = __pthread_self ();
+
+  __pthread_mutex_lock(&thread->mutex);
+
   if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
-    return EINVAL;
-  *oldstate = thread->cancelstate;
-  thread->cancelstate = state;
-  return 0;
+    result = EINVAL;
+  else
+    {
+      if (oldstate)
+        *oldstate = thread->cancelstate;
+      thread->cancelstate = state;
+    }
+
+  __pthread_mutex_unlock(&thread->mutex);
+
+  return result;
 }
 
 int
 __pthread_setcanceltype (int type, int *oldtype)
 {
+  int result = 0;
   class pthread *thread = __pthread_self ();
+
+  __pthread_mutex_lock(&thread->mutex);
+
   if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
-    return EINVAL;
-  *oldtype = thread->canceltype;
-  thread->canceltype = type;
-  return 0;
+    result = EINVAL;
+  else
+    {
+      if (oldtype)
+        *oldtype = thread->canceltype;
+      thread->canceltype = type;
+    }
+
+  __pthread_mutex_unlock(&thread->mutex);
+
+  return result;
 }
 
 /*deferred cancellation request handler */
@@ -1230,8 +1301,9 @@ __pthread_testcancel (void)
   class pthread *thread = __pthread_self ();
   if (thread->cancelstate == PTHREAD_CANCEL_DISABLE)
     return;
-  /*check the cancellation event object here - not neededuntil pthread_cancel actually
-   *does something*/
+
+  if( WAIT_OBJECT_0 == WaitForSingleObject (thread->cancel_event, 0 ) )
+    __pthread_cancel_self ();
 }
 
 void
@@ -1557,6 +1629,7 @@ __pthread_exit (void *value_ptr)
   MT_INTERFACE->destructors.IterateNull ();
 
   __pthread_mutex_lock(&thread->mutex);
+
   if( __pthread_equal(&thread->joiner, &thread ) )
     // cleanup if thread is in detached state and not joined
     delete thread;
@@ -1589,6 +1662,7 @@ __pthread_join (pthread_t *thread, void 
     }
 
   __pthread_mutex_lock(&(*thread)->mutex);
+
   if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
     {
        __pthread_mutex_unlock(&(*thread)->mutex);
@@ -1621,6 +1695,7 @@ __pthread_detach (pthread_t *thread)
     return ESRCH;
 
   __pthread_mutex_lock(&(*thread)->mutex);
+
   if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
     {
       __pthread_mutex_unlock(&(*thread)->mutex);
diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h
--- src.old/winsup/cygwin/thread.h	Thu Apr 25 09:15:17 2002
+++ src/winsup/cygwin/thread.h	Thu Apr 25 17:33:29 2002
@@ -239,6 +239,7 @@ public:
   void *return_ptr;
   bool suspended;
   int cancelstate, canceltype;
+  HANDLE cancel_event;
   pthread_mutex *mutex;
   __pthread_cleanup_handler *cleanup_handlers;
   pthread_t joiner;
@@ -502,6 +503,7 @@ int __pthread_setschedparam (pthread_t t
 
 /* cancelability states */
 int __pthread_cancel (pthread_t thread);
+void __pthread_cancel_self (void);
 int __pthread_setcancelstate (int state, int *oldstate);
 int __pthread_setcanceltype (int type, int *oldtype);
 void __pthread_testcancel (void);
