* 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:
parent
80c74a5f38
commit
c25695bbb9
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue