source: rtems/cpukit/score/src/mpci.c @ 0e1d11f3

5
Last change on this file since 0e1d11f3 was 0e1d11f3, checked in by Sebastian Huber <sebastian.huber@…>, on 05/27/16 at 11:26:53

score: Add _Thread_queue_Context_set_MP_callout()

Add _Thread_queue_Context_set_MP_callout() to simplify
_Thread_queue_Context_initialize(). This makes it possible to more
easily add additional fields to Thread_queue_Context.

  • Property mode set to 100644
File size: 12.0 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  ISR_lock_Context lock_context;
138  Objects_Name     name;
139
140
141  if ( !_System_state_Is_multiprocessing )
142    return;
143
144  /*
145   *  Initialize the MPCI Receive Server
146   */
147
148  _MPCI_Receive_server_tcb = _Thread_Internal_allocate();
149
150  name.name_u32 = _Objects_Build_name( 'M', 'P', 'C', 'I' );
151  _Thread_Initialize(
152    &_Thread_Internal_information,
153    _MPCI_Receive_server_tcb,
154    _Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() ),
155    NULL,        /* allocate the stack */
156    _Stack_Minimum() +
157      CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK +
158      _Configuration_MP_table->extra_mpci_receive_server_stack,
159    CPU_ALL_TASKS_ARE_FP,
160    PRIORITY_PSEUDO_ISR,
161    false,       /* no preempt */
162    THREAD_CPU_BUDGET_ALGORITHM_NONE,
163    NULL,        /* no budget algorithm callout */
164    0,           /* all interrupts enabled */
165    name
166  );
167
168  _ISR_lock_ISR_disable( &lock_context );
169  _Thread_Start( _MPCI_Receive_server_tcb, &entry, &lock_context );
170}
171
172static void _MPCI_Initialization( void )
173{
174  (*_MPCI_table->initialization)();
175}
176
177void _MPCI_Register_packet_processor(
178  MP_packet_Classes      the_class,
179  MPCI_Packet_processor  the_packet_processor
180
181)
182{
183  _MPCI_Packet_processors[ the_class ] = the_packet_processor;
184}
185
186MP_packet_Prefix *_MPCI_Get_packet ( void )
187{
188  MP_packet_Prefix  *the_packet;
189
190  (*_MPCI_table->get_packet)( &the_packet );
191
192  if ( the_packet == NULL )
193    _Terminate(
194      INTERNAL_ERROR_CORE,
195      true,
196      INTERNAL_ERROR_OUT_OF_PACKETS
197    );
198
199  /*
200   *  Put in a default timeout that will be used for
201   *  all packets that do not otherwise have a timeout.
202   */
203
204  the_packet->timeout = MPCI_DEFAULT_TIMEOUT;
205
206  return the_packet;
207}
208
209void _MPCI_Return_packet (
210  MP_packet_Prefix   *the_packet
211)
212{
213  (*_MPCI_table->return_packet)( the_packet );
214}
215
216void _MPCI_Send_process_packet (
217  uint32_t            destination,
218  MP_packet_Prefix   *the_packet
219)
220{
221  the_packet->source_tid = _Thread_Executing->Object.id;
222  the_packet->to_convert =
223     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
224
225  (*_MPCI_table->send_packet)( destination, the_packet );
226}
227
228Status_Control _MPCI_Send_request_packet(
229  uint32_t          destination,
230  MP_packet_Prefix *the_packet,
231  States_Control    extra_state
232)
233{
234  Per_CPU_Control *cpu_self;
235  Thread_Control  *executing;
236
237  cpu_self = _Thread_Dispatch_disable();
238
239    executing = _Per_CPU_Get_executing( cpu_self );
240
241    the_packet->source_tid      = executing->Object.id;
242    the_packet->source_priority = executing->current_priority;
243    the_packet->to_convert =
244       ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
245
246    executing->Wait.remote_id = the_packet->id;
247
248    (*_MPCI_table->send_packet)( destination, the_packet );
249
250    /*
251     *  See if we need a default timeout
252     */
253
254    if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
255        the_packet->timeout = _MPCI_table->default_timeout;
256
257    _Thread_queue_Enqueue(
258      &_MPCI_Remote_blocked_threads,
259      &_Thread_queue_Operations_FIFO,
260      executing,
261      STATES_WAITING_FOR_RPC_REPLY | extra_state,
262      the_packet->timeout
263    );
264
265  _Thread_Dispatch_enable( cpu_self );
266
267  return _Thread_Wait_get_status( executing );
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  ISR_lock_Context  lock_context;
294  Thread_Control   *the_thread;
295
296  the_thread = _Thread_Get( the_packet->id, &lock_context );
297  _Assert( the_thread != NULL );
298
299  /*
300   * FIXME: This is broken on SMP, see https://devel.rtems.org/ticket/2703.
301   *
302   * Should use _Thread_queue_Extract_critical() instead with a handler
303   * function provided by the caller of _MPCI_Process_response().  Similar to
304   * the filter function in _Thread_queue_Flush_critical().
305   */
306  _ISR_lock_ISR_enable( &lock_context );
307  _Thread_queue_Extract( the_thread );
308  the_thread->Wait.return_code = the_packet->return_code;
309  return the_thread;
310}
311
312/*
313 *  _MPCI_Receive_server
314 *
315 */
316
317void _MPCI_Receive_server(
318  Thread_Entry_numeric_type ignored
319)
320{
321
322  MP_packet_Prefix      *the_packet;
323  MPCI_Packet_processor  the_function;
324  Thread_Control        *executing;
325  Thread_queue_Context   queue_context;
326
327  executing = _Thread_Get_executing();
328  _Thread_queue_Context_initialize( &queue_context );
329
330  for ( ; ; ) {
331
332    executing->receive_packet = NULL;
333
334    _ISR_lock_ISR_disable( &queue_context.Lock_context );
335    _CORE_semaphore_Seize(
336      &_MPCI_Semaphore,
337      executing,
338      true,
339      WATCHDOG_NO_TIMEOUT,
340      &queue_context
341    );
342
343    for ( ; ; ) {
344      executing->receive_packet = NULL;
345
346      the_packet = _MPCI_Receive_packet();
347
348      if ( !the_packet )
349        break;
350
351      executing->receive_packet = the_packet;
352
353      if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
354        break;
355
356      the_function = _MPCI_Packet_processors[ the_packet->the_class ];
357
358      if ( !the_function )
359        _Terminate(
360          INTERNAL_ERROR_CORE,
361          true,
362          INTERNAL_ERROR_BAD_PACKET
363        );
364
365       (*the_function)( the_packet );
366    }
367  }
368}
369
370void _MPCI_Announce ( void )
371{
372  Thread_queue_Context queue_context;
373
374  _ISR_lock_ISR_disable( &queue_context.Lock_context );
375  (void) _CORE_semaphore_Surrender( &_MPCI_Semaphore, UINT32_MAX, &queue_context );
376}
377
378void _MPCI_Internal_packets_Send_process_packet (
379   MPCI_Internal_Remote_operations operation
380)
381{
382  MPCI_Internal_packet *the_packet;
383
384  switch ( operation ) {
385
386    case MPCI_PACKETS_SYSTEM_VERIFY:
387
388      the_packet                    = _MPCI_Internal_packets_Get_packet();
389      the_packet->Prefix.the_class  = MP_PACKET_MPCI_INTERNAL;
390      the_packet->Prefix.length     = sizeof ( MPCI_Internal_packet );
391      the_packet->Prefix.to_convert = sizeof ( MPCI_Internal_packet );
392      the_packet->operation         = operation;
393
394      the_packet->maximum_nodes = _Objects_Maximum_nodes;
395
396      the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
397
398      _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
399      break;
400  }
401}
402
403/*
404 *  _MPCI_Internal_packets_Send_request_packet
405 *
406 *  This subprogram is not needed since there are no request
407 *  packets to be sent by this manager.
408 *
409 */
410
411/*
412 *  _MPCI_Internal_packets_Send_response_packet
413 *
414 *  This subprogram is not needed since there are no response
415 *  packets to be sent by this manager.
416 *
417 */
418
419void _MPCI_Internal_packets_Process_packet (
420  MP_packet_Prefix  *the_packet_prefix
421)
422{
423  MPCI_Internal_packet *the_packet;
424  uint32_t                    maximum_nodes;
425  uint32_t                    maximum_global_objects;
426
427  the_packet = (MPCI_Internal_packet *) the_packet_prefix;
428
429  switch ( the_packet->operation ) {
430
431    case MPCI_PACKETS_SYSTEM_VERIFY:
432
433      maximum_nodes          = the_packet->maximum_nodes;
434      maximum_global_objects = the_packet->maximum_global_objects;
435      if ( maximum_nodes != _Objects_Maximum_nodes ||
436           maximum_global_objects != _Objects_MP_Maximum_global_objects ) {
437
438        _MPCI_Return_packet( the_packet_prefix );
439
440        _Terminate(
441          INTERNAL_ERROR_CORE,
442          true,
443          INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION
444        );
445      }
446
447      _MPCI_Return_packet( the_packet_prefix );
448
449      break;
450  }
451}
452
453/*
454 *  _MPCI_Internal_packets_Send_object_was_deleted
455 *
456 *  This subprogram is not needed since there are no objects
457 *  deleted by this manager.
458 *
459 */
460
461/*
462 *  _MPCI_Internal_packets_Send_extract_proxy
463 *
464 *  This subprogram is not needed since there are no objects
465 *  deleted by this manager.
466 *
467 */
468
469MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
470{
471  return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
472}
473
474static void _MPCI_Finalize( void )
475{
476  if ( _System_state_Is_multiprocessing ) {
477    _MPCI_Initialization();
478    _MPCI_Internal_packets_Send_process_packet( MPCI_PACKETS_SYSTEM_VERIFY );
479  }
480}
481
482RTEMS_SYSINIT_ITEM(
483  _MPCI_Handler_early_initialization,
484  RTEMS_SYSINIT_MP_EARLY,
485  RTEMS_SYSINIT_ORDER_MIDDLE
486);
487
488RTEMS_SYSINIT_ITEM(
489  _MPCI_Handler_initialization,
490  RTEMS_SYSINIT_MP,
491  RTEMS_SYSINIT_ORDER_MIDDLE
492);
493
494RTEMS_SYSINIT_ITEM(
495  _MPCI_Create_server,
496  RTEMS_SYSINIT_MP_SERVER,
497  RTEMS_SYSINIT_ORDER_MIDDLE
498);
499
500RTEMS_SYSINIT_ITEM(
501  _MPCI_Finalize,
502  RTEMS_SYSINIT_MP_FINALIZE,
503  RTEMS_SYSINIT_ORDER_MIDDLE
504);
505
506/* end of file */
Note: See TracBrowser for help on using the repository browser.