source: rtems/cpukit/score/src/mpci.c @ 469dc47

5
Last change on this file since 469dc47 was 97312fcc, checked in by Sebastian Huber <sebastian.huber@…>, on 04/05/16 at 12:36:30

score: Delete Thread_Wait_information::id

This field was only by the monitor in non-multiprocessing
configurations. Add new field Thread_Wait_information::remote_id in
multiprocessing configurations and use it for the remote procedure call
thread queue.

Add _Thread_Wait_get_id() to obtain the object identifier for debug and
system information tools. Ensure the object layout via static asserts.
Add test cases to sptests/spthreadq01.

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