From 43e1573c1f02194a4fa754dfbff51862130742a5 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sat, 28 Feb 2015 18:06:37 +0100 Subject: score: Add ISR lock to Objects_Control This enables per-object SMP locks on SMP configurations and is the first step to support fine-grained locking. On uni-processor configuration there will be no overhead. The _Objects_Acquire() is intended to replace _Objects_Get_isr_disable(). Update #2273. --- cpukit/score/Makefile.am | 1 + cpukit/score/include/rtems/score/object.h | 3 + cpukit/score/include/rtems/score/objectimpl.h | 80 +++++++++++++++++++++++++++ cpukit/score/src/objectacquire.c | 80 +++++++++++++++++++++++++++ cpukit/score/src/objectclose.c | 2 + 5 files changed, 166 insertions(+) create mode 100644 cpukit/score/src/objectacquire.c diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index a2d440b255..509a243c11 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -202,6 +202,7 @@ libscore_a_SOURCES += src/objectallocate.c src/objectclose.c \ src/objectgetinfo.c src/objectgetinfoid.c src/objectapimaximumclass.c \ src/objectnamespaceremove.c \ src/objectactivecount.c +libscore_a_SOURCES += src/objectacquire.c ## SCHEDULER_C_FILES libscore_a_SOURCES += src/log2table.c diff --git a/cpukit/score/include/rtems/score/object.h b/cpukit/score/include/rtems/score/object.h index 70e5fe630c..36449431d4 100644 --- a/cpukit/score/include/rtems/score/object.h +++ b/cpukit/score/include/rtems/score/object.h @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -236,6 +237,8 @@ typedef struct { Objects_Id id; /** This is the object's name. */ Objects_Name name; + /** This is the object's ISR lock. */ + ISR_LOCK_MEMBER( Lock ) } Objects_Control; #if defined( RTEMS_MULTIPROCESSING ) diff --git a/cpukit/score/include/rtems/score/objectimpl.h b/cpukit/score/include/rtems/score/objectimpl.h index 2928effb57..c681c9a9a5 100644 --- a/cpukit/score/include/rtems/score/objectimpl.h +++ b/cpukit/score/include/rtems/score/objectimpl.h @@ -590,6 +590,83 @@ Objects_Control *_Objects_Get_no_protection( Objects_Locations *location ); +/** + * @brief Acquires an object by its identifier. + * + * This function is similar to _Objects_Get_isr_disable(). It acquires the + * object specific ISR lock for local objects. Thread dispatching is not + * disabled for local objects. For remote objects thread dispatching is + * disabled. + * + * @param[in] information The object information. + * @param[in] id The object identifier. + * @param[in] location The location of the object. + * @param[in] lock_context The lock context for local objects. + * + * @retval object The object corresponding to the identifier. + * @retval NULL No object exists in this domain for this identifer. + * + * @see _Objects_Release(), _Objects_Release_and_ISR_enable(), and + * _Objects_Release_and_thread_dispatch_disable(). + */ +Objects_Control *_Objects_Acquire( + const Objects_Information *information, + Objects_Id id, + Objects_Locations *location, + ISR_lock_Context *lock_context +); + +/** + * @brief Releases a local object. + * + * @param[in] the_object The local object acquired by _Objects_Acquire(). + * @param[in] lock_context The lock context initialized by _Objects_Acquire(). + */ +RTEMS_INLINE_ROUTINE void _Objects_Release( + Objects_Control *the_object, + ISR_lock_Context *lock_context +) +{ + _ISR_lock_Release( &the_object->Lock, lock_context ); +} + +/** + * @brief Releases a local object and restores the interrupt level. + * + * @param[in] the_object The local object acquired by _Objects_Acquire(). + * @param[in] lock_context The lock context initialized by _Objects_Acquire(). + */ +RTEMS_INLINE_ROUTINE void _Objects_Release_and_ISR_enable( + Objects_Control *the_object, + ISR_lock_Context *lock_context +) +{ + _ISR_lock_Release_and_ISR_enable( &the_object->Lock, lock_context ); +} + +/** + * @brief Releases a local object, disables thread dispatching and restores the + * interrupt level. + * + * @param[in] the_object The local object acquired by _Objects_Acquire(). + * @param[in] lock_context The lock context initialized by _Objects_Acquire(). + * + * @return The current processor. + */ +RTEMS_INLINE_ROUTINE Per_CPU_Control * +_Objects_Release_and_thread_dispatch_disable( + Objects_Control *the_object, + ISR_lock_Context *lock_context +) +{ + Per_CPU_Control *cpu_self = _Per_CPU_Get(); + + _Thread_Dispatch_disable_critical( cpu_self ); + _Objects_Release_and_ISR_enable( the_object, lock_context ); + + return cpu_self; +} + /** * Like @ref _Objects_Get, but is used to find "next" open object. * @@ -903,6 +980,7 @@ RTEMS_INLINE_ROUTINE void _Objects_Open( _Assert( the_object != NULL ); the_object->name = name; + _ISR_lock_Initialize( &the_object->Lock, "Object" ); _Objects_Set_local_object( information, @@ -927,6 +1005,7 @@ RTEMS_INLINE_ROUTINE void _Objects_Open_u32( { /* ASSERT: information->is_string == false */ the_object->name.name_u32 = name; + _ISR_lock_Initialize( &the_object->Lock, "Object" ); _Objects_Set_local_object( information, @@ -953,6 +1032,7 @@ RTEMS_INLINE_ROUTINE void _Objects_Open_string( /* ASSERT: information->is_string */ the_object->name.name_p = name; #endif + _ISR_lock_Initialize( &the_object->Lock, "Object" ); _Objects_Set_local_object( information, diff --git a/cpukit/score/src/objectacquire.c b/cpukit/score/src/objectacquire.c new file mode 100644 index 0000000000..57d38f47bd --- /dev/null +++ b/cpukit/score/src/objectacquire.c @@ -0,0 +1,80 @@ +/** + * @file + * + * @brief Object Acquire + * + * @ingroup ScoreObject + */ + +/* + * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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 + +Objects_Control *_Objects_Acquire( + const Objects_Information *information, + Objects_Id id, + Objects_Locations *location, + ISR_lock_Context *lock_context +) +{ + Objects_Control *the_object; + uint32_t index; + + index = id - information->minimum_id + 1; + + if ( information->maximum >= index ) { + /* + * On uni-processor configurations we disable interrupts before we use the + * local table. This prevents use of freed memory in case the object + * information is extended in between. On SMP configurations bad things + * can happen, see https://devel.rtems.org/ticket/2280. + */ +#if !defined(RTEMS_SMP) + ISR_Level level; + + _ISR_Disable( level ); +#endif + if ( ( the_object = information->local_table[ index ] ) != NULL ) { + *location = OBJECTS_LOCAL; +#if defined(RTEMS_SMP) + _ISR_lock_ISR_disable_and_acquire( &the_object->Lock, lock_context ); +#else + lock_context->isr_level = level; +#endif + + return the_object; + } +#if !defined(RTEMS_SMP) + _ISR_Enable( level ); +#endif + *location = OBJECTS_ERROR; + + return NULL; + } + + *location = OBJECTS_ERROR; + +#if defined(RTEMS_MULTIPROCESSING) + _Objects_MP_Is_remote( information, id, location, &the_object ); + + return the_object; +#else + return NULL; +#endif +} diff --git a/cpukit/score/src/objectclose.c b/cpukit/score/src/objectclose.c index 52eb10c60b..25c7aa1a36 100644 --- a/cpukit/score/src/objectclose.c +++ b/cpukit/score/src/objectclose.c @@ -28,4 +28,6 @@ void _Objects_Close( _Objects_Invalidate_Id( information, the_object ); _Objects_Namespace_remove( information, the_object ); + + _ISR_lock_Destroy( &the_object->Lock ); } -- cgit v1.2.3