summaryrefslogtreecommitdiffstats
path: root/cpukit/include/rtems/score/smpimpl.h
blob: ef32687beccedcbf775085f6923e5003dc93a6ae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/* SPDX-License-Identifier: BSD-2-Clause */

/**
 * @file
 *
 * @ingroup RTEMSScoreSMP
 *
 * @brief This header file provides interfaces of the
 *   @ref RTEMSScoreSMP which are only used by the implementation.
 */

/*
 *  COPYRIGHT (c) 1989-2011.
 *  On-Line Applications Research Corporation (OAR).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _RTEMS_SCORE_SMPIMPL_H
#define _RTEMS_SCORE_SMPIMPL_H

#include <rtems/score/smp.h>
#include <rtems/score/percpu.h>
#include <rtems/score/processormask.h>
#include <rtems/fatal.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @addtogroup RTEMSScoreSMP
 *
 * This defines the interface of the SuperCore SMP support.
 *
 * @{
 */

/**
 * @brief SMP message to request a processor shutdown.
 *
 * @see _SMP_Send_message().
 */
#define SMP_MESSAGE_SHUTDOWN 0x1UL

/**
 * @brief SMP message to perform per-processor jobs.
 *
 * @see _SMP_Send_message().
 */
#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 {
  SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER,
  SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT,
  SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR,
  SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR,
  SMP_FATAL_SHUTDOWN,
  SMP_FATAL_SHUTDOWN_RESPONSE,
  SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED,
  SMP_FATAL_SCHEDULER_PIN_OR_UNPIN_NOT_SUPPORTED,
  SMP_FATAL_WRONG_CPU_STATE_TO_PERFORM_JOBS,
  SMP_FATAL_SCHEDULER_REQUIRES_EXACTLY_ONE_PROCESSOR,
  SMP_FATAL_MULTITASKING_START_ON_NOT_ONLINE_PROCESSOR
} SMP_Fatal_code;

/**
 * @brief Terminates with the given code.
 *
 * @param code The code for the termination.
 */
static inline void _SMP_Fatal( SMP_Fatal_code code )
{
  _Terminate( RTEMS_FATAL_SOURCE_SMP, code );
}

/**
 * @brief Initializes SMP Handler
 *
 * This method initialize the SMP Handler.
 */
#if defined( RTEMS_SMP )
  void _SMP_Handler_initialize( void );
#else
  #define _SMP_Handler_initialize() \
    do { } while ( 0 )
#endif

#if defined( RTEMS_SMP )

/**
 * @brief Set of online processors.
 *
 * A processor is online if was started during system initialization.  In this
 * case its corresponding bit in the mask is set.
 *
 * @see _SMP_Handler_initialize().
 */
extern Processor_mask _SMP_Online_processors;

/**
 * @brief Performs high-level initialization of a secondary processor and runs
 * the application threads.
 *
 * The low-level initialization code must call this function to hand over the
 * control of this processor to RTEMS.  Interrupts must be disabled.  It must
 * be possible to send inter-processor interrupts to this processor.  Since
 * interrupts are disabled the inter-processor interrupt delivery is postponed
 * until interrupts are enabled the first time.  Interrupts are enabled during
 * the execution begin of threads in case they have interrupt level zero (this
 * is the default).
 *
 * The pre-requisites for the call to this function are
 * - disabled interrupts,
 * - delivery of inter-processor interrupts is possible,
 * - a valid stack pointer and enough stack space,
 * - a valid code memory, and
 * - a valid BSS section.
 *
 * This function must not be called by the main processor.  The main processor
 * uses _Thread_Start_multitasking() instead.
 *
 * This function does not return to the caller.
 *
 * @param cpu_self The current processor control.
 */
RTEMS_NO_RETURN void _SMP_Start_multitasking_on_secondary_processor(
  Per_CPU_Control *cpu_self
);

/**
 * @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 is the processor control of the processor executing
 *   this function.
 *
 * @return Returns the processed message.
 */
static inline long unsigned _SMP_Inter_processor_interrupt_handler(
  Per_CPU_Control *cpu_self
)
{
  unsigned long message;

  /*
   * In the common case the inter-processor interrupt is issued to carry out a
   * thread dispatch.
   */
  cpu_self->dispatch_necessary = true;

  message = _Atomic_Exchange_ulong(
    &cpu_self->message,
    0,
    ATOMIC_ORDER_ACQUIRE
  );

  if ( RTEMS_PREDICT_FALSE( message != 0 ) ) {
    return _SMP_Process_message( cpu_self, message );
  }

  return message;
}

/**
 * @brief Checks if the processor with the specified index should be started.
 *
 * @param cpu_index The processor index.
 *
 * @retval true The processor should be started.
 * @retval false The processor should not be started.
 */
bool _SMP_Should_start_processor( uint32_t cpu_index );

/**
 * @brief Sends the SMP message to the processor.
 *
 * The target processor may be the sending processor.
 *
 * @param[in, out] cpu is the processor control of the target processor.
 *
 * @param message is the message to send.
 */
void _SMP_Send_message( Per_CPU_Control *cpu, unsigned long message );

typedef void ( *SMP_Action_handler )( void *arg );

/**
 * @brief Initiates an SMP multicast action to the set of target processors.
 *
 * The current processor may be part of the set.  The caller must ensure that
 * no thread dispatch can happen during the call of this function, otherwise
 * the behaviour is undefined.  In case a target processor is in a wrong state
 * to process per-processor jobs, then this function results in an
 * SMP_FATAL_WRONG_CPU_STATE_TO_PERFORM_JOBS fatal SMP error.
 *
 * @param targets The set of target processors for the action.
 * @param handler The multicast action handler.
 * @param arg The multicast action argument.
 */
void _SMP_Multicast_action(
  const Processor_mask *targets,
  SMP_Action_handler    handler,
  void                 *arg
);

/**
 * @brief Initiates an SMP multicast action to the set of all online
 * processors.
 *
 * Simply calls _SMP_Multicast_action() with _SMP_Get_online_processors() as
 * the target processor set.
 *
 * @param handler The multicast action handler.
 * @param arg The multicast action argument.
 */
void _SMP_Broadcast_action(
  SMP_Action_handler  handler,
  void               *arg
);

/**
 * @brief Initiates an SMP multicast action to the set of all online
 * processors excluding the current processor.
 *
 * Simply calls _SMP_Multicast_action() with _SMP_Get_online_processors() as
 * the target processor set excluding the current processor.
 *
 * @param handler The multicast action handler.
 * @param arg The multicast action argument.
 */
void _SMP_Othercast_action(
  SMP_Action_handler  handler,
  void               *arg
);

/**
 * @brief Initiates an SMP action on the specified target processor.
 *
 * This is an optimized variant of _SMP_Multicast_action().
 *
 * @param cpu_index The index of the target processor.
 * @param handler The action handler.
 * @param arg The action argument.
 */
void _SMP_Unicast_action(
  uint32_t            cpu_index,
  SMP_Action_handler  handler,
  void               *arg
);

/**
 * @brief Ensures that all store operations issued by the current processor
 * before the call this function are visible to all other online processors.
 *
 * Simply calls _SMP_Othercast_action() with an empty multicast action.
 */
void _SMP_Synchronize( void );

#endif /* defined( RTEMS_SMP ) */

/**
 * @brief Requests a multitasking start on all configured and available
 * processors.
 */
#if defined( RTEMS_SMP )
  void _SMP_Request_start_multitasking( void );
#else
  #define _SMP_Request_start_multitasking() \
    do { } while ( 0 )
#endif

/**
 * @brief Requests a shutdown of all processors.
 *
 * This function is a part of the system termination procedure.
 *
 * @see _Terminate().
 */
#if defined( RTEMS_SMP )
  void _SMP_Request_shutdown( void );
#else
  #define _SMP_Request_shutdown() \
    do { } while ( 0 )
#endif

/**
 * @brief Gets all online processors
 *
 * @return The processor mask with all online processors.
 */
static inline const Processor_mask *_SMP_Get_online_processors( void )
{
#if defined(RTEMS_SMP)
  return &_SMP_Online_processors;
#else
  return &_Processor_mask_The_one_and_only;
#endif
}

/**
 * @brief Indicate if inter-processor interrupts are needed.
 *
 * @return True if inter-processor interrupts are needed for the correct system
 * operation, otherwise false.
 */
static inline bool _SMP_Need_inter_processor_interrupts( void )
{
  /*
   * Use the configured processor maximum instead of the actual to allow
   * testing on uni-processor systems.
   */
  return _SMP_Processor_configured_maximum > 1;
}

/** @} */

#ifdef __cplusplus
}
#endif

#endif
/* end of include file */