summaryrefslogtreecommitdiffstats
path: root/cpukit/include
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-27 13:40:51 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-28 19:32:24 +0200
commitcbb1103a3ca9d2f42501ba373b5d559b981fb1c7 (patch)
tree8e20c863237d95390b49c82d7ee45791389b5a2a /cpukit/include
parentscore: Remove processor event broadcast/receive (diff)
downloadrtems-cbb1103a3ca9d2f42501ba373b5d559b981fb1c7.tar.bz2
score: Simplify SMP processor state handling
The per-CPU states which control the SMP system initialization were added quite early during the SMP support development. Replace this initial implementation with a simplified one. There is no longer a global SMP lock required which serialized the state changes of all processors. The new implementation better integrates with the per-CPU jobs.
Diffstat (limited to '')
-rw-r--r--cpukit/include/rtems/score/percpu.h42
-rw-r--r--cpukit/include/rtems/score/smpimpl.h61
2 files changed, 66 insertions, 37 deletions
diff --git a/cpukit/include/rtems/score/percpu.h b/cpukit/include/rtems/score/percpu.h
index e79596c244..f72339620d 100644
--- a/cpukit/include/rtems/score/percpu.h
+++ b/cpukit/include/rtems/score/percpu.h
@@ -102,15 +102,18 @@ struct Scheduler_Context;
* The processor state controls the life cycle of processors at the lowest
* level. No multi-threading or other high-level concepts matter here.
*
- * State changes must be initiated via _Per_CPU_State_change(). This function
- * may not return in case someone requested a shutdown. The
- * _SMP_Send_message() function will be used to notify other processors about
- * state changes if the other processor is in the up state.
+ * The state of a processor is indicated by the Per_CPU_Control::state membe.
+ * The current state of a processor can be get by _Per_CPU_Get_state(). Only
+ * the processor associated with the control may change its state using
+ * _Per_CPU_Set_state().
*
* Due to the sequential nature of the basic system initialization one
* processor has a special role. It is the processor executing the boot_card()
* function. This processor is called the boot processor. All other
- * processors are called secondary.
+ * processors are called secondary. The boot processor uses
+ * _SMP_Request_start_multitasking() to indicate that processors should start
+ * multiprocessing. Secondary processors will wait for this request in
+ * _SMP_Start_multitasking_on_secondary_processor().
*
* @dot
* digraph states {
@@ -150,23 +153,13 @@ typedef enum {
* the first time. The boot processor will wait for all secondary processors
* to change into this state. In case a secondary processor does not reach
* this state the system will not start. The secondary processors wait now
- * for a change into the PER_CPU_STATE_REQUEST_START_MULTITASKING state set
- * by the boot processor once all secondary processors reached the
- * PER_CPU_STATE_READY_TO_START_MULTITASKING state.
+ * for a change into the PER_CPU_STATE_UP state set requested by the boot
+ * processor through ::_SMP_Ready_to_start_multitasking once all secondary
+ * processors reached the PER_CPU_STATE_READY_TO_START_MULTITASKING state.
*/
PER_CPU_STATE_READY_TO_START_MULTITASKING,
/**
- * @brief Multitasking start of processor is requested.
- *
- * The boot processor completed system initialization and is about to perform
- * a context switch to its heir thread. Secondary processors should now
- * issue a context switch to the heir thread. This normally enables
- * interrupts on the processor for the first time.
- */
- PER_CPU_STATE_REQUEST_START_MULTITASKING,
-
- /**
* @brief Normal multitasking state.
*/
PER_CPU_STATE_UP,
@@ -547,11 +540,12 @@ typedef struct Per_CPU_Control {
char *data;
/**
- * @brief Indicates the current state of the CPU.
+ * @brief Indicates the current state of the processor.
*
- * This member is protected by the _Per_CPU_State_lock lock.
+ * Only the processor associated with this control is allowed to change
+ * this member.
*
- * @see _Per_CPU_State_change().
+ * @see _Per_CPU_Get_state() and _Per_CPU_Set_state().
*/
Atomic_Uint state;
@@ -801,6 +795,7 @@ static inline void _Per_CPU_Set_state(
Per_CPU_State state
)
{
+ _Assert( cpu_self == _Per_CPU_Get() );
_Atomic_Store_uint(
&cpu_self->state,
(unsigned int) state,
@@ -808,11 +803,6 @@ static inline void _Per_CPU_Set_state(
);
}
-void _Per_CPU_State_change(
- Per_CPU_Control *cpu,
- Per_CPU_State new_state
-);
-
/**
* @brief Waits for a processor to change into a non-initial state.
*
diff --git a/cpukit/include/rtems/score/smpimpl.h b/cpukit/include/rtems/score/smpimpl.h
index 32704d7288..eea48f5060 100644
--- a/cpukit/include/rtems/score/smpimpl.h
+++ b/cpukit/include/rtems/score/smpimpl.h
@@ -51,6 +51,16 @@ extern "C" {
#define SMP_MESSAGE_PERFORM_JOBS 0x2UL
/**
+ * @brief SMP message to force the message processing in
+ * _SMP_Try_to_process_message().
+ *
+ * This message bit is never sent to a processor. It is only used to force the
+ * message processing in _SMP_Try_to_process_message(). Any non-zero value
+ * would do it.
+ */
+#define SMP_MESSAGE_FORCE_PROCESSING 0x4UL
+
+/**
* @brief SMP fatal codes.
*/
typedef enum {
@@ -130,11 +140,47 @@ RTEMS_NO_RETURN void _SMP_Start_multitasking_on_secondary_processor(
);
/**
- * @brief Interrupts handler for inter-processor interrupts.
+ * @brief Processes the SMP message.
+ *
+ * @param[in, out] cpu_self is the processor control of the processor executing
+ * this function.
+ *
+ * @return Returns the processed message.
+ */
+long unsigned _SMP_Process_message(
+ Per_CPU_Control *cpu_self,
+ long unsigned message
+);
+
+/**
+ * @brief Tries to process the current SMP message.
+ *
+ * This function may be used in busy wait loops.
+ *
+ * @param cpu_self is the processor control of the processor executing this
+ * function.
+ *
+ * @param message is used to check if the SMP message processing should be
+ * carried out. If it is not equal to zero, then _SMP_Process_message() is
+ * called with a newly fetched message. This parameter is not used to process
+ * the message. It is only used to check if the processing is necessary.
+ * Use #SMP_MESSAGE_FORCE_PROCESSING to force the message processing.
+ */
+void _SMP_Try_to_process_message(
+ Per_CPU_Control *cpu_self,
+ unsigned long message
+);
+
+/**
+ * @brief Processes an inter-processor interrupt.
+ *
+ * Use this function for the inter-processor interrupt handler. Never call
+ * this function in a tight loop.
*
- * @param[in, out] cpu_self The cpu control for the operation.
+ * @param[in, out] cpu_self is the processor control of the processor executing
+ * this function.
*
- * @return The received message.
+ * @return Returns the processed message.
*/
static inline long unsigned _SMP_Inter_processor_interrupt_handler(
Per_CPU_Control *cpu_self
@@ -155,14 +201,7 @@ static inline long unsigned _SMP_Inter_processor_interrupt_handler(
);
if ( RTEMS_PREDICT_FALSE( message != 0 ) ) {
- if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
- _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE );
- /* does not continue past here */
- }
-
- if ( ( message & SMP_MESSAGE_PERFORM_JOBS ) != 0 ) {
- _Per_CPU_Perform_jobs( cpu_self );
- }
+ return _SMP_Process_message( cpu_self, message );
}
return message;