[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. a2eb1ba0e8aa3b258dcf48e580f4b7e9f7fdc225 |
Date: |
Sat, 30 Jan 2010 10:29:05 +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 a2eb1ba0e8aa3b258dcf48e580f4b7e9f7fdc225 (commit)
from c3ac178896b2603e34654237bc0bfdb9b7b4c9e3 (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=a2eb1ba0e8aa3b258dcf48e580f4b7e9f7fdc225
commit a2eb1ba0e8aa3b258dcf48e580f4b7e9f7fdc225
Author: Klaus Treichel <address@hidden>
Date: Sat Jan 30 11:28:37 2010 +0100
Add a condition variable based interruptible lock implementation for
pthread based systems.
Change _ILMonitorCreate so that the returned monitor is already owned by
the calling thread.
diff --git a/ChangeLog b/ChangeLog
index df81bf5..5045765 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2010-01-30 Klaus Treichel <address@hidden>
+
+ * support/monitor.c (_ILMonitorInit): Initialize a monitor so that it's
+ initially owned by the calling thread.
+ (ILMonitorDestroy): Adjust the call to _ILMonitorDestroy to the new
+ macro definitions.
+ (_ILMonitorPoolAllocMonitor): Install the new monitor (now owned by the
+ current thread) at the given monitor location now.
+ (ILMonitorTimedTryEnter): Handle the case when there is no monitor
+ attached to the given location completely in _ILMonitorPoolAllocMonitor
+ now.
+
+ * support/no_defs.h (_ILMonitorCreate, _ILMonitorDestroy): Change macros
+ so that the return value is an additional argument.
+
+ * support/pt_defs.h (_ILMonitorCreate, _ILMonitorDestroy): Change macros
+ so that the return value is an additional argument.
+ Add checks if semaphore or condition variable based locks should be
used.
+ Add definitions for condition variable based interruptible locks.
+
+ * support/pt_defs.c: (SemWaitInterruptible, SemTimedWaitInterruptible,
+ SemWaitUninterruptible): Rename to LockWaitInterruptible,
+ LockTimedWaitInterruptible and LockWaitUninterruptible.
+ (LockSignal, LockSignalCount, LockTrywait): Add functions for semaphore
+ based interruptible locks.
+ (LockSignal, LockSignalCount, LockTrywait, LockWaitInterruptible,
+ LockTimedWaitInterruptible, LockWaitUninterruptible): Add
implementations
+ for condition variable based interruptible locks.
+ (_ILThreadInterrupt): Add thread interrupt for condition variable based
+ interruptible locks.
+ (_ILMonitorExit): Call LockSignal now.
+ (_ILMonitorTimedTryEnter): Call LockTryWait now if timeout is 0.
+ Pass a timespec now to LockTimedWaitInterruptible instead of the number
+ of milliseconds.
+ (_ILMonitorPulse): Call LockSignal now.
+ (_ILMonitorPulseAll): Call LockSignalCount now.
+
+ * support/w32_defs.h (_ILCondMutexCreateOwned): Add macro.
+ (_ILMonitorCreate, _ILMonitorDestroy): Change macros so that the return
+ value is an additional argument.
+ (_ILMonitorCreate): Change so that the monitor is initially owned by the
+ calling thread.
+
+ * tests/test_thread.c: Adjust the primitive monitor tests to the changed
+ semantics of a new created monitor.
+
2010-01-10 Klaus Treichel <address@hidden>
* support/pt_defs.h: Disable longjmp out of signal handler for NetBSD.
diff --git a/support/monitor.c b/support/monitor.c
index c53d188..e6595c1 100755
--- a/support/monitor.c
+++ b/support/monitor.c
@@ -1,7 +1,7 @@
/*
* monitor.c - Syncronization Monitor routines.
*
- * Copyright (C) 2009 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2009, 2010 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -64,22 +64,27 @@ struct _tagILMonitorPool
*/
static _ILMonitorPool _MonitorPool;
-static void ILMonitorInit(ILMonitor *monitor)
+static int ILMonitorInit(ILMonitor *monitor, ILThread *thread)
{
+ int result;
+
monitor->next = 0;
- monitor->owner = 0;
- monitor->enterCount = 0;
- monitor->users = 0;
- _ILMonitorCreate(&(monitor->monitor));
+ monitor->owner = thread;
+ monitor->enterCount = 1;
+ monitor->users = 1;
+ _ILMonitorCreate(&(monitor->monitor), result);
+ return result;
}
static void ILMonitorDestroy(ILMonitor *monitor)
{
+ int result;
+
monitor->next = 0;
monitor->owner = 0;
monitor->enterCount = 0;
monitor->users = 0;
- _ILMonitorDestroy(&(monitor->monitor));
+ _ILMonitorDestroy(&(monitor->monitor), result);
}
static void DestroyMonitorList(ILMonitor *monitor)
@@ -151,33 +156,64 @@ static void _ILMonitorPoolDestroy(void)
/*
* Get a new monitor from the monitor pool.
+ * The thread parameter *MUST* be the current thread.
+ * The monitor is owned by the current if the function returns success.
* This function must be called with the monitorpool lock held.
*/
-static ILMonitor *_ILMonitorPoolAllocMonitor(void)
+static int _ILMonitorPoolAllocMonitor(ILThread *thread, void **monitorLocation)
{
ILMonitor *monitor;
+ int result;
if(_MonitorPool.freeList)
{
/* We have a monitor on the freelist so reuse this one */
monitor = _MonitorPool.freeList;
_MonitorPool.freeList = monitor->next;
- /* And add the monitor to the used list */
- monitor->next = _MonitorPool.usedList;
- _MonitorPool.usedList = monitor;
+ if((result = _ILMonitorTryEnter(&(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);
+ }
+ else
+ {
+ /* Move this monitor back to the freelist */
+ monitor->next = _MonitorPool.freeList;
+ _MonitorPool.freeList = monitor;
+ }
+ return result;
}
else
{
monitor = ILMemPoolAllocItem(&(_MonitorPool.pool));
if(monitor)
{
- ILMonitorInit(monitor);
- /* And add the monitor to the used list */
- monitor->next = _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);
+ }
+ else
+ {
+ /* Move this monitor to the freelist */
+ monitor->next = _MonitorPool.freeList;
+ _MonitorPool.freeList = monitor;
+ }
+ return result;
}
+ return IL_THREAD_ERR_OUTOFMEMORY;
}
- return monitor;
+ return IL_THREAD_ERR_UNKNOWN;
}
/*
@@ -298,41 +334,10 @@ int ILMonitorTimedTryEnter(void **monitorLocation,
ILUInt32 ms)
if(monitor == 0)
{
/* We have to allocate a new monitor */
- monitor = _ILMonitorPoolAllocMonitor();
- if(!monitor)
- {
- /* Unlock the monitor system */
- _ILCriticalSectionLeave(&(_MonitorPool.lock));
- return IL_THREAD_ERR_OUTOFMEMORY;
- }
-
- /* Set me as monitor user */
- monitor->users = 1;
-
- /*
- * 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;
-
- /* Store the monitor at the location given */
- ILInterlockedStoreP(monitorLocation, monitor);
- }
- else
- {
- _ILMonitorPoolMoveToFreeList(&_MonitorPool,
monitor);
- result = IL_THREAD_ERR_UNKNOWN;
- }
+ result = _ILMonitorPoolAllocMonitor(thread,
monitorLocation);
/* Unlock the monitor system */
_ILCriticalSectionLeave(&(_MonitorPool.lock));
-
+
return result;
}
if(monitor->owner == 0)
diff --git a/support/no_defs.h b/support/no_defs.h
index 6cc5755..686d1b6 100755
--- a/support/no_defs.h
+++ b/support/no_defs.h
@@ -1,7 +1,7 @@
/*
* no_defs.h - Thread definitions for systems without thread support.
*
- * Copyright (C) 2002 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009, 2010 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -134,8 +134,8 @@ int _ILCondVarTimedWait(_ILCondVar *cond, _ILCondMutex
*mutex, ILUInt32 ms);
/*
* Primitive monitor operations.
*/
-#define _ILMonitorCreate(mon) IL_THREAD_OK
-#define _ILMonitorDestroy(mon) IL_THREAD_OK
+#define _ILMonitorCreate(mon, result) do { (result) =
IL_THREAD_OK; } while(0)
+#define _ILMonitorDestroy(mon, result) do { (result) =
IL_THREAD_OK; } while(0)
#define _ILMonitorPulse(mon) IL_THREAD_OK
#define _ILMonitorPulseAll(mon) IL_THREAD_OK
#define _ILMonitorTimedTryEnter(mon, ms) IL_THREAD_OK
diff --git a/support/pt_defs.c b/support/pt_defs.c
index 6123a13..ce2d4fc 100755
--- a/support/pt_defs.c
+++ b/support/pt_defs.c
@@ -1,7 +1,7 @@
/*
* pt_defs.c - Thread definitions for using pthreads.
*
- * Copyright (C) 2002 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009, 2010 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,12 +57,6 @@ extern "C" {
*/
/*
- * Special flag in the private threadstate to indicate that the interrupt
- * should be noticed but no interrupt should occure.
- */
-#define IL_TS_UNINTERRUPTIBLE 0x1000
-
-/*
* This macro checks if an interrupt orrured after enabling the
* IL_SIG_INTERRUPT signal and sets __result in this case without
* entering the code that has to be executed.
@@ -74,6 +68,12 @@ extern "C" {
* flag too.
*/
#ifdef _IL_PT_INTERRUPT_JMP
+/*
+ * Special flag in the private threadstate to indicate that the interrupt
+ * should be noticed in the signal handler but the longjmp should not be taken.
+ */
+#define IL_TS_UNINTERRUPTIBLE 0x1000
+
#define IL_START_INTERRUPTIBLE(__result) \
{ \
ILThread *__myThread; \
@@ -182,10 +182,10 @@ extern "C" {
__threadState =
ILInterlockedLoadU2(&(__myThread->state.split.priv)); \
if((__threadState & IL_TS_INTERRUPTED) != 0) \
{ \
+ __threadState &= ~IL_TS_INTERRUPTED; \
+
ILInterlockedStoreU2(&(__myThread->state.split.priv), __threadState); \
__result = IL_THREAD_ERR_INTERRUPT; \
} \
- __threadState &= ~(IL_TS_UNINTERRUPTIBLE |
IL_TS_INTERRUPTED); \
- ILInterlockedStoreU2(&(__myThread->state.split.priv),
__threadState); \
}
#endif /* !_IL_PT_INTERRUPT_JMP */
@@ -395,17 +395,49 @@ int sem_timedwait(sem_t *sem,
}
#endif /* !HAVE_SEM_TIMEDWAIT */
+#ifdef _IL_PT_LOCK_SEM
+static int LockSignal(_ILLock *lock)
+{
+ return (sem_post(&(lock)->_sem) == 0 ? IL_THREAD_OK :
IL_THREAD_ERR_UNKNOWN);
+}
+
+static int LockSignalCount(_ILLock *lock, int count)
+{
+ while(count > 0)
+ {
+ sem_post(&(lock)->_sem);
+ --count;
+ }
+ return IL_THREAD_OK;
+}
+
+static int LockTryWait(_ILLock *lock)
+{
+ int result;
+
+ result = sem_trywait(&(lock->_sem));
+ if(result == -1)
+ {
+ if(errno == EAGAIN)
+ {
+ return IL_THREAD_BUSY;
+ }
+ return IL_THREAD_ERR_UNKNOWN;
+ }
+ return IL_THREAD_OK;
+}
+
/*
* Interruptible wait on a semaphore.
*/
-static int SemWaitInterruptible(sem_t *sem)
+static int LockWaitInterruptible(_ILLock *lock)
{
int result;
IL_START_INTERRUPTIBLE(result)
do
{
- result = sem_wait(sem);
+ result = sem_wait(&(lock->_sem));
if(result == 0)
{
break;
@@ -433,24 +465,14 @@ static int SemWaitInterruptible(sem_t *sem)
/*
* Interruptible timed wait on a semaphore.
*/
-static int SemTimedWaitInterruptible(sem_t *sem, ILUInt32 ms)
+static int LockTimedWaitInterruptible(_ILLock *lock, const struct timespec *ts)
{
- struct timeval tv;
- struct timespec ts;
int result;
- gettimeofday(&tv, 0);
- ts.tv_sec = tv.tv_sec + (long)(ms / 1000);
- ts.tv_nsec = (tv.tv_usec + (long)((ms % 1000) * 1000)) * 1000L;
- if(ts.tv_nsec >= 1000000000L)
- {
- ++(ts.tv_sec);
- ts.tv_nsec -= 1000000000L;
- }
IL_START_INTERRUPTIBLE(result)
do
{
- result = sem_timedwait(sem, &ts);
+ result = sem_timedwait(&(lock->_sem), ts);
if(result == 0)
{
break;
@@ -480,14 +502,14 @@ static int SemTimedWaitInterruptible(sem_t *sem, ILUInt32
ms)
return result;
}
-static int SemWaitUninterruptible(sem_t *sem)
+static int LockWaitUninterruptible(_ILLock *lock)
{
int result = IL_THREAD_OK;
IL_START_UNINTERRUPTIBLE()
do
{
- if(sem_wait(sem) == 0)
+ if(sem_wait(&(lock->_sem)) == 0)
{
break;
}
@@ -505,6 +527,408 @@ static int SemWaitUninterruptible(sem_t *sem)
IL_END_UNINTERRUPTIBLE(result)
return result;
}
+#elif defined(_IL_PT_LOCK_COND)
+static int LockSignal(_ILLock *lock)
+{
+ _ILCondMutexLock(&(lock->_mutex));
+ lock->_value += 1;
+ if(lock->_value <= 0)
+ {
+ /* We have to release a waiter */
+ if(lock->_interrupted)
+ {
+ /*
+ * See if there is a thread woken up by an interrupt of
an other
+ * thread waiting on this lock
+ */
+ ILThread *thread;
+
+ thread = lock->_waiters;
+ while(thread)
+ {
+ ILUInt16 threadState;
+
+ threadState =
ILInterlockedLoadU2(&(thread->state.split.priv));
+ if((threadState & IL_TS_NOTINTERRUPTED) != 0)
+ {
+ /*
+ * Clear the not interrupted flag so
that the thread
+ * will not continue waiting
+ */
+ threadState &= ~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(thread->state.split.priv), threadState);
+ break;
+ }
+ thread = thread->nextWaiter;
+ }
+ if(!thread)
+ {
+ /*
+ * There was no thread waiting with the
IL_TS_NOTINTERRUPTED
+ * flag set so clear the interropted flag of
the lock.
+ */
+ lock->_interrupted = 0;
+ /* And signal a thread to wake up */
+ _ILCondVarSignal(&(lock->_cond));
+ }
+ }
+ else
+ {
+ _ILCondVarSignal(&(lock->_cond));
+ }
+ }
+ _ILCondMutexUnlock(&(lock->_mutex));
+
+ return IL_THREAD_OK;
+}
+
+static int LockSignalCount(_ILLock *lock, int count)
+{
+ _ILCondMutexLock(&(lock->_mutex));
+ lock->_value += count;
+ if(lock->_value > 0)
+ {
+ count -= lock->_value;
+ }
+ if(lock->_interrupted)
+ {
+ /*
+ * Process the threads woken up by interrupting an other thread
+ * and not being able to process the not interrupted first.
+ */
+ ILThread *thread;
+
+ thread = lock->_waiters;
+ while(thread && (count > 0))
+ {
+ ILUInt16 threadState;
+
+ threadState =
ILInterlockedLoadU2(&(thread->state.split.priv));
+ if((threadState & IL_TS_NOTINTERRUPTED) != 0)
+ {
+ /*
+ * Clear the not interrupted flag so that the
thread
+ * will not continue waiting
+ */
+ threadState &= ~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(thread->state.split.priv), threadState);
+ /* and decrement the number of waiters that
should be awakened */
+ --count;
+ if(count <= 0)
+ {
+ break;
+ }
+ }
+ thread = thread->nextWaiter;
+ }
+ if(!thread)
+ {
+ /*
+ * There are no more threads waiting with the
IL_TS_NOTINTERRUPTED
+ * flag set so clear the interropted flag of the lock.
+ */
+ lock->_interrupted = 0;
+ }
+ }
+ if(lock->_value == 0)
+ {
+ /* Release all waiters */
+ _ILCondVarSignalAll(&(lock->_cond));
+ }
+ else
+ {
+ /* Release the number of waiters */
+ while(count > 0)
+ {
+ _ILCondVarSignal(&(lock->_cond));
+ --count;
+ }
+ }
+ _ILCondMutexUnlock(&(lock->_mutex));
+
+ return IL_THREAD_OK;
+}
+
+static int LockTryWait(_ILLock *lock)
+{
+ int result;
+
+ _ILCondMutexLock(&(lock->_mutex));
+ if(lock->_value > 0)
+ {
+ lock->_value -= 1;
+ result = IL_THREAD_OK;
+ }
+ else
+ {
+ result = IL_THREAD_BUSY;
+ }
+ _ILCondMutexUnlock(&(lock->_mutex));
+
+ return result;
+}
+
+/*
+ * Interruptible wait on a lock.
+ */
+static int LockWaitInterruptible(_ILLock *lock)
+{
+ int result = IL_THREAD_OK;
+
+ IL_START_INTERRUPTIBLE(result)
+ _ILCondMutexLock(&(lock->_mutex));
+ lock->_value -= 1;
+ if(lock->_value < 0)
+ {
+ /*
+ * Record this lock in the ILThread structure and add the
thread to
+ * the waiters on this lock.
+ */
+ __myThread->lockWaitingOn = lock;
+ __myThread->nextWaiter = lock->_waiters;
+ lock->_waiters = __myThread;
+ do
+ {
+ result = pthread_cond_wait(&(lock->_cond),
&(lock->_mutex));
+ if(result == 0)
+ {
+ /* Check if we are interrupted */
+ __threadState =
ILInterlockedLoadU2(&(__myThread->state.split.priv));
+ if((__threadState & IL_TS_INTERRUPTED) != 0)
+ {
+ /* Leave the wait loop */
+ break;
+ }
+ else if((__threadState & IL_TS_NOTINTERRUPTED)
!= 0)
+ {
+ /* Clear the not interrupted flag */
+ __threadState &= ~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(__myThread->state.split.priv), __threadState);
+ /* And continue waiting */
+ continue;
+ }
+ result = IL_THREAD_OK;
+ break;
+ }
+ else
+ {
+ /* Remove me from the number of waiters */
+ lock->_value += 1;
+ result = IL_THREAD_ERR_UNKNOWN;
+ break;
+ }
+ } while(1);
+ /*
+ * Clear the lock in the ILThread structure and remove the
thread from
+ * the waiters on this lock.
+ */
+ __myThread->lockWaitingOn = 0;
+ if(lock->_waiters == __myThread)
+ {
+ lock->_waiters = __myThread->nextWaiter;
+ __myThread->nextWaiter = 0;
+ }
+ else
+ {
+ ILThread *nextThread;
+
+ nextThread = lock->_waiters;
+ while(nextThread)
+ {
+ if(nextThread->nextWaiter == __myThread)
+ {
+ nextThread->nextWaiter =
__myThread->nextWaiter;
+ __myThread->nextWaiter = 0;
+ break;
+ }
+ nextThread = nextThread->nextWaiter;
+ }
+ }
+ }
+ _ILCondMutexUnlock(&(lock->_mutex));
+ IL_END_INTERRUPTIBLE(result)
+ return result;
+}
+
+/*
+ * Interruptible timed wait on a lock.
+ */
+static int LockTimedWaitInterruptible(_ILLock *lock, const struct timespec *ts)
+{
+ int result = IL_THREAD_OK;
+
+ IL_START_INTERRUPTIBLE(result)
+ _ILCondMutexLock(&(lock->_mutex));
+ lock->_value -= 1;
+ if(lock->_value < 0)
+ {
+ /*
+ * Record this lock in the ILThread structure and add the
thread to
+ * the waiters on this lock.
+ */
+ __myThread->lockWaitingOn = lock;
+ __myThread->nextWaiter = lock->_waiters;
+ lock->_waiters = __myThread;
+ do
+ {
+ result = pthread_cond_timedwait(&(lock->_cond),
&(lock->_mutex), ts);
+ if(result == 0)
+ {
+ /* Check if we are interrupted */
+ __threadState =
ILInterlockedLoadU2(&(__myThread->state.split.priv));
+ if((__threadState & IL_TS_INTERRUPTED) != 0)
+ {
+ /* Leave the wait loop */
+ break;
+ }
+ else if((__threadState & IL_TS_NOTINTERRUPTED)
!= 0)
+ {
+ /* Clear the not interrupted flag */
+ __threadState &= ~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(__myThread->state.split.priv), __threadState);
+ /* And continue waiting */
+ continue;
+ }
+ result = IL_THREAD_OK;
+ break;
+ }
+ else if(result == ETIMEDOUT)
+ {
+ /* Clear the not interrupted flag if present */
+ __threadState =
ILInterlockedLoadU2(&(__myThread->state.split.priv));
+ if((__threadState & IL_TS_NOTINTERRUPTED) != 0)
+ {
+ __threadState &= ~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(__myThread->state.split.priv), __threadState);
+ }
+ lock->_value += 1;
+ result = IL_THREAD_BUSY;
+ break;
+ }
+ else
+ {
+ lock->_value += 1;
+ result = IL_THREAD_ERR_UNKNOWN;
+ break;
+ }
+ } while(1);
+ /*
+ * Clear the lock in the ILThread structure and remove the
thread from
+ * the waiters on this lock.
+ */
+ __myThread->lockWaitingOn = 0;
+ if(lock->_waiters == __myThread)
+ {
+ lock->_waiters = __myThread->nextWaiter;
+ __myThread->nextWaiter = 0;
+ }
+ else
+ {
+ ILThread *nextThread;
+
+ nextThread = lock->_waiters;
+ while(nextThread)
+ {
+ if(nextThread->nextWaiter == __myThread)
+ {
+ nextThread->nextWaiter =
__myThread->nextWaiter;
+ __myThread->nextWaiter = 0;
+ break;
+ }
+ nextThread = nextThread->nextWaiter;
+ }
+ }
+ }
+ _ILCondMutexUnlock(&(lock->_mutex));
+ IL_END_INTERRUPTIBLE(result)
+ return result;
+}
+
+static int LockWaitUninterruptible(_ILLock *lock)
+{
+ int result = IL_THREAD_OK;
+
+ IL_START_UNINTERRUPTIBLE()
+ _ILCondMutexLock(&(lock->_mutex));
+ lock->_value -= 1;
+ if(lock->_value < 0)
+ {
+ /*
+ * Record this lock in the ILThread structure and add the
thread to
+ * the waiters on this lock.
+ */
+ __myThread->lockWaitingOn = lock;
+ __myThread->nextWaiter = lock->_waiters;
+ lock->_waiters = __myThread;
+ do
+ {
+ if(pthread_cond_wait(&(lock->_cond), &(lock->_mutex))
== 0)
+ {
+ /* Check if we are interrupted */
+ __threadState =
ILInterlockedLoadU2(&(__myThread->state.split.priv));
+ if((__threadState & IL_TS_INTERRUPTED) != 0)
+ {
+ /* Clear the interrupted flag */
+ __threadState &= ~IL_TS_INTERRUPTED;
+
ILInterlockedStoreU2(&(__myThread->state.split.priv), __threadState);
+ /* Readd me to the number of waiters. */
+ lock->_value -= 1;
+ /* Set the result to interrupted */
+ result = IL_THREAD_ERR_INTERRUPT;
+ /* and continue waiting */
+ continue;
+ }
+ else if((__threadState & IL_TS_NOTINTERRUPTED)
!= 0)
+ {
+ /* Clear the not interrupted flag */
+ __threadState &= ~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(__myThread->state.split.priv), __threadState);
+ /* And continue waiting */
+ continue;
+ }
+ result = IL_THREAD_OK;
+ break;
+ }
+ else
+ {
+ /* An unexpected error occured so bail out */
+ lock->_value += 1;
+ result = IL_THREAD_ERR_UNKNOWN;
+ break;
+ }
+ } while(1);
+ /*
+ * Clear the lock in the ILThread structure and remove the
thread from
+ * the waiters on this lock.
+ */
+ __myThread->lockWaitingOn = 0;
+ if(lock->_waiters == __myThread)
+ {
+ lock->_waiters = __myThread->nextWaiter;
+ __myThread->nextWaiter = 0;
+ }
+ else
+ {
+ ILThread *nextThread;
+
+ nextThread = lock->_waiters;
+ while(nextThread)
+ {
+ if(nextThread->nextWaiter == __myThread)
+ {
+ nextThread->nextWaiter =
__myThread->nextWaiter;
+ __myThread->nextWaiter = 0;
+ break;
+ }
+ nextThread = nextThread->nextWaiter;
+ }
+ }
+ }
+ _ILCondMutexUnlock(&(lock->_mutex));
+ IL_END_UNINTERRUPTIBLE(result)
+ return result;
+}
+#endif /* _IL_PT_LOCK_COND */
/*
* This function is only used for initializing an ILThread
@@ -666,10 +1090,98 @@ void _ILThreadInterrupt(ILThread *thread)
{
if(thread)
{
+#ifdef _IL_PT_LOCK_COND
+ _ILLock *lock;
+ ILUInt16 threadState;
+
+ threadState = ILInterlockedLoadU2(&(thread->state.split.priv));
+ lock = (_ILLock *)ILInterlockedLoadP((void
**)&(thread->lockWaitingOn));
+#endif /* _IL_PT_LOCK_COND */
/*
* Send the interrupt request to the thread.
*/
pthread_kill(thread->handle, IL_SIG_INTERRUPT);
+#ifdef _IL_PT_LOCK_COND
+ if(lock != 0)
+ {
+ /* Acquire the lock */
+ _ILCondMutexLock(&(lock->_mutex));
+ /* Recheck if the thread is still waiting on the same
lock */
+ if(lock == (_ILLock *)ILInterlockedLoadP((void
**)&(thread->lockWaitingOn)))
+ {
+ /*
+ * First check if the thread to be interrupted
should be awakened
+ * because of an other interrupt processing.
+ */
+ if((threadState & IL_TS_INTERRUPTED) == 0)
+ {
+ /* Remove the thread from the number od
waiters */
+ lock->_value += 1;
+
+ threadState |= IL_TS_INTERRUPTED;
+ if((threadState & IL_TS_NOTINTERRUPTED)
!= 0)
+ {
+ threadState &=
~IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(thread->state.split.priv), threadState);
+ }
+ else
+ {
+ /*
+ * Mark all other threads
waiting on the lock as not
+ * interrupted so that they
will continue waiting at
+ * their next wakeup.
+ */
+ ILThread *otherThread;
+ ILInt32 value;
+ int otherWaiter = 0;
+
+ /*
+ * Set the interrupted flag
here so that we don't depend
+ * on the signal processing
timing to set the flag.
+ */
+
ILInterlockedStoreU2(&(thread->state.split.priv), threadState);
+
+ /*
+ * Process at most
(-lock->_value) waiters.
+ */
+ value = lock->_value;
+ otherThread = lock->_waiters;
+ while(otherThread && (value <
0))
+ {
+ if(otherThread !=
thread)
+ {
+ threadState =
ILInterlockedLoadU2(&(otherThread->state.split.priv));
+ if((threadState
& IL_TS_INTERRUPTED) == 0)
+ {
+
threadState |= IL_TS_NOTINTERRUPTED;
+
ILInterlockedStoreU2(&(otherThread->state.split.priv), threadState);
+ /*
+ * Set
the flag that there is an other thread waiting
+ * on
the lock
+ */
+
otherWaiter = 1;
+ }
+ ++value;
+ }
+ otherThread =
otherThread->nextWaiter;
+ }
+ if(otherWaiter)
+ {
+ /*
+ * Mark the lock that
there is interrupt processing on
+ * the way
+ */
+ lock->_interrupted = 1;
+ }
+ /* Wake up all threads waiting
on the lock */
+
_ILCondVarSignalAll(&(lock->_cond));
+ }
+ }
+ }
+ /* Release the lock */
+ _ILCondMutexUnlock(&(lock->_mutex));
+ }
+#endif /* _IL_PT_LOCK_COND */
}
}
@@ -707,7 +1219,7 @@ int _ILThreadSleep(ILUInt32 ms)
#ifndef _IL_PT_INTERRUPT_JMP
/* Check and clear the interrupted flag
*/
__threadState =
ILInterlockedLoadU2(&(__myThread->state.split.priv));
- if((__threadState | IL_TS_INTERRUPTED)
!= 0)
+ if((__threadState & IL_TS_INTERRUPTED)
!= 0)
{
result =
IL_THREAD_ERR_INTERRUPT;
break;
@@ -1033,32 +1545,33 @@ int _ILCountSemaphoreTimedWait(_ILCountSemaphore *sem,
ILUInt32 ms)
int _ILMonitorExit(_ILMonitor *mon)
{
- int result;
-
- if((result = sem_post(&(mon->_enterSem))) == 0)
- {
- return IL_THREAD_OK;
- }
- return IL_THREAD_ERR_UNKNOWN;
+ return LockSignal(&(mon->_enterLock));
}
int _ILMonitorTimedTryEnter(_ILMonitor *mon, ILUInt32 ms)
{
if(ms == 0)
{
- if(sem_trywait(&(mon->_enterSem)) == 0)
- {
- return IL_THREAD_OK;
- }
- return errno == EAGAIN ? IL_THREAD_BUSY : IL_THREAD_ERR_UNKNOWN;
+ return LockTryWait(&(mon->_enterLock));
}
else if(ms == IL_MAX_UINT32)
{
- return SemWaitInterruptible(&(mon->_enterSem));
+ return LockWaitInterruptible(&(mon->_enterLock));
}
else if(ms <= IL_MAX_INT32)
{
- return SemTimedWaitInterruptible(&(mon->_enterSem), ms);
+ struct timeval tv;
+ struct timespec ts;
+
+ gettimeofday(&tv, 0);
+ ts.tv_sec = tv.tv_sec + (long)(ms / 1000);
+ ts.tv_nsec = (tv.tv_usec + (long)((ms % 1000) * 1000)) * 1000L;
+ if(ts.tv_nsec >= 1000000000L)
+ {
+ ++(ts.tv_sec);
+ ts.tv_nsec -= 1000000000L;
+ }
+ return LockTimedWaitInterruptible(&(mon->_enterLock), &ts);
}
else
{
@@ -1078,9 +1591,10 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms)
* In this case we don't have to enter the waiting queue but
simply
* release and reenter the ready state.
*/
- if((result = sem_post(&(mon->_enterSem))) != 0)
+ result = LockSignal(&(mon->_enterLock));
+ if(result != IL_THREAD_OK)
{
- return IL_THREAD_ERR_UNKNOWN;
+ return result;
}
}
else if((ms == IL_MAX_UINT32) || (ms <= IL_MAX_INT32))
@@ -1093,7 +1607,8 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms)
/*
* Release the ownership of the monitor.
*/
- if(sem_post(&(mon->_enterSem)) != 0)
+ result = LockSignal(&(mon->_enterLock));
+ if(result != IL_THREAD_OK)
{
/*
* Leave the wait queue and return with error
@@ -1104,7 +1619,7 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms)
if(ms == IL_MAX_UINT32)
{
- result = SemWaitInterruptible(&(mon->_waitSem));
+ result = LockWaitInterruptible(&(mon->_waitLock));
if(result)
{
/*
@@ -1116,7 +1631,18 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms)
}
else
{
- result = SemTimedWaitInterruptible(&(mon->_waitSem),
ms);
+ struct timeval tv;
+ struct timespec ts;
+
+ gettimeofday(&tv, 0);
+ ts.tv_sec = tv.tv_sec + (long)(ms / 1000);
+ ts.tv_nsec = (tv.tv_usec + (long)((ms % 1000) * 1000))
* 1000L;
+ if(ts.tv_nsec >= 1000000000L)
+ {
+ ++(ts.tv_sec);
+ ts.tv_nsec -= 1000000000L;
+ }
+ result = LockTimedWaitInterruptible(&(mon->_waitLock),
&ts);
if(result)
{
/*
@@ -1135,7 +1661,7 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms)
/*
* Now we have to regain the ownership of the monitor
*/
- enterResult = SemWaitUninterruptible(&(mon->_enterSem));
+ enterResult = LockWaitUninterruptible(&(mon->_enterLock));
if(result == IL_THREAD_OK)
{
result = enterResult;
@@ -1145,17 +1671,21 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms)
int _ILMonitorPulse(_ILMonitor *mon)
{
+ int result;
+
+ result = IL_THREAD_OK;
if(mon)
{
ILInt32 waitValue;
-
+
+ result = IL_THREAD_OK;
waitValue = ILInterlockedLoadI4(&(mon->_waitValue));
if(waitValue < 0)
{
waitValue =
ILInterlockedIncrementI4_Acquire(&(mon->_waitValue));
if(waitValue <= 0)
{
- sem_post(&(mon->_waitSem));
+ result = LockSignal(&(mon->_waitLock));
}
else
{
@@ -1163,7 +1693,7 @@ int _ILMonitorPulse(_ILMonitor *mon)
}
}
}
- return IL_THREAD_OK;
+ return result;
}
int _ILMonitorPulseAll(_ILMonitor *mon)
@@ -1180,11 +1710,7 @@ int _ILMonitorPulseAll(_ILMonitor *mon)
if(waitValue < 0)
{
/* Release the waiters */
- while(waitValue < 0)
- {
- sem_post(&(mon->_waitSem));
- ++waitValue;
- }
+ LockSignalCount(&(mon->_waitLock), -waitValue);
}
else if(waitValue > 0)
{
diff --git a/support/pt_defs.h b/support/pt_defs.h
index 7d8592f..c50071b 100755
--- a/support/pt_defs.h
+++ b/support/pt_defs.h
@@ -1,7 +1,7 @@
/*
* pt_defs.h - Thread definitions for using pthreads.
*
- * Copyright (C) 2002 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009, 2010 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +41,20 @@ extern "C" {
#endif
/*
+ * This is a real thread package.
+ */
+#define _ILThreadIsReal 1
+
+/*
+ * Define IL_USE_COND_LOCK if condition variable based locks should be used.
+ * They are used by default if sem_timedwait is not available.
+ * This has to be done if the semaphore implementation on the OS doesn't
+ * return with errno set to EINTR if the waiting thread was interrupted by
+ * a signal (like on various BSD implementations).
+ */
+/* #define IL_USE_COND_LOCK 1 */
+
+/*
* Determine the minimum and maximum real-time signal numbers.
*/
#if !defined(__SIGRTMIN) && defined(SIGRTMIN)
@@ -108,6 +122,21 @@ extern "C" {
#endif
/*
+ * Get or set the thread object that is associated with "self".
+ */
+#if defined(USE_COMPILER_TLS)
+extern _THREAD_ ILThread *_myThread;
+#define _ILThreadGetSelf() (_myThread)
+#define _ILThreadSetSelf(object) (_myThread = (object))
+#else
+extern pthread_key_t _ILThreadObjectKey;
+#define _ILThreadGetSelf() \
+ ((ILThread *)(pthread_getspecific(_ILThreadObjectKey)))
+#define _ILThreadSetSelf(object) \
+ (pthread_setspecific(_ILThreadObjectKey, (object)))
+#endif
+
+/*
* Types that are needed elsewhere.
*/
typedef pthread_mutex_t _ILCriticalSection;
@@ -150,13 +179,62 @@ typedef pthread_mutex_t _ILRWLock;
#endif
/*
- * pthread specific extensions for an ILThread
+ * Check which type of lock to use on this architecture
*/
+#if !defined(IL_USE_COND_LOCK) && defined(HAVE_SEM_TIMEDWAIT) &&
defined(_IL_PT_INTERRUPT_JMP)
+#define _IL_PT_LOCK_SEM 1
+#else
#ifdef _IL_PT_INTERRUPT_JMP
+#undef _IL_PT_INTERRUPT_JMP
+#endif
+#define _IL_PT_LOCK_COND 1
+/*
+ * An additional flag in the private thread state part to indicate that the
+ * thread was woken up because of an interruption of an other thread waiting
+ * on the same lock.
+ * NOTE: We extend the modifiability of the private thread state part by
+ * foreign threads here if the following conditions are met:
+ * 1. The thread whose private thread state shall be modified must be waiting
+ * on a lock. (-> the member lockWaitingOn is != 0).
+ * 2. The thread wanting to modify the private state of the other thread
+ * *MUST* hold the lockWaitingOn lock.
+ */
+#define IL_TS_NOTINTERRUPTED 0x0800
+#endif
+
+/*
+ * Define the type of lock to use.
+ */
+#if defined(_IL_PT_LOCK_SEM)
+typedef struct
+{
+ _ILSemaphore _sem;
+} _ILLock;
+#elif defined(_IL_PT_LOCK_COND)
+typedef struct
+{
+ _ILCondVar _cond;
+ _ILCondMutex _mutex;
+ ILThread *_waiters;
+ ILInt32 _value;
+ ILInt32 _interrupted;
+} _ILLock;
+#else
+#error "No lock type defined for this architecture"
+#endif
+
+/*
+ * pthread specific extensions for an ILThread
+ */
+#if defined(_IL_PT_INTERRUPT_JMP)
#define _IL_THREAD_EXT \
sigjmp_buf interruptJmpBuf;
-
+#elif defined(_IL_PT_LOCK_COND)
+#define _IL_THREAD_EXT \
+ _ILLock *lockWaitingOn; \
+ ILThread *nextWaiter;
#endif
+
/*
* Semaphore which allows to release multiple or all waiters.
* The semantic for posix and windows semaphores is the same and the
@@ -179,16 +257,11 @@ typedef struct
typedef struct
{
ILInt32 _waitValue;
- _ILSemaphore _waitSem;
- _ILSemaphore _enterSem;
+ _ILLock _waitLock;
+ _ILLock _enterLock;
} _ILMonitor;
/*
- * This is a real thread package.
- */
-#define _ILThreadIsReal 1
-
-/*
* Determine if a thread corresponds to "self".
*/
#define _ILThreadIsSelf(thread) \
@@ -348,6 +421,8 @@ int _ILSemaphorePostMultiple(_ILSemaphore *sem, ILUInt32
count);
(pthread_cond_destroy((cond)))
#define _ILCondVarSignal(cond) \
(pthread_cond_signal((cond)))
+#define _ILCondVarSignalAll(cond) \
+ (pthread_cond_broadcast((cond)))
int _ILCondVarTimedWait(_ILCondVar *cond, _ILCondMutex *mutex, ILUInt32 ms);
/*
@@ -370,29 +445,77 @@ int _ILCountSemaphoreTimedWait(_ILCountSemaphore *sem,
ILUInt32 ms);
#define _ILCountSemaphoreWait(sem) _ILCountSemaphoreTimedWait((sem),
IL_MAX_UINT32)
#define _ILCountSemaphoreTryWait(sem) _ILCountSemaphoreTimedWait((sem), 0)
+#if defined(_IL_PT_LOCK_SEM)
+#define _ILLockCreate(lock, result) \
+ do { \
+ (result) = (sem_init(&((lock)->_sem), 0, 0) == 0 ? IL_THREAD_OK
: IL_THREAD_ERR_UNKNOWN); \
+ } while(0)
+#define _ILLockDestroy(lock, result) \
+ do { \
+ (result) = (sem_destroy(&((lock)->_sem)) == 0 ? IL_THREAD_OK :
IL_THREAD_ERR_UNKNOWN); \
+ } while(0)
+#elif defined(_IL_PT_LOCK_COND)
+#define _ILLockCreate(lock, result) \
+ do { \
+ (lock)->_waiters = 0; \
+ (lock)->_value = 0; \
+ (lock)->_interrupted = 0; \
+ if(!_ILCondMutexCreate(&((lock)->_mutex))) \
+ { \
+ if(!_ILCondVarCreate((&((lock)->_cond)))) \
+ { \
+ (result) = IL_THREAD_OK; \
+ } \
+ else \
+ { \
+ (result) = IL_THREAD_ERR_UNKNOWN; \
+ } \
+ } \
+ else \
+ { \
+ (result) = IL_THREAD_ERR_UNKNOWN; \
+ } \
+ } while(0)
+#define _ILLockDestroy(lock, result) \
+ do { \
+ if(!_ILCondMutexDestroy(&((lock)->_mutex))) \
+ { \
+ if(!_ILCondVarDestroy((&((lock)->_cond)))) \
+ { \
+ (result) = IL_THREAD_OK; \
+ } \
+ else \
+ { \
+ (result) = IL_THREAD_ERR_UNKNOWN; \
+ } \
+ } \
+ else \
+ { \
+ (result) = IL_THREAD_ERR_UNKNOWN; \
+ } \
+ } while(0)
+#endif /* _IL_PT_LOCK_COND) */
+
/*
* Primitive monitor operations.
*/
-#define _ILMonitorCreate(mon) \
- ({ \
- int __result; \
+#define _ILMonitorCreate(mon, result) \
+ do { \
(mon)->_waitValue = 0; \
- __result = sem_init(&((mon)->_waitSem), 0, 0); \
- if(!__result) \
+ _ILLockCreate(&((mon)->_waitLock), (result)); \
+ if(!(result)) \
{ \
- __result = sem_init(&((mon)->_enterSem), 0, 1);
\
+ _ILLockCreate(&((mon)->_enterLock), (result)); \
} \
- __result == 0 ? IL_THREAD_OK : IL_THREAD_ERR_UNKNOWN; \
- })
-#define _ILMonitorDestroy(mon) \
- ({ \
- int __result = _ILSemaphoreDestroy(&((mon)->_waitSem));
\
- if(!__result) \
+ } while(0)
+#define _ILMonitorDestroy(mon, result) \
+ do { \
+ _ILLockDestroy(&((mon)->_waitLock),(result)); \
+ if(!(result)) \
{ \
- __result =
_ILSemaphoreDestroy(&((mon)->_enterSem)); \
+ _ILLockDestroy(&((mon)->_enterLock), (result));
\
} \
- __result == 0 ? IL_THREAD_OK : IL_THREAD_ERR_UNKNOWN; \
- })
+ } while(0)
int _ILMonitorPulse(_ILMonitor *mon);
int _ILMonitorPulseAll(_ILMonitor *mon);
int _ILMonitorTimedTryEnter(_ILMonitor *mon, ILUInt32 ms);
@@ -403,21 +526,6 @@ int _ILMonitorTimedWait(_ILMonitor *mon, ILUInt32 ms);
#define _ILMonitorWait(mon) _ILMonitorTimedWait((mon), IL_MAX_UINT32)
/*
- * Get or set the thread object that is associated with "self".
- */
-#if defined(USE_COMPILER_TLS)
-extern _THREAD_ ILThread *_myThread;
-#define _ILThreadGetSelf() (_myThread)
-#define _ILThreadSetSelf(object) (_myThread = (object))
-#else
-extern pthread_key_t _ILThreadObjectKey;
-#define _ILThreadGetSelf() \
- ((ILThread *)(pthread_getspecific(_ILThreadObjectKey)))
-#define _ILThreadSetSelf(object) \
- (pthread_setspecific(_ILThreadObjectKey, (object)))
-#endif
-
-/*
* Call a function "once".
*/
#define _ILCallOnce(func) \
diff --git a/support/w32_defs.h b/support/w32_defs.h
index 11e89e7..05faaea 100755
--- a/support/w32_defs.h
+++ b/support/w32_defs.h
@@ -1,7 +1,7 @@
/*
* w32_defs.h - Thread definitions for using Win32 threads.
*
- * Copyright (C) 2002 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009, 2010 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -195,6 +195,11 @@ int _ILThreadSleep(ILUInt32 ms);
*(mutex) = CreateMutex(NULL, FALSE, NULL); \
*(mutex) != 0 ? IL_THREAD_OK :
IL_THREAD_ERR_UNKNOWN; \
})
+#define _ILCondMutexCreateOwned(mutex) \
+ ({ \
+ *(mutex) = CreateMutex(NULL, TRUE, NULL); \
+ *(mutex) != 0 ? IL_THREAD_OK :
IL_THREAD_ERR_UNKNOWN; \
+ })
#define _ILCondMutexDestroy(mutex) _ILWaitHandleClose(*(mutex))
#define _ILCondMutexLockUnsafe(mutex) _ILWaitHandleWait(*(mutex))
#define _ILCondMutexTryLockUnsafe(mutex)
_ILWaitHandleTimedWait(*(mutex), 0)
@@ -280,29 +285,29 @@ int _ILCountSemaphoreTimedWait(_ILCountSemaphore *sem,
ILUInt32 ms);
/*
* Primitive monitor operations.
*/
-#define _ILMonitorCreate(mon) \
- ({ \
- int _result = 0; \
+#define _ILMonitorCreate(mon, result) \
+ do { \
(mon)->_waitValue = 0; \
- if((_result = _ILCondMutexCreate(&((mon)->_mutex))) ==
IL_THREAD_OK) \
+ if(((result) =
_ILCondMutexCreateOwned(&((mon)->_mutex))) == IL_THREAD_OK) \
{ \
- _result = _ILSemaphoreCreate(&((mon)->_sem)); \
+ (result) = _ILSemaphoreCreate(&((mon)->_sem)); \
} \
- _result == IL_THREAD_OK ? IL_THREAD_OK :
IL_THREAD_ERR_UNKNOWN; \
- })
-#define _ILMonitorDestroy(mon) \
- ({ \
- int _result = IL_THREAD_OK; \
- if(_ILSemaphoreDestroy(&((mon)->_sem)) != IL_THREAD_OK)
\
+ if((result) != IL_THREAD_OK) \
{ \
- _result = IL_THREAD_ERR_UNKNOWN; \
+ (result) = IL_THREAD_ERR_UNKNOWN; \
} \
- if(_ILCondMutexDestroy(&((mon)->_mutex)) !=
IL_THREAD_OK) \
+ } while(0)
+#define _ILMonitorDestroy(mon, result) \
+ do { \
+ if(((result) = _ILSemaphoreDestroy(&((mon)->_sem))) ==
IL_THREAD_OK) \
{ \
- _result = IL_THREAD_ERR_UNKNOWN; \
+ (result) =
_ILCondMutexDestroy(&((mon)->_mutex)); \
} \
- _result; \
- })
+ if((result) != IL_THREAD_OK) \
+ { \
+ (result) = IL_THREAD_ERR_UNKNOWN; \
+ } \
+ } while(0)
/*
* Release one waiter from the waiting queue.
diff --git a/tests/test_thread.c b/tests/test_thread.c
index d6dc02a..9f0a479 100755
--- a/tests/test_thread.c
+++ b/tests/test_thread.c
@@ -1,7 +1,7 @@
/*
* test_thread.c - Test the thread routines in "support".
*
- * Copyright (C) 2002 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2009, 2010 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1775,43 +1775,45 @@ static void wait_monitor_suspend(void *arg)
}
/*
- * Test monitor creation.
+ * Test monitor create primitive.
*/
static void primitive_monitor_create(void *arg)
{
/* We are using the primitive versions for now. */
_ILMonitor mon;
- if(_ILMonitorCreate(&mon))
+ int result;
+
+ _ILMonitorCreate(&mon, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- _ILMonitorDestroy(&mon);
+ if(_ILMonitorExit(&mon))
+ {
+ ILUnitFailed("could not exit a monitor");
+ }
+ _ILMonitorDestroy(&mon, result);
}
/*
- * Test monitor enter.
+ * Test monitor enter primitive.
*/
static void primitive_monitor_enter(void *arg)
{
int result = 0;
-
- /* We are using the primitive versions for now. */
_ILMonitor mon;
- if(_ILMonitorCreate(&mon))
+
+ _ILMonitorCreate(&mon, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- if((result = _ILMonitorEnter(&mon)))
- {
- _ILMonitorDestroy(&mon);
- ILUnitFailed("could not enter a monitor");
- }
if((result = _ILMonitorExit(&mon)))
{
- _ILMonitorDestroy(&mon);
+ _ILMonitorDestroy(&mon, result);
ILUnitFailed("could not exit a monitor");
}
- _ILMonitorDestroy(&mon);
+ _ILMonitorDestroy(&mon, result);
}
static volatile int _result;
@@ -1833,7 +1835,8 @@ static void primitive_monitor_exit_unowned(void *arg)
int result = 0;
ILThread *thread;
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
@@ -1842,16 +1845,10 @@ static void primitive_monitor_exit_unowned(void *arg)
thread = ILThreadCreate(_primitive_monitor_exit_unowned, &_mon1);
if(!thread)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
- if((result = _ILMonitorEnter(&_mon1)))
- {
- _ILMonitorDestroy(&_mon1);
- ILUnitFailed("could not enter a monitor");
- }
-
/* Set the result to an invalid value. */
_result = -1;
@@ -1867,7 +1864,7 @@ static void primitive_monitor_exit_unowned(void *arg)
if(_result != IL_THREAD_ERR_SYNCLOCK)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitFailMessage("exiting an unowned monitor returned the
wrong result");
ILUnitFailMessage("the Wrong result is %i", _result);
if(_result == IL_THREAD_OK)
@@ -1879,10 +1876,10 @@ static void primitive_monitor_exit_unowned(void *arg)
if((result = _ILMonitorExit(&_mon1)))
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitFailed("could not exit a monitor");
}
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
}
#endif /* !IL_USE_PTHREADS */
@@ -1914,23 +1911,18 @@ static void primitive_monitor_enter1(void *arg)
int result2 = 0;
/* We are using the primitive versions for now. */
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- if((result = _ILMonitorEnter(&_mon1)))
- {
- _ILMonitorDestroy(&_mon1);
- ILUnitFailed("could not enter a monitor");
- }
-
/* Create the thread */
thread = ILThreadCreate(_primitive_monitor_enter_locked, &_mon1);
if(!thread)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
@@ -1947,7 +1939,7 @@ static void primitive_monitor_enter1(void *arg)
if((result = _ILMonitorExit(&_mon1)))
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILThreadDestroy(thread);
ILUnitFailed("could not exit a monitor");
}
@@ -1963,11 +1955,12 @@ static void primitive_monitor_enter1(void *arg)
if(result1 != 1 || result2 != 2)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitFailed("lock on monitor enter doesn't work");
}
- if((result = _ILMonitorDestroy(&_mon1)))
+ _ILMonitorDestroy(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not destroy a monitor");
}
@@ -2010,23 +2003,18 @@ static void primitive_monitor_tryenter1(void *arg)
int result1 = 0;
/* We are using the primitive versions for now. */
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- if((result = _ILMonitorEnter(&_mon1)))
- {
- _ILMonitorDestroy(&_mon1);
- ILUnitFailed("could not enter a monitor");
- }
-
/* Create the thread */
thread = ILThreadCreate(_primitive_monitor_tryenter_locked, &_mon1);
if(!thread)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
@@ -2043,7 +2031,7 @@ static void primitive_monitor_tryenter1(void *arg)
if((result = _ILMonitorExit(&_mon1)))
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILThreadDestroy(thread);
ILUnitFailed("could not exit a monitor");
}
@@ -2053,12 +2041,13 @@ static void primitive_monitor_tryenter1(void *arg)
if(result1 != 1)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
printf("Wrong result is %i\n", result1);
ILUnitFailed("tryenter on a locked monitor doesn't work");
}
- if((result = _ILMonitorDestroy(&_mon1)))
+ _ILMonitorDestroy(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not destroy a monitor");
}
@@ -2071,7 +2060,8 @@ static void primitive_monitor_tryenter2(void *arg)
int result1 = 0;
/* We are using the primitive versions for now. */
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
@@ -2081,10 +2071,17 @@ static void primitive_monitor_tryenter2(void *arg)
if(!thread)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
+ if((result = _ILMonitorExit(&_mon1)))
+ {
+ _ILMonitorDestroy(&_mon1, result);
+ ILThreadDestroy(thread);
+ ILUnitFailed("could not exit a monitor");
+ }
+
_result = -1;
/* Start the thread, which should immediately try to enter the monitor.
*/
@@ -2100,12 +2097,13 @@ static void primitive_monitor_tryenter2(void *arg)
if(result1 != 0)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
printf("Wrong result is %i\n", result1);
ILUnitFailed("tryenter on a unlocked monitor doesn't work");
}
- if((result = _ILMonitorDestroy(&_mon1)))
+ _ILMonitorDestroy(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not destroy a monitor");
}
@@ -2148,23 +2146,18 @@ static void primitive_monitor_timed_tryenter1(void *arg)
int result1 = 0;
/* We are using the primitive versions for now. */
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- if((result = _ILMonitorEnter(&_mon1)))
- {
- _ILMonitorDestroy(&_mon1);
- ILUnitFailed("could not enter a monitor");
- }
-
/* Create the thread */
thread = ILThreadCreate(_primitive_monitor_timed_tryenter, &_mon1);
if(!thread)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
@@ -2183,19 +2176,20 @@ static void primitive_monitor_timed_tryenter1(void *arg)
if((result = _ILMonitorExit(&_mon1)))
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILThreadDestroy(thread);
ILUnitFailed("could not exit a monitor");
}
if(result1 != 1)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
printf("Wrong result is %i\n", result1);
ILUnitFailed("timed tryenter on a locked monitor with timeout
doesn't work");
}
- if((result = _ILMonitorDestroy(&_mon1)))
+ _ILMonitorDestroy(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not destroy a monitor");
}
@@ -2243,23 +2237,18 @@ static void primitive_monitor_wait1(void *arg)
int result2 = 0;
/* We are using the primitive versions for now. */
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- if(_ILMonitorEnter(&_mon1))
- {
- _ILMonitorDestroy(&_mon1);
- ILUnitFailed("could not enter a monitor");
- }
-
/* Create the thread */
thread = ILThreadCreate(_primitive_monitor_wait1, &_mon1);
if(!thread)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
@@ -2278,7 +2267,7 @@ static void primitive_monitor_wait1(void *arg)
{
/* Clean up the thread object. */
ILThreadDestroy(thread);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitFailed("wait on a monitor doesn't work");
}
@@ -2293,18 +2282,19 @@ static void primitive_monitor_wait1(void *arg)
if(result1 != 0)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
printf("Wrong result is %i\n", result1);
ILUnitFailed("tryenter on a locked monitor doesn't work");
}
if((result = _ILMonitorExit(&_mon1)))
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitFailed("could not exit a monitor");
}
- if((result = _ILMonitorDestroy(&_mon1)))
+ _ILMonitorDestroy(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not destroy a monitor");
}
@@ -2379,23 +2369,18 @@ static void primitive_monitor_timed_wait1(void *arg)
int result2 = 0;
/* We are using the primitive versions for now. */
- if(_ILMonitorCreate(&_mon1))
+ _ILMonitorCreate(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not create a monitor");
}
- if(_ILMonitorEnter(&_mon1))
- {
- _ILMonitorDestroy(&_mon1);
- ILUnitFailed("could not enter a monitor");
- }
-
/* Create the thread */
thread = ILThreadCreate(_primitive_monitor_timed_wait1, &_mon1);
if(!thread)
{
_ILMonitorExit(&_mon1);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitOutOfMemory();
}
@@ -2415,7 +2400,7 @@ static void primitive_monitor_timed_wait1(void *arg)
{
/* Clean up the thread object. */
ILThreadDestroy(thread);
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result1);
printf("Wrong result is %i\n", result);
ILUnitFailed("timed wait on a monitor doesn't work");
}
@@ -2431,18 +2416,19 @@ static void primitive_monitor_timed_wait1(void *arg)
if(result1 != 0 || result2 != 3)
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
printf("Wrong result is %i\n", result1);
ILUnitFailed("tryenter on a locked monitor doesn't work");
}
if((result = _ILMonitorExit(&_mon1)))
{
- _ILMonitorDestroy(&_mon1);
+ _ILMonitorDestroy(&_mon1, result);
ILUnitFailed("could not exit a monitor");
}
- if((result = _ILMonitorDestroy(&_mon1)))
+ _ILMonitorDestroy(&_mon1, result);
+ if(result)
{
ILUnitFailed("could not destroy a monitor");
}
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 46 ++++
support/monitor.c | 103 +++++----
support/no_defs.h | 6 +-
support/pt_defs.c | 634 ++++++++++++++++++++++++++++++++++++++++++++++-----
support/pt_defs.h | 188 ++++++++++++----
support/w32_defs.h | 39 ++--
tests/test_thread.c | 160 ++++++-------
7 files changed, 926 insertions(+), 250 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. a2eb1ba0e8aa3b258dcf48e580f4b7e9f7fdc225,
Klaus Treichel <=