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/posix/src/pspin.c | 51 ---------------------- cpukit/posix/src/pspindestroy.c | 30 +++---------- cpukit/posix/src/pspininit.c | 52 +++------------------- cpukit/posix/src/pspinlock.c | 96 +++++++++++++++++++++++++++++++++++------ cpukit/posix/src/pspintrylock.c | 42 ------------------ cpukit/posix/src/pspinunlock.c | 36 +++++++++++----- 6 files changed, 122 insertions(+), 185 deletions(-) delete mode 100644 cpukit/posix/src/pspin.c delete mode 100644 cpukit/posix/src/pspintrylock.c (limited to 'cpukit/posix/src') diff --git a/cpukit/posix/src/pspin.c b/cpukit/posix/src/pspin.c deleted file mode 100644 index 6c466bcab5..0000000000 --- a/cpukit/posix/src/pspin.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file - * - * This file contains the initialization of the POSIX Spinlock Manager. - */ - -/* - * COPYRIGHT (c) 1989-2013. - * 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 -#include -#include -#include - -Objects_Information _POSIX_Spinlock_Information; - -/** - * @brief _POSIX_Spinlock_Manager_initialization - */ -static void _POSIX_Spinlock_Manager_initialization(void) -{ - _Objects_Initialize_information( - &_POSIX_Spinlock_Information, /* object information table */ - OBJECTS_POSIX_API, /* object API */ - OBJECTS_POSIX_SPINLOCKS, /* object class */ - Configuration_POSIX_API.maximum_spinlocks, - /* maximum objects of this class */ - sizeof( POSIX_Spinlock_Control ),/* size of this object's control block */ - true, /* true if the name is a string */ - _POSIX_PATH_MAX, /* maximum length of each object's name */ - NULL /* Proxy extraction support callout */ - ); -} - -RTEMS_SYSINIT_ITEM( - _POSIX_Spinlock_Manager_initialization, - RTEMS_SYSINIT_POSIX_SPINLOCK, - RTEMS_SYSINIT_ORDER_MIDDLE -); diff --git a/cpukit/posix/src/pspindestroy.c b/cpukit/posix/src/pspindestroy.c index 42a6e76806..f5de88f04b 100644 --- a/cpukit/posix/src/pspindestroy.c +++ b/cpukit/posix/src/pspindestroy.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH + * * 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. @@ -20,33 +22,13 @@ #include -#include - int pthread_spin_destroy( pthread_spinlock_t *spinlock ) { +#if defined(RTEMS_SMP) && defined(POSIX_SPINLOCKS_ARE_SELF_CONTAINED) POSIX_Spinlock_Control *the_spinlock; - ISR_lock_Context lock_context; - - _Objects_Allocator_lock(); - - the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context ); - if ( the_spinlock == NULL ) { - _Objects_Allocator_unlock(); - return EINVAL; - } - _CORE_spinlock_Acquire_critical( &the_spinlock->Spinlock, &lock_context ); - - if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) { - _CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context ); - _Objects_Allocator_unlock(); - return EBUSY; - } - - _CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context ); - - _Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object ); - _POSIX_Spinlock_Free( the_spinlock ); - _Objects_Allocator_unlock(); + the_spinlock = _POSIX_Spinlock_Get( spinlock ); + _SMP_ticket_lock_Destroy( &the_spinlock->Lock ); +#endif return 0; } diff --git a/cpukit/posix/src/pspininit.c b/cpukit/posix/src/pspininit.c index bc131e2e81..313633a11e 100644 --- a/cpukit/posix/src/pspininit.c +++ b/cpukit/posix/src/pspininit.c @@ -11,6 +11,8 @@ * COPYRIGHT (c) 1989-2006. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH + * * 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. @@ -20,58 +22,18 @@ #include "config.h" #endif -#include -#include - -#include #include -/* - * pthread_spinlock_init - * - * This directive creates a spinlock. A spinlock id is returned. - * - * Input parameters: - * spinlock - pointer to spinlock id - * pshared - is this spinlock shared between processes - * - * Output parameters: - * spinlock - spinlock id - * 0 - if successful - * error code - if unsuccessful - */ - int pthread_spin_init( pthread_spinlock_t *spinlock, int pshared ) { - POSIX_Spinlock_Control *the_spinlock; +#if defined(RTEMS_SMP) && defined(POSIX_SPINLOCKS_ARE_SELF_CONTAINED) + POSIX_Spinlock_Control *the_spinlock; - if ( !spinlock ) - return EINVAL; - - switch ( pshared ) { - case PTHREAD_PROCESS_PRIVATE: /* only supported values */ - break; - case PTHREAD_PROCESS_SHARED: - default: - return EINVAL; - } - - the_spinlock = _POSIX_Spinlock_Allocate(); - - if ( !the_spinlock ) { - _Objects_Allocator_unlock(); - return EAGAIN; - } - - _CORE_spinlock_Initialize( &the_spinlock->Spinlock ); - - _Objects_Open_u32( &_POSIX_Spinlock_Information, &the_spinlock->Object, 0 ); - - *spinlock = the_spinlock->Object.id; - - _Objects_Allocator_unlock(); + the_spinlock = _POSIX_Spinlock_Get( spinlock ); + _SMP_ticket_lock_Initialize( &the_spinlock->Lock ); +#endif return 0; } diff --git a/cpukit/posix/src/pspinlock.c b/cpukit/posix/src/pspinlock.c index a2db911698..a9b04d8392 100644 --- a/cpukit/posix/src/pspinlock.c +++ b/cpukit/posix/src/pspinlock.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH + * * 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. @@ -19,24 +21,92 @@ #endif #include -#include + +#if defined(POSIX_SPINLOCKS_ARE_SELF_CONTAINED) +RTEMS_STATIC_ASSERT( +#if defined(RTEMS_SMP) + offsetof( POSIX_Spinlock_Control, Lock.next_ticket ) +#else + offsetof( POSIX_Spinlock_Control, reserved[ 0 ] ) +#endif + == offsetof( pthread_spinlock_t, _Lock._next_ticket ), + POSIX_SPINLOCK_T_LOCK_NEXT_TICKET +); + +RTEMS_STATIC_ASSERT( +#if defined(RTEMS_SMP) + offsetof( POSIX_Spinlock_Control, Lock.now_serving ) +#else + offsetof( POSIX_Spinlock_Control, reserved[ 1 ] ) +#endif + == offsetof( pthread_spinlock_t, _Lock._now_serving ), + POSIX_SPINLOCK_T_LOCK_NOW_SERVING +); + +RTEMS_STATIC_ASSERT( + offsetof( POSIX_Spinlock_Control, interrupt_state ) + == offsetof( pthread_spinlock_t, _interrupt_state ), + POSIX_SPINLOCK_T_INTERRUPT_STATE +); + +RTEMS_STATIC_ASSERT( + sizeof( POSIX_Spinlock_Control ) == sizeof( pthread_spinlock_t ), + POSIX_SPINLOCK_T_SIZE +); +#else +#if defined(RTEMS_SMP) +POSIX_Spinlock_Control _POSIX_Spinlock_Global; + +uint32_t _POSIX_Spinlock_Owner = 0xffffffff; +#endif + +int _POSIX_Spinlock_Nest_level; +#endif int pthread_spin_lock( pthread_spinlock_t *spinlock ) { POSIX_Spinlock_Control *the_spinlock; - ISR_lock_Context lock_context; - Status_Control status; + ISR_Level level; +#if defined(RTEMS_SMP) && defined(RTEMS_PROFILING) + Per_CPU_Control *cpu_self; +#endif - the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context ); - if ( the_spinlock == NULL ) { - return EINVAL; + the_spinlock = _POSIX_Spinlock_Get( spinlock ); + _ISR_Local_disable( level ); +#if defined(POSIX_SPINLOCKS_ARE_SELF_CONTAINED) +#if defined(RTEMS_SMP) +#if defined(RTEMS_PROFILING) + /* The lock statistics are incorrect in case of nested pthread spinlocks */ + cpu_self = _Per_CPU_Get(); +#endif + _SMP_ticket_lock_Acquire( + &the_spinlock->Lock, + &cpu_self->Lock_stats, + &cpu_self->Lock_stats_context + ); +#endif + the_spinlock->interrupt_state = level; +#else +#if defined(RTEMS_SMP) + if ( _POSIX_Spinlock_Owner != _SMP_Get_current_processor() ) { +#if defined(RTEMS_PROFILING) + cpu_self = _Per_CPU_Get(); +#endif + _SMP_ticket_lock_Acquire( + &the_spinlock->Lock, + &cpu_self->Lock_stats, + &cpu_self->Lock_stats_context + ); + _POSIX_Spinlock_Owner = _SMP_Get_current_processor(); +#endif } - status = _CORE_spinlock_Seize( - &the_spinlock->Spinlock, - true, - 0, - &lock_context - ); - return _POSIX_Get_error( status ); + if ( ++_POSIX_Spinlock_Nest_level == 1) { + the_spinlock->interrupt_state = level; + } +#endif + return 0; } + +int pthread_spin_trylock( pthread_spinlock_t *spinlock ) + RTEMS_ALIAS( pthread_spin_lock ); diff --git a/cpukit/posix/src/pspintrylock.c b/cpukit/posix/src/pspintrylock.c deleted file mode 100644 index a8264aba97..0000000000 --- a/cpukit/posix/src/pspintrylock.c +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file - * - * @brief Wait at a Spinlock - * @ingroup POSIXAPI - */ - -/* - * COPYRIGHT (c) 1989-2007. - * 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 - -int pthread_spin_trylock( pthread_spinlock_t *spinlock ) -{ - POSIX_Spinlock_Control *the_spinlock; - ISR_lock_Context lock_context; - Status_Control status; - - the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context ); - if ( the_spinlock == NULL ) { - return EINVAL; - } - - status = _CORE_spinlock_Seize( - &the_spinlock->Spinlock, - false, - 0, - &lock_context - ); - return _POSIX_Get_error( status ); -} diff --git a/cpukit/posix/src/pspinunlock.c b/cpukit/posix/src/pspinunlock.c index b92473d7c1..b508df7384 100644 --- a/cpukit/posix/src/pspinunlock.c +++ b/cpukit/posix/src/pspinunlock.c @@ -11,6 +11,8 @@ * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH + * * 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. @@ -21,19 +23,33 @@ #endif #include -#include -int pthread_spin_unlock( pthread_spinlock_t *spinlock ) +int pthread_spin_unlock( pthread_spinlock_t *lock ) { POSIX_Spinlock_Control *the_spinlock; - ISR_lock_Context lock_context; - Status_Control status; + ISR_Level level; - the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context ); - if ( the_spinlock == NULL ) { - return EINVAL; + the_spinlock = _POSIX_Spinlock_Get( lock ); + level = the_spinlock->interrupt_state; +#if defined(POSIX_SPINLOCKS_ARE_SELF_CONTAINED) +#if defined(RTEMS_SMP) + _SMP_ticket_lock_Release( + &the_spinlock->Lock, + &_Per_CPU_Get()->Lock_stats_context + ); +#endif + _ISR_Local_enable( level ); +#else + if ( --_POSIX_Spinlock_Nest_level == 0 ) { +#if defined(RTEMS_SMP) + _POSIX_Spinlock_Owner = 0xffffffff; + _SMP_ticket_lock_Release( + &the_spinlock->Lock, + &_Per_CPU_Get()->Lock_stats_context + ); +#endif + _ISR_Local_enable( level ); } - - status = _CORE_spinlock_Surrender( &the_spinlock->Spinlock, &lock_context ); - return _POSIX_Get_error( status ); +#endif + return 0; } -- cgit v1.2.3