source: rtems/cpukit/score/src/percpu.c @ 2f6108f9

4.115
Last change on this file since 2f6108f9 was 2f6108f9, checked in by Sebastian Huber <sebastian.huber@…>, on May 28, 2013 at 8:58:19 AM

smp: Simplify SMP initialization sequence

Delete bsp_smp_wait_for(). Other parts of the system work without
timeout, e.g. the spinlocks. Using a timeout here does not make the
system more robust.

Delete bsp_smp_cpu_state and replace it with Per_CPU_State. The
Per_CPU_State follows the Score naming conventions. Add
_Per_CPU_Change_state() and _Per_CPU_Wait_for_state() functions to
change and observe states.

Use Per_CPU_State in Per_CPU_Control instead of the anonymous integer.

Add _CPU_Processor_event_broadcast() and _CPU_Processor_event_receive()
functions provided by the CPU port. Use these functions in
_Per_CPU_Change_state() and _Per_CPU_Wait_for_state().

Add prototype for _SMP_Send_message().

Delete RTEMS_BSP_SMP_FIRST_TASK message. The first context switch is
now performed in rtems_smp_secondary_cpu_initialize(). Issuing the
first context switch in the context of the inter-processor interrupt is
not possible on systems with a modern interrupt controller. Such an
interrupt controler usually requires a handshake protocol with interrupt
acknowledge and end of interrupt signals. A direct context switch in an
interrupt handler circumvents the interrupt processing epilogue and may
leave the system in an inconsistent state.

Release lock in rtems_smp_process_interrupt() even if no message was
delivered. This prevents deadlock of the system.

Simplify and format _SMP_Send_message(),
_SMP_Request_other_cores_to_perform_first_context_switch(),
_SMP_Request_other_cores_to_dispatch() and
_SMP_Request_other_cores_to_shutdown().

  • Property mode set to 100644
File size: 2.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief Allocate and Initialize Per CPU Structures
5 * @ingroup PerCPU
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2011.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/thread.h>
23#include <rtems/score/percpu.h>
24#include <rtems/score/wkspace.h>
25#include <rtems/config.h>
26#include <string.h>
27
28#if defined(RTEMS_SMP)
29
30  #include <rtems/score/smp.h>
31
32  void _SMP_Handler_initialize(void)
33  {
34    uint32_t max_cpus = rtems_configuration_get_maximum_processors();
35    uint32_t cpu;
36
37    /*
38     *  Initialize per cpu pointer table
39     */
40    _Per_CPU_Information_p[0] = &_Per_CPU_Information[0];
41    for ( cpu = 1 ; cpu < max_cpus; ++cpu ) {
42
43      Per_CPU_Control *p = &_Per_CPU_Information[cpu];
44
45      _Per_CPU_Information_p[cpu] = p;
46
47#if CPU_ALLOCATE_INTERRUPT_STACK == TRUE
48      {
49        size_t size = rtems_configuration_get_interrupt_stack_size();
50        uintptr_t ptr;
51
52        p->interrupt_stack_low = _Workspace_Allocate_or_fatal_error( size );
53
54        ptr = (uintptr_t) _Addresses_Add_offset( p->interrupt_stack_low, size );
55        ptr &= ~(CPU_STACK_ALIGNMENT - 1);
56        p->interrupt_stack_high = (void *)ptr;
57      }
58#endif
59    }
60
61    /*
62     * Discover and initialize the secondary cores in an SMP system.
63     */
64    max_cpus = bsp_smp_initialize( max_cpus );
65
66    _SMP_Processor_count = max_cpus;
67
68    for ( cpu = 1 ; cpu < max_cpus; ++cpu ) {
69      _Per_CPU_Wait_for_state(
70        &_Per_CPU_Information[ cpu ],
71        PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
72      );
73    }
74  }
75
76  void _Per_CPU_Change_state(
77    Per_CPU_Control *per_cpu,
78    Per_CPU_State new_state
79  )
80  {
81    per_cpu->state = new_state;
82    _CPU_Processor_event_broadcast();
83  }
84
85  void _Per_CPU_Wait_for_state(
86    const Per_CPU_Control *per_cpu,
87    Per_CPU_State desired_state
88  )
89  {
90    while ( per_cpu->state != desired_state ) {
91      _CPU_Processor_event_receive();
92    }
93  }
94#else
95  /*
96   * On single core systems, we can efficiently directly access a single
97   * statically allocated per cpu structure.  And the fields are initialized
98   * as individual elements just like it has always been done.
99   */
100  Per_CPU_Control _Per_CPU_Information[1];
101#endif
Note: See TracBrowser for help on using the repository browser.