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>
#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 ()
{
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
muto::acquire (DWORD ms)
{
DWORD this_tid = GetCurrentThreadId ();
+ if (exiting_thread)
+ return this_tid == exiting_thread;
if (tid != this_tid)
{
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);
}
}
+gotit:
tid = this_tid; /* register this thread. */
return ++visits; /* Increment visit count. */
}
muto::release ()
{
DWORD this_tid = GetCurrentThreadId ();
+ if (exiting_thread)
+ return this_tid == exiting_thread;
if (tid != this_tid || !visits)
{
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. */
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);
+ }
+}