[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnet/engine lib_thread.c,1.11,1.12 monitor.c
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnet/engine lib_thread.c,1.11,1.12 monitor.c,1.2,1.3 |
Date: |
Thu, 26 Jun 2003 18:23:37 -0400 |
Update of /cvsroot/dotgnu-pnet/pnet/engine
In directory subversions:/tmp/cvs-serv17806/engine
Modified Files:
lib_thread.c monitor.c
Log Message:
Fix recursive entry/leave bug in ILWaitMonitorSpeculativeLeave/CompleteLeave.
Added implementation of SetObjectMonitor for hashing monitors.
Index: lib_thread.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/lib_thread.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -r1.11 -r1.12
*** lib_thread.c 26 Jun 2003 03:39:25 -0000 1.11
--- lib_thread.c 26 Jun 2003 22:23:35 -0000 1.12
***************
*** 57,60 ****
--- 57,91 ----
/*
+ * Spins until the object is unmarked and the current thread can mark it.
+ */
+ static void _IL_ObjectLockword_WaitAndMark(ILExecThread *thread, ILObject
*obj)
+ {
+ ILLockWord lockword;
+
+ for (;;)
+ {
+ lockword = GetObjectLockWord(thread, obj);
+
+ if ((CompareAndExchangeObjectLockWord(thread, obj,
IL_LW_MARK(lockword),
+ IL_LW_UNMARK(lockword)) == IL_LW_UNMARK(lockword)))
+ {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Unmarks an object's lockword.
+ */
+ static void _IL_ObjectLockword_Unmark(ILExecThread *thread, ILObject *obj)
+ {
+ ILLockWord lockword;
+
+ lockword = GetObjectLockWord(thread, obj);
+
+ SetObjectLockWord(thread, obj, IL_LW_UNMARK(lockword));
+ }
+
+ /*
* Checks if the monitor is longer being used and returns it to the free
list and
* zeros
***************
*** 85,89 ****
{
int result;
! ILLockWord raw;
ILExecMonitor *monitor, *next;
--- 116,120 ----
{
int result;
! ILLockWord lockword;
ILExecMonitor *monitor, *next;
***************
*** 115,122 ****
retry:
! /* Get the raw lock word */
! raw = GetObjectLockWord(thread, obj);
! if (raw == 0)
{
/* There is no monitor installed for this object */
--- 146,153 ----
retry:
! /* Get the lockword lock word */
! lockword = GetObjectLockWord(thread, obj);
! if (lockword == 0)
{
/* There is no monitor installed for this object */
***************
*** 137,142 ****
obj,
monitor,
! raw
! ) == raw)
{
/* Succesfully installed the new monitor */
--- 168,173 ----
obj,
monitor,
! lockword
! ) == lockword)
{
/* Succesfully installed the new monitor */
***************
*** 162,190 ****
}
! if (IL_LW_MARKED(raw))
{
goto retry;
}
! monitor = IL_LW_UNMARK(raw);
_IL_Interlocked_Increment_Ri(thread, (ILInt32 *)&monitor->waiters);
! raw = GetObjectLockWord(thread, obj);
! if (IL_LW_MARKED(raw))
{
! _IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
_IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
goto retry;
}
! /* If the thread manages to get here then no other thread is going to
return
! obj's monitor to the freelist. The monitor we have is not stale.
*/
! /* Try entering the monitor */
!
result = ILWaitMonitorTryEnter(monitor->supportMonitor, timeout);
--- 193,233 ----
}
! /* If the lockword is marked then it means that another thread is
attempting
! disassociate the monitor with the object. */
! if (IL_LW_MARKED(lockword))
{
+ /* Spin */
goto retry;
}
! monitor = IL_LW_UNMARK(lockword);
+ /* Speculatively increment the number of waiters */
_IL_Interlocked_Increment_Ri(thread, (ILInt32 *)&monitor->waiters);
! /* Now double check and see if another thread is trying to exit the
! now that monitor->waiters has been incremented monitor */
! lockword = GetObjectLockWord(thread, obj);
! if (IL_LW_MARKED(lockword))
{
! /* Mark the object's lockword */
! _IL_ObjectLockword_WaitAndMark(thread, obj);
!
! /* The current thread has exclusive access to the object's
lockword */
+ _IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
_IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
+ /* Unmark the object's lockword */
+ _IL_ObjectLockword_Unmark(thread, obj);
+
goto retry;
}
! /* If we get here then we know that no other thread can reassign the
object's
! monitor */
! /* Try entering the monitor */
result = ILWaitMonitorTryEnter(monitor->supportMonitor, timeout);
***************
*** 194,198 ****
--- 237,250 ----
if (result != 0)
{
+ /* Mark the object's lockword */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
+
+ /* The current thread has exclusive access to the object's
lockword */
+
+ _IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
_IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
+
+ /* Unmark the object's lockword */
+ _IL_ObjectLockword_Unmark(thread, obj);
}
***************
*** 208,214 ****
void _IL_Monitor_Exit(ILExecThread *thread, ILObject *obj)
{
! ILLockWord raw;
ILExecMonitor *monitor;
!
/* Make sure obj isn't null */
if(obj == 0)
--- 260,266 ----
void _IL_Monitor_Exit(ILExecThread *thread, ILObject *obj)
{
! ILLockWord lockword;
ILExecMonitor *monitor;
!
/* Make sure obj isn't null */
if(obj == 0)
***************
*** 218,229 ****
return;
}
! retry:
!
! /* Get the monitor */
! raw = GetObjectLockWord(thread, obj);
!
! monitor = IL_LW_UNMARK(raw);
if (monitor == 0)
{
--- 270,283 ----
return;
}
+
+ /* Make sure noone is allowed to change the object's monitor */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
! /* Get the most up to date lock word. It can't change from here on in
*/
! lockword = GetObjectLockWord(thread, obj);
+ monitor = IL_LW_UNMARK(lockword);
+
+ /* Make sure the monitor is valid */
if (monitor == 0)
{
***************
*** 232,238 ****
ILExecThreadThrowSystem
(
! thread,
!
"System.Threading.SynchronizationLockException",
! "Exception_ThreadNeedsLock"
);
--- 286,292 ----
ILExecThreadThrowSystem
(
! thread,
! "System.ArgumentException",
! "Exception_ThreadNeedsLock"
);
***************
*** 240,276 ****
}
- /*
- * Problem:
- *
- * The following code relies on the fact that no thread is allowed to
enter,
- * wait or exit the monitor. If this condition is met and there are no
and
- * the monitor nolonger has owners or waiters, we can return the monitor
- * to the free list.
- *
- * Solution:
- * Use a marker in the object pointer (the first bit).
- * When this marker is marked, threads attempting to enter/wait/exit
will spin.
- * Note: Threads attempting to enter/wait/exit need to:
- * Check the marker. If marker is 1 then spin.
- * Increment the monitor's waiter count.
- * Check the marker. If the marker is one then decrement
and spin.
- * Do the enter/wait/exit.
- */
-
- if (CompareAndExchangeObjectLockWord(thread, obj, IL_LW_MARK(raw),
- IL_LW_UNMARK(raw)) != IL_LW_UNMARK(raw))
- {
- /* Some other thread is trying to exit the same object! Either
this or the
- other thread is mistaken. Spin until the other thread
exits enter. */
-
- goto retry;
- }
-
- /* From this point on, other new threads attempting to wait, enter or
exit
- the object will spin. */
-
- /* This is the number of waiters there are. This can not increase until
- we unmark the lock word, but, it can decrease */
-
if (ILWaitMonitorSpeculativeLeave(monitor->supportMonitor) == 1
/* Note: No need to check for aborts on call to leave */)
--- 294,297 ----
***************
*** 278,289 ****
if (!_IL_Monitor_CheckAndReturnMonitorToFreeList(thread,
monitor, obj))
{
! /* There are waiters */
! /* Simply unmark the lock word */
!
! SetObjectLockWord(thread, obj, IL_LW_UNMARK(raw));
}
else
! {
! /* There are no waiters. The monitor has been returned
to the free list. */
}
--- 299,308 ----
if (!_IL_Monitor_CheckAndReturnMonitorToFreeList(thread,
monitor, obj))
{
! /* There are waiters. Unmark the lockword */
! _IL_ObjectLockword_Unmark(thread, obj);
}
else
! {
! /* The object's lockword has been cleared. This
implicitly unmarks it */
}
***************
*** 293,297 ****
{
/* We don't own the monitor */
!
ILExecThreadThrowSystem
(
--- 312,316 ----
{
/* We don't own the monitor */
!
ILExecThreadThrowSystem
(
***************
*** 301,306 ****
);
! /* Restore the lockword back to its unoriginal unmarked state */
! SetObjectLockWord(thread, obj, IL_LW_UNMARK(raw));
}
}
--- 320,325 ----
);
! /* Unmark the lockword */
! _IL_ObjectLockword_Unmark(thread, obj);
}
}
***************
*** 313,321 ****
{
int result;
! ILLockWord raw;
ILExecMonitor *monitor;
- retry:
-
/* Make sure obj isn't null */
if (obj == 0)
--- 332,338 ----
{
int result;
! ILLockWord lockword;
ILExecMonitor *monitor;
/* Make sure obj isn't null */
if (obj == 0)
***************
*** 326,352 ****
}
! raw = GetObjectLockWord(thread, obj);
!
! if (IL_LW_MARKED(raw))
! {
! /* Exit is being called on the object's monitor. We have to
spin. */
! goto retry;
! }
! monitor = IL_LW_UNMARK(raw);
!
! if (monitor == 0)
{
! /* Object doesn't even have a lock */
!
! ILExecThreadThrowSystem
! (
! thread,
! "System.Threading.SynchronizationLockException",
! "Exception_ThreadNeedsLock"
! );
!
! return 0;
}
--- 343,356 ----
}
! retry:
! lockword = GetObjectLockWord(thread, obj);
! /* If the lockword is marked then it means that another thread is
attempting
! disassociate the monitor with the object. */
! if (IL_LW_MARKED(lockword))
{
! /* Spin */
! goto retry;
}
***************
*** 367,375 ****
*/
_IL_Interlocked_Increment_Ri(thread, (ILInt32 *)&monitor->waiters);
! raw = GetObjectLockWord(thread, obj);
! if (IL_LW_MARKED(raw))
{
/*
--- 371,381 ----
*/
+ monitor = IL_LW_UNMARK(lockword);
+
_IL_Interlocked_Increment_Ri(thread, (ILInt32 *)&monitor->waiters);
! lockword = GetObjectLockWord(thread, obj);
! if (IL_LW_MARKED(lockword))
{
/*
***************
*** 390,401 ****
*/
- _IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
-
/*
* Problem:
*
* A gets here after failing the double check cause B *just*
marked the lock word.
! * B notices there are no waiters.
! * B returns the monitor to the free list.
* A notices that B has marked the lock word.
* A decrements the waiter count.
--- 396,406 ----
*/
/*
* Problem:
*
* A gets here after failing the double check cause B *just*
marked the lock word.
! * A decrements counter.
! * B notices there are no waiters.
! * B returns the monitor to the free list.
* A notices that B has marked the lock word.
* A decrements the waiter count.
***************
*** 412,422 ****
*/
_IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
goto retry;
}
! /* If we get here then we know the object's monitor can't be removed
! by anyone. */
switch (result = ILWaitMonitorWait(monitor->supportMonitor, timeout))
--- 417,473 ----
*/
+ /*
+ * Problem:
+ *
+ * A gets here (monitor->waiters = 1)
+ * B does speculative leave (monitor->Waiters = 1)
+ * A decrements monitor->waiters (monitor->waiters = 0).
+ * B return monitor to free list.
+ * A returns monitor to free list.
+ *
+ * A gets here (monitor->waiters = 1)
+ * A decrements monitor->waiters (monitor->waiters = 0).
+ * b notices waters = 0.
+ * B does speculative leave (monitor->Waiters = 0)
+ * B return monitor to free list.
+ * A returns monitor to free list.
+ *
+ * Don't decrement monitor->waiters until we know B has unmarked
+ * the lockword thus preventing B from returning the monitor to
the
+ * free list.
+ */
+
+ /* Mark the object's lockword */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
+
+ /* The current thread has exclusive access to the object's
lockword */
+
+ _IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
_IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
+ /* Unmark the object's lockword */
+ _IL_ObjectLockword_Unmark(thread, obj);
+
goto retry;
}
+
+ monitor = IL_LW_UNMARK(lockword);
+
+ if (monitor == 0)
+ {
+ /* Object doesn't even have a lock */
+
+ ILExecThreadThrowSystem
+ (
+ thread,
+ "System.Threading.SynchronizationLockException",
+ "Exception_ThreadNeedsLock"
+ );
+
+ return 0;
+ }
! /* If we get here then we know that no other thread can reassign the
object's
! monitor */
switch (result = ILWaitMonitorWait(monitor->supportMonitor, timeout))
Index: monitor.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/monitor.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** monitor.c 26 Jun 2003 11:52:51 -0000 1.2
--- monitor.c 26 Jun 2003 22:23:35 -0000 1.3
***************
*** 226,229 ****
--- 226,238 ----
/*
+ * Implementation of SetObjectLockWord using hashtables.
+ */
+ void SetObjectLockWord(ILExecThread *thread, ILObject *obj, value)
+ {
+ *GetObjectLockWordPtr(thread, obj) = value;
+ }
+
+
+ /*
* Implementation of CompareAndExchangeObjectLockWord using hashtables.
*/
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnet/engine lib_thread.c,1.11,1.12 monitor.c,1.2,1.3,
Rhys Weatherley <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] CVS: pnet ChangeLog,1.2469,1.2470 configure.in,1.130,1.131
- Next by Date:
[Dotgnu-pnet-commits] CVS: pnet/cscc/csharp cs_gather.c,1.41,1.42 cs_internal.h,1.19,1.20 cs_modifiers.c,1.6,1.7
- Previous by thread:
[Dotgnu-pnet-commits] CVS: pnet ChangeLog,1.2469,1.2470 configure.in,1.130,1.131
- Next by thread:
[Dotgnu-pnet-commits] CVS: pnet/cscc/csharp cs_gather.c,1.41,1.42 cs_internal.h,1.19,1.20 cs_modifiers.c,1.6,1.7
- Index(es):