diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2006-09-25 13:36:58 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2006-09-25 13:36:58 +0000 |
commit | 9c191eea63fd6c5511c01186297722e594220032 (patch) | |
tree | d5ad903d3005a0c24511851d829e0a00b2c1c53c /cpukit/score/src | |
parent | 2006-09-14 Joel Sherrill <joel@OARcorp.com> (diff) | |
download | rtems-9c191eea63fd6c5511c01186297722e594220032.tar.bz2 |
* score/Makefile.am, score/preinstall.am,
score/include/rtems/score/coresem.h,
score/include/rtems/score/object.h,
score/include/rtems/score/states.h,
score/inline/rtems/score/coresem.inl: Add SuperCore Barriers,
SpinLocks and a partial implementation of RWLocks.
* score/include/rtems/score/corebarrier.h,
score/include/rtems/score/corerwlock.h,
score/include/rtems/score/corespinlock.h,
score/inline/rtems/score/corebarrier.inl,
score/inline/rtems/score/corerwlock.inl,
score/inline/rtems/score/corespinlock.inl,
score/macros/rtems/score/corebarrier.inl,
score/macros/rtems/score/corerwlock.inl,
score/macros/rtems/score/corespinlock.inl, score/src/corebarrier.c,
score/src/corebarrierrelease.c, score/src/corebarrierwait.c,
score/src/corerwlock.c, score/src/corerwlockobtainread.c,
score/src/corerwlockobtainwrite.c, score/src/corerwlockrelease.c,
score/src/corespinlock.c, score/src/corespinlockrelease.c,
score/src/corespinlockwait.c: New files.
Diffstat (limited to 'cpukit/score/src')
-rw-r--r-- | cpukit/score/src/corebarrier.c | 60 | ||||
-rw-r--r-- | cpukit/score/src/corebarrierrelease.c | 68 | ||||
-rw-r--r-- | cpukit/score/src/corebarrierwait.c | 81 | ||||
-rw-r--r-- | cpukit/score/src/corerwlock.c | 62 | ||||
-rw-r--r-- | cpukit/score/src/corerwlockobtainread.c | 103 | ||||
-rw-r--r-- | cpukit/score/src/corerwlockobtainwrite.c | 93 | ||||
-rw-r--r-- | cpukit/score/src/corerwlockrelease.c | 80 | ||||
-rw-r--r-- | cpukit/score/src/corespinlock.c | 56 | ||||
-rw-r--r-- | cpukit/score/src/corespinlockrelease.c | 53 | ||||
-rw-r--r-- | cpukit/score/src/corespinlockwait.c | 110 |
10 files changed, 766 insertions, 0 deletions
diff --git a/cpukit/score/src/corebarrier.c b/cpukit/score/src/corebarrier.c new file mode 100644 index 0000000000..b118944bbe --- /dev/null +++ b/cpukit/score/src/corebarrier.c @@ -0,0 +1,60 @@ +/* + * SuperCore Barrier Handler + * + * DESCRIPTION: + * + * This package is part of the implementation of the SuperCore Barrier Handler. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corebarrier.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif + +/*PAGE + * + * _CORE_barrier_Initialize + * + * This function initialize a barrier and sets the initial value based + * on the given count. + * + * Input parameters: + * the_barrier - the barrier control block to initialize + * the_barrier_attributes - the attributes specified at create time + * + * Output parameters: NONE + */ + +void _CORE_barrier_Initialize( + CORE_barrier_Control *the_barrier, + CORE_barrier_Attributes *the_barrier_attributes +) +{ + + the_barrier->Attributes = *the_barrier_attributes; + the_barrier->number_of_waiting_threads = 0; + + _Thread_queue_Initialize( + &the_barrier->Wait_queue, + THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_BARRIER, + CORE_BARRIER_TIMEOUT + ); +} diff --git a/cpukit/score/src/corebarrierrelease.c b/cpukit/score/src/corebarrierrelease.c new file mode 100644 index 0000000000..a93efa4c70 --- /dev/null +++ b/cpukit/score/src/corebarrierrelease.c @@ -0,0 +1,68 @@ +/* + * SuperCore Barrier Handler + * + * DESCRIPTION: + * + * This package is part of the implementation of the SuperCore Barrier Handler. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/corebarrier.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif + +/*PAGE + * + * _CORE_barrier_Release + * + * Input parameters: + * the_barrier - the barrier to be flushed + * id - id of the object for a remote unblock + * api_barrier_mp_support - api dependent MP support actions + * + * Output parameters: + * CORE_BARRIER_STATUS_SUCCESSFUL - if successful + * core error code - if unsuccessful + * + * Output parameters: + * returns number of threads unblocked + */ + +uint32_t _CORE_barrier_Release( + CORE_barrier_Control *the_barrier, + Objects_Id id, + CORE_barrier_API_mp_support_callout api_barrier_mp_support +) +{ + Thread_Control *the_thread; + uint32_t count; + + count = 0; + while ( (the_thread = _Thread_queue_Dequeue(&the_barrier->Wait_queue)) ) { +#if defined(RTEMS_MULTIPROCESSING) + if ( !_Objects_Is_local_id( the_thread->Object.id ) ) + (*api_barrier_mp_support) ( the_thread, id ); +#endif + count++; + } + the_barrier->number_of_waiting_threads = 0; + return count; +} diff --git a/cpukit/score/src/corebarrierwait.c b/cpukit/score/src/corebarrierwait.c new file mode 100644 index 0000000000..f00b3d73d5 --- /dev/null +++ b/cpukit/score/src/corebarrierwait.c @@ -0,0 +1,81 @@ +/* + * SuperCore Barrier Handler + * + * DESCRIPTION: + * + * This package is part of the implementation of the SuperCore Barrier Handler. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/corebarrier.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif + +/*PAGE + * + * _CORE_barrier_Wait + * + * Input parameters: + * the_barrier - pointer to barrier control block + * id - id of object to wait on + * wait - TRUE if wait is allowed, FALSE otherwise + * timeout - number of ticks to wait (0 means forever) + * api_barrier_mp_support - api dependent MP support actions + * + * Output parameters: NONE + * + * INTERRUPT LATENCY: + * available + * wait + */ + +void _CORE_barrier_Wait( + CORE_barrier_Control *the_barrier, + Objects_Id id, + boolean wait, + Watchdog_Interval timeout, + CORE_barrier_API_mp_support_callout api_barrier_mp_support +) +{ + Thread_Control *executing; + ISR_Level level; + + executing = _Thread_Executing; + executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL; + _ISR_Disable( level ); + the_barrier->number_of_waiting_threads++; + if ( the_barrier->number_of_waiting_threads == + the_barrier->Attributes.maximum_count) { + if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) { + executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED; + _ISR_Enable( level ); + _CORE_barrier_Release( the_barrier, id, api_barrier_mp_support ); + return; + } + } + + _Thread_queue_Enter_critical_section( &the_barrier->Wait_queue ); + executing->Wait.queue = &the_barrier->Wait_queue; + executing->Wait.id = id; + _ISR_Enable( level ); + + _Thread_queue_Enqueue( &the_barrier->Wait_queue, timeout ); +} diff --git a/cpukit/score/src/corerwlock.c b/cpukit/score/src/corerwlock.c new file mode 100644 index 0000000000..3629f146aa --- /dev/null +++ b/cpukit/score/src/corerwlock.c @@ -0,0 +1,62 @@ +/* + * SuperCore RWLock Handler + * + * DESCRIPTION: + * + * This package is part of the implementation of the SuperCore RWLock Handler. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corerwlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif + +/*PAGE + * + * _CORE_RWLock_Initialize + * + * This function initialize a rwlock and sets the initial value based + * on the given count. + * + * Input parameters: + * the_rwlock - the rwlock control block to initialize + * the_rwlock_attributes - the attributes specified at create time + * + * Output parameters: NONE + */ + +void _CORE_RWLock_Initialize( + CORE_RWLock_Control *the_rwlock, + CORE_RWLock_Attributes *the_rwlock_attributes +) +{ + + the_rwlock->Attributes = *the_rwlock_attributes; +/* + the_rwlock->number_of_waiting_threads = 0; +*/ + + _Thread_queue_Initialize( + &the_rwlock->Wait_queue, + THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_RWLOCK, + CORE_RWLOCK_TIMEOUT + ); +} diff --git a/cpukit/score/src/corerwlockobtainread.c b/cpukit/score/src/corerwlockobtainread.c new file mode 100644 index 0000000000..c90bf02f07 --- /dev/null +++ b/cpukit/score/src/corerwlockobtainread.c @@ -0,0 +1,103 @@ +/* + * SuperCore RWLock Handler -- Obtain RWLock for reading + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corerwlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * _CORE_rwlock_Obtain_for_reading + * + * This function waits for the rwlock to become available. Optionally, + * a limit may be placed on the duration of the spin. + * + * Input parameters: + * the_rwlock - the rwlock control block to initialize + * timeout_allowed - true if timeout allowed + * timeout - the maximum number of ticks to spin + * + * Output parameters: NONE + */ + +void _CORE_RWLock_Obtain_for_reading( + CORE_RWLock_Control *the_rwlock, + Objects_Id id, + boolean wait, + Watchdog_Interval timeout, + CORE_RWLock_API_mp_support_callout api_rwlock_mp_support +) +{ + ISR_Level level; + Thread_Control *executing = _Thread_Executing; + + /* + * If unlocked, then OK to read. + * If locked for reading and no waiters, then OK to read. + * If any thread is waiting, then we wait. + */ + + _ISR_Disable( level ); + switch ( the_rwlock->current_state ) { + case CORE_RWLOCK_UNLOCKED: + the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING; + the_rwlock->number_of_readers += 1; + _ISR_Enable( level ); + executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; + return; + + case CORE_RWLOCK_LOCKED_FOR_READING: { + Thread_Control *waiter; + waiter = _Thread_queue_First( &the_rwlock->Wait_queue ); + if ( !waiter ) { + the_rwlock->number_of_readers += 1; + _ISR_Enable( level ); + executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; + return; + } + break; + } + case CORE_RWLOCK_LOCKED_FOR_WRITING: + break; + } + + /* + * If the thread is not willing to wait, then return immediately. + */ + + if ( !wait ) { + _ISR_Enable( level ); + executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE; + } + + /* + * We need to wait to enter this critical section + */ + + _Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue ); + executing->Wait.queue = &the_rwlock->Wait_queue; + executing->Wait.id = id; + executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE; + executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; + _ISR_Enable( level ); + + _Thread_queue_Enqueue( &the_rwlock->Wait_queue, timeout ); + + /* return to API level so it can dispatch and we block */ +} diff --git a/cpukit/score/src/corerwlockobtainwrite.c b/cpukit/score/src/corerwlockobtainwrite.c new file mode 100644 index 0000000000..02e7906249 --- /dev/null +++ b/cpukit/score/src/corerwlockobtainwrite.c @@ -0,0 +1,93 @@ +/* + * SuperCore RWLock Handler -- Obtain RWLock for writing + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corerwlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * _CORE_rwlock_Obtain_for_writing + * + * This function waits for the rwlock to become available. Optionally, + * a limit may be placed on the duration of the spin. + * + * Input parameters: + * the_rwlock - the rwlock control block to initialize + * timeout_allowed - true if timeout allowed + * timeout - the maximum number of ticks to spin + * + * Output parameters: NONE + */ + +void _CORE_RWLock_Obtain_for_writing( + CORE_RWLock_Control *the_rwlock, + Objects_Id id, + boolean wait, + Watchdog_Interval timeout, + CORE_RWLock_API_mp_support_callout api_rwlock_mp_support +) +{ + ISR_Level level; + Thread_Control *executing = _Thread_Executing; + + /* + * If unlocked, then OK to read. + * Otherwise, we have to block. + * If locked for reading and no waiters, then OK to read. + * If any thread is waiting, then we wait. + */ + + _ISR_Disable( level ); + switch ( the_rwlock->current_state ) { + case CORE_RWLOCK_UNLOCKED: + the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING; + _ISR_Enable( level ); + executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; + return; + + case CORE_RWLOCK_LOCKED_FOR_READING: + case CORE_RWLOCK_LOCKED_FOR_WRITING: + break; + } + + /* + * If the thread is not willing to wait, then return immediately. + */ + + if ( !wait ) { + _ISR_Enable( level ); + executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE; + } + + /* + * We need to wait to enter this critical section + */ + + _Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue ); + executing->Wait.queue = &the_rwlock->Wait_queue; + executing->Wait.id = id; + executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE; + executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; + _ISR_Enable( level ); + + _Thread_queue_Enqueue( &the_rwlock->Wait_queue, timeout ); + + /* return to API level so it can dispatch and we block */ +} diff --git a/cpukit/score/src/corerwlockrelease.c b/cpukit/score/src/corerwlockrelease.c new file mode 100644 index 0000000000..5943785664 --- /dev/null +++ b/cpukit/score/src/corerwlockrelease.c @@ -0,0 +1,80 @@ +/* + * SuperCore RWLock Handler -- Release a RWLock + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corerwlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * _CORE_RWLock_Release + * + * This function releases the rwlock. + * + * Input parameters: + * the_rwlock - the rwlock control block to initialize + * + * Output parameters: NONE + */ + +CORE_RWLock_Status _CORE_RWLock_Release( + CORE_RWLock_Control *the_rwlock +) +{ + ISR_Level level; + Thread_Control *executing = _Thread_Executing; + + /* + * If unlocked, then OK to read. + * Otherwise, we have to block. + * If locked for reading and no waiters, then OK to read. + * If any thread is waiting, then we wait. + */ + + _ISR_Disable( level ); + switch ( the_rwlock->current_state ) { + case CORE_RWLOCK_UNLOCKED: + _ISR_Enable( level ); + executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE; + return CORE_RWLOCK_SUCCESSFUL; + + case CORE_RWLOCK_LOCKED_FOR_READING: + the_rwlock->number_of_readers -= 1; + if ( the_rwlock->number_of_readers != 0 ) { + /* must be unlocked again */ + _ISR_Enable( level ); + return CORE_RWLOCK_SUCCESSFUL; + } + executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL; + break; + case CORE_RWLOCK_LOCKED_FOR_WRITING: + break; + } + + /* + * Implicitly transition to "unlocked" and find another thread interested + * in obtaining this rwlock. + */ + + /* XXX need to put read/write lock request indicator in Wait info */ + + /* XXX find one writer or multiple readers to take off */ + _ISR_Enable( level ); + return CORE_RWLOCK_SUCCESSFUL; +} diff --git a/cpukit/score/src/corespinlock.c b/cpukit/score/src/corespinlock.c new file mode 100644 index 0000000000..ff16057021 --- /dev/null +++ b/cpukit/score/src/corespinlock.c @@ -0,0 +1,56 @@ +/* + * SuperCore Spinlock Handler + * + * DESCRIPTION: + * + * This package is part of the implementation of the SuperCore Spinlock Handler. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corespinlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif + +/*PAGE + * + * _CORE_spinlock_Initialize + * + * This function initialize a spinlock and sets the initial value based + * on the given count. + * + * Input parameters: + * the_spinlock - the spinlock control block to initialize + * the_spinlock_attributes - the attributes specified at create time + * + * Output parameters: NONE + */ + +void _CORE_spinlock_Initialize( + CORE_spinlock_Control *the_spinlock, + CORE_spinlock_Attributes *the_spinlock_attributes +) +{ + + the_spinlock->Attributes = *the_spinlock_attributes; + + the_spinlock->lock = 0; + the_spinlock->users = 0; + the_spinlock->holder = 0; +} diff --git a/cpukit/score/src/corespinlockrelease.c b/cpukit/score/src/corespinlockrelease.c new file mode 100644 index 0000000000..05aec32c4c --- /dev/null +++ b/cpukit/score/src/corespinlockrelease.c @@ -0,0 +1,53 @@ +/* + * SuperCore Spinlock Handler -- Release a Spinlock + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corespinlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * _CORE_spinlock_Release + * + * This function releases the spinlock. + * + * Input parameters: + * the_spinlock - the spinlock control block to initialize + * + * Output parameters: NONE + */ + +CORE_spinlock_Status _CORE_spinlock_Release( + CORE_spinlock_Control *the_spinlock +) +{ + ISR_Level level; + + _ISR_Disable( level ); + if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) { + _ISR_Enable( level ); + return CORE_SPINLOCK_NOT_LOCKED; + } + + the_spinlock->users -= 1; + the_spinlock->lock = CORE_SPINLOCK_UNLOCKED; + the_spinlock->holder = 0; + _ISR_Enable( level ); + return CORE_SPINLOCK_SUCCESSFUL; +} diff --git a/cpukit/score/src/corespinlockwait.c b/cpukit/score/src/corespinlockwait.c new file mode 100644 index 0000000000..96c173855b --- /dev/null +++ b/cpukit/score/src/corespinlockwait.c @@ -0,0 +1,110 @@ +/* + * SuperCore Spinlock Handler -- Wait for Spinlock + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/corespinlock.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * _CORE_spinlock_Wait + * + * This function waits for the spinlock to become available. Optionally, + * a limit may be placed on the duration of the spin. + * + * Input parameters: + * the_spinlock - the spinlock control block to initialize + * wait - true if willing to wait + * timeout - the maximum number of ticks to spin (0 is forever) + * + * Output parameters: NONE + */ + +CORE_spinlock_Status _CORE_spinlock_Wait( + CORE_spinlock_Control *the_spinlock, + boolean wait, + Watchdog_Interval timeout +) +{ + ISR_Level level; + Watchdog_Interval limit = _Watchdog_Ticks_since_boot + timeout; + + _ISR_Disable( level ); + if ( (the_spinlock->lock == CORE_SPINLOCK_LOCKED) && + (the_spinlock->holder == _Thread_Executing->Object.id) ) { + _ISR_Enable( level ); + return CORE_SPINLOCK_HOLDER_RELOCKING; + } + the_spinlock->users += 1; + for ( ;; ) { + if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) { + the_spinlock->lock = CORE_SPINLOCK_LOCKED; + the_spinlock->holder = _Thread_Executing->Object.id; + _ISR_Enable( level ); + return CORE_SPINLOCK_SUCCESSFUL; + } + + /* + * Spinlock is unavailable. If not willing to wait, return. + */ + if ( !wait ) { + the_spinlock->users -= 1; + _ISR_Enable( level ); + return CORE_SPINLOCK_UNAVAILABLE; + } + + /* + * They are willing to wait but there could be a timeout. + */ + if ( timeout && (limit >= _Watchdog_Ticks_since_boot)) { + the_spinlock->users -= 1; + _ISR_Enable( level ); + return CORE_SPINLOCK_TIMEOUT; + } + + /* + * The thread is willing to spin so let's set things up so + * another thread has a chance of running. This spinlock has + * to be released by either another thread or an ISR. Since + * POSIX does not say anything about ISRs, that implies that + * another thread must be able to run while spinning. We are + * not blocking so that implies we are at least preemptible + * and possibly time-sliced. + * + * So first, we will enable interrpts to allow for them to happen. + * Then we will "flash" the thread dispatching critical section + * so other threads have a chance to run. + * + * A spinlock cannot be deleted while it is being used so we are + * safe from deletion. + */ + + _ISR_Enable( level ); + /* An ISR could occur here */ + + _Thread_Enable_dispatch(); + /* Another thread could get dispatched here */ + + /* Reenter the critical sections so we can attempt the lock again. */ + _Thread_Disable_dispatch(); + + _ISR_Disable( level ); + } + +} |