From c42be504c92d76d2e06d0fc8ebd05fc913376d2d Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 16 Nov 2016 14:50:09 +0100 Subject: posix: Add self-contained pthread spinlock Turn pthread_spinlock_t into a self-contained object. On uni-processor configurations, interrupts are disabled in the lock/trylock operations and the previous interrupt status is restored in the corresponding unlock operations. On SMP configurations, a ticket lock is a acquired and released in addition. The self-contained pthread_spinlock_t object is defined by Newlib in . typedef struct { struct _Ticket_lock_Control _lock; __uint32_t _interrupt_state; } pthread_spinlock_t; This implementation is simple and efficient. However, this test case of the Linux Test Project would fail due to call of printf() and sleep() during spin lock ownership: https://github.com/linux-test-project/ltp/blob/master/testcases/open_posix_testsuite/conformance/interfaces/pthread_spin_lock/1-2.c There is only limited support for profiling on SMP configurations. Delete CORE spinlock implementation. Update #2674. --- cpukit/score/Makefile.am | 8 -- cpukit/score/include/rtems/score/corespinlock.h | 77 ------------ .../score/include/rtems/score/corespinlockimpl.h | 130 --------------------- cpukit/score/include/rtems/score/objectimpl.h | 3 +- cpukit/score/include/rtems/sysinit.h | 1 - cpukit/score/preinstall.am | 8 -- cpukit/score/src/corespinlockrelease.c | 51 -------- cpukit/score/src/corespinlockwait.c | 102 ---------------- 8 files changed, 1 insertion(+), 379 deletions(-) delete mode 100644 cpukit/score/include/rtems/score/corespinlock.h delete mode 100644 cpukit/score/include/rtems/score/corespinlockimpl.h delete mode 100644 cpukit/score/src/corespinlockrelease.c delete mode 100644 cpukit/score/src/corespinlockwait.c (limited to 'cpukit/score') diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 02b0bfb260..9b376c3f06 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -112,8 +112,6 @@ include_rtems_score_HEADERS += include/rtems/score/cpuopts.h include_rtems_score_HEADERS += include/rtems/score/basedefs.h if HAS_PTHREADS -include_rtems_score_HEADERS += include/rtems/score/corespinlock.h -include_rtems_score_HEADERS += include/rtems/score/corespinlockimpl.h include_rtems_score_HEADERS += include/rtems/score/corerwlock.h include_rtems_score_HEADERS += include/rtems/score/corerwlockimpl.h endif @@ -196,12 +194,6 @@ endif ## CORE_SEMAPHORE_C_FILES libscore_a_SOURCES += src/coresem.c -## CORE_SPINLOCK_C_FILES -if HAS_PTHREADS -libscore_a_SOURCES += src/corespinlockrelease.c \ - src/corespinlockwait.c -endif - ## HEAP_C_FILES libscore_a_SOURCES += src/heap.c src/heapallocate.c src/heapextend.c \ src/heapfree.c src/heapsizeofuserarea.c src/heapwalk.c src/heapgetinfo.c \ diff --git a/cpukit/score/include/rtems/score/corespinlock.h b/cpukit/score/include/rtems/score/corespinlock.h deleted file mode 100644 index 1666538bf6..0000000000 --- a/cpukit/score/include/rtems/score/corespinlock.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file rtems/score/corespinlock.h - * - * @brief Constants and Structures Associated with the Spinlock Handler - * - * This include file contains all the constants and structures associated - * with the 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.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_CORESPINLOCK_H -#define _RTEMS_SCORE_CORESPINLOCK_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup ScoreSpinlock Spinlock Handler - * - * @ingroup Score - * - * This handler encapsulates functionality which provides the foundation - * Spinlock services used in all of the APIs supported by RTEMS. - */ -/**@{*/ - -/** - * The following defines the control block used to manage each - * spinlock. - */ -typedef struct { - /** - * @brief Lock to protect the other fields. - * - * This implementation is a bit stupid. However, test cases in the Linux - * Test Project do things like sleep() and printf() while owning a - * pthread_spinlock_t, e.g. - * testcases/open_posix_testsuite/conformance/interfaces/pthread_spin_lock/1-2.c - */ - ISR_LOCK_MEMBER( Lock ) - - /** This field is the lock. - */ - uint32_t lock; - - /** This field is a count of the current number of threads using - * this spinlock. It includes the thread holding the lock as well - * as those waiting. - */ - uint32_t users; - - /** This field is the Id of the thread holding the lock. It may or may - * not be the thread which acquired it. - */ - Thread_Control *holder; -} CORE_spinlock_Control; - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif -/* end of include file */ diff --git a/cpukit/score/include/rtems/score/corespinlockimpl.h b/cpukit/score/include/rtems/score/corespinlockimpl.h deleted file mode 100644 index 140529b573..0000000000 --- a/cpukit/score/include/rtems/score/corespinlockimpl.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @file - * - * @brief Inlined Routines Associated with the SuperCore Spinlock - * - * This include file contains all of the inlined routines associated - * with the SuperCore spinlock. - */ - -/* - * COPYRIGHT (c) 1989-2008. - * 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.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_CORESPINLOCKIMPL_H -#define _RTEMS_SCORE_CORESPINLOCKIMPL_H - -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @addtogroup ScoreSpinlock - */ -/**@{**/ - -/** This indicates the lock is available. */ -#define CORE_SPINLOCK_UNLOCKED 0 - -/** This indicates the lock is unavailable. */ -#define CORE_SPINLOCK_LOCKED 1 - -/** - * @brief Initialize the spinlock. - * - * This routine initializes the spinlock based on the parameters passed. - * - * @param[in] the_spinlock is the spinlock control block to initialize - */ -RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize( - CORE_spinlock_Control *the_spinlock -) -{ - memset( the_spinlock, 0, sizeof( *the_spinlock ) ); -} - -RTEMS_INLINE_ROUTINE void _CORE_spinlock_Acquire_critical( - CORE_spinlock_Control *the_spinlock, - ISR_lock_Context *lock_context -) -{ - _ISR_lock_Acquire( &the_spinlock->Lock, lock_context ); -} - -RTEMS_INLINE_ROUTINE void _CORE_spinlock_Release( - CORE_spinlock_Control *the_spinlock, - ISR_lock_Context *lock_context -) -{ - _ISR_lock_Release_and_ISR_enable( &the_spinlock->Lock, lock_context ); -} - -/** - * @brief Wait for spinlock. - * - * This routine wait for the spinlock to be released. If the spinlock - * is set to automatic and this is the appropriate thread, then it returns - * immediately. Otherwise, the calling thread is blocked until the spinlock - * is released. - * - * @param[in] the_spinlock is the spinlock to wait for - * @param[in] wait is true if willing to wait - * @param[in] timeout is the maximum number of ticks to spin (0 is forever) - * - * @retval A status is returned which indicates the success or failure of - * this operation. - */ -Status_Control _CORE_spinlock_Seize( - CORE_spinlock_Control *the_spinlock, - bool wait, - Watchdog_Interval timeout, - ISR_lock_Context *lock_context -); - -/** - * @brief Manually release the spinlock. - * - * This routine manually releases the spinlock. All of the threads waiting - * for the spinlock will be readied. - * - * @param[in] the_spinlock is the spinlock to surrender - */ -Status_Control _CORE_spinlock_Surrender( - CORE_spinlock_Control *the_spinlock, - ISR_lock_Context *lock_context -); - -/** - * This method is used to determine if the spinlock is available or not. - * - * @param[in] the_spinlock will be checked - * - * @return This method will return true if the spinlock is busy - * and false otherwise. - */ -RTEMS_INLINE_ROUTINE bool _CORE_spinlock_Is_busy( - CORE_spinlock_Control *the_spinlock -) -{ - return (the_spinlock->users != 0); -} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif -/* end of include file */ diff --git a/cpukit/score/include/rtems/score/objectimpl.h b/cpukit/score/include/rtems/score/objectimpl.h index f5beb3b971..a00aa2276e 100644 --- a/cpukit/score/include/rtems/score/objectimpl.h +++ b/cpukit/score/include/rtems/score/objectimpl.h @@ -92,8 +92,7 @@ typedef enum { OBJECTS_POSIX_CONDITION_VARIABLES = 8, OBJECTS_POSIX_TIMERS = 9, OBJECTS_POSIX_BARRIERS = 10, - OBJECTS_POSIX_SPINLOCKS = 11, - OBJECTS_POSIX_RWLOCKS = 12 + OBJECTS_POSIX_RWLOCKS = 11 } Objects_POSIX_API; /** This macro is used to generically specify the last API index. */ diff --git a/cpukit/score/include/rtems/sysinit.h b/cpukit/score/include/rtems/sysinit.h index ad68c45c5c..a0ab17c8ec 100644 --- a/cpukit/score/include/rtems/sysinit.h +++ b/cpukit/score/include/rtems/sysinit.h @@ -54,7 +54,6 @@ extern "C" { #define RTEMS_SYSINIT_POSIX_TIMER 000366 #define RTEMS_SYSINIT_POSIX_BARRIER 000367 #define RTEMS_SYSINIT_POSIX_RWLOCK 000368 -#define RTEMS_SYSINIT_POSIX_SPINLOCK 000369 #define RTEMS_SYSINIT_POSIX_CLEANUP 00036a #define RTEMS_SYSINIT_POSIX_KEYS 00036b #define RTEMS_SYSINIT_IDLE_THREADS 000380 diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index a6943244b5..4d468e5dde 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -409,14 +409,6 @@ $(PROJECT_INCLUDE)/rtems/score/basedefs.h: include/rtems/score/basedefs.h $(PROJ PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/basedefs.h if HAS_PTHREADS -$(PROJECT_INCLUDE)/rtems/score/corespinlock.h: include/rtems/score/corespinlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/corespinlock.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/corespinlock.h - -$(PROJECT_INCLUDE)/rtems/score/corespinlockimpl.h: include/rtems/score/corespinlockimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/corespinlockimpl.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/corespinlockimpl.h - $(PROJECT_INCLUDE)/rtems/score/corerwlock.h: include/rtems/score/corerwlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/corerwlock.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/corerwlock.h diff --git a/cpukit/score/src/corespinlockrelease.c b/cpukit/score/src/corespinlockrelease.c deleted file mode 100644 index 4a4f9528b3..0000000000 --- a/cpukit/score/src/corespinlockrelease.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file - * - * @brief Release a Spinlock - * @ingroup ScoreSpinlock - */ - -/* - * 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.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -Status_Control _CORE_spinlock_Surrender( - CORE_spinlock_Control *the_spinlock, - ISR_lock_Context *lock_context -) -{ - _CORE_spinlock_Acquire_critical( the_spinlock, lock_context ); - - /* - * It must locked by the current thread before it can be unlocked. - */ - if ( - the_spinlock->lock != CORE_SPINLOCK_LOCKED - || the_spinlock->holder != _Thread_Executing - ) { - _CORE_spinlock_Release( the_spinlock, lock_context ); - return STATUS_NOT_OWNER; - } - - /* - * Let it be unlocked. - */ - the_spinlock->users -= 1; - the_spinlock->lock = CORE_SPINLOCK_UNLOCKED; - the_spinlock->holder = 0; - - _CORE_spinlock_Release( the_spinlock, lock_context ); - return STATUS_SUCCESSFUL; -} diff --git a/cpukit/score/src/corespinlockwait.c b/cpukit/score/src/corespinlockwait.c deleted file mode 100644 index 4aacb60b74..0000000000 --- a/cpukit/score/src/corespinlockwait.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * @file - * - * @brief Wait for Spinlock - * @ingroup ScoreSpinlock - */ - -/* - * COPYRIGHT (c) 1989-2009. - * 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.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -Status_Control _CORE_spinlock_Seize( - CORE_spinlock_Control *the_spinlock, - bool wait, - Watchdog_Interval timeout, - ISR_lock_Context *lock_context -) -{ - Thread_Control *executing; - - #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) - Watchdog_Interval limit = _Watchdog_Ticks_since_boot + timeout; - #endif - - executing = _Thread_Executing; - - _CORE_spinlock_Acquire_critical( the_spinlock, lock_context ); - if ( the_spinlock->lock == CORE_SPINLOCK_LOCKED && - the_spinlock->holder == executing ) { - _CORE_spinlock_Release( the_spinlock, lock_context ); - return STATUS_NESTING_NOT_ALLOWED; - } - the_spinlock->users += 1; - for ( ;; ) { - if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) { - the_spinlock->lock = CORE_SPINLOCK_LOCKED; - the_spinlock->holder = executing; - _CORE_spinlock_Release( the_spinlock, lock_context ); - return STATUS_SUCCESSFUL; - } - - /* - * Spinlock is unavailable. If not willing to wait, return. - */ - if ( !wait ) { - the_spinlock->users -= 1; - _CORE_spinlock_Release( the_spinlock, lock_context ); - return STATUS_UNAVAILABLE; - } - - #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) - /* - * They are willing to wait but there could be a timeout. - */ - if ( timeout && (limit <= _Watchdog_Ticks_since_boot) ) { - the_spinlock->users -= 1; - _CORE_spinlock_Release( the_spinlock, lock_context ); - return STATUS_TIMEOUT; - } - #endif - - /* - * 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. - */ - - _CORE_spinlock_Release( the_spinlock, lock_context ); - - /* - * An ISR could occur here. Another thread could get dispatched here. - * Reenter the critical sections so we can attempt the lock again. - */ - - _ISR_lock_ISR_disable( lock_context ); - _CORE_spinlock_Acquire_critical( the_spinlock, lock_context ); - } - -} -- cgit v1.2.3