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
RevLine 
[bf54252]1/**
2 * @file
[ac7d5ef0]3 *
[bf54252]4 * @brief Multiprocessing Communications Interface (MPCI) Handler
5 * @ingroup ScoreMPCI
6 */
7
8/*
[1ed8762e]9 *  COPYRIGHT (c) 1989-2014.
[ac7d5ef0]10 *  On-Line Applications Research Corporation (OAR).
11 *
[98e4ebf5]12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
[c499856]14 *  http://www.rtems.org/license/LICENSE.
[ac7d5ef0]15 */
16
[a8eed23]17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
[7f04cb18]21#include <rtems/score/mpciimpl.h>
22#include <rtems/score/coresemimpl.h>
[976162a6]23#include <rtems/score/interr.h>
[8ca372e]24#include <rtems/score/objectmp.h>
[a112364]25#include <rtems/score/stackimpl.h>
[5e9b32b]26#include <rtems/score/sysstate.h>
[1ed8762e]27#include <rtems/score/schedulerimpl.h>
[7f04cb18]28#include <rtems/score/threadimpl.h>
29#include <rtems/score/threadqimpl.h>
[976162a6]30#include <rtems/config.h>
[8ca372e]31#include <rtems/sysinit.h>
[3a4ae6c]32
[d689de0]33RTEMS_STATIC_ASSERT(
34  sizeof(MPCI_Internal_packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
35  MPCI_Internal_packet
36);
37
[2581a56]38#define MPCI_SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
39
[358bd740]40bool _System_state_Is_multiprocessing;
41
[8ca372e]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
[26f5aa0]54/**
55 *  This is the core semaphore which the MPCI Receive Server blocks on.
56 */
57CORE_semaphore_Control _MPCI_Semaphore;
58
[1e1a91ed]59Thread_queue_Control _MPCI_Remote_blocked_threads =
60  THREAD_QUEUE_INITIALIZER( "MPCI Remote Blocked Threads" );
[358bd740]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
[8ca372e]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 )
[ac7d5ef0]90{
[790b50b]91  MPCI_Control               *users_mpci_table;
92
[8ca372e]93  _Objects_MP_Handler_initialization();
94
[790b50b]95  users_mpci_table = _Configuration_MP_table->User_mpci_table;
[3a4ae6c]96
97  if ( _System_state_Is_multiprocessing && !users_mpci_table )
[3a659b04]98    _Internal_error( INTERNAL_ERROR_NO_MPCI );
[3a4ae6c]99
100  _MPCI_table = users_mpci_table;
101
[adf98bd]102  if ( !_System_state_Is_multiprocessing )
103    return;
104
105  /*
106   *  Register the MP Process Packet routine.
107   */
[05279b84]108
[adf98bd]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
[3a4ae6c]118  _CORE_semaphore_Initialize(
119    &_MPCI_Semaphore,
[ef9505a9]120    0                         /* initial_value */
[3a4ae6c]121  );
[ac7d5ef0]122}
123
[8ca372e]124static void _MPCI_Create_server( void )
[adf98bd]125{
[885c342e]126  Thread_Entry_information entry = {
127    .adaptor = _Thread_Entry_adaptor_numeric,
128    .Kinds = {
129      .Numeric = {
130        .entry = _MPCI_Receive_server
131      }
132    }
133  };
[33829ce]134  ISR_lock_Context lock_context;
135  Objects_Name     name;
[def9eef]136
[adf98bd]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();
[05279b84]146
[def9eef]147  name.name_u32 = _Objects_Build_name( 'M', 'P', 'C', 'I' );
[adf98bd]148  _Thread_Initialize(
[21275b58]149    &_Thread_Information,
[adf98bd]150    _MPCI_Receive_server_tcb,
[947814ca]151    &_Scheduler_Table[ 0 ],
[adf98bd]152    NULL,        /* allocate the stack */
[28352fae]153    _Stack_Minimum() +
[976162a6]154      CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK +
155      _Configuration_MP_table->extra_mpci_receive_server_stack,
[adf98bd]156    CPU_ALL_TASKS_ARE_FP,
[81b03c6]157    PRIORITY_PSEUDO_ISR,
[aae7f1a1]158    false,       /* no preempt */
[ebd40c0]159    THREAD_CPU_BUDGET_ALGORITHM_NONE,
160    NULL,        /* no budget algorithm callout */
[adf98bd]161    0,           /* all interrupts enabled */
[def9eef]162    name
[adf98bd]163  );
[05279b84]164
[33829ce]165  _ISR_lock_ISR_disable( &lock_context );
166  _Thread_Start( _MPCI_Receive_server_tcb, &entry, &lock_context );
[adf98bd]167}
168
[8ca372e]169static void _MPCI_Initialization( void )
[ac7d5ef0]170{
[3a4ae6c]171  (*_MPCI_table->initialization)();
172}
173
174void _MPCI_Register_packet_processor(
[3fd3da4]175  MP_packet_Classes      the_class,
[3a4ae6c]176  MPCI_Packet_processor  the_packet_processor
[05279b84]177
[3a4ae6c]178)
179{
180  _MPCI_Packet_processors[ the_class ] = the_packet_processor;
[ac7d5ef0]181}
182
[3a4ae6c]183MP_packet_Prefix *_MPCI_Get_packet ( void )
[ac7d5ef0]184{
[3a4ae6c]185  MP_packet_Prefix  *the_packet;
[ac7d5ef0]186
[3a4ae6c]187  (*_MPCI_table->get_packet)( &the_packet );
[ac7d5ef0]188
189  if ( the_packet == NULL )
[3a659b04]190    _Internal_error( INTERNAL_ERROR_OUT_OF_PACKETS );
[ac7d5ef0]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 (
[3a4ae6c]203  MP_packet_Prefix   *the_packet
[ac7d5ef0]204)
205{
[3a4ae6c]206  (*_MPCI_table->return_packet)( the_packet );
[ac7d5ef0]207}
208
209void _MPCI_Send_process_packet (
[3127180]210  uint32_t            destination,
[3a4ae6c]211  MP_packet_Prefix   *the_packet
[ac7d5ef0]212)
213{
214  the_packet->source_tid = _Thread_Executing->Object.id;
215  the_packet->to_convert =
[a5b6cdd]216     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
[ac7d5ef0]217
[3a4ae6c]218  (*_MPCI_table->send_packet)( destination, the_packet );
[ac7d5ef0]219}
220
[125f248]221static void _MPCI_Enqueue_callout(
[3da2f471]222  Thread_queue_Queue     *queue,
223  Thread_Control         *the_thread,
224  struct Per_CPU_Control *cpu_self,
225  Thread_queue_Context   *queue_context
[125f248]226)
227{
[7353422f]228  _Thread_queue_Add_timeout_ticks( queue, the_thread, cpu_self, queue_context );
[3da2f471]229  _Thread_Dispatch_unnest( cpu_self );
[125f248]230}
231
[dce48791]232Status_Control _MPCI_Send_request_packet(
233  uint32_t          destination,
234  MP_packet_Prefix *the_packet,
235  States_Control    extra_state
[ac7d5ef0]236)
237{
[125f248]238  Per_CPU_Control      *cpu_self;
239  Thread_queue_Context  queue_context;
240  Thread_Control       *executing;
[07332ae]241
[125f248]242  /*
243   *  See if we need a default timeout
244   */
[ac7d5ef0]245
[125f248]246  if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
247      the_packet->timeout = _MPCI_table->default_timeout;
[ac7d5ef0]248
[125f248]249  _Thread_queue_Context_initialize( &queue_context );
[620b23e]250  _Thread_queue_Context_set_thread_state(
251    &queue_context,
252    STATES_WAITING_FOR_RPC_REPLY | extra_state
253  );
[7353422f]254  _Thread_queue_Context_set_timeout_ticks( &queue_context, the_packet->timeout );
[125f248]255  _Thread_queue_Context_set_enqueue_callout(
256    &queue_context,
257    _MPCI_Enqueue_callout
258  );
[ac7d5ef0]259
[125f248]260  cpu_self = _Thread_Dispatch_disable();
[ac7d5ef0]261
[125f248]262  executing = _Per_CPU_Get_executing( cpu_self );
263  executing->Wait.remote_id = the_packet->id;
[ac7d5ef0]264
[125f248]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);
[ac7d5ef0]269
[125f248]270  (*_MPCI_table->send_packet)( destination, the_packet );
[ac7d5ef0]271
[125f248]272  _Thread_queue_Acquire( &_MPCI_Remote_blocked_threads, &queue_context );
[a4217c6]273  _Thread_queue_Enqueue(
[125f248]274    &_MPCI_Remote_blocked_threads.Queue,
275    &_Thread_queue_Operations_FIFO,
276    executing,
277    &queue_context
278  );
[dce48791]279  return _Thread_Wait_get_status( executing );
[ac7d5ef0]280}
281
282void _MPCI_Send_response_packet (
[3127180]283  uint32_t            destination,
[3a4ae6c]284  MP_packet_Prefix   *the_packet
[ac7d5ef0]285)
286{
287  the_packet->source_tid = _Thread_Executing->Object.id;
288
[3a4ae6c]289  (*_MPCI_table->send_packet)( destination, the_packet );
[ac7d5ef0]290}
291
[3a4ae6c]292MP_packet_Prefix  *_MPCI_Receive_packet ( void )
[ac7d5ef0]293{
[3a4ae6c]294  MP_packet_Prefix  *the_packet;
[ac7d5ef0]295
[3a4ae6c]296  (*_MPCI_table->receive_packet)( &the_packet );
[ac7d5ef0]297
298  return the_packet;
299}
300
301Thread_Control *_MPCI_Process_response (
[3a4ae6c]302  MP_packet_Prefix  *the_packet
[ac7d5ef0]303)
304{
[b30ab25]305  ISR_lock_Context  lock_context;
306  Thread_Control   *the_thread;
307
[e266d13]308  the_thread = _Thread_Get( the_packet->id, &lock_context );
[b30ab25]309  _Assert( the_thread != NULL );
[ac7d5ef0]310
[b30ab25]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;
[ac7d5ef0]321  return the_thread;
322}
323
[64adc13]324/*
[3a4ae6c]325 *  _MPCI_Receive_server
326 *
327 */
328
[885c342e]329void _MPCI_Receive_server(
330  Thread_Entry_numeric_type ignored
[adf98bd]331)
[3a4ae6c]332{
[05279b84]333
[631b3c8]334  MP_packet_Prefix      *the_packet;
335  MPCI_Packet_processor  the_function;
336  Thread_Control        *executing;
337  Thread_queue_Context   queue_context;
[05279b84]338
[e36f2b8]339  executing = _Thread_Get_executing();
[0e1d11f3]340  _Thread_queue_Context_initialize( &queue_context );
[3da2f471]341  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
[3a4ae6c]342
343  for ( ; ; ) {
[05279b84]344
[3a4ae6c]345    executing->receive_packet = NULL;
346
[e41308ea]347    _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
[e36f2b8]348    _CORE_semaphore_Seize(
349      &_MPCI_Semaphore,
[2581a56]350      MPCI_SEMAPHORE_TQ_OPERATIONS,
[e36f2b8]351      executing,
352      true,
[631b3c8]353      &queue_context
[e36f2b8]354    );
[05279b84]355
[3a4ae6c]356    for ( ; ; ) {
[a62c3aa3]357      executing->receive_packet = NULL;
358
[3a4ae6c]359      the_packet = _MPCI_Receive_packet();
[05279b84]360
[3a4ae6c]361      if ( !the_packet )
362        break;
[05279b84]363
[3a4ae6c]364      executing->receive_packet = the_packet;
[05279b84]365
[3a4ae6c]366      if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
367        break;
[05279b84]368
[3a4ae6c]369      the_function = _MPCI_Packet_processors[ the_packet->the_class ];
[05279b84]370
[3a4ae6c]371      if ( !the_function )
[3a659b04]372        _Internal_error( INTERNAL_ERROR_BAD_PACKET );
[05279b84]373
[885c342e]374       (*the_function)( the_packet );
[3a4ae6c]375    }
376  }
377}
378
379void _MPCI_Announce ( void )
380{
[631b3c8]381  Thread_queue_Context queue_context;
[e76c517]382
[e41308ea]383  _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
[2581a56]384  (void) _CORE_semaphore_Surrender(
385    &_MPCI_Semaphore,
386    MPCI_SEMAPHORE_TQ_OPERATIONS,
387    UINT32_MAX,
388    &queue_context
389  );
[3a4ae6c]390}
391
[adf98bd]392void _MPCI_Internal_packets_Send_process_packet (
393   MPCI_Internal_Remote_operations operation
394)
395{
396  MPCI_Internal_packet *the_packet;
[05279b84]397
[adf98bd]398  switch ( operation ) {
[05279b84]399
[adf98bd]400    case MPCI_PACKETS_SYSTEM_VERIFY:
[05279b84]401
[adf98bd]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;
[05279b84]407
[adf98bd]408      the_packet->maximum_nodes = _Objects_Maximum_nodes;
[05279b84]409
[adf98bd]410      the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
[05279b84]411
[adf98bd]412      _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
413      break;
414  }
415}
[05279b84]416
[64adc13]417/*
[adf98bd]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 */
[05279b84]424
[64adc13]425/*
[adf98bd]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 */
[05279b84]432
[adf98bd]433void _MPCI_Internal_packets_Process_packet (
434  MP_packet_Prefix  *the_packet_prefix
435)
436{
437  MPCI_Internal_packet *the_packet;
[3127180]438  uint32_t                    maximum_nodes;
439  uint32_t                    maximum_global_objects;
[05279b84]440
[adf98bd]441  the_packet = (MPCI_Internal_packet *) the_packet_prefix;
[05279b84]442
[adf98bd]443  switch ( the_packet->operation ) {
[05279b84]444
[adf98bd]445    case MPCI_PACKETS_SYSTEM_VERIFY:
[05279b84]446
[adf98bd]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 ) {
[05279b84]451
[adf98bd]452        _MPCI_Return_packet( the_packet_prefix );
[05279b84]453
[3a659b04]454        _Internal_error( INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION );
[adf98bd]455      }
[05279b84]456
[adf98bd]457      _MPCI_Return_packet( the_packet_prefix );
[05279b84]458
[adf98bd]459      break;
460  }
461}
[05279b84]462
[64adc13]463/*
[adf98bd]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 */
[05279b84]470
[64adc13]471/*
[adf98bd]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 */
[05279b84]478
[adf98bd]479MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
480{
481  return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
482}
483
[8ca372e]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
[ac7d5ef0]516/* end of file */
Note: See TracBrowser for help on using the repository browser.