rtems: Add SMP support for signals

Add and use _ASR_Get_posted_signals().  The post-switch handler is not
protected by disabled thread dispatching.  Use proper SMP lock for
signal management.
This commit is contained in:
Sebastian Huber
2013-08-27 10:48:17 +02:00
parent ef3640f7a7
commit 75f6d18ee0
4 changed files with 40 additions and 27 deletions
+3
View File
@@ -22,6 +22,7 @@
#ifndef _RTEMS_RTEMS_ASR_H
#define _RTEMS_RTEMS_ASR_H
#include <rtems/score/isrlock.h>
#include <rtems/rtems/modes.h>
#ifdef __cplusplus
@@ -73,6 +74,8 @@ typedef struct {
rtems_signal_set signals_pending;
/** This field indicates if nest level of signals being processed */
uint32_t nest_level;
/** Lock to protect this structure */
ISR_lock_Control Lock;
} ASR_Information;
/*
+34 -18
View File
@@ -18,7 +18,6 @@
#define _RTEMS_RTEMS_ASRIMPL_H
#include <rtems/rtems/asr.h>
#include <rtems/score/isrlevel.h>
#ifdef __cplusplus
extern "C" {
@@ -38,15 +37,16 @@ extern "C" {
* This routine initializes the given RTEMS_ASR information record.
*/
RTEMS_INLINE_ROUTINE void _ASR_Initialize (
ASR_Information *information
ASR_Information *asr
)
{
information->is_enabled = false;
information->handler = NULL;
information->mode_set = RTEMS_DEFAULT_MODES;
information->signals_posted = 0;
information->signals_pending = 0;
information->nest_level = 0;
asr->is_enabled = false;
asr->handler = NULL;
asr->mode_set = RTEMS_DEFAULT_MODES;
asr->signals_posted = 0;
asr->signals_pending = 0;
asr->nest_level = 0;
_ISR_lock_Initialize( &asr->Lock );
}
/**
@@ -57,17 +57,17 @@ RTEMS_INLINE_ROUTINE void _ASR_Initialize (
* way that the RTEMS_ASR disable/enable flag changes.
*/
RTEMS_INLINE_ROUTINE void _ASR_Swap_signals (
ASR_Information *information
ASR_Information *asr
)
{
rtems_signal_set _signals;
ISR_Level _level;
_ISR_Disable( _level );
_signals = information->signals_pending;
information->signals_pending = information->signals_posted;
information->signals_posted = _signals;
_ISR_Enable( _level );
_ISR_lock_ISR_disable_and_acquire( &asr->Lock, _level );
_signals = asr->signals_pending;
asr->signals_pending = asr->signals_posted;
asr->signals_posted = _signals;
_ISR_lock_Release_and_ISR_enable( &asr->Lock, _level );
}
/**
@@ -90,10 +90,10 @@ RTEMS_INLINE_ROUTINE bool _ASR_Is_null_handler (
* given RTEMS_ASR information record and FALSE otherwise.
*/
RTEMS_INLINE_ROUTINE bool _ASR_Are_signals_pending (
ASR_Information *information
ASR_Information *asr
)
{
return information->signals_posted != 0;
return asr->signals_posted != 0;
}
/**
@@ -105,15 +105,31 @@ RTEMS_INLINE_ROUTINE bool _ASR_Are_signals_pending (
* NOTE: This must be implemented as a macro.
*/
RTEMS_INLINE_ROUTINE void _ASR_Post_signals(
ASR_Information *asr,
rtems_signal_set signals,
rtems_signal_set *signal_set
)
{
ISR_Level _level;
_ISR_Disable( _level );
_ISR_lock_ISR_disable_and_acquire( &asr->Lock, _level );
*signal_set |= signals;
_ISR_Enable( _level );
_ISR_lock_Release_and_ISR_enable( &asr->Lock, _level );
}
RTEMS_INLINE_ROUTINE rtems_signal_set _ASR_Get_posted_signals(
ASR_Information *asr
)
{
rtems_signal_set signal_set;
ISR_Level _level;
_ISR_lock_ISR_disable_and_acquire( &asr->Lock, _level );
signal_set = asr->signals_posted;
asr->signals_posted = 0;
_ISR_lock_Release_and_ISR_enable( &asr->Lock, _level );
return signal_set;
}
/**@}*/
+1 -7
View File
@@ -27,7 +27,6 @@
static void _RTEMS_signal_Post_switch_hook( Thread_Control *executing )
{
ISR_Level level;
RTEMS_API_Control *api;
ASR_Information *asr;
rtems_signal_set signal_set;
@@ -42,12 +41,7 @@ static void _RTEMS_signal_Post_switch_hook( Thread_Control *executing )
*/
asr = &api->Signal;
_ISR_Disable( level );
signal_set = asr->signals_posted;
asr->signals_posted = 0;
_ISR_Enable( level );
signal_set = _ASR_Get_posted_signals( asr );
if ( !signal_set ) /* similar to _ASR_Are_signals_pending( asr ) */
return;
+2 -2
View File
@@ -46,10 +46,10 @@ rtems_status_code rtems_signal_send(
if ( ! _ASR_Is_null_handler( asr->handler ) ) {
if ( asr->is_enabled ) {
_ASR_Post_signals( signal_set, &asr->signals_posted );
_ASR_Post_signals( asr, signal_set, &asr->signals_posted );
_Thread_Signal_notification( the_thread );
} else {
_ASR_Post_signals( signal_set, &asr->signals_pending );
_ASR_Post_signals( asr, signal_set, &asr->signals_pending );
}
_Objects_Put( &the_thread->Object );
return RTEMS_SUCCESSFUL;