source: rtems/cpukit/score/src/percpu.c @ 3e3684ba

4.115
Last change on this file since 3e3684ba was 3e3684ba, checked in by Sebastian Huber <sebastian.huber@…>, on 03/17/15 at 07:30:40

score: Ensure properties of CPU_Uint32ptr

  • Property mode set to 100644
File size: 4.2 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.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/score/percpu.h>
22#include <rtems/score/assert.h>
23#include <rtems/score/smpimpl.h>
24#include <rtems/config.h>
25
26RTEMS_STATIC_ASSERT(
27  sizeof( CPU_Uint32ptr ) >= sizeof( uintptr_t ),
28  CPU_Uint32ptr_greater_equal_uintptr_t
29);
30
31RTEMS_STATIC_ASSERT(
32  sizeof( CPU_Uint32ptr ) >= sizeof( uint32_t ),
33  CPU_Uint32ptr_greater_equal_uint32_t
34);
35
36#if defined(RTEMS_SMP)
37
38static SMP_lock_Control _Per_CPU_State_lock =
39  SMP_LOCK_INITIALIZER("per-CPU state");
40
41static void _Per_CPU_State_busy_wait(
42  const Per_CPU_Control *cpu,
43  Per_CPU_State new_state
44)
45{
46  Per_CPU_State state = cpu->state;
47
48  switch ( new_state ) {
49    case PER_CPU_STATE_REQUEST_START_MULTITASKING:
50      while (
51        state != PER_CPU_STATE_READY_TO_START_MULTITASKING
52          && state != PER_CPU_STATE_SHUTDOWN
53      ) {
54        _CPU_SMP_Processor_event_receive();
55        state = cpu->state;
56      }
57      break;
58    case PER_CPU_STATE_UP:
59      while (
60        state != PER_CPU_STATE_REQUEST_START_MULTITASKING
61          && state != PER_CPU_STATE_SHUTDOWN
62      ) {
63        _CPU_SMP_Processor_event_receive();
64        state = cpu->state;
65      }
66      break;
67    default:
68      /* No need to wait */
69      break;
70  }
71}
72
73static Per_CPU_State _Per_CPU_State_get_next(
74  Per_CPU_State current_state,
75  Per_CPU_State new_state
76)
77{
78  switch ( current_state ) {
79    case PER_CPU_STATE_INITIAL:
80      switch ( new_state ) {
81        case PER_CPU_STATE_READY_TO_START_MULTITASKING:
82        case PER_CPU_STATE_SHUTDOWN:
83          /* Change is acceptable */
84          break;
85        default:
86          new_state = PER_CPU_STATE_SHUTDOWN;
87          break;
88      }
89      break;
90    case PER_CPU_STATE_READY_TO_START_MULTITASKING:
91      switch ( new_state ) {
92        case PER_CPU_STATE_REQUEST_START_MULTITASKING:
93        case PER_CPU_STATE_SHUTDOWN:
94          /* Change is acceptable */
95          break;
96        default:
97          new_state = PER_CPU_STATE_SHUTDOWN;
98          break;
99      }
100      break;
101    case PER_CPU_STATE_REQUEST_START_MULTITASKING:
102      switch ( new_state ) {
103        case PER_CPU_STATE_UP:
104        case PER_CPU_STATE_SHUTDOWN:
105          /* Change is acceptable */
106          break;
107        default:
108          new_state = PER_CPU_STATE_SHUTDOWN;
109          break;
110      }
111      break;
112    default:
113      new_state = PER_CPU_STATE_SHUTDOWN;
114      break;
115  }
116
117  return new_state;
118}
119
120void _Per_CPU_State_change(
121  Per_CPU_Control *cpu,
122  Per_CPU_State new_state
123)
124{
125  SMP_lock_Control *lock = &_Per_CPU_State_lock;
126  SMP_lock_Context lock_context;
127  Per_CPU_State next_state;
128
129  _Per_CPU_State_busy_wait( cpu, new_state );
130
131  _SMP_lock_ISR_disable_and_acquire( lock, &lock_context );
132
133  next_state = _Per_CPU_State_get_next( cpu->state, new_state );
134  cpu->state = next_state;
135
136  if ( next_state == PER_CPU_STATE_SHUTDOWN ) {
137    uint32_t cpu_max = rtems_configuration_get_maximum_processors();
138    uint32_t cpu_index;
139
140    for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
141      Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index( cpu_index );
142
143      if ( cpu_other != cpu ) {
144        switch ( cpu_other->state ) {
145          case PER_CPU_STATE_UP:
146            _SMP_Send_message( cpu_index, SMP_MESSAGE_SHUTDOWN );
147            break;
148          default:
149            /* Nothing to do */
150            break;
151        }
152
153        cpu_other->state = PER_CPU_STATE_SHUTDOWN;
154      }
155    }
156  }
157
158  _CPU_SMP_Processor_event_broadcast();
159
160  _SMP_lock_Release_and_ISR_enable( lock, &lock_context );
161
162  if (
163    next_state == PER_CPU_STATE_SHUTDOWN
164      && new_state != PER_CPU_STATE_SHUTDOWN
165  ) {
166    _SMP_Fatal( SMP_FATAL_SHUTDOWN );
167  }
168}
169
170#else
171  /*
172   * On single core systems, we can efficiently directly access a single
173   * statically allocated per cpu structure.  And the fields are initialized
174   * as individual elements just like it has always been done.
175   */
176  Per_CPU_Control_envelope _Per_CPU_Information[1];
177#endif
Note: See TracBrowser for help on using the repository browser.