dotgnu-pnet-commits
[Top][All Lists]
Advanced

[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.
   */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]