OSDN Git Service

* cygtls.h (_threadinfo::call): Remove regparm declaration to work around
[pf3gnuchains/sourceware.git] / winsup / cygwin / sync.cc
index f5c2159..dbc2630 100644 (file)
@@ -4,7 +4,7 @@
    which is intended to operate similarly to a mutex but attempts to
    avoid making expensive calls to the kernel.
 
-   Copyright 2000 Cygnus Solutions.
+   Copyright 2000, 2001, 2002 Red Hat, Inc.
 
    Written by Christopher Faylor <cgf@cygnus.com>
 
@@ -21,24 +21,29 @@ details. */
 #include <errno.h>
 #include <stdlib.h>
 #include "sync.h"
-
-muto NO_COPY muto_start;
+#include "security.h"
 
 #undef WaitForSingleObject
 
+DWORD NO_COPY muto::exiting_thread;
+
 /* Constructor */
-muto::muto (int inh, const char *s) : sync (0), visits(0), waiters(-1), tid (0), next (NULL)
+muto *
+muto::init (const char *s)
 {
+  waiters = -1;
   /* Create event which is used in the fallback case when blocking is necessary */
-  if (!(bruteforce = CreateEvent (inh ? &sec_all_nih : &sec_none_nih, FALSE, FALSE, name)))
+  if (!(bruteforce = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL)))
     {
       DWORD oerr = GetLastError ();
       SetLastError (oerr);
-      return;
+      return NULL;
     }
   name = s;
+  return this;
 }
 
+#if 0 /* FIXME: Do we need this? mutos aren't destroyed until process exit */
 /* Destructor (racy?) */
 muto::~muto ()
 {
@@ -46,11 +51,12 @@ muto::~muto ()
     release ();
 
   HANDLE h = bruteforce;
-  h = NULL;
+  bruteforce = NULL;
   /* Just need to close the event handle */
   if (h)
     CloseHandle (h);
 }
+#endif
 
 /* Acquire the lock.  Argument is the number of milliseconds to wait for
    the lock.  Multiple visits from the same thread are allowed and should
@@ -63,6 +69,8 @@ int
 muto::acquire (DWORD ms)
 {
   DWORD this_tid = GetCurrentThreadId ();
+  if (exiting_thread)
+    return this_tid == exiting_thread;
 
   if (tid != this_tid)
     {
@@ -81,12 +89,12 @@ muto::acquire (DWORD ms)
         case, it is possible for a thread which is going to wait for bruteforce
         to wake up immediately.  It will then attempt to grab sync but will fail
         and go back to waiting.  */
-      while (tid != this_tid && (was_waiting || InterlockedExchange (&sync, 1) != 0))
+      if (tid != this_tid && (was_waiting || InterlockedExchange (&sync, 1) != 0))
        {
          switch (WaitForSingleObject (bruteforce, ms))
              {
              case WAIT_OBJECT_0:
-               was_waiting = 0;
+               goto gotit;
                break;
              default:
                InterlockedDecrement (&waiters);
@@ -95,6 +103,7 @@ muto::acquire (DWORD ms)
        }
     }
 
+gotit:
   tid = this_tid;      /* register this thread. */
   return ++visits;     /* Increment visit count. */
 }
@@ -104,6 +113,8 @@ int
 muto::release ()
 {
   DWORD this_tid = GetCurrentThreadId ();
+  if (exiting_thread)
+    return this_tid == exiting_thread;
 
   if (tid != this_tid || !visits)
     {
@@ -115,7 +126,7 @@ muto::release ()
   if (!--visits)
     {
       tid = 0;         /* We were the last unlocker. */
-      InterlockedExchange (&sync, 0); /* Reset trigger. */
+      (void) InterlockedExchange (&sync, 0); /* Reset trigger. */
       /* This thread had incremented waiters but had never decremented it.
         Decrement it now.  If it is >= 0 then there are possibly other
         threads waiting for the lock, so trigger bruteforce. */
@@ -125,3 +136,22 @@ muto::release ()
 
   return 1;    /* success. */
 }
+
+bool
+muto::acquired ()
+{
+  return tid == GetCurrentThreadId ();
+}
+
+/* Call only when we're exiting.  This is not thread safe. */
+void
+muto::reset ()
+{
+  visits = sync = tid = 0;
+  InterlockedExchange (&waiters, -1);
+  if (bruteforce)
+    {
+      CloseHandle (bruteforce);
+      bruteforce = CreateEvent (&sec_none_nih, FALSE, FALSE, name);
+    }
+}