--- cpukit/score/Makefile.am | 1 + cpukit/score/include/rtems/score/smprwlock.h | 181 ++++++++++++++++++++++++++ cpukit/score/preinstall.am | 4 + 3 files changed, 186 insertions(+) create mode 100644 cpukit/score/include/rtems/score/smprwlock.h
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index c9d2d47..c0b7939 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -86,6 +86,7 @@ include_rtems_score_HEADERS += include/rtems/score/basedefs.h if ATOMIC include_rtems_score_HEADERS += include/rtems/score/atomic.h include_rtems_score_HEADERS += include/rtems/score/cpustdatomic.h +include_rtems_score_HEADERS += include/rtems/score/smprwlock.h endif if HAS_PTHREADS diff --git a/cpukit/score/include/rtems/score/smprwlock.h b/cpukit/score/include/rtems/score/smprwlock.h new file mode 100644 index 0000000..e35ec83 --- /dev/null +++ b/cpukit/score/include/rtems/score/smprwlock.h @@ -0,0 +1,181 @@ +/** + * @file + * + * @ingroup ScoreSMPRWlock + * + * @brief SMP Lock API + */ + +/* + * COPYRIGHT (c) 2012-2013 Deng Hengyi. + * + * 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. + */ + +#ifndef _RTEMS_SCORE_SMPRWLOCK_H +#define _RTEMS_SCORE_SMPRWLOCK_H + +#include <rtems/score/cpuopts.h> + +#if defined( RTEMS_SMP ) + +#include <rtems/rtems/atomic.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup ScoreSMPRWlock SMP Locks + * + * @ingroup Score + * + * The SMP rw lock implementation is architecture dependent. Now the rw lock + * is based on the implementation of phase-fairness lock. The phase-fairness + * lock use atomic ops to implement. So the architectures which do not support + * atomic ops will not use it. + * + * @{ + */ + +/** + * @brief SMP rw lock control. + * + * This is used by phase-fairness lock. + */ +typedef struct { + Atomic_Uint rin; + Atomic_Uint rout; + Atomic_Uint win; + Atomic_Uint wout; +} SMP_rwlock_Control; + +/** + * @brief SMP rw lock control macro. + */ +#define SMP_RWLOCK_LSB 0xFFFFFFF0 +#define SMP_RWLOCK_RINC 0x100 /* Reader increment value. */ +#define SMP_RWLOCK_WBITS 0x3 /* Writer bits in reader. */ +#define SMP_RWLOCK_PRES 0x2 /* Writer present bit. */ +#define SMP_RWLOCK_PHID 0x1 /* Phase ID bit. */ + +/** + * @brief SMP rwlock control initializer for static initialization. + */ +#define SMP_RWLOCK_INITIALIZER { ATOMIC_INITIALIZER_UINT( 0 ), \ + ATOMIC_INITIALIZER_UINT( 0 ), \ + ATOMIC_INITIALIZER_UINT( 0 ), \ + ATOMIC_INITIALIZER_UINT( 0 ) } + +/** + * @brief Initializes a SMP rwlock control. + * + * Concurrent initialization leads to unpredictable results. + * + * @param[out] lock The SMP rwlock control. + */ +static inline void _SMP_rwlock_Initialize( SMP_rwlock_Control *lock ) +{ + _Atomic_Init_uint( &(lock->rin), 0 ); + _Atomic_Init_uint( &(lock->rout), 0 ); + _Atomic_Init_uint( &(lock->win), 0 ); + _Atomic_Init_uint( &(lock->wout), 0 ); +} + +/** + * @brief Acquires a SMP rwlock for read. + * + * This function will implementation phase-fairness read lock. + * + * @param[in,out] lock The SMP rwlock control. + */ +static inline void _SMP_rwlock_Acquire_read( SMP_rwlock_Control *lock ) +{ + uint_fast32_t w; + + /* + * If no writer is present, then the operation has completed + * successfully. + */ + w = _Atomic_Fetch_add_uint(&lock->rin, SMP_RWLOCK_RINC, ATOMIC_ORDER_ACQUIRE) + & SMP_RWLOCK_WBITS; + if (w == 0) + return; + + /* Wait for current write phase to complete. */ + while ((_Atomic_Load_uint(&lock->rin, ATOMIC_ORDER_ACQUIRE) + & SMP_RWLOCK_WBITS) == w); + + return; +} + +/** + * @brief Releases a SMP rwlock for read. + * + * @param[in,out] lock The SMP rwlock control. + */ +static inline void _SMP_rwlock_Release_read( SMP_rwlock_Control *lock ) +{ + _Atomic_Fetch_add_uint(&lock->rout, SMP_RWLOCK_RINC, ATOMIC_ORDER_RELEASE); + + return; +} + +/** + * @brief Acquires a SMP rwlock for write. + * + * This function will implementation phase-fairness write lock. + * + * @param[in,out] lock The SMP rwlock control. + */ +static inline void _SMP_rwlock_Acquire_write( SMP_rwlock_Control *lock ) +{ + uint_fast32_t ticket; + + /* Acquire ownership of write-phase. */ + ticket = _Atomic_Fetch_add_uint(&lock->win, 1, ATOMIC_ORDER_RELEASE); + + while (_Atomic_Load_uint(&lock->wout, ATOMIC_ORDER_ACQUIRE) != ticket); + + /* + * Acquire ticket on read-side in order to allow them + * to flush. Indicates to any incoming reader that a + * write-phase is pending. + */ + ticket = _Atomic_Fetch_add_uint(&lock->rin, + (ticket & SMP_RWLOCK_PHID) | SMP_RWLOCK_PRES, + ATOMIC_ORDER_RELEASE); + + /* Wait for any pending readers to flush. */ + while (_Atomic_Load_uint(&lock->rout, ATOMIC_ORDER_ACQUIRE) != ticket); + + return; +} + +/** + * @brief Releases a SMP rwlock for write. + * + * @param[in,out] lock The SMP rwlock control. + */ +static inline void _SMP_rwlock_Release_write( SMP_rwlock_Control *lock ) +{ + /* Migrate from write phase to read phase. */ + _Atomic_Fetch_and_uint(&lock->rin, SMP_RWLOCK_LSB, ATOMIC_ORDER_RELEASE); + + /* Allow other writers to continue. */ + _Atomic_Fetch_add_uint(&lock->wout, 1, ATOMIC_ORDER_RELEASE); + + return; +} + +/**@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined( RTEMS_SMP ) */ + +#endif /* _RTEMS_SCORE_SMPRWLOCK_H */ diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index 79a18b5..3c22c8e 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -323,6 +323,10 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/atomic.h $(PROJECT_INCLUDE)/rtems/score/cpustdatomic.h: include/rtems/score/cpustdatomic.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpustdatomic.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpustdatomic.h + +$(PROJECT_INCLUDE)/rtems/score/smprwlock.h: include/rtems/score/smprwlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smprwlock.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smprwlock.h endif if HAS_PTHREADS $(PROJECT_INCLUDE)/rtems/score/corespinlock.h: include/rtems/score/corespinlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) -- 1.7.9.5 _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel