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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and to


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. 86899efd7040d519f7770461e1d2cc6c829ab1e5
Date: Sun, 21 Feb 2010 14:14:19 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "DotGNU Portable.NET engine, compilers and tools (pnet)".

The branch, master has been updated
       via  86899efd7040d519f7770461e1d2cc6c829ab1e5 (commit)
      from  dd4a200f0ed7033d8d0c1f7a17b4fdbe796105bc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/pnet.git/commit/?id=86899efd7040d519f7770461e1d2cc6c829ab1e5

commit 86899efd7040d519f7770461e1d2cc6c829ab1e5
Author: Klaus Treichel <address@hidden>
Date:   Sun Feb 21 15:13:59 2010 +0100

    Add support for a thread local monitor free list.

diff --git a/ChangeLog b/ChangeLog
index d059cc0..9b412ab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2010-02-21  Klaus Treichel  <address@hidden>
+
+       * support/monitor.c: Replace the single list of monitors by one with
+       all monitors and one global free list.
+       (_ILMonitorInit, _ILMonitorDestroy): Adjust for the two lists.
+       (DestroyMonitorList): Rename to DestroyMonitorUsedList.
+       (ListCount): Replace by the new functions FreeListCount and
+       UsedListCount.
+       (ILMonitorPrintStats): Relplace calls to ListCount by calls to the
+       replacements.
+       (_ILMonitorPoolDestoy): Destroy only the monitors on the used list
+       because all monitors are on this list now..
+       (_ILMonitorPoolAllocMonitor): Adjust for the two monitor lists and
+       use _ILMonitorAcquire to get the ownership of a monitor on the global
+       free list.
+       (_ILMonitorPoolReclaimMonitor): Adjust for the two monitor lists.
+       (_ILMonitorPoolMoveToFreeList): Rename to _ILMonitorPoolAddToFreeList.
+       (_ILMonitorPoolAddListToFreeList): Add function for adding a monitor
+       list to the fglobal free list.
+       (_ILMonitorDestroyThread): Add function for cleaning up thread local
+       monitor free lists.
+       (ILMonitorTimedTryEnter): Add handling for thread local monitor free
+       lists.
+       (ILMonitorExit): likewise
+
+       * support/no_defs.h, support/pt_defs.h, support/w32_defs.h: Add
+       definitions for _ILMonitorAcquire and _ILMonitorRelease.
+
+       * support/thr_defs.h: Add members for the thread local monitor free
+       list to the ILThread declaration.
+       (_ILMonitorDestroyThread): Add prototype.
+
+       * support/thread.c (_ILThreadDeinit, ILThreadRunSelf, _ILThreadRun):
+       Add calls to the new monitor cleanup function.
+
 2010-02-14  Klaus Treichel  <address@hidden>
 
        * configure.in: Extend the  --with-libffi switch so that it's possible
diff --git a/support/monitor.c b/support/monitor.c
index e6595c1..8ae4a88 100755
--- a/support/monitor.c
+++ b/support/monitor.c
@@ -34,9 +34,21 @@
 extern "C" {
 #endif
 
+/*
+ * Number of monitors that should be kept in the thread local freelist.
+ */
+#define MIN_FREELIST_MONITORS  2
+
+/*
+ * Number of monitors in the thread local freelist that triggers a move of
+ * monitors from the thread local freelist to the global freelist.
+ */
+#define MAX_FREELIST_MONITORS  5
+
 struct _tagILMonitor
 {
-       ILMonitor                  *next;               /* The next monitor in 
the list */
+       ILMonitor                  *nextUsed;   /* The next monitor in the used 
list */
+       ILMonitor                  *nextFree;   /* The next monitor in the free 
list */
        ILThread * volatile     owner;          /* The current owner of the 
monotor */
        ILInt32                         enterCount;     /* The number of enters 
without corresponding leave by the owner */
        ILUInt32                        users;          /* The number of 
threads using this monitor */
@@ -68,7 +80,7 @@ static int ILMonitorInit(ILMonitor *monitor, ILThread *thread)
 {
        int result;
 
-       monitor->next = 0;
+       monitor->nextFree = 0;
        monitor->owner = thread;
        monitor->enterCount = 1;
        monitor->users = 1;
@@ -80,27 +92,41 @@ static void ILMonitorDestroy(ILMonitor *monitor)
 {
        int result;
 
-       monitor->next = 0;
+       monitor->nextUsed = 0;
+       monitor->nextFree = 0;
        monitor->owner = 0;
        monitor->enterCount = 0;
        monitor->users = 0;
        _ILMonitorDestroy(&(monitor->monitor), result);
 }
 
-static void DestroyMonitorList(ILMonitor *monitor)
+static void DestroyMonitorUsedList(ILMonitor *monitor)
 {
        while(monitor)
        {
                ILMonitor *next;
 
-               next = monitor->next;
+               next = monitor->nextUsed;
                ILMonitorDestroy(monitor);
                monitor = next;
        }
 }
 
 #ifdef IL_THREAD_DEBUG
-static int ListCount(ILMonitor *monitor)
+static int FreeListCount(ILMonitor *monitor)
+{
+       int count;
+
+       count = 0;
+       while(monitor)
+       {
+               ++count;
+               monitor = monitor->nextFree;
+       }
+       return count;
+}
+
+static int UsedListCount(ILMonitor *monitor)
 {
        int count;
 
@@ -108,7 +134,7 @@ static int ListCount(ILMonitor *monitor)
        while(monitor)
        {
                ++count;
-               monitor = monitor->next;
+               monitor = monitor->nextUsed;
        }
        return count;
 }
@@ -116,9 +142,9 @@ static int ListCount(ILMonitor *monitor)
 void ILMonitorPrintStats()
 {
        fprintf(stderr, "Number of monitors in the used list: %i\n",
-                   ListCount(_MonitorPool.usedList));
+                   UsedListCount(_MonitorPool.usedList));
        fprintf(stderr, "Number of monitors in the free list: %i\n",
-                   ListCount(_MonitorPool.freeList));
+                   FreeListCount(_MonitorPool.freeList));
        fprintf(stderr, "Number of reclaimed monitors: %i\n",
                                        _MonitorPool.numReclaimed);
        fprintf(stderr, "Number of abandoned monitors: %i\n",
@@ -142,14 +168,13 @@ static void _ILMonitorPoolDestroy(void)
 #ifdef IL_THREAD_DEBUG
        ILMonitorPrintStats();
 #endif
-       DestroyMonitorList(_MonitorPool.freeList);
-       _MonitorPool.freeList = 0;
        /*
         * NOTE: If the usedList is not 0 we will be in very big trouble 
afterwards
         * if references to monitors in the pool are used later.
         */
-       DestroyMonitorList(_MonitorPool.usedList);
+       DestroyMonitorUsedList(_MonitorPool.usedList);
        _MonitorPool.usedList = 0;
+       _MonitorPool.freeList = 0;
        _ILCriticalSectionDestroy(&(_MonitorPool.lock));
        ILMemPoolDestroy(&(_MonitorPool.pool));
 }
@@ -160,32 +185,30 @@ static void _ILMonitorPoolDestroy(void)
  * The monitor is owned by the current if the function returns success.
  * This function must be called with the monitorpool lock held.
  */
-static int _ILMonitorPoolAllocMonitor(ILThread *thread, void **monitorLocation)
+static int _ILMonitorPoolAllocMonitor(ILThread *thread, ILMonitor 
**monitorLocation)
 {
        ILMonitor *monitor;
        int result;
 
        if(_MonitorPool.freeList)
        {
-               /* We have a monitor on the freelist so reuse this one */
+               /* We have a monitor on the global freelist so reuse this one */
                monitor = _MonitorPool.freeList;
-               _MonitorPool.freeList = monitor->next;
-               if((result = _ILMonitorTryEnter(&(monitor->monitor))) == 
IL_THREAD_OK)
+               _MonitorPool.freeList = monitor->nextFree;
+               monitor->nextFree = (ILMonitor *)0;
+               if((result = _ILMonitorAcquire(&(monitor->monitor))) == 
IL_THREAD_OK)
                {
                        /* Initialize the monitor state */
                        monitor->owner = thread;
                        monitor->enterCount = 1;
                        monitor->users = 1;
-                       /* Add the monitor to the used list */
-                       monitor->next = _MonitorPool.usedList;
-                       _MonitorPool.usedList = monitor;
-                       /* Store the monitor at the monitor location given */
-                       ILInterlockedStoreP(monitorLocation, monitor);
+                       /* Return the monitor */
+                       *monitorLocation = monitor;
                }
                else
                {
-                       /* Move this monitor back to the freelist */
-                       monitor->next = _MonitorPool.freeList;
+                       /* Add this monitor to the freelist */
+                       monitor->nextFree = _MonitorPool.freeList;
                        _MonitorPool.freeList = monitor;
                }
                return result;
@@ -195,18 +218,19 @@ static int _ILMonitorPoolAllocMonitor(ILThread *thread, 
void **monitorLocation)
                monitor = ILMemPoolAllocItem(&(_MonitorPool.pool));
                if(monitor)
                {
+                       /* Add the monitor to the list of monitors*/
+                       monitor->nextUsed = _MonitorPool.usedList;
+                       _MonitorPool.usedList = monitor;
+
                        if((result = ILMonitorInit(monitor, thread)) == 
IL_THREAD_OK)
                        {
-                               /* Add the monitor to the used list */
-                               monitor->next = _MonitorPool.usedList;
-                               _MonitorPool.usedList = monitor;
-                               /* Store the monitor at the monitor location 
given */
-                               ILInterlockedStoreP(monitorLocation, monitor);
+                               /* Return the monitor */
+                               *monitorLocation = monitor;
                        }
                        else
                        {
-                               /* Move this monitor to the freelist */
-                               monitor->next = _MonitorPool.freeList;
+                               /* Add this monitor to the freelist */
+                               monitor->nextFree = _MonitorPool.freeList;
                                _MonitorPool.freeList = monitor;
                        }
                        return result;
@@ -227,7 +251,7 @@ static void _ILMonitorPoolReclaimMonitor(_ILMonitorPool 
*pool,
 {
        if(pool->usedList == monitor)
        {
-               pool->usedList = monitor->next;
+               pool->usedList = monitor->nextUsed;
                ILMonitorDestroy(monitor);
                ILMemPoolFree(&(pool->pool), monitor);
 #ifdef IL_THREAD_DEBUG
@@ -241,9 +265,9 @@ static void _ILMonitorPoolReclaimMonitor(_ILMonitorPool 
*pool,
                prevMonitor = pool->usedList;
                while(prevMonitor)
                {
-                       if(prevMonitor->next == monitor)
+                       if(prevMonitor->nextUsed == monitor)
                        {
-                               prevMonitor->next = monitor->next;
+                               prevMonitor->nextUsed = monitor->nextUsed;
                                ILMonitorDestroy(monitor);
                                ILMemPoolFree(&(pool->pool), monitor);
 #ifdef IL_THREAD_DEBUG
@@ -251,41 +275,32 @@ static void _ILMonitorPoolReclaimMonitor(_ILMonitorPool 
*pool,
 #endif
                                return;
                        }
-                       prevMonitor = prevMonitor->next;
+                       prevMonitor = prevMonitor->nextUsed;
                }
        }
 }
 
 /*
- * Move a monitor from the used list to the free list of the monitor pool.
- * This function must be called with the monitorpool lock held.
+ * Add a monitor to the global freelist.
+ * The monitor pool lock must be held.
  */
-static void _ILMonitorPoolMoveToFreeList(_ILMonitorPool *pool,
+static void _ILMonitorPoolAddToFreeList(_ILMonitorPool *pool,
                                                                                
 ILMonitor *monitor)
 {
-       if(pool->usedList == monitor)
-       {
-               pool->usedList = monitor->next;
-               monitor->next = pool->freeList;
-               pool->freeList = monitor;
-       }
-       else
-       {
-               ILMonitor *prevMonitor;
+       monitor->nextFree = pool->freeList;
+       pool->freeList = monitor;
+}
 
-               prevMonitor = pool->usedList;
-               while(prevMonitor)
-               {
-                       if(prevMonitor->next == monitor)
-                       {
-                               prevMonitor->next = monitor->next;
-                               monitor->next = pool->freeList;
-                               pool->freeList = monitor;
-                               return;
-                       }
-                       prevMonitor = prevMonitor->next;
-               }
-       }
+/*
+ * Add a list of monitors to the global freelist.
+ * The monitor pool lock must be held.
+ */
+static void _ILMonitorPoolAddListToFreeList(_ILMonitorPool *pool,
+                                                                               
         ILMonitor *firstMonitor,
+                                                                               
         ILMonitor *lastMonitor)
+{
+       lastMonitor->nextFree = pool->freeList;
+       pool->freeList = firstMonitor;
 }
 
 void _ILMonitorSystemInit()
@@ -298,10 +313,47 @@ void _ILMonitorSystemDeinit()
        _ILMonitorPoolDestroy();
 }
 
+void _ILMonitorDestroyThread(ILThread *thread)
+{
+       IL_THREAD_ASSERT(thread == _ILThreadGetSelf());
+       if(thread->monitorFreeList)
+       {
+               ILMonitor *firstMonitor;
+               ILMonitor *lastMonitor;
+
+               firstMonitor = thread->monitorFreeList;
+               thread->monitorFreeList = 0;
+               lastMonitor = firstMonitor;
+               while(lastMonitor)
+               {
+                       IL_THREAD_ASSERT(lastMonitor->users == 1)
+                       lastMonitor->owner = 0;
+                       lastMonitor->users = 0;
+                       _ILMonitorRelease(&(lastMonitor->monitor));
+                       if(lastMonitor->nextFree == 0)
+                       {
+                               break;
+                       }
+                       lastMonitor = lastMonitor->nextFree;
+               }
+
+               /* Lock the monitor system */
+               _ILCriticalSectionEnter(&(_MonitorPool.lock));
+
+               _ILMonitorPoolAddListToFreeList(&_MonitorPool,
+                                                                               
firstMonitor, lastMonitor);
+
+               /* Unlock the monitor system */
+               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+       }
+}
+
 int ILMonitorTimedTryEnter(void **monitorLocation, ILUInt32 ms)
 {
        ILMonitor *monitor;
        ILThread *thread;
+       int result;
+       int waitStateResult;
 
        if(!monitorLocation)
        {
@@ -311,153 +363,211 @@ int ILMonitorTimedTryEnter(void **monitorLocation, 
ILUInt32 ms)
        thread = _ILThreadGetSelf();
 
        monitor = (ILMonitor *)ILInterlockedLoadP(monitorLocation);
-       if((monitor != 0) && (monitor->owner == thread))
+       if(monitor != 0)
        {
-               /*
-                * I'm already the owner of this monitor.
-                * So simply increase the enter count.
-                */
-               ++(monitor->enterCount);
+               if(monitor->owner == thread)
+               {
+                       /*
+                        * I'm already the owner of this monitor.
+                        * So simply increase the enter count.
+                        */
+                       ++(monitor->enterCount);
+                       return IL_THREAD_OK;
+               }
        }
-       else
+       else if(thread->monitorFreeList)
        {
                /*
-                * We have to enter the monitor.
+                * The monitor location is not occupied and there is a monitor 
in the
+                * thread's freelist so try to get the monitor without 
acquiring the
+                * monitor pool lock.
                 */
-               int result;
-               int waitStateResult;
+               monitor = thread->monitorFreeList;
+               if(ILInterlockedCompareAndExchangeP_Acquire(monitorLocation,
+                                                                               
                        monitor, 0) == 0)
+               {
+                       /*
+                        * Remove the monitor from the thread's freelist.
+                        */
+                       thread->monitorFreeList = monitor->nextFree;
+                       monitor->nextFree = 0;
+                       --thread->monitorFreeCount;
+                       return IL_THREAD_OK;
+               }
+       }
+       /*
+        * If we get here we have to acquire the monitor the hard way.
+        */
 
-               /* Lock the monitor system */
-               _ILCriticalSectionEnter(&(_MonitorPool.lock));
-               
-               monitor = (ILMonitor *)ILInterlockedLoadP(monitorLocation);
-               if(monitor == 0)
+       /* Lock the monitor system */
+       _ILCriticalSectionEnter(&(_MonitorPool.lock));
+
+       monitor = (ILMonitor *)ILInterlockedLoadP(monitorLocation);
+       if(monitor == 0)
+       {
+               if(thread->monitorFreeList)
                {
-                       /* We have to allocate a new monitor */
-                       result = _ILMonitorPoolAllocMonitor(thread, 
monitorLocation);
-                       /* Unlock the monitor system */
-                       _ILCriticalSectionLeave(&(_MonitorPool.lock));
+                       monitor = thread->monitorFreeList;
+                       
if(ILInterlockedCompareAndExchangeP_Acquire(monitorLocation,
+                                                                               
                                monitor, 0) == 0)
+                       {
+                               /*
+                                * Release the global monitor lock.
+                                */
+                               _ILCriticalSectionLeave(&(_MonitorPool.lock));
 
-                       return result;
+                               /*
+                                * And remove the monitor from the thread's 
freelist.
+                                */
+                               thread->monitorFreeList = monitor->nextFree;
+                               monitor->nextFree = 0;
+                               --thread->monitorFreeCount;
+                               return IL_THREAD_OK;
+                       }
+                       monitor = (ILMonitor 
*)ILInterlockedLoadP(monitorLocation);
                }
-               if(monitor->owner == 0)
+               else
                {
-                       /* Add me to the monitor users */
-                       ++(monitor->users);
+                       /* We have to allocate a new monitor */
+                       result = _ILMonitorPoolAllocMonitor(thread, &monitor);
 
-                       /*
-                        * We can acquire the monitor in the lock here because 
we are
-                        * sure that it's not owned by someone else.
-                        */
-                       result = _ILMonitorTryEnter(&(monitor->monitor));
                        if(result == IL_THREAD_OK)
                        {
-                               /* Set me as owner of the monitor */
-                               monitor->owner = thread;
-                               /* And initialize my enter count to 1 */
-                               monitor->enterCount = 1;
-                               
-                               /* Unlock the monitor system */
-                               _ILCriticalSectionLeave(&(_MonitorPool.lock));
-                       
-                               return result;
-                       }
-                       else if(result == IL_THREAD_BUSY)
-                       {
-                               if(ms == 0)
+                               
if(ILInterlockedCompareAndExchangeP_Acquire(monitorLocation,
+                                                                               
                                        monitor, 0) == 0)
                                {
-                                       /* Rmove me from the monitor users */
-                                       --(monitor->users);
-                                       
-                                       /* Unlock the monitor system */
+                                       /*
+                                        * Release the global monitor lock.
+                                        */
                                        
_ILCriticalSectionLeave(&(_MonitorPool.lock));
-                       
                                        return result;
                                }
+                               monitor = (ILMonitor 
*)ILInterlockedLoadP(monitorLocation);
+                       }
+                       else
+                       {
+                               /* Unlock the monitor system */
+                               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+                               return result;
                        }
-                       /* Rmove me from the monitor users */
-                       --(monitor->users);
                }
-               if(ms == 0)
+       }
+       if(monitor->owner == 0)
+       {
+               /* Add me to the monitor users */
+               ++(monitor->users);
+
+               /*
+                * We can acquire the monitor in the lock here because we are
+                * sure that it's not owned by someone else.
+                */
+               result = _ILMonitorTryEnter(&(monitor->monitor));
+               if(result == IL_THREAD_OK)
                {
-                       /*
-                        * We have to acquire the monitor lock without waiting.
-                        * This is not possible.
-                        */
+                       /* Set me as owner of the monitor */
+                       monitor->owner = thread;
+                       /* And initialize my enter count to 1 */
+                       monitor->enterCount = 1;
 
                        /* Unlock the monitor system */
                        _ILCriticalSectionLeave(&(_MonitorPool.lock));
 
-                       return IL_THREAD_BUSY;
+                       return result;
                }
-               /*
-                * Enter the Wait/Sleep/Join state.
-                */
-               result = _ILThreadEnterWaitState(thread);
-               if(result != IL_THREAD_OK)
+               else if(result == IL_THREAD_BUSY)
                {
-                       /* Unlock the monitor pool */
-                       _ILCriticalSectionLeave(&(_MonitorPool.lock));
+                       if(ms == 0)
+                       {
+                               /* Rmove me from the monitor users */
+                               --(monitor->users);
 
-                       return result;
+                               /* Unlock the monitor system */
+                               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+
+                               return result;
+                       }
                }
-               /* Add me to the monitor users */
-               ++(monitor->users);
+               /* Rmove me from the monitor users */
+               --(monitor->users);
+       }
+       if(ms == 0)
+       {
+               /*
+                * We have to acquire the monitor lock without waiting.
+                * This is not possible.
+                */
 
+               /* Unlock the monitor system */
+               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+
+               return IL_THREAD_BUSY;
+       }
+       /*
+        * Enter the Wait/Sleep/Join state.
+        */
+       result = _ILThreadEnterWaitState(thread);
+       if(result != IL_THREAD_OK)
+       {
                /* Unlock the monitor pool */
                _ILCriticalSectionLeave(&(_MonitorPool.lock));
 
-               /* Try to acquire the monitor */
-               result = _ILMonitorTimedTryEnter(&(monitor->monitor), ms);
+               return result;
+       }
+       /* Add me to the monitor users */
+       ++(monitor->users);
 
-               waitStateResult = _ILThreadLeaveWaitState(thread, result);
+       /* Unlock the monitor pool */
+       _ILCriticalSectionLeave(&(_MonitorPool.lock));
 
-               if((result == IL_THREAD_OK) && (waitStateResult == 
IL_THREAD_OK))
-               {
-                       /*
-                        * The owner should be 0 at this point.
-                        */
-                       monitor->owner = thread;
-                       monitor->enterCount = 1;
-               }
-               else
-               {
-                       /* Lock the monitor system again */
-                       _ILCriticalSectionEnter(&(_MonitorPool.lock));
+       /* Try to acquire the monitor */
+       result = _ILMonitorTimedTryEnter(&(monitor->monitor), ms);
 
-                       /* Remove me from the user list */
-                       --(monitor->users);
+       waitStateResult = _ILThreadLeaveWaitState(thread, result);
 
-                       /*
-                        * If we acquired the monitor successfully but got 
interrupted
-                        * we have to exit the monitor now.
-                        */
-                       if(result == IL_THREAD_OK)
-                       {
-                               _ILMonitorExit(&(monitor->monitor));
-                       }
+       if((result == IL_THREAD_OK) && (waitStateResult == IL_THREAD_OK))
+       {
+               /*
+                * The owner should be 0 at this point.
+                */
+               monitor->owner = thread;
+               monitor->enterCount = 1;
+       }
+       else
+       {
+               /* Lock the monitor system again */
+               _ILCriticalSectionEnter(&(_MonitorPool.lock));
 
-                       if(monitor->users <= 0)
-                       {
-                               /* No other waiters on the monitor */
-                               monitor->users = 0;
-                               /* So move the monitor to the free list of the  
pool */
-                               _ILMonitorPoolMoveToFreeList(&_MonitorPool, 
monitor);
-                               /* And clear the monitor location */
-                               ILInterlockedStoreP(monitorLocation, 0);
-                       }
+               /* Remove me from the user list */
+               --(monitor->users);
 
-                       /* Unlock the monitor pool */
-                       _ILCriticalSectionLeave(&(_MonitorPool.lock));
+               /*
+                * If we acquired the monitor successfully but got interrupted
+                * we have to exit the monitor now.
+                */
+               if(result == IL_THREAD_OK)
+               {
+                       _ILMonitorExit(&(monitor->monitor));
+               }
 
-                       if(waitStateResult != IL_THREAD_OK)
-                       {
-                               result = waitStateResult;
-                       }
+               if(monitor->users <= 0)
+               {
+                       /* No other waiters on the monitor */
+                       monitor->users = 0;
+                       /* So move the monitor to the free list of the  pool */
+                       _ILMonitorPoolAddToFreeList(&_MonitorPool, monitor);
+                       /* And clear the monitor location */
+                       ILInterlockedStoreP(monitorLocation, 0);
+               }
+
+               /* Unlock the monitor pool */
+               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+
+               if(waitStateResult != IL_THREAD_OK)
+               {
+                       result = waitStateResult;
                }
-               return result;
        }
-       return IL_THREAD_OK;
+       return result;
 }
 
 int ILMonitorExit(void **monitorLocation)
@@ -481,29 +591,126 @@ int ILMonitorExit(void **monitorLocation)
        {
                return IL_THREAD_ERR_SYNCLOCK;
        }
-       /* Decrement the enter count */
-       --(monitor->enterCount);
-       if(monitor->enterCount <= 0)
+       if(monitor->enterCount <= 1)
        {
                /* We really are leaving the monitor */
                _ILCriticalSectionEnter(&(_MonitorPool.lock));
 
-               /* Remove me from the monitor users */
-               --(monitor->users);
-               /* Clear the owner */
-               monitor->owner = 0;
-               monitor->enterCount = 0;
-               if(monitor->users <= 0)
+               if(monitor->users <= 1)
                {
-                       /* No other waiters on the monitor */
-                       monitor->users = 0;
-                       /* So move the monitor to the free list of the  pool */
-                       _ILMonitorPoolMoveToFreeList(&_MonitorPool, monitor);
-                       /* And clear the monitor location */
-                       *monitorLocation = 0;
+                       /*
+                        * I'm the only thread in this monitor.
+                        * So move the monitor to the freelist.
+                        */
+
+                       /* Clear the monitor location first */
+                       ILInterlockedStoreP(monitorLocation,  0);
+
+                       _ILCriticalSectionLeave(&(_MonitorPool.lock));
+
+                       if(thread->monitorFreeCount < MAX_FREELIST_MONITORS)
+                       {
+                               /* Add the monitor to the thread local freelist 
*/
+                               monitor->nextFree = thread->monitorFreeList;
+                               thread->monitorFreeList = monitor;
+                               ++thread->monitorFreeCount;
+                       }
+                       else
+                       {
+                               /*
+                                * Move monitors from the thread local freelist 
to the global
+                                * freelist.
+                                */
+                               ILMonitor *firstMonitor;
+                               ILMonitor *lastMonitor;
+                               int current;
+
+                               /*
+                                * First look for the last monitor that should 
stay on the
+                                * local freelist.
+                                */
+                               firstMonitor = thread->monitorFreeList;
+                               for(current = 0; current < 
(MIN_FREELIST_MONITORS - 1); ++current)
+                               {
+                                       if(firstMonitor == 0)
+                                       {
+                                               break;
+                                       }
+                                       firstMonitor = firstMonitor->nextFree;
+                               }
+
+                               if(firstMonitor)
+                               {
+                                       lastMonitor = firstMonitor->nextFree;
+                                       firstMonitor->nextFree = 0;
+                                       firstMonitor = lastMonitor;
+                                       thread->monitorFreeCount = current + 1;
+
+                                       while(lastMonitor)
+                                       {
+                                               
IL_THREAD_ASSERT(lastMonitor->users == 1)
+                                               lastMonitor->owner = 0;
+                                               lastMonitor->users = 0;
+                                               
_ILMonitorRelease(&(lastMonitor->monitor));
+                                               if(lastMonitor->nextFree == 0)
+                                               {
+                                                       break;
+                                               }
+                                               lastMonitor = 
lastMonitor->nextFree;
+                                       }
+                                       /*
+                                        * Make the  current monitor the head 
of the monitor list
+                                        * to be moved to the global freelist.
+                                        */
+                                       monitor->nextFree = firstMonitor;
+                                       firstMonitor = monitor;
+                               }
+                               else
+                               {
+                                       /*
+                                        * If this happens something is wrong 
or MIN and MAX
+                                        * FREELIST_MONITORS are not set 
correctly.
+                                        * So simply make monitor a single 
element list.
+                                        */
+                                       firstMonitor = monitor;
+                                       lastMonitor = monitor;
+                                       thread->monitorFreeCount = current;
+                               }
+
+                               /* Release the current monitor */
+                               IL_THREAD_ASSERT(monitor->users == 1)
+                               monitor->owner = 0;
+                               monitor->users = 0;
+                               _ILMonitorRelease(&(monitor->monitor));
+
+                               /* Lock the monitor system */
+                               _ILCriticalSectionEnter(&(_MonitorPool.lock));
+
+                               _ILMonitorPoolAddListToFreeList(&_MonitorPool,
+                                                                               
                firstMonitor,
+                                                                               
                lastMonitor);
+
+                               /* Unlock the monitor system */
+                               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+                       }
                }
-               _ILMonitorExit(&(monitor->monitor));
-               _ILCriticalSectionLeave(&(_MonitorPool.lock));
+               else
+               {
+                       /* Remove me from the monitor users */
+                       --(monitor->users);
+                       
+                       /* Clear the owner and owner private data */
+                       monitor->owner = 0;
+                       monitor->enterCount = 0;
+
+                       _ILCriticalSectionLeave(&(_MonitorPool.lock));
+                       _ILMonitorExit(&(monitor->monitor));
+               }
+       }
+       else
+       {
+               /* Simpy decrement the enter count */
+               --(monitor->enterCount);
        }
        return IL_THREAD_OK;
 }
diff --git a/support/no_defs.h b/support/no_defs.h
index 686d1b6..2cd7563 100755
--- a/support/no_defs.h
+++ b/support/no_defs.h
@@ -144,6 +144,13 @@ int _ILCondVarTimedWait(_ILCondVar *cond, _ILCondMutex 
*mutex, ILUInt32 ms);
 #define        _ILMonitorExit(mon)                                     
IL_THREAD_OK
 #define _ILMonitorTimedWait(mon, ms)           IL_THREAD_OK
 #define _ILMonitorWait(mon)                                    IL_THREAD_OK
+/*
+ * Operations for acquiring and releasing a monitor where it is guaranteed
+ * that no other thread is trying to enter or waiting on the monitor.
+ * They are used for managing thread local freelists.
+ */
+#define _ILMonitorAcquire(mon)                         IL_THREAD_OK
+#define _ILMonitorRelease(mon)                         IL_THREAD_OK
 
 /*
  * Get or set the thread object that is associated with "self".
diff --git a/support/pt_defs.h b/support/pt_defs.h
index c50071b..036d2b3 100755
--- a/support/pt_defs.h
+++ b/support/pt_defs.h
@@ -518,12 +518,19 @@ int _ILCountSemaphoreTimedWait(_ILCountSemaphore *sem, 
ILUInt32 ms);
                } while(0)
 int _ILMonitorPulse(_ILMonitor *mon);
 int _ILMonitorPulseAll(_ILMonitor *mon);
-int    _ILMonitorTimedTryEnter(_ILMonitor *mon, ILUInt32 ms);
+int _ILMonitorTimedTryEnter(_ILMonitor *mon, ILUInt32 ms);
 #define _ILMonitorTryEnter(mon) _ILMonitorTimedTryEnter((mon), 0)
 #define _ILMonitorEnter(mon) _ILMonitorTimedTryEnter((mon), IL_MAX_UINT32)
 int _ILMonitorExit(_ILMonitor *mon);
 int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms);
 #define _ILMonitorWait(mon) _ILMonitorTimedWait((mon), IL_MAX_UINT32)
+/*
+ * Operations for acquiring and releasing a monitor where it is guaranteed
+ * that no other thread is trying to enter or waiting on the monitor.
+ * They are used for managing thread local freelists.
+ */
+#define _ILMonitorAcquire(mon) IL_THREAD_OK
+#define _ILMonitorRelease(mon) IL_THREAD_OK
 
 /*
  * Call a function "once".
diff --git a/support/thr_defs.h b/support/thr_defs.h
index 663ddd2..7ae44ea 100755
--- a/support/thr_defs.h
+++ b/support/thr_defs.h
@@ -211,6 +211,8 @@ struct _tagILThread
        ILThreadCleanupEntry                    *firstCleanupEntry;
        ILThreadCleanupEntry                    *lastCleanupEntry;
        ILWaitHandle                                    *monitor;
+       ILMonitor                                               
*monitorFreeList;
+       ILUInt32                                                
monitorFreeCount;
        /* 1 if the gc knows the thread and is allowed to execute managed code 
*/
 #if defined(IL_INTERRUPT_SUPPORTS)
        ILInterruptHandler                              interruptHandler;
@@ -664,6 +666,11 @@ void _ILMonitorSystemInit();
  */
 void _ILMonitorSystemDeinit();
 
+/*
+ * Perform cleanup actions when a thread stops execution.
+ */
+void _ILMonitorDestroyThread(ILThread *thread);
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/support/thread.c b/support/thread.c
index 5f752ff..58f2927 100644
--- a/support/thread.c
+++ b/support/thread.c
@@ -122,6 +122,7 @@ static void _ILThreadInit(void)
 static void _ILThreadDeinit(void)
 {
        /* Cleanup the monitor subsystem */
+       _ILMonitorDestroyThread(&mainThread);
        _ILMonitorSystemDeinit();
 
        _ILInterruptDeinit();
@@ -321,6 +322,7 @@ void *ILThreadRunSelf(void *(* thread_func)(void *), void 
*arg)
        _ILThreadRunAndFreeCleanups(thread_self);
 
        /* and now destroy the ILThread instance. */
+       _ILMonitorDestroyThread(thread_self);
        ILWaitHandleClose(thread_self->monitor);
        _ILSemaphoreDestroy(&(thread_self->suspendAck));
        _ILSemaphoreDestroy(&(thread_self->resumeAck));
@@ -367,7 +369,7 @@ void _ILThreadRun(ILThread *thread)
        }
 
        thread->startArg = 0;
-       
+
        /* Mark the thread as stopped */
        threadState.comb = ILInterlockedLoadU4(&(thread->state.comb));
        threadState.split.priv |= IL_TS_STOPPED;
@@ -376,6 +378,9 @@ void _ILThreadRun(ILThread *thread)
        /* Change the thread count */
        _ILThreadAdjustCount(-1, ((threadState.split.pub & IL_TS_BACKGROUND) != 
0) ? -1 : 0);
 
+       /* Clean up the monitors used */
+       _ILMonitorDestroyThread(thread);
+
        _ILCriticalSectionEnter(&(thread->lock));
        {
                /* Wakeup everyone waiting to join */
@@ -1304,9 +1309,6 @@ int ILThreadUnregisterCleanup(ILThread *thread, 
ILThreadCleanupFunc func)
        ILThreadCleanupEntry *entry, *prev;
        _ILThreadState threadState;
 
-       IL_THREAD_ASSERT((thread->state.split.pub & IL_TS_UNSTARTED) ||
-                                        (thread == _ILThreadGetSelf()));
-
        /* Lock down the thread */
        _ILCriticalSectionEnter(&(thread->lock));
 
diff --git a/support/w32_defs.h b/support/w32_defs.h
index 05faaea..05f6937 100755
--- a/support/w32_defs.h
+++ b/support/w32_defs.h
@@ -325,6 +325,13 @@ int _ILMonitorTimedTryEnter(_ILMonitor *mon, ILUInt32 ms);
 #define        _ILMonitorExit(mon)             
_ILCondMutexUnlockUnsafe(&((mon)->_mutex))
 int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms);
 #define _ILMonitorWait(mon)    _ILMonitorTimedWait((mon), IL_MAX_UINT32)
+/*
+ * Operations for acquiring and releasing a monitor where it is guaranteed
+ * that no other thread is trying to enter or waiting on the monitor.
+ * They are used for managing thread local freelists.
+ */
+#define _ILMonitorAcquire(mon)         _ILMonitorTryEnter(mon)
+#define _ILMonitorRelease(mon)         _ILMonitorExit(mon)
 
 /*
  * Get or set the thread object that is associated with "self".

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog          |   35 ++++
 support/monitor.c  |  571 +++++++++++++++++++++++++++++++++++-----------------
 support/no_defs.h  |    7 +
 support/pt_defs.h  |    9 +-
 support/thr_defs.h |    7 +
 support/thread.c   |   10 +-
 support/w32_defs.h |    7 +
 7 files changed, 459 insertions(+), 187 deletions(-)


hooks/post-receive
-- 
DotGNU Portable.NET engine, compilers and tools (pnet)




reply via email to

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