source: rtems/cpukit/score/src/smp.c

Last change on this file was 48f693a9, checked in by Sebastian Huber <sebastian.huber@…>, on 01/24/23 at 15:53:03

score: Remove unused return value

Several SMP message processing functions returned a value. This value
was always unused.

Close #4822.

  • Property mode set to 100644
File size: 10.2 KB
RevLine 
[4a0e418]1/* SPDX-License-Identifier: BSD-2-Clause */
2
[e655f7e]3/**
[9278f3d]4 * @file
[e655f7e]5 *
[9278f3d]6 * @ingroup RTEMSScoreSMP
7 *
8 * @brief This source file contains the definition of ::_SMP_Online_processors
9 *   and ::_SMP_Processor_maximum and the implementation of
[cbb1103]10 *   _SMP_Handler_initialize(),  _SMP_Process_message(),
11 *   _SMP_Request_shutdown(), _SMP_Request_start_multitasking(),
[70ec9bd]12 *   _SMP_Send_message(), _SMP_Should_start_processor(),
[cbb1103]13 *   _SMP_Start_multitasking_on_secondary_processor(), and
14 *   _SMP_Try_to_process_message().
[e655f7e]15 */
16
[06dcaf0]17/*
18 *  COPYRIGHT (c) 1989-2011.
19 *  On-Line Applications Research Corporation (OAR).
20 *
[4a0e418]21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 *    notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in the
28 *    documentation and/or other materials provided with the distribution.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 * POSSIBILITY OF SUCH DAMAGE.
[06dcaf0]41 */
42
[80cf60e]43#ifdef HAVE_CONFIG_H
[06dcaf0]44#include "config.h"
45#endif
46
[6ca4f6a]47#include <rtems/score/smpimpl.h>
[f8ff2a0]48#include <rtems/score/assert.h>
[c5831a3f]49#include <rtems/score/schedulerimpl.h>
[b4b309c]50#include <rtems/score/threadimpl.h>
[8a6de83]51#include <rtems/config.h>
[06dcaf0]52
[8042107a]53#if CPU_USE_DEFERRED_FP_SWITCH == TRUE
54  #error "deferred FP switch not implemented for SMP"
55#endif
56
[cbb1103]57/**
58 * @brief Indicates if the system is ready to start multitasking.
59 *
60 * Only the boot processor is allowed to change this object.  If the object has
61 * a non-zero value and no fatal error occurred, then secondary processors
62 * should call _Thread_Start_multitasking() to start multiprocessing.
63 */
64static Atomic_Uint _SMP_Ready_to_start_multitasking;
65
[b3a4c48e]66Processor_mask _SMP_Online_processors;
67
[cfcd6dc9]68uint32_t _SMP_Processor_maximum;
[358bd740]69
[e610785]70static const Scheduler_Assignment *_Scheduler_Get_initial_assignment(
71  uint32_t cpu_index
72)
73{
74  return &_Scheduler_Initial_assignments[ cpu_index ];
75}
76
77static bool _Scheduler_Is_mandatory_processor(
78  const Scheduler_Assignment *assignment
79)
80{
81  return (assignment->attributes & SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) != 0;
82}
83
84static bool _Scheduler_Should_start_processor(
85  const Scheduler_Assignment *assignment
86)
87{
88  return assignment->scheduler != NULL;
89}
90
[ad87de4]91static void _SMP_Start_processors( uint32_t cpu_max )
[c5831a3f]92{
[e610785]93  uint32_t cpu_index_self;
[c5831a3f]94  uint32_t cpu_index;
95
[e610785]96  cpu_index_self = _SMP_Get_current_processor();
97
[ad87de4]98  for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
[e610785]99    const Scheduler_Assignment *assignment;
100    Per_CPU_Control            *cpu;
101    bool                        started;
102
103    assignment = _Scheduler_Get_initial_assignment( cpu_index );
104    cpu = _Per_CPU_Get_by_index( cpu_index );
[c5831a3f]105
[3380ee8]106    if ( cpu_index != cpu_index_self ) {
[c5831a3f]107      if ( _Scheduler_Should_start_processor( assignment ) ) {
108        started = _CPU_SMP_Start_processor( cpu_index );
109
110        if ( !started && _Scheduler_Is_mandatory_processor( assignment ) ) {
111          _SMP_Fatal( SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED );
112        }
113      } else {
114        started = false;
115      }
116    } else {
117      started = true;
118
[3c103ba]119      cpu->boot = true;
120
[c5831a3f]121      if ( !_Scheduler_Should_start_processor( assignment ) ) {
122        _SMP_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER );
123      }
124    }
125
[c284a16]126    cpu->online = started;
[c5831a3f]127
128    if ( started ) {
[1c46b80]129      const Scheduler_Control *scheduler;
130      Scheduler_Context       *context;
131
132      scheduler = assignment->scheduler;
133      context = _Scheduler_Get_context( scheduler );
[38b59a6]134
[6b1d8c7]135      _Processor_mask_Set( &_SMP_Online_processors, cpu_index );
136      _Processor_mask_Set( &context->Processors, cpu_index );
[1c46b80]137      cpu->Scheduler.control = scheduler;
138      cpu->Scheduler.context = context;
[c5831a3f]139    }
140  }
141}
142
[282bfd3]143void _SMP_Handler_initialize( void )
144{
[ad87de4]145  uint32_t cpu_config_max;
146  uint32_t cpu_max;
[53e008b]147  uint32_t cpu_index;
[282bfd3]148
[ad87de4]149  cpu_config_max = rtems_configuration_get_maximum_processors();
150
151  for ( cpu_index = 0 ; cpu_index < cpu_config_max; ++cpu_index ) {
[18d45d9]152    Per_CPU_Control *cpu;
[b1d08a58]153
[18d45d9]154    cpu = _Per_CPU_Get_by_index( cpu_index );
[e97b7c9a]155    _ISR_lock_Set_name( &cpu->Lock, "Per-CPU" );
[e90486a]156    _ISR_lock_Set_name( &cpu->Jobs.Lock, "Per-CPU Jobs" );
[18d45d9]157    _ISR_lock_Set_name( &cpu->Watchdog.Lock, "Per-CPU Watchdog" );
[351c14d]158    _Chain_Initialize_empty( &cpu->Threads_in_need_for_help );
[b1d08a58]159  }
160
[282bfd3]161  /*
162   * Discover and initialize the secondary cores in an SMP system.
163   */
164
[ad87de4]165  cpu_max = _CPU_SMP_Initialize();
166  cpu_max = cpu_max < cpu_config_max ? cpu_max : cpu_config_max;
167  _SMP_Processor_maximum = cpu_max;
[53e008b]168
[ad87de4]169  for ( cpu_index = cpu_max ; cpu_index < cpu_config_max; ++cpu_index ) {
[e610785]170    const Scheduler_Assignment *assignment;
171
172    assignment = _Scheduler_Get_initial_assignment( cpu_index );
[53e008b]173
[c5831a3f]174    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
175      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
[53e008b]176    }
177  }
178
[ad87de4]179  _SMP_Start_processors( cpu_max );
[c5831a3f]180
[ad87de4]181  _CPU_SMP_Finalize_initialization( cpu_max );
[282bfd3]182}
183
[7336be9d]184void _SMP_Request_start_multitasking( void )
[06dcaf0]185{
[406dd62]186  Per_CPU_Control *cpu_self;
[ad87de4]187  uint32_t         cpu_max;
[406dd62]188  uint32_t         cpu_index;
189
[ad87de4]190  cpu_max = _SMP_Get_processor_maximum();
[cbb1103]191  cpu_self = _Per_CPU_Get();
[2f6108f9]192
[cbb1103]193  /*
194   * Wait until all other online processors reached the
195   * PER_CPU_STATE_READY_TO_START_MULTITASKING state.  The waiting is done
196   * without a timeout.  If secondary processors cannot reach this state, then
197   * it is expected that they indicate this failure with an
198   * ::SMP_MESSAGE_SHUTDOWN message or reset the system.
199   */
[ad87de4]200  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
[406dd62]201    Per_CPU_Control *cpu;
202
203    cpu = _Per_CPU_Get_by_index( cpu_index );
[7336be9d]204
[cbb1103]205    if ( cpu != cpu_self && _Per_CPU_Is_processor_online( cpu ) ) {
206      while (
207        _Per_CPU_Get_state( cpu ) != PER_CPU_STATE_READY_TO_START_MULTITASKING
208      ) {
209        _SMP_Try_to_process_message(
210          cpu_self,
211          _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED )
212        );
213      }
[6c36946f]214    }
[7336be9d]215  }
[cbb1103]216
217  _Atomic_Store_uint(
218    &_SMP_Ready_to_start_multitasking,
219    1U,
220    ATOMIC_ORDER_RELEASE
221  );
[7336be9d]222}
[2f6108f9]223
[2a4f9d7]224bool _SMP_Should_start_processor( uint32_t cpu_index )
225{
[e610785]226  const Scheduler_Assignment *assignment;
[2a4f9d7]227
[e610785]228  assignment = _Scheduler_Get_initial_assignment( cpu_index );
[2a4f9d7]229  return _Scheduler_Should_start_processor( assignment );
230}
231
[cbb1103]232static void _SMP_Wait_for_start_multitasking( Per_CPU_Control *cpu_self )
233{
234  unsigned int ready;
235
236  do {
237    _SMP_Try_to_process_message(
238      cpu_self,
239      _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED )
240    );
241    ready = _Atomic_Load_uint(
242      &_SMP_Ready_to_start_multitasking,
243      ATOMIC_ORDER_ACQUIRE
244    );
245  } while ( ready == 0U );
246}
247
[406dd62]248void _SMP_Start_multitasking_on_secondary_processor(
249  Per_CPU_Control *cpu_self
250)
[7336be9d]251{
[406dd62]252  uint32_t cpu_index_self;
253
254  cpu_index_self = _Per_CPU_Get_index( cpu_self );
[2f6108f9]255
[5fcc2ca]256  /*
257   * Call fatal error and per-CPU job handlers with thread dispatching
258   * disabled.
259   */
260  cpu_self->thread_dispatch_disable_level = 1;
261
[d134adeb]262  if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
263    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
264  }
265
[2a4f9d7]266  if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
[c5831a3f]267    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
268  }
269
[cbb1103]270  _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING );
271  _SMP_Wait_for_start_multitasking( cpu_self );
[3661518]272
273  if ( !_Per_CPU_Is_processor_online( cpu_self ) ) {
274    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_NOT_ONLINE_PROCESSOR );
275  }
276
[514705d]277  _Thread_Start_multitasking();
[06dcaf0]278}
279
[7336be9d]280void _SMP_Request_shutdown( void )
281{
[6f6cf785]282  ISR_Level level;
[cbb1103]283  uint32_t  cpu_max;
284  uint32_t  cpu_index_self;
285  uint32_t  cpu_index;
[6f6cf785]286
287  _ISR_Local_disable( level );
288  (void) level;
[7336be9d]289
[cbb1103]290  cpu_max = _SMP_Processor_configured_maximum;
291  cpu_index_self = _SMP_Get_current_processor();
292
293  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
294    Per_CPU_Control *cpu;
295
296    cpu = _Per_CPU_Get_by_index( cpu_index );
297
298    if ( cpu_index == cpu_index_self ) {
299      _Per_CPU_Set_state( cpu, PER_CPU_STATE_SHUTDOWN );
300    } else {
301      _Atomic_Fetch_or_ulong(
302        &cpu->message,
303        SMP_MESSAGE_SHUTDOWN,
304        ATOMIC_ORDER_RELEASE
305      );
306
307      if ( _Per_CPU_Get_state( cpu ) == PER_CPU_STATE_UP ) {
308        _CPU_SMP_Send_interrupt( cpu_index );
309      }
310    }
311  }
312}
313
[48f693a9]314void _SMP_Process_message( Per_CPU_Control *cpu_self, long unsigned message )
[cbb1103]315{
316  if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
[53c84ac]317    ISR_Level level;
318
319    _CPU_ISR_Disable( level );
320    (void) level;
321
[cbb1103]322    /* Check the state to prevent recursive shutdowns */
323    if ( _Per_CPU_Get_state( cpu_self ) != PER_CPU_STATE_SHUTDOWN ) {
324      _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_SHUTDOWN );
325      _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE );
326    }
327  }
328
329  if ( ( message & SMP_MESSAGE_PERFORM_JOBS ) != 0 ) {
330    _Per_CPU_Perform_jobs( cpu_self );
331  }
332}
333
334void _SMP_Try_to_process_message(
335  Per_CPU_Control *cpu_self,
336  unsigned long    message
337)
338{
339  if ( message != 0 ) {
340    /*
341     * Fetch the current message.  Only a read-modify-write operation
342     * guarantees that we get an up to date message.  This is especially
343     * important if the function was called using SMP_MESSAGE_FORCE_PROCESSING.
344     */
345    message = _Atomic_Exchange_ulong(
346      &cpu_self->message,
347      0,
348      ATOMIC_ORDER_ACQUIRE
349    );
350
351    _SMP_Process_message( cpu_self, message );
352  }
[7336be9d]353}
354
[6c39df7e]355void _SMP_Send_message( Per_CPU_Control *cpu, unsigned long message )
[06dcaf0]356{
[cbb1103]357  (void) _Atomic_Fetch_or_ulong(
358    &cpu->message, message,
359    ATOMIC_ORDER_RELEASE
360  );
[2f6108f9]361
[cbb1103]362  if ( _Per_CPU_Get_state( cpu ) == PER_CPU_STATE_UP ) {
[6c39df7e]363    _CPU_SMP_Send_interrupt( _Per_CPU_Get_index( cpu ) );
[cbb1103]364  }
[06dcaf0]365}
Note: See TracBrowser for help on using the repository browser.