* exceptions.cc (try_to_debug): Report on tid of caller.

* sync.cc (muto::acquire): Fix some races.
* sync.h (muto): Expose some fields for easier debugging.
This commit is contained in:
Christopher Faylor 2004-03-15 15:50:20 +00:00
parent 80c74a5f38
commit c25695bbb9
4 changed files with 31 additions and 31 deletions

View File

@ -1,3 +1,10 @@
2004-03-15 Christopher Faylor <cgf@redhat.com>
* exceptions.cc (try_to_debug): Report on tid of caller.
* sync.cc (muto::acquire): Fix some races.
* sync.h (muto): Expose some fields for easier debugging.
2004-03-15 Corinna Vinschen <corinna@vinschen.de> 2004-03-15 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (fhandler_dev_tape::tape_get_pos): Declare with extra * fhandler.h (fhandler_dev_tape::tape_get_pos): Declare with extra

View File

@ -349,8 +349,8 @@ try_to_debug (bool waitloop)
} }
} }
console_printf ("*** starting debugger for pid %u\n", console_printf ("*** starting debugger for pid %u, tid %u\n",
cygwin_pid (GetCurrentProcessId ())); cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
BOOL dbg; BOOL dbg;
dbg = CreateProcess (NULL, dbg = CreateProcess (NULL,
debugger_command, debugger_command,

View File

@ -64,7 +64,8 @@ muto::~muto ()
Note: The goal here is to minimize, as much as possible, calls to the Note: The goal here is to minimize, as much as possible, calls to the
OS. Hence the use of InterlockedIncrement, etc., rather than (much) more OS. Hence the use of InterlockedIncrement, etc., rather than (much) more
expensive OS mutexes. */ expensive OS mutexes. Also note that the only two valid "ms" times are
0 and INFINITE. */
int int
muto::acquire (DWORD ms) muto::acquire (DWORD ms)
{ {
@ -78,35 +79,27 @@ muto::acquire (DWORD ms)
{ {
/* Increment the waiters part of the class. Need to do this first to /* Increment the waiters part of the class. Need to do this first to
avoid potential races. */ avoid potential races. */
LONG was_waiting = InterlockedIncrement (&waiters); LONG was_waiting = ms ? InterlockedIncrement (&waiters) : 0;
/* This is deceptively simple. Basically, it allows multiple attempts to while (was_waiting || InterlockedExchange (&sync, 1) != 0)
lock the same muto to succeed without attempting to manipulate sync. {
If the muto is already locked then this thread will wait for ms until switch (WaitForSingleObject (bruteforce, ms))
it is signalled by muto::release. Then it will attempt to grab the {
sync field. If it succeeds, then this thread owns the muto. case WAIT_OBJECT_0:
was_waiting = 0;
break;
default:
return 0; /* failed. */
}
}
There is a pathological condition where a thread times out waiting for /* Have to do it this way to avoid a race */
bruteforce but the release code triggers the bruteforce event. In this if (!ms)
case, it is possible for a thread which is going to wait for bruteforce InterlockedIncrement (&waiters);
to wake up immediately. It will then attempt to grab sync but will fail
and go back to waiting. */ tid = this_tid; /* register this thread. */
if (tid != this_tid && (was_waiting || InterlockedExchange (&sync, 1) != 0))
{
switch (WaitForSingleObject (bruteforce, ms))
{
case WAIT_OBJECT_0:
goto gotit;
break;
default:
InterlockedDecrement (&waiters);
return 0; /* failed. */
}
}
} }
gotit:
tid = this_tid; /* register this thread. */
return ++visits; /* Increment visit count. */ return ++visits; /* Increment visit count. */
} }
@ -129,7 +122,7 @@ muto::release ()
(void) InterlockedExchange (&sync, 0); /* Reset trigger. */ (void) InterlockedExchange (&sync, 0); /* Reset trigger. */
/* This thread had incremented waiters but had never decremented it. /* This thread had incremented waiters but had never decremented it.
Decrement it now. If it is >= 0 then there are possibly other Decrement it now. If it is >= 0 then there are possibly other
threads waiting for the lock, so trigger bruteforce. */ threads waiting for the lock, so trigger bruteforce. */
if (InterlockedDecrement (&waiters) >= 0) if (InterlockedDecrement (&waiters) >= 0)
(void) SetEvent (bruteforce); /* Wake up one of the waiting threads */ (void) SetEvent (bruteforce); /* Wake up one of the waiting threads */
} }

View File

@ -18,11 +18,11 @@ class muto
{ {
static DWORD exiting_thread; static DWORD exiting_thread;
LONG sync; /* Used to serialize access to this class. */ LONG sync; /* Used to serialize access to this class. */
LONG visits; /* Count of number of times a thread has called acquire. */
LONG waiters; /* Number of threads waiting for lock. */ LONG waiters; /* Number of threads waiting for lock. */
HANDLE bruteforce; /* event handle used to control waiting for lock. */ HANDLE bruteforce; /* event handle used to control waiting for lock. */
DWORD tid; /* Thread Id of lock owner. */
public: public:
LONG visits; /* Count of number of times a thread has called acquire. */
DWORD tid; /* Thread Id of lock owner. */
// class muto *next; // class muto *next;
const char *name; const char *name;