[Top][All Lists]
[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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. 86899efd7040d519f7770461e1d2cc6c829ab1e5,
Klaus Treichel <=
- Prev by Date:
[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. dd4a200f0ed7033d8d0c1f7a17b4fdbe796105bc
- Next by Date:
[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET Class Library (pnetlib) branch, master, updated. 75d055aceb87120740df2394e3f045a650e0049b
- Previous by thread:
[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. dd4a200f0ed7033d8d0c1f7a17b4fdbe796105bc
- Next by thread:
[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET Class Library (pnetlib) branch, master, updated. 75d055aceb87120740df2394e3f045a650e0049b
- Index(es):