score: Fix scheduler yield in SMP configurations

Check that no ask help request is registered during unblock and yield
scheduler operations.  There is no need to ask for help if a scheduled
thread yields, since this is already covered by the pre-emption
detection.

Update #2556.
This commit is contained in:
Sebastian Huber
2017-03-07 13:07:02 +01:00
parent a11e1ff576
commit 088acbb01f
4 changed files with 46 additions and 20 deletions

View File

@@ -161,6 +161,7 @@ libscore_a_SOURCES += src/cpusetprintsupport.c
libscore_a_SOURCES += src/schedulerdefaultaskforhelp.c
libscore_a_SOURCES += src/schedulerdefaultgetaffinity.c
libscore_a_SOURCES += src/schedulerdefaultsetaffinity.c
libscore_a_SOURCES += src/schedulersmp.c
libscore_a_SOURCES += src/schedulersmpstartidle.c
endif

View File

@@ -10,7 +10,7 @@
/*
* Copyright (C) 2010 Gedare Bloom.
* Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
* Copyright (c) 2014, 2016 embedded brains GmbH
* Copyright (c) 2014, 2017 embedded brains GmbH
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -114,8 +114,10 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Release_critical(
}
#if defined(RTEMS_SMP)
void _Scheduler_Request_ask_for_help( Thread_Control *the_thread );
/**
* @brief Registers an ask for help request.
* @brief Registers an ask for help request if necessary.
*
* The actual ask for help operation is carried out during
* _Thread_Do_dispatch() on a processor related to the thread. This yields a
@@ -130,22 +132,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Ask_for_help( Thread_Control *the_thread )
_Assert( _Thread_State_is_owner( the_thread ) );
if ( the_thread->Scheduler.helping_nodes > 0 ) {
ISR_lock_Context lock_context;
Per_CPU_Control *cpu;
_Thread_Scheduler_acquire_critical( the_thread, &lock_context );
cpu = _Thread_Get_CPU( the_thread );
_Per_CPU_Acquire( cpu );
_Chain_Append_unprotected(
&cpu->Threads_in_need_for_help,
&the_thread->Scheduler.Help_node
);
_Per_CPU_Release( cpu );
_Thread_Scheduler_release_critical( the_thread, &lock_context );
_Thread_Dispatch_request( _Per_CPU_Get(), cpu );
_Scheduler_Request_ask_for_help( the_thread );
}
}
#endif

View File

@@ -1085,8 +1085,8 @@ static inline void _Scheduler_SMP_Yield(
if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
_Scheduler_SMP_Extract_from_scheduled( node );
needs_help = ( *enqueue_scheduled_fifo )( context, node );
( *enqueue_scheduled_fifo )( context, node );
needs_help = false;
} else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
( *extract_from_ready )( context, node );

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2014, 2017 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.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/score/schedulersmpimpl.h>
void _Scheduler_Request_ask_for_help( Thread_Control *the_thread )
{
ISR_lock_Context lock_context;
_Thread_Scheduler_acquire_critical( the_thread, &lock_context );
if ( _Chain_Is_node_off_chain( &the_thread->Scheduler.Help_node ) ) {
Per_CPU_Control *cpu;
cpu = _Thread_Get_CPU( the_thread );
_Per_CPU_Acquire( cpu );
_Chain_Append_unprotected(
&cpu->Threads_in_need_for_help,
&the_thread->Scheduler.Help_node
);
_Per_CPU_Release( cpu );
_Thread_Dispatch_request( _Per_CPU_Get(), cpu );
}
_Thread_Scheduler_release_critical( the_thread, &lock_context );
}