Update #2556. --- cpukit/libmisc/monitor/mon-sema.c | 2 +- cpukit/sapi/src/interrtext.c | 3 +- cpukit/score/include/rtems/score/interr.h | 3 +- cpukit/score/include/rtems/score/mrsp.h | 80 +----- cpukit/score/include/rtems/score/mrspimpl.h | 284 ++++++--------------- cpukit/score/include/rtems/score/schedulerimpl.h | 56 ++++ cpukit/score/include/rtems/score/status.h | 2 - cpukit/score/include/rtems/score/threadimpl.h | 11 + cpukit/score/include/rtems/score/threadqimpl.h | 62 +++++ cpukit/score/src/threadchangepriority.c | 17 ++ cpukit/score/src/threadqenqueue.c | 151 +++++++++-- testsuites/smptests/Makefile.am | 1 + testsuites/smptests/configure.ac | 1 + testsuites/smptests/smpfatal03/Makefile.am | 19 ++ testsuites/smptests/smpfatal03/init.c | 108 ++++++++ testsuites/smptests/smpfatal03/smpfatal03.doc | 12 + testsuites/smptests/smpfatal03/smpfatal03.scn | 2 + testsuites/smptests/smpmrsp01/init.c | 118 +++++---- testsuites/sptests/spinternalerror02/init.c | 2 +- .../spinternalerror02/spinternalerror02.scn | 1 + 20 files changed, 569 insertions(+), 366 deletions(-) create mode 100644 testsuites/smptests/smpfatal03/Makefile.am create mode 100644 testsuites/smptests/smpfatal03/init.c create mode 100644 testsuites/smptests/smpfatal03/smpfatal03.doc create mode 100644 testsuites/smptests/smpfatal03/smpfatal03.scn
diff --git a/cpukit/libmisc/monitor/mon-sema.c b/cpukit/libmisc/monitor/mon-sema.c index 7334611..3dc7172 100644 --- a/cpukit/libmisc/monitor/mon-sema.c +++ b/cpukit/libmisc/monitor/mon-sema.c @@ -84,7 +84,7 @@ rtems_monitor_sema_canonical( #if defined(RTEMS_SMP) case SEMAPHORE_VARIANT_MRSP: canonical_sema->cur_count = - rtems_sema->Core_control.MRSP.Resource.owner == NULL; + _MRSP_Get_owner( &rtems_sema->Core_control.MRSP ) == NULL; canonical_sema->max_count = 1; break; #endif diff --git a/cpukit/sapi/src/interrtext.c b/cpukit/sapi/src/interrtext.c index 8408061..6653022 100644 --- a/cpukit/sapi/src/interrtext.c +++ b/cpukit/sapi/src/interrtext.c @@ -55,7 +55,8 @@ static const char *const internal_error_text[] = { "INTERNAL_ERROR_RESOURCE_IN_USE", "INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL", "INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL", - "INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK" + "INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK", + "INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE" }; const char *rtems_internal_error_text( rtems_fatal_code error ) diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h index 845dc6f..dff6101 100644 --- a/cpukit/score/include/rtems/score/interr.h +++ b/cpukit/score/include/rtems/score/interr.h @@ -164,7 +164,8 @@ typedef enum { INTERNAL_ERROR_RESOURCE_IN_USE, INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL, INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL, - INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK + INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK, + INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE } Internal_errors_Core_list; typedef CPU_Uint32ptr Internal_errors_t; diff --git a/cpukit/score/include/rtems/score/mrsp.h b/cpukit/score/include/rtems/score/mrsp.h index 5af3a06..85cbff7 100644 --- a/cpukit/score/include/rtems/score/mrsp.h +++ b/cpukit/score/include/rtems/score/mrsp.h @@ -19,9 +19,6 @@ #if defined(RTEMS_SMP) -#include <rtems/score/chain.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/thread.h> #include <rtems/score/threadq.h> #ifdef __cplusplus @@ -51,87 +48,16 @@ extern "C" { * @{ */ -typedef struct MRSP_Control MRSP_Control; - -/** - * @brief MrsP rival. - * - * The rivals are used by threads waiting for resource ownership. They are - * registered in the MrsP control block. - */ -typedef struct { - /** - * @brief The node for registration in the MrsP rival chain. - * - * The chain operations are protected by the MrsP control lock. - * - * @see MRSP_Control::Rivals. - */ - Chain_Node Node; - - /** - * @brief The corresponding MrsP control block. - */ - MRSP_Control *resource; - - /** - * @brief Identification of the rival thread. - */ - Thread_Control *thread; - - /** - * @brief The ceiling priority used by the rival thread. - */ - Priority_Node Ceiling_priority; - - /** - * @brief The initial help state of the thread at the begin of the resource - * obtain sequence. - * - * Used to restore this state after a timeout. - */ - Scheduler_Help_state initial_help_state; - - /** - * @brief The rival status. - * - * Initially the status is set to MRSP_WAIT_FOR_OWNERSHIP. The rival will - * busy wait until a status change happens. This can be STATUS_SUCCESSFUL or - * STATUS_TIMEOUT. State changes are protected by the MrsP control lock. - */ - volatile int status; - - /** - * @brief Watchdog for timeouts. - */ - Watchdog_Control Watchdog; -} MRSP_Rival; - /** * @brief MrsP control block. */ -struct MRSP_Control { +typedef struct { /** - * @brief Lock to protect the resource dependency tree. - * - * This is a thread queue since this simplifies the Classic semaphore - * implementation. Only the lock part of the thread queue is used. + * @brief The thread queue to manage ownership and waiting threads. */ Thread_queue_Control Wait_queue; /** - * @brief Basic resource control. - */ - Resource_Control Resource; - - /** - * @brief A chain of MrsP rivals waiting for resource ownership. - * - * @see MRSP_Rival::Node. - */ - Chain_Control Rivals; - - /** * @brief The ceiling priority used by the owner thread. */ Priority_Node Ceiling_priority; @@ -140,7 +66,7 @@ struct MRSP_Control { * @brief One ceiling priority per scheduler instance. */ Priority_Control *ceiling_priorities; -}; +} MRSP_Control; /** @} */ diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h index 92cc566..4b4e8c3 100644 --- a/cpukit/score/include/rtems/score/mrspimpl.h +++ b/cpukit/score/include/rtems/score/mrspimpl.h @@ -20,9 +20,6 @@ #if defined(RTEMS_SMP) #include <rtems/score/assert.h> -#include <rtems/score/chainimpl.h> -#include <rtems/score/resourceimpl.h> -#include <rtems/score/schedulerimpl.h> #include <rtems/score/status.h> #include <rtems/score/threadqimpl.h> #include <rtems/score/watchdogimpl.h> @@ -38,28 +35,7 @@ extern "C" { * @{ */ -/** - * @brief Internal state used for MRSP_Rival::status to indicate that this - * rival waits for resource ownership. - */ -#define MRSP_WAIT_FOR_OWNERSHIP STATUS_MINUS_ONE - -/* - * FIXME: Operations with the resource dependency tree are protected by the - * global scheduler lock. Since the scheduler lock should be scheduler - * instance specific in the future this will only work temporarily. A more - * sophisticated locking strategy is necessary. - */ - -RTEMS_INLINE_ROUTINE void _MRSP_Giant_acquire( ISR_lock_Context *lock_context ) -{ - /* FIXME: MrsP protocol implementation will be reworked soon */ -} - -RTEMS_INLINE_ROUTINE void _MRSP_Giant_release( ISR_lock_Context *lock_context ) -{ - /* FIXME: MrsP protocol implementation will be reworked soon */ -} +#define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit RTEMS_INLINE_ROUTINE void _MRSP_Acquire_critical( MRSP_Control *mrsp, @@ -77,6 +53,19 @@ RTEMS_INLINE_ROUTINE void _MRSP_Release( _Thread_queue_Release( &mrsp->Wait_queue, queue_context ); } +RTEMS_INLINE_ROUTINE Thread_Control *_MRSP_Get_owner( MRSP_Control *mrsp ) +{ + return mrsp->Wait_queue.Queue.owner; +} + +RTEMS_INLINE_ROUTINE void _MRSP_Set_owner( + MRSP_Control *mrsp, + Thread_Control *owner +) +{ + mrsp->Wait_queue.Queue.owner = owner; +} + RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority( const MRSP_Control *mrsp, const Scheduler_Control *scheduler @@ -149,23 +138,23 @@ RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority( RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority( MRSP_Control *mrsp, Thread_Control *thread, - MRSP_Rival *rival + Priority_Node *ceiling_priority ) { ISR_lock_Context lock_context; - _Thread_Wait_acquire_default_critical( thread, &lock_context ); + _Thread_Wait_acquire_default( thread, &lock_context ); _Thread_Priority_replace( thread, - &rival->Ceiling_priority, + ceiling_priority, &mrsp->Ceiling_priority ); - _Thread_Wait_release_default_critical( thread, &lock_context ); + _Thread_Wait_release_default( thread, &lock_context ); } RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership( MRSP_Control *mrsp, - Thread_Control *new_owner, + Thread_Control *executing, Thread_queue_Context *queue_context ) { @@ -174,7 +163,7 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership( status = _MRSP_Raise_priority( mrsp, - new_owner, + executing, &mrsp->Ceiling_priority, queue_context ); @@ -184,17 +173,12 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership( return status; } - _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource ); - _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node ); - _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER ); - + _MRSP_Set_owner( mrsp, executing ); cpu_self = _Thread_Dispatch_disable_critical( &queue_context->Lock_context.Lock_context ); _MRSP_Release( mrsp, queue_context ); - - _Thread_Priority_update( queue_context ); - + _Thread_Priority_and_sticky_update( executing, 1 ); _Thread_Dispatch_enable( cpu_self ); return STATUS_SUCCESSFUL; } @@ -234,74 +218,23 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize( } } - _Resource_Initialize( &mrsp->Resource ); - _Chain_Initialize_empty( &mrsp->Rivals ); _Thread_queue_Initialize( &mrsp->Wait_queue ); - return STATUS_SUCCESSFUL; } -RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog ) -{ - MRSP_Rival *rival; - MRSP_Control *mrsp; - Thread_Control *thread; - Thread_queue_Context queue_context; - - rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog ); - mrsp = rival->resource; - thread = rival->thread; - - _Thread_queue_Context_initialize( &queue_context ); - _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context ); - _MRSP_Acquire_critical( mrsp, &queue_context ); - - if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) { - ISR_lock_Context giant_lock_context; - - _MRSP_Remove_priority( thread, &rival->Ceiling_priority, &queue_context ); - - _MRSP_Giant_acquire( &giant_lock_context ); - - _Chain_Extract_unprotected( &rival->Node ); - _Resource_Node_extract( &thread->Resource_node ); - _Resource_Node_set_dependency( &thread->Resource_node, NULL ); - _Scheduler_Thread_change_help_state( thread, rival->initial_help_state ); - _Scheduler_Thread_change_resource_root( thread, thread ); - - _MRSP_Giant_release( &giant_lock_context ); - - rival->status = STATUS_TIMEOUT; - - _MRSP_Release( mrsp, &queue_context ); - - _Thread_Priority_update( &queue_context ); - } else { - _MRSP_Release( mrsp, &queue_context ); - } -} - RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership( MRSP_Control *mrsp, - Resource_Node *owner, Thread_Control *executing, Thread_queue_Context *queue_context ) { - Status_Control status; - MRSP_Rival rival; - Thread_Life_state life_state; - Per_CPU_Control *cpu_self; - ISR_lock_Context giant_lock_context; - ISR_Level level; - Watchdog_Interval timeout; - - _Assert( queue_context->timeout_discipline == WATCHDOG_RELATIVE ); + Status_Control status; + Priority_Node ceiling_priority; status = _MRSP_Raise_priority( mrsp, executing, - &rival.Ceiling_priority, + &ceiling_priority, queue_context ); @@ -310,64 +243,38 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership( return status; } - rival.thread = executing; - rival.resource = mrsp; - _Chain_Initialize_node( &rival.Node ); - - _MRSP_Giant_acquire( &giant_lock_context ); - - rival.initial_help_state = - _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_ACTIVE_RIVAL ); - rival.status = MRSP_WAIT_FOR_OWNERSHIP; - - _Chain_Initialize_node( &rival.Node ); - _Chain_Append_unprotected( &mrsp->Rivals, &rival.Node ); - _Resource_Add_rival( &mrsp->Resource, &executing->Resource_node ); - _Resource_Node_set_dependency( &executing->Resource_node, &mrsp->Resource ); - _Scheduler_Thread_change_resource_root( - executing, - THREAD_RESOURCE_NODE_TO_THREAD( _Resource_Node_get_root( owner ) ) + _Thread_queue_Context_set_deadlock_callout( + queue_context, + _Thread_queue_Deadlock_status ); - - _MRSP_Giant_release( &giant_lock_context ); - - cpu_self = _Thread_Dispatch_disable_critical( - &queue_context->Lock_context.Lock_context + status = _Thread_queue_Enqueue_sticky( + &mrsp->Wait_queue.Queue, + MRSP_TQ_OPERATIONS, + executing, + queue_context ); - _MRSP_Release( mrsp, queue_context ); - - _Thread_Priority_update( queue_context ); - timeout = (Watchdog_Interval) queue_context->timeout; - - if ( timeout > 0 ) { - _Watchdog_Preinitialize( &rival.Watchdog, cpu_self ); - _Watchdog_Initialize( &rival.Watchdog, _MRSP_Timeout ); - _ISR_Local_disable( level ); - _Watchdog_Per_CPU_insert_relative( &rival.Watchdog, cpu_self, timeout ); - _ISR_Local_enable( level ); - } - - life_state = _Thread_Set_life_protection( THREAD_LIFE_PROTECTED ); - _Thread_Dispatch_enable( cpu_self ); - - _Assert( _Debug_Is_thread_dispatching_allowed() ); - - /* Wait for state change */ - do { - status = rival.status; - } while ( status == MRSP_WAIT_FOR_OWNERSHIP ); + if ( status == STATUS_SUCCESSFUL ) { + _MRSP_Replace_priority( mrsp, executing, &ceiling_priority ); + } else { + Thread_queue_Context queue_context; + Per_CPU_Control *cpu_self; + int sticky_level_change; - _Thread_Set_life_protection( life_state ); + if ( status != STATUS_DEADLOCK ) { + sticky_level_change = -1; + } else { + sticky_level_change = 0; + } - if ( timeout > 0 ) { - _ISR_Local_disable( level ); - _Watchdog_Per_CPU_remove( - &rival.Watchdog, - cpu_self, - &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ] + _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context ); + _MRSP_Remove_priority( executing, &ceiling_priority, &queue_context ); + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context.Lock_context.Lock_context ); - _ISR_Local_enable( level ); + _ISR_lock_ISR_enable( &queue_context.Lock_context.Lock_context ); + _Thread_Priority_and_sticky_update( executing, sticky_level_change ); + _Thread_Dispatch_enable( cpu_self ); } return status; @@ -381,22 +288,21 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize( ) { Status_Control status; - Resource_Node *owner; + Thread_Control *owner; _MRSP_Acquire_critical( mrsp, queue_context ); - owner = _Resource_Get_owner( &mrsp->Resource ); + owner = _MRSP_Get_owner( mrsp ); if ( owner == NULL ) { status = _MRSP_Claim_ownership( mrsp, executing, queue_context ); - } else if ( - wait - && _Resource_Node_get_root( owner ) != &executing->Resource_node - ) { - status = _MRSP_Wait_for_ownership( mrsp, owner, executing, queue_context ); + } else if ( owner == executing ) { + _MRSP_Release( mrsp, queue_context ); + status = STATUS_UNAVAILABLE; + } else if ( wait ) { + status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context ); } else { _MRSP_Release( mrsp, queue_context ); - /* Not available, nested access or deadlock */ status = STATUS_UNAVAILABLE; } @@ -409,77 +315,45 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender( Thread_queue_Context *queue_context ) { - ISR_lock_Context giant_lock_context; - Per_CPU_Control *cpu_self; + Thread_queue_Heads *heads; - if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) { + if ( _MRSP_Get_owner( mrsp ) != executing ) { _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context ); return STATUS_NOT_OWNER; } - if ( - !_Resource_Is_most_recently_obtained( - &mrsp->Resource, - &executing->Resource_node - ) - ) { - _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context ); - return STATUS_RELEASE_ORDER_VIOLATION; - } - _MRSP_Acquire_critical( mrsp, queue_context ); - _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context ); - _MRSP_Giant_acquire( &giant_lock_context ); - - _Resource_Extract( &mrsp->Resource ); - if ( _Chain_Is_empty( &mrsp->Rivals ) ) { - _Resource_Set_owner( &mrsp->Resource, NULL ); - } else { - MRSP_Rival *rival; - Thread_Control *new_owner; - - rival = (MRSP_Rival *) _Chain_Get_first_unprotected( &mrsp->Rivals ); - - /* - * This must be inside the critical section since the status prevents a - * potential double extraction in _MRSP_Timeout(). - */ - rival->status = STATUS_SUCCESSFUL; - - new_owner = rival->thread; + _MRSP_Set_owner( mrsp, NULL ); + _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context ); - _MRSP_Replace_priority( mrsp, new_owner, rival ); + heads = mrsp->Wait_queue.Queue.heads; - _Resource_Node_extract( &new_owner->Resource_node ); - _Resource_Node_set_dependency( &new_owner->Resource_node, NULL ); - _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource ); - _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node ); - _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER ); - _Scheduler_Thread_change_resource_root( new_owner, new_owner ); - } + if ( heads == NULL ) { + Per_CPU_Control *cpu_self; - if ( !_Resource_Node_owns_resources( &executing->Resource_node ) ) { - _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_YOURSELF ); + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context->Lock_context.Lock_context + ); + _MRSP_Release( mrsp, queue_context ); + _Thread_Priority_and_sticky_update( executing, -1 ); + _Thread_Dispatch_enable( cpu_self ); + return STATUS_SUCCESSFUL; } - _MRSP_Giant_release( &giant_lock_context ); - - cpu_self = _Thread_Dispatch_disable_critical( - &queue_context->Lock_context.Lock_context + _Thread_queue_Surrender_sticky( + &mrsp->Wait_queue.Queue, + heads, + executing, + queue_context, + MRSP_TQ_OPERATIONS ); - _MRSP_Release( mrsp, queue_context ); - - _Thread_Priority_update( queue_context ); - - _Thread_Dispatch_enable( cpu_self ); - return STATUS_SUCCESSFUL; } RTEMS_INLINE_ROUTINE Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp ) { - if ( _Resource_Get_owner( &mrsp->Resource ) != NULL ) { + if ( _MRSP_Get_owner( mrsp ) != NULL ) { return STATUS_RESOURCE_IN_USE; } diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 25b961f..92b08e5 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -553,6 +553,62 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Update_priority( Thread_Control *the_thread #endif } +#if defined(RTEMS_SMP) +/** + * @brief Changes the sticky level of the home scheduler node and propagates a + * priority change of a thread to the scheduler. + * + * @param[in] the_thread The thread changing its priority or sticky level. + * + * @see _Scheduler_Update_priority(). + */ +RTEMS_INLINE_ROUTINE void _Scheduler_Priority_and_sticky_update( + Thread_Control *the_thread, + int sticky_level_change +) +{ + Chain_Node *node; + const Chain_Node *tail; + Scheduler_Node *scheduler_node; + const Scheduler_Control *scheduler; + ISR_lock_Context lock_context; + + _Thread_Scheduler_process_requests( the_thread ); + + node = _Chain_First( &the_thread->Scheduler.Scheduler_nodes ); + scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node ); + scheduler = _Scheduler_Node_get_scheduler( scheduler_node ); + + _Scheduler_Acquire_critical( scheduler, &lock_context ); + + ( *scheduler->Operations.update_priority )( + scheduler, + the_thread, + scheduler_node + ); + + _Scheduler_Release_critical( scheduler, &lock_context ); + + tail = _Chain_Immutable_tail( &the_thread->Scheduler.Scheduler_nodes ); + node = _Chain_Next( node ); + + while ( node != tail ) { + scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node ); + scheduler = _Scheduler_Node_get_scheduler( scheduler_node ); + + _Scheduler_Acquire_critical( scheduler, &lock_context ); + ( *scheduler->Operations.update_priority )( + scheduler, + the_thread, + scheduler_node + ); + _Scheduler_Release_critical( scheduler, &lock_context ); + + node = _Chain_Next( node ); + } +} +#endif + /** * @brief Maps a thread priority from the user domain to the scheduler domain. * diff --git a/cpukit/score/include/rtems/score/status.h b/cpukit/score/include/rtems/score/status.h index 453bf11..6b6f3c5 100644 --- a/cpukit/score/include/rtems/score/status.h +++ b/cpukit/score/include/rtems/score/status.h @@ -113,8 +113,6 @@ typedef enum { STATUS_BUILD( STATUS_CLASSIC_NOT_OWNER_OF_RESOURCE, EPERM ), STATUS_OBJECT_WAS_DELETED = STATUS_BUILD( STATUS_CLASSIC_OBJECT_WAS_DELETED, EINVAL ), - STATUS_RELEASE_ORDER_VIOLATION = - STATUS_BUILD( STATUS_CLASSIC_INCORRECT_STATE, EPERM ), STATUS_RESOURCE_IN_USE = STATUS_BUILD( STATUS_CLASSIC_RESOURCE_IN_USE, EBUSY ), STATUS_SUCCESSFUL = diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 0d8074e..79239db 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -1705,6 +1705,17 @@ RTEMS_INLINE_ROUTINE Thread_Wait_flags _Thread_Wait_flags_get( #endif } +RTEMS_INLINE_ROUTINE Thread_Wait_flags _Thread_Wait_flags_get_acquire( + const Thread_Control *the_thread +) +{ +#if defined(RTEMS_SMP) + return _Atomic_Load_uint( &the_thread->Wait.flags, ATOMIC_ORDER_ACQUIRE ); +#else + return the_thread->Wait.flags; +#endif +} + /** * @brief Tries to change the thread wait flags with release semantics in case * of success. diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h index e24beec..f74436d 100644 --- a/cpukit/score/include/rtems/score/threadqimpl.h +++ b/cpukit/score/include/rtems/score/threadqimpl.h @@ -24,6 +24,7 @@ #include <rtems/score/priorityimpl.h> #include <rtems/score/scheduler.h> #include <rtems/score/smp.h> +#include <rtems/score/status.h> #include <rtems/score/thread.h> #if defined(RTEMS_DEBUG) @@ -553,6 +554,37 @@ void _Thread_queue_Enqueue_critical( Thread_queue_Context *queue_context ); +#if defined(RTEMS_SMP) +/** + * @brief Enqueues the thread on the thread queue and busy waits for dequeue. + * + * Optionally starts the thread timer in case the timeout discipline is not + * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context. + * + * The caller must be the owner of the thread queue lock. This function will + * release the thread queue lock and register it as the new thread lock. + * + * The thread priorities of the owner and the are updated with respect to the + * scheduler. The sticky level of the thread is incremented. A thread + * dispatch is performed if necessary. + * + * Afterwards, the thread busy waits on the thread wait flags until a timeout + * occurs or the thread queue is surrendered to this thread. So, it sticks to + * the processor instead of blocking with respect to the scheduler. + * + * @param[in] queue The actual thread queue. + * @param[in] operations The thread queue operations. + * @param[in] the_thread The thread to enqueue. + * @param[in] queue_context The thread queue context of the lock acquire. + */ +Status_Control _Thread_queue_Enqueue_sticky( + Thread_queue_Queue *queue, + const Thread_queue_Operations *operations, + Thread_Control *the_thread, + Thread_queue_Context *queue_context +); +#endif + /** * @brief Acquires the thread queue lock and calls * _Thread_queue_Enqueue_critical(). @@ -733,6 +765,36 @@ void _Thread_queue_Surrender( const Thread_queue_Operations *operations ); +#if defined(RTEMS_SMP) +/** + * @brief Surrenders the thread queue previously owned by the thread to the + * first enqueued thread. + * + * The owner of the thread queue must be set to NULL by the caller. + * + * The caller must be the owner of the thread queue lock. This function will + * release the thread queue. + * + * The thread priorities of the previous owner and the new owner are updated. The + * sticky level of the previous owner is decremented. A thread dispatch is + * performed if necessary. + * + * @param[in] queue The actual thread queue. + * @param[in] heads The thread queue heads. It must not be NULL. + * @param[in] previous_owner The previous owner thread surrendering the thread + * queue. + * @param[in] queue_context The thread queue context of the lock acquire. + * @param[in] operations The thread queue operations. + */ +void _Thread_queue_Surrender_sticky( + Thread_queue_Queue *queue, + Thread_queue_Heads *heads, + Thread_Control *previous_owner, + Thread_queue_Context *queue_context, + const Thread_queue_Operations *operations +); +#endif + RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_empty( const Thread_queue_Queue *queue ) diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c index e107bcc..4fd4c02 100644 --- a/cpukit/score/src/threadchangepriority.c +++ b/cpukit/score/src/threadchangepriority.c @@ -353,3 +353,20 @@ void _Thread_Priority_update( Thread_queue_Context *queue_context ) _Thread_State_release( the_thread, &lock_context ); } } + +#if defined(RTEMS_SMP) +void _Thread_Priority_and_sticky_update( + Thread_Control *the_thread, + int sticky_level_change +) +{ + ISR_lock_Context lock_context; + + _Thread_State_acquire( the_thread, &lock_context ); + _Scheduler_Priority_and_sticky_update( + the_thread, + sticky_level_change + ); + _Thread_State_release( the_thread, &lock_context ); +} +#endif diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c index 362ce8f..335ee0f 100644 --- a/cpukit/score/src/threadqenqueue.c +++ b/cpukit/score/src/threadqenqueue.c @@ -370,6 +370,37 @@ void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread ) ); } +static void _Thread_queue_Timeout( + Thread_Control *the_thread, + Per_CPU_Control *cpu_self, + Thread_queue_Context *queue_context +) +{ + switch ( queue_context->timeout_discipline ) { + case WATCHDOG_RELATIVE: + /* A relative timeout of 0 is a special case indefinite (no) timeout */ + if ( queue_context->timeout != 0 ) { + _Thread_Timer_insert_relative( + the_thread, + cpu_self, + _Thread_Timeout, + (Watchdog_Interval) queue_context->timeout + ); + } + break; + case WATCHDOG_ABSOLUTE: + _Thread_Timer_insert_absolute( + the_thread, + cpu_self, + _Thread_Timeout, + queue_context->timeout + ); + break; + default: + break; + } +} + void _Thread_queue_Enqueue_critical( Thread_queue_Queue *queue, const Thread_queue_Operations *operations, @@ -430,29 +461,7 @@ void _Thread_queue_Enqueue_critical( /* * If the thread wants to timeout, then schedule its timer. */ - switch ( queue_context->timeout_discipline ) { - case WATCHDOG_RELATIVE: - /* A relative timeout of 0 is a special case indefinite (no) timeout */ - if ( queue_context->timeout != 0 ) { - _Thread_Timer_insert_relative( - the_thread, - cpu_self, - _Thread_Timeout, - (Watchdog_Interval) queue_context->timeout - ); - } - break; - case WATCHDOG_ABSOLUTE: - _Thread_Timer_insert_absolute( - the_thread, - cpu_self, - _Thread_Timeout, - queue_context->timeout - ); - break; - default: - break; - } + _Thread_queue_Timeout( the_thread, cpu_self, queue_context ); /* * At this point thread dispatching is disabled, however, we already released @@ -476,6 +485,65 @@ void _Thread_queue_Enqueue_critical( _Thread_Dispatch_enable( cpu_self ); } +#if defined(RTEMS_SMP) +Status_Control _Thread_queue_Enqueue_sticky( + Thread_queue_Queue *queue, + const Thread_queue_Operations *operations, + Thread_Control *the_thread, + Thread_queue_Context *queue_context +) +{ + Per_CPU_Control *cpu_self; + + _Thread_Wait_claim( the_thread, queue ); + + if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) { + _Thread_queue_Path_release_critical( queue_context ); + _Thread_Wait_restore_default( the_thread ); + _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context ); + _Thread_Wait_tranquilize( the_thread ); + ( *queue_context->deadlock_callout )( the_thread ); + return _Thread_Wait_get_status( the_thread ); + } + + _Thread_queue_Context_clear_priority_updates( queue_context ); + _Thread_Wait_claim_finalize( the_thread, operations ); + ( *operations->enqueue )( queue, the_thread, queue_context ); + + _Thread_queue_Path_release_critical( queue_context ); + + the_thread->Wait.return_code = STATUS_SUCCESSFUL; + _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK ); + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context->Lock_context.Lock_context + ); + _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context ); + + if ( cpu_self->thread_dispatch_disable_level != 1 ) { + _Terminate( + INTERNAL_ERROR_CORE, + false, + INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE + ); + } + + _Thread_queue_Timeout( the_thread, cpu_self, queue_context ); + _Thread_Priority_update( queue_context ); + _Thread_Priority_and_sticky_update( the_thread, 1 ); + _Thread_Dispatch_enable( cpu_self ); + + while ( + _Thread_Wait_flags_get_acquire( the_thread ) == THREAD_QUEUE_INTEND_TO_BLOCK + ) { + /* Wait */ + } + + _Thread_Wait_tranquilize( the_thread ); + _Thread_Timer_remove( the_thread ); + return _Thread_Wait_get_status( the_thread ); +} +#endif + #if defined(RTEMS_MULTIPROCESSING) static bool _Thread_queue_MP_set_callout( Thread_Control *the_thread, @@ -666,6 +734,43 @@ void _Thread_queue_Surrender( _Thread_Dispatch_enable( cpu_self ); } +#if defined(RTEMS_SMP) +void _Thread_queue_Surrender_sticky( + Thread_queue_Queue *queue, + Thread_queue_Heads *heads, + Thread_Control *previous_owner, + Thread_queue_Context *queue_context, + const Thread_queue_Operations *operations +) +{ + Thread_Control *new_owner; + Per_CPU_Control *cpu_self; + + _Assert( heads != NULL ); + + _Thread_queue_Context_clear_priority_updates( queue_context ); + new_owner = ( *operations->surrender )( + queue, + heads, + previous_owner, + queue_context + ); + queue->owner = new_owner; + _Thread_queue_Make_ready_again( new_owner ); + + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context->Lock_context.Lock_context + ); + _Thread_queue_Queue_release( + queue, + &queue_context->Lock_context.Lock_context + ); + _Thread_Priority_and_sticky_update( previous_owner, -1 ); + _Thread_Priority_and_sticky_update( new_owner, 0 ); + _Thread_Dispatch_enable( cpu_self ); +} +#endif + Thread_Control *_Thread_queue_Do_dequeue( Thread_queue_Control *the_thread_queue, const Thread_queue_Operations *operations diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am index 02d1dfc..63398e3 100644 --- a/testsuites/smptests/Makefile.am +++ b/testsuites/smptests/Makefile.am @@ -17,6 +17,7 @@ SUBDIRS += smpcapture02 SUBDIRS += smpclock01 SUBDIRS += smpfatal01 SUBDIRS += smpfatal02 +SUBDIRS += smpfatal03 SUBDIRS += smpfatal04 SUBDIRS += smpfatal05 SUBDIRS += smpfatal08 diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac index 8c8476f..6c632ce 100644 --- a/testsuites/smptests/configure.ac +++ b/testsuites/smptests/configure.ac @@ -75,6 +75,7 @@ smpcapture02/Makefile smpclock01/Makefile smpfatal01/Makefile smpfatal02/Makefile +smpfatal03/Makefile smpfatal04/Makefile smpfatal05/Makefile smpfatal08/Makefile diff --git a/testsuites/smptests/smpfatal03/Makefile.am b/testsuites/smptests/smpfatal03/Makefile.am new file mode 100644 index 0000000..4ec2862 --- /dev/null +++ b/testsuites/smptests/smpfatal03/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = smpfatal03 +smpfatal03_SOURCES = init.c + +dist_rtems_tests_DATA = smpfatal03.scn smpfatal03.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(smpfatal03_OBJECTS) +LINK_LIBS = $(smpfatal03_LDLIBS) + +smpfatal03$(EXEEXT): $(smpfatal03_OBJECTS) $(smpfatal03_DEPENDENCIES) + @rm -f smpfatal03$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/smptests/smpfatal03/init.c b/testsuites/smptests/smpfatal03/init.c new file mode 100644 index 0000000..0eb15aa --- /dev/null +++ b/testsuites/smptests/smpfatal03/init.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define TESTS_USE_PRINTK +#include "tmacros.h" + +const char rtems_test_name[] = "SMPFATAL 3"; + +static void task(rtems_task_argument arg) +{ + rtems_status_code sc; + rtems_id *sem_id; + + sem_id = (rtems_id *) arg; + + sc = rtems_semaphore_obtain(*sem_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(0); +} + +static void Init(rtems_task_argument arg) +{ + rtems_status_code sc; + rtems_id task_id; + rtems_id sem_id; + + TEST_BEGIN(); + + sc = rtems_semaphore_create( + rtems_build_name('M', 'R', 'S', 'P'), + 1, + RTEMS_MULTIPROCESSOR_RESOURCE_SHARING + | RTEMS_BINARY_SEMAPHORE, + 1, + &sem_id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('T', 'A', 'S', 'K'), + 1, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &task_id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(task_id, task, (rtems_task_argument) &sem_id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + _Thread_Dispatch_disable(); + rtems_semaphore_obtain(sem_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(0); +} + +static void fatal_extension( + rtems_fatal_source source, + bool is_internal, + rtems_fatal_code code +) +{ + if ( + source == INTERNAL_ERROR_CORE + && !is_internal + && code == INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE + ) { + TEST_END(); + } +} + +#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_INITIAL_EXTENSIONS \ + { .fatal = fatal_extension }, \ + RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_MAXIMUM_TASKS 2 +#define CONFIGURE_MAXIMUM_MRSP_SEMAPHORES 1 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> diff --git a/testsuites/smptests/smpfatal03/smpfatal03.doc b/testsuites/smptests/smpfatal03/smpfatal03.doc new file mode 100644 index 0000000..6d7e829 --- /dev/null +++ b/testsuites/smptests/smpfatal03/smpfatal03.doc @@ -0,0 +1,12 @@ +This file describes the directives and concepts tested by this test set. + +test set name: smpfatal03 + +directives: + + - _Thread_queue_Enqueue_sticky() + +concepts: + + - Trigger the INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE fatal + error. diff --git a/testsuites/smptests/smpfatal03/smpfatal03.scn b/testsuites/smptests/smpfatal03/smpfatal03.scn new file mode 100644 index 0000000..5ec996f --- /dev/null +++ b/testsuites/smptests/smpfatal03/smpfatal03.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST SMPFATAL 3 *** +*** END OF TEST SMPFATAL 3 *** diff --git a/testsuites/smptests/smpmrsp01/init.c b/testsuites/smptests/smpmrsp01/init.c index efc997a..de5f31c 100644 --- a/testsuites/smptests/smpmrsp01/init.c +++ b/testsuites/smptests/smpmrsp01/init.c @@ -214,6 +214,37 @@ static void print_switch_events(test_context *ctx) } } +static void create_timer(test_context *ctx) +{ + rtems_status_code sc; + + sc = rtems_timer_create( + rtems_build_name('T', 'I', 'M', 'R'), + &ctx->timer_id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void delete_timer(test_context *ctx) +{ + rtems_status_code sc; + + sc = rtems_timer_delete(ctx->timer_id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void fire_timer( + test_context *ctx, + rtems_interval interval, + rtems_timer_service_routine_entry routine +) +{ + rtems_status_code sc; + + sc = rtems_timer_fire_after(ctx->timer_id, interval, routine, ctx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + static void create_mrsp_sema( test_context *ctx, rtems_id *id, @@ -744,37 +775,11 @@ static void test_mrsp_nested_obtain_error(test_context *ctx) rtems_test_assert(sc == RTEMS_SUCCESSFUL); } -static void test_mrsp_unlock_order_error(test_context *ctx) +static void deadlock_timer(rtems_id timer_id, void *arg) { - rtems_status_code sc; - rtems_id id_a; - rtems_id id_b; - - puts("test MrsP unlock order error"); - - create_mrsp_sema(ctx, &id_a, 1); - create_mrsp_sema(ctx, &id_b, 1); - - sc = rtems_semaphore_obtain(id_a, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - - sc = rtems_semaphore_obtain(id_b, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - - sc = rtems_semaphore_release(id_a); - rtems_test_assert(sc == RTEMS_INCORRECT_STATE); - - sc = rtems_semaphore_release(id_b); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - - sc = rtems_semaphore_release(id_a); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - - sc = rtems_semaphore_delete(id_a); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + test_context *ctx = arg; - sc = rtems_semaphore_delete(id_b); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + change_prio(ctx->main_task_id, 1); } static void deadlock_worker(rtems_task_argument arg) @@ -785,6 +790,8 @@ static void deadlock_worker(rtems_task_argument arg) sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); + fire_timer(ctx, 2, deadlock_timer); + sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -810,6 +817,7 @@ static void test_mrsp_deadlock_error(test_context *ctx) change_prio(RTEMS_SELF, prio); + create_timer(ctx); create_mrsp_sema(ctx, &ctx->mrsp_ids[0], prio); create_mrsp_sema(ctx, &ctx->mrsp_ids[1], prio); @@ -832,8 +840,26 @@ static void test_mrsp_deadlock_error(test_context *ctx) sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); rtems_test_assert(sc == RTEMS_SUCCESSFUL); + prio = 1; + sc = rtems_semaphore_set_priority( + ctx->mrsp_ids[1], + ctx->scheduler_ids[0], + prio, + &prio + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(prio == 2); + sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT); - rtems_test_assert(sc == RTEMS_UNSATISFIED); + rtems_test_assert(sc == RTEMS_INCORRECT_STATE); + + sc = rtems_semaphore_set_priority( + ctx->mrsp_ids[1], + ctx->scheduler_ids[0], + prio, + &prio + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_semaphore_release(ctx->mrsp_ids[0]); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -849,6 +875,8 @@ static void test_mrsp_deadlock_error(test_context *ctx) sc = rtems_semaphore_delete(ctx->mrsp_ids[1]); rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + delete_timer(ctx); } static void test_mrsp_multiple_obtain(test_context *ctx) @@ -1006,8 +1034,7 @@ static void unblock_ready_owner(test_context *ctx) assert_prio(RTEMS_SELF, 3); - sc = rtems_timer_fire_after(ctx->timer_id, 2, unblock_ready_timer, ctx); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + fire_timer(ctx, 2, unblock_ready_timer); sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -1103,13 +1130,7 @@ static void various_block_unblock(test_context *ctx) * user. */ - sc = rtems_timer_fire_after( - ctx->timer_id, - 2, - unblock_owner_before_rival_timer, - ctx - ); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + fire_timer(ctx, 2, unblock_owner_before_rival_timer); /* This will take the processor away from us, the timer will help later */ sc = rtems_task_resume(ctx->high_task_id[1]); @@ -1123,13 +1144,7 @@ static void various_block_unblock(test_context *ctx) sc = rtems_task_resume(ctx->high_task_id[0]); rtems_test_assert(sc == RTEMS_SUCCESSFUL); - sc = rtems_timer_fire_after( - ctx->timer_id, - 2, - unblock_owner_after_rival_timer, - ctx - ); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + fire_timer(ctx, 2, unblock_owner_after_rival_timer); /* This will take the processor away from us, the timer will help later */ sc = rtems_task_resume(ctx->high_task_id[1]); @@ -1229,11 +1244,7 @@ static void test_mrsp_various_block_and_unblock(test_context *ctx) sc = rtems_task_start(ctx->worker_ids[0], ready_unlock_worker, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); - sc = rtems_timer_create( - rtems_build_name('T', 'I', 'M', 'R'), - &ctx->timer_id - ); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + create_timer(ctx); /* In case these tasks run, then we have a MrsP protocol violation */ start_low_task(ctx, 0); @@ -1246,9 +1257,7 @@ static void test_mrsp_various_block_and_unblock(test_context *ctx) rtems_test_assert(!ctx->low_run[1]); print_switch_events(ctx); - - sc = rtems_timer_delete(ctx->timer_id); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); + delete_timer(ctx); sc = rtems_task_delete(ctx->high_task_id[0]); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -1749,7 +1758,6 @@ static void Init(rtems_task_argument arg) test_mrsp_flush_error(ctx); test_mrsp_initially_locked_error(); test_mrsp_nested_obtain_error(ctx); - test_mrsp_unlock_order_error(ctx); test_mrsp_deadlock_error(ctx); test_mrsp_multiple_obtain(ctx); diff --git a/testsuites/sptests/spinternalerror02/init.c b/testsuites/sptests/spinternalerror02/init.c index eac90a0..3de5ef9 100644 --- a/testsuites/sptests/spinternalerror02/init.c +++ b/testsuites/sptests/spinternalerror02/init.c @@ -36,7 +36,7 @@ static void test_internal_error_text(void) } while ( text != text_last ); rtems_test_assert( - error - 3 == INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK + error - 3 == INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE ); } diff --git a/testsuites/sptests/spinternalerror02/spinternalerror02.scn b/testsuites/sptests/spinternalerror02/spinternalerror02.scn index ff04560..2be58f4 100644 --- a/testsuites/sptests/spinternalerror02/spinternalerror02.scn +++ b/testsuites/sptests/spinternalerror02/spinternalerror02.scn @@ -28,6 +28,7 @@ INTERNAL_ERROR_RESOURCE_IN_USE INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK +INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE ? ? INTERNAL_ERROR_CORE -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel