source: rtems/cpukit/score/src/percpu.c @ 439c494

4.115
Last change on this file since 439c494 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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