source: rtems/cpukit/score/src/mpci.c @ 21275b58

5
Last change on this file since 21275b58 was 21275b58, checked in by Sebastian Huber <sebastian.huber@…>, on 11/22/18 at 18:14:51

score: Static Objects_Information initialization

Statically allocate the objects information together with the initial
set of objects either via <rtems/confdefs.h>. Provide default object
informations with zero objects via librtemscpu.a. This greatly
simplifies the workspace size estimate. RTEMS applications which do not
use the unlimited objects option are easier to debug since all objects
reside now in statically allocated objects of the right types.

Close #3621.

  • Property mode set to 100644
File size: 12.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief Multiprocessing Communications Interface (MPCI) Handler
5 * @ingroup ScoreMPCI
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
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/mpciimpl.h>
22#include <rtems/score/coresemimpl.h>
23#include <rtems/score/interr.h>
24#include <rtems/score/objectmp.h>
25#include <rtems/score/stackimpl.h>
26#include <rtems/score/sysstate.h>
27#include <rtems/score/schedulerimpl.h>
28#include <rtems/score/threadimpl.h>
29#include <rtems/score/threadqimpl.h>
30#include <rtems/config.h>
31#include <rtems/sysinit.h>
32
33RTEMS_STATIC_ASSERT(
34  sizeof(MPCI_Internal_packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
35  MPCI_Internal_packet
36);
37
38#define MPCI_SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
39
40bool _System_state_Is_multiprocessing;
41
42rtems_multiprocessing_table *_Configuration_MP_table;
43
44const rtems_multiprocessing_table
45 _Initialization_Default_multiprocessing_table = {
46  1,                        /* local node number */
47  1,                        /* maximum number nodes in system */
48  0,                        /* maximum number global objects */
49  0,                        /* maximum number proxies */
50  STACK_MINIMUM_SIZE,       /* MPCI receive server stack size */
51  NULL                      /* pointer to MPCI address table */
52};
53
54/**
55 *  This is the core semaphore which the MPCI Receive Server blocks on.
56 */
57CORE_semaphore_Control _MPCI_Semaphore;
58
59Thread_queue_Control _MPCI_Remote_blocked_threads =
60  THREAD_QUEUE_INITIALIZER( "MPCI Remote Blocked Threads" );
61
62MPCI_Control *_MPCI_table;
63
64Thread_Control *_MPCI_Receive_server_tcb;
65
66MPCI_Packet_processor _MPCI_Packet_processors[ MP_PACKET_CLASSES_LAST + 1 ];
67
68static void _MPCI_Handler_early_initialization( void )
69{
70  /*
71   *  Initialize the system state based on whether this is an MP system.
72   *  In an MP configuration, internally we view single processor
73   *  systems as a very restricted multiprocessor system.
74   */
75  _Configuration_MP_table = rtems_configuration_get_user_multiprocessing_table();
76
77  if ( _Configuration_MP_table == NULL ) {
78    _Configuration_MP_table = RTEMS_DECONST(
79      rtems_multiprocessing_table *,
80      &_Initialization_Default_multiprocessing_table
81    );
82  } else {
83    _System_state_Is_multiprocessing = true;
84  }
85
86  _Objects_MP_Handler_early_initialization();
87}
88
89static void _MPCI_Handler_initialization( void )
90{
91  MPCI_Control               *users_mpci_table;
92
93  _Objects_MP_Handler_initialization();
94
95  users_mpci_table = _Configuration_MP_table->User_mpci_table;
96
97  if ( _System_state_Is_multiprocessing && !users_mpci_table )
98    _Internal_error( INTERNAL_ERROR_NO_MPCI );
99
100  _MPCI_table = users_mpci_table;
101
102  if ( !_System_state_Is_multiprocessing )
103    return;
104
105  /*
106   *  Register the MP Process Packet routine.
107   */
108
109  _MPCI_Register_packet_processor(
110    MP_PACKET_MPCI_INTERNAL,
111    _MPCI_Internal_packets_Process_packet
112  );
113
114  /*
115   *  Create the counting semaphore used by the MPCI Receive Server.
116   */
117
118  _CORE_semaphore_Initialize(
119    &_MPCI_Semaphore,
120    0                         /* initial_value */
121  );
122}
123
124static void _MPCI_Create_server( void )
125{
126  Thread_Entry_information entry = {
127    .adaptor = _Thread_Entry_adaptor_numeric,
128    .Kinds = {
129      .Numeric = {
130        .entry = _MPCI_Receive_server
131      }
132    }
133  };
134  ISR_lock_Context lock_context;
135  Objects_Name     name;
136
137
138  if ( !_System_state_Is_multiprocessing )
139    return;
140
141  /*
142   *  Initialize the MPCI Receive Server
143   */
144
145  _MPCI_Receive_server_tcb = _Thread_Internal_allocate();
146
147  name.name_u32 = _Objects_Build_name( 'M', 'P', 'C', 'I' );
148  _Thread_Initialize(
149    &_Thread_Information,
150    _MPCI_Receive_server_tcb,
151    &_Scheduler_Table[ 0 ],
152    NULL,        /* allocate the stack */
153    _Stack_Minimum() +
154      CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK +
155      _Configuration_MP_table->extra_mpci_receive_server_stack,
156    CPU_ALL_TASKS_ARE_FP,
157    PRIORITY_PSEUDO_ISR,
158    false,       /* no preempt */
159    THREAD_CPU_BUDGET_ALGORITHM_NONE,
160    NULL,        /* no budget algorithm callout */
161    0,           /* all interrupts enabled */
162    name
163  );
164
165  _ISR_lock_ISR_disable( &lock_context );
166  _Thread_Start( _MPCI_Receive_server_tcb, &entry, &lock_context );
167}
168
169static void _MPCI_Initialization( void )
170{
171  (*_MPCI_table->initialization)();
172}
173
174void _MPCI_Register_packet_processor(
175  MP_packet_Classes      the_class,
176  MPCI_Packet_processor  the_packet_processor
177
178)
179{
180  _MPCI_Packet_processors[ the_class ] = the_packet_processor;
181}
182
183MP_packet_Prefix *_MPCI_Get_packet ( void )
184{
185  MP_packet_Prefix  *the_packet;
186
187  (*_MPCI_table->get_packet)( &the_packet );
188
189  if ( the_packet == NULL )
190    _Internal_error( INTERNAL_ERROR_OUT_OF_PACKETS );
191
192  /*
193   *  Put in a default timeout that will be used for
194   *  all packets that do not otherwise have a timeout.
195   */
196
197  the_packet->timeout = MPCI_DEFAULT_TIMEOUT;
198
199  return the_packet;
200}
201
202void _MPCI_Return_packet (
203  MP_packet_Prefix   *the_packet
204)
205{
206  (*_MPCI_table->return_packet)( the_packet );
207}
208
209void _MPCI_Send_process_packet (
210  uint32_t            destination,
211  MP_packet_Prefix   *the_packet
212)
213{
214  the_packet->source_tid = _Thread_Executing->Object.id;
215  the_packet->to_convert =
216     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
217
218  (*_MPCI_table->send_packet)( destination, the_packet );
219}
220
221static void _MPCI_Enqueue_callout(
222  Thread_queue_Queue     *queue,
223  Thread_Control         *the_thread,
224  struct Per_CPU_Control *cpu_self,
225  Thread_queue_Context   *queue_context
226)
227{
228  _Thread_queue_Add_timeout_ticks( queue, the_thread, cpu_self, queue_context );
229  _Thread_Dispatch_unnest( cpu_self );
230}
231
232Status_Control _MPCI_Send_request_packet(
233  uint32_t          destination,
234  MP_packet_Prefix *the_packet,
235  States_Control    extra_state
236)
237{
238  Per_CPU_Control      *cpu_self;
239  Thread_queue_Context  queue_context;
240  Thread_Control       *executing;
241
242  /*
243   *  See if we need a default timeout
244   */
245
246  if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
247      the_packet->timeout = _MPCI_table->default_timeout;
248
249  _Thread_queue_Context_initialize( &queue_context );
250  _Thread_queue_Context_set_thread_state(
251    &queue_context,
252    STATES_WAITING_FOR_RPC_REPLY | extra_state
253  );
254  _Thread_queue_Context_set_timeout_ticks( &queue_context, the_packet->timeout );
255  _Thread_queue_Context_set_enqueue_callout(
256    &queue_context,
257    _MPCI_Enqueue_callout
258  );
259
260  cpu_self = _Thread_Dispatch_disable();
261
262  executing = _Per_CPU_Get_executing( cpu_self );
263  executing->Wait.remote_id = the_packet->id;
264
265  the_packet->source_tid      = executing->Object.id;
266  the_packet->source_priority = _Thread_Get_priority( executing );
267  the_packet->to_convert =
268     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
269
270  (*_MPCI_table->send_packet)( destination, the_packet );
271
272  _Thread_queue_Acquire( &_MPCI_Remote_blocked_threads, &queue_context );
273  _Thread_queue_Enqueue(
274    &_MPCI_Remote_blocked_threads.Queue,
275    &_Thread_queue_Operations_FIFO,
276    executing,
277    &queue_context
278  );
279  return _Thread_Wait_get_status( executing );
280}
281
282void _MPCI_Send_response_packet (
283  uint32_t            destination,
284  MP_packet_Prefix   *the_packet
285)
286{
287  the_packet->source_tid = _Thread_Executing->Object.id;
288
289  (*_MPCI_table->send_packet)( destination, the_packet );
290}
291
292MP_packet_Prefix  *_MPCI_Receive_packet ( void )
293{
294  MP_packet_Prefix  *the_packet;
295
296  (*_MPCI_table->receive_packet)( &the_packet );
297
298  return the_packet;
299}
300
301Thread_Control *_MPCI_Process_response (
302  MP_packet_Prefix  *the_packet
303)
304{
305  ISR_lock_Context  lock_context;
306  Thread_Control   *the_thread;
307
308  the_thread = _Thread_Get( the_packet->id, &lock_context );
309  _Assert( the_thread != NULL );
310
311  /*
312   * FIXME: This is broken on SMP, see https://devel.rtems.org/ticket/2703.
313   *
314   * Should use _Thread_queue_Extract_critical() instead with a handler
315   * function provided by the caller of _MPCI_Process_response().  Similar to
316   * the filter function in _Thread_queue_Flush_critical().
317   */
318  _ISR_lock_ISR_enable( &lock_context );
319  _Thread_queue_Extract( the_thread );
320  the_thread->Wait.return_code = the_packet->return_code;
321  return the_thread;
322}
323
324/*
325 *  _MPCI_Receive_server
326 *
327 */
328
329void _MPCI_Receive_server(
330  Thread_Entry_numeric_type ignored
331)
332{
333
334  MP_packet_Prefix      *the_packet;
335  MPCI_Packet_processor  the_function;
336  Thread_Control        *executing;
337  Thread_queue_Context   queue_context;
338
339  executing = _Thread_Get_executing();
340  _Thread_queue_Context_initialize( &queue_context );
341  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
342
343  for ( ; ; ) {
344
345    executing->receive_packet = NULL;
346
347    _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
348    _CORE_semaphore_Seize(
349      &_MPCI_Semaphore,
350      MPCI_SEMAPHORE_TQ_OPERATIONS,
351      executing,
352      true,
353      &queue_context
354    );
355
356    for ( ; ; ) {
357      executing->receive_packet = NULL;
358
359      the_packet = _MPCI_Receive_packet();
360
361      if ( !the_packet )
362        break;
363
364      executing->receive_packet = the_packet;
365
366      if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
367        break;
368
369      the_function = _MPCI_Packet_processors[ the_packet->the_class ];
370
371      if ( !the_function )
372        _Internal_error( INTERNAL_ERROR_BAD_PACKET );
373
374       (*the_function)( the_packet );
375    }
376  }
377}
378
379void _MPCI_Announce ( void )
380{
381  Thread_queue_Context queue_context;
382
383  _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
384  (void) _CORE_semaphore_Surrender(
385    &_MPCI_Semaphore,
386    MPCI_SEMAPHORE_TQ_OPERATIONS,
387    UINT32_MAX,
388    &queue_context
389  );
390}
391
392void _MPCI_Internal_packets_Send_process_packet (
393   MPCI_Internal_Remote_operations operation
394)
395{
396  MPCI_Internal_packet *the_packet;
397
398  switch ( operation ) {
399
400    case MPCI_PACKETS_SYSTEM_VERIFY:
401
402      the_packet                    = _MPCI_Internal_packets_Get_packet();
403      the_packet->Prefix.the_class  = MP_PACKET_MPCI_INTERNAL;
404      the_packet->Prefix.length     = sizeof ( MPCI_Internal_packet );
405      the_packet->Prefix.to_convert = sizeof ( MPCI_Internal_packet );
406      the_packet->operation         = operation;
407
408      the_packet->maximum_nodes = _Objects_Maximum_nodes;
409
410      the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
411
412      _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
413      break;
414  }
415}
416
417/*
418 *  _MPCI_Internal_packets_Send_request_packet
419 *
420 *  This subprogram is not needed since there are no request
421 *  packets to be sent by this manager.
422 *
423 */
424
425/*
426 *  _MPCI_Internal_packets_Send_response_packet
427 *
428 *  This subprogram is not needed since there are no response
429 *  packets to be sent by this manager.
430 *
431 */
432
433void _MPCI_Internal_packets_Process_packet (
434  MP_packet_Prefix  *the_packet_prefix
435)
436{
437  MPCI_Internal_packet *the_packet;
438  uint32_t                    maximum_nodes;
439  uint32_t                    maximum_global_objects;
440
441  the_packet = (MPCI_Internal_packet *) the_packet_prefix;
442
443  switch ( the_packet->operation ) {
444
445    case MPCI_PACKETS_SYSTEM_VERIFY:
446
447      maximum_nodes          = the_packet->maximum_nodes;
448      maximum_global_objects = the_packet->maximum_global_objects;
449      if ( maximum_nodes != _Objects_Maximum_nodes ||
450           maximum_global_objects != _Objects_MP_Maximum_global_objects ) {
451
452        _MPCI_Return_packet( the_packet_prefix );
453
454        _Internal_error( INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION );
455      }
456
457      _MPCI_Return_packet( the_packet_prefix );
458
459      break;
460  }
461}
462
463/*
464 *  _MPCI_Internal_packets_Send_object_was_deleted
465 *
466 *  This subprogram is not needed since there are no objects
467 *  deleted by this manager.
468 *
469 */
470
471/*
472 *  _MPCI_Internal_packets_Send_extract_proxy
473 *
474 *  This subprogram is not needed since there are no objects
475 *  deleted by this manager.
476 *
477 */
478
479MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
480{
481  return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
482}
483
484static void _MPCI_Finalize( void )
485{
486  if ( _System_state_Is_multiprocessing ) {
487    _MPCI_Initialization();
488    _MPCI_Internal_packets_Send_process_packet( MPCI_PACKETS_SYSTEM_VERIFY );
489  }
490}
491
492RTEMS_SYSINIT_ITEM(
493  _MPCI_Handler_early_initialization,
494  RTEMS_SYSINIT_MP_EARLY,
495  RTEMS_SYSINIT_ORDER_MIDDLE
496);
497
498RTEMS_SYSINIT_ITEM(
499  _MPCI_Handler_initialization,
500  RTEMS_SYSINIT_MP,
501  RTEMS_SYSINIT_ORDER_MIDDLE
502);
503
504RTEMS_SYSINIT_ITEM(
505  _MPCI_Create_server,
506  RTEMS_SYSINIT_MP_SERVER,
507  RTEMS_SYSINIT_ORDER_MIDDLE
508);
509
510RTEMS_SYSINIT_ITEM(
511  _MPCI_Finalize,
512  RTEMS_SYSINIT_MP_FINALIZE,
513  RTEMS_SYSINIT_ORDER_MIDDLE
514);
515
516/* end of file */
Note: See TracBrowser for help on using the repository browser.