source: rtems/cpukit/score/src/mpci.c @ d689de0

4.115
Last change on this file since d689de0 was d689de0, checked in by Sebastian Huber <sebastian.huber@…>, on 09/09/11 at 10:57:58

2011-09-09 Sebastian Huber <sebastian.huber@…>

  • score/include/rtems/score/basedefs.h: Typo.
  • score/src/mpci.c, rtems/src/eventmp.c, rtems/src/msgmp.c, rtems/src/partmp.c, rtems/src/regionmp.c, rtems/src/semmp.c, rtems/src/signalmp.c, rtems/src/taskmp.c: Use RTEMS_STATIC_ASSERT() to ensure that the packet size is small enough.
  • Property mode set to 100644
File size: 11.3 KB
Line 
1/*
2 *  Multiprocessing Communications Interface (MPCI) Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-2008.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 */
14
15#if HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/system.h>
20#if defined(RTEMS_MULTIPROCESSING)
21#include <rtems/score/mpci.h>
22#include <rtems/score/mppkt.h>
23#endif
24#include <rtems/config.h>
25#include <rtems/score/cpu.h>
26#include <rtems/score/interr.h>
27#include <rtems/score/states.h>
28#include <rtems/score/thread.h>
29#include <rtems/score/threadq.h>
30#include <rtems/score/tqdata.h>
31#include <rtems/score/watchdog.h>
32#include <rtems/score/sysstate.h>
33
34#include <rtems/score/coresem.h>
35#include <rtems/config.h>
36
37RTEMS_STATIC_ASSERT(
38  sizeof(MPCI_Internal_packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
39  MPCI_Internal_packet
40);
41
42/**
43 *  This is the core semaphore which the MPCI Receive Server blocks on.
44 */
45CORE_semaphore_Control _MPCI_Semaphore;
46
47/*
48 *  _MPCI_Handler_initialization
49 *
50 *  This subprogram performs the initialization necessary for this handler.
51 */
52
53void _MPCI_Handler_initialization(
54  uint32_t   timeout_status
55)
56{
57  CORE_semaphore_Attributes   attributes;
58  MPCI_Control               *users_mpci_table;
59
60  users_mpci_table = _Configuration_MP_table->User_mpci_table;
61
62  if ( _System_state_Is_multiprocessing && !users_mpci_table )
63    _Internal_error_Occurred(
64      INTERNAL_ERROR_CORE,
65      true,
66      INTERNAL_ERROR_NO_MPCI
67    );
68
69  _MPCI_table = users_mpci_table;
70
71  if ( !_System_state_Is_multiprocessing )
72    return;
73
74  /*
75   *  Register the MP Process Packet routine.
76   */
77
78  _MPCI_Register_packet_processor(
79    MP_PACKET_MPCI_INTERNAL,
80    _MPCI_Internal_packets_Process_packet
81  );
82
83  /*
84   *  Create the counting semaphore used by the MPCI Receive Server.
85   */
86
87  attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
88
89  _CORE_semaphore_Initialize(
90    &_MPCI_Semaphore,
91    &attributes,              /* the_semaphore_attributes */
92    0                         /* initial_value */
93  );
94
95  _Thread_queue_Initialize(
96    &_MPCI_Remote_blocked_threads,
97    THREAD_QUEUE_DISCIPLINE_FIFO,
98    STATES_WAITING_FOR_RPC_REPLY,
99    timeout_status
100  );
101}
102
103/*
104 *  _MPCI_Create_server
105 *
106 *  This subprogram creates the MPCI receive server.
107 */
108
109void _MPCI_Create_server( void )
110{
111  Objects_Name name;
112
113
114  if ( !_System_state_Is_multiprocessing )
115    return;
116
117  /*
118   *  Initialize the MPCI Receive Server
119   */
120
121  _MPCI_Receive_server_tcb = _Thread_Internal_allocate();
122
123  name.name_u32 = _Objects_Build_name( 'M', 'P', 'C', 'I' );
124  _Thread_Initialize(
125    &_Thread_Internal_information,
126    _MPCI_Receive_server_tcb,
127    NULL,        /* allocate the stack */
128    _Stack_Minimum() +
129      CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK +
130      _Configuration_MP_table->extra_mpci_receive_server_stack,
131    CPU_ALL_TASKS_ARE_FP,
132    PRIORITY_MINIMUM,
133    false,       /* no preempt */
134    THREAD_CPU_BUDGET_ALGORITHM_NONE,
135    NULL,        /* no budget algorithm callout */
136    0,           /* all interrupts enabled */
137    name
138  );
139
140  _Thread_Start(
141    _MPCI_Receive_server_tcb,
142    THREAD_START_NUMERIC,
143    (void *) _MPCI_Receive_server,
144    NULL,
145    0
146  );
147}
148
149/*
150 *  _MPCI_Initialization
151 *
152 *  This subprogram initializes the MPCI driver by
153 *  invoking the user provided MPCI initialization callout.
154 */
155
156void _MPCI_Initialization ( void )
157{
158  (*_MPCI_table->initialization)();
159}
160
161/*
162 *  _MPCI_Register_packet_processor
163 *
164 *  This routine registers the MPCI packet processor for the
165 *  designated object class.
166 */
167
168void _MPCI_Register_packet_processor(
169  MP_packet_Classes      the_class,
170  MPCI_Packet_processor  the_packet_processor
171
172)
173{
174  _MPCI_Packet_processors[ the_class ] = the_packet_processor;
175}
176
177/*
178 *  _MPCI_Get_packet
179 *
180 *  This subprogram obtains a packet by invoking the user provided
181 *  MPCI get packet callout.
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    _Internal_error_Occurred(
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
207/*
208 *  _MPCI_Return_packet
209 *
210 *  This subprogram returns a packet by invoking the user provided
211 *  MPCI return packet callout.
212 */
213
214void _MPCI_Return_packet (
215  MP_packet_Prefix   *the_packet
216)
217{
218  (*_MPCI_table->return_packet)( the_packet );
219}
220
221/*
222 *  _MPCI_Send_process_packet
223 *
224 *  This subprogram sends a process packet by invoking the user provided
225 *  MPCI send callout.
226 */
227
228void _MPCI_Send_process_packet (
229  uint32_t            destination,
230  MP_packet_Prefix   *the_packet
231)
232{
233  the_packet->source_tid = _Thread_Executing->Object.id;
234  the_packet->to_convert =
235     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
236
237  (*_MPCI_table->send_packet)( destination, the_packet );
238}
239
240/*
241 *  _MPCI_Send_request_packet
242 *
243 *  This subprogram sends a request packet by invoking the user provided
244 *  MPCI send callout.
245 */
246
247uint32_t   _MPCI_Send_request_packet (
248  uint32_t            destination,
249  MP_packet_Prefix   *the_packet,
250  States_Control      extra_state
251)
252{
253  the_packet->source_tid      = _Thread_Executing->Object.id;
254  the_packet->source_priority = _Thread_Executing->current_priority;
255  the_packet->to_convert =
256     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
257
258  _Thread_Executing->Wait.id = the_packet->id;
259
260  _Thread_Executing->Wait.queue = &_MPCI_Remote_blocked_threads;
261
262  _Thread_Disable_dispatch();
263
264    (*_MPCI_table->send_packet)( destination, the_packet );
265
266    _Thread_queue_Enter_critical_section( &_MPCI_Remote_blocked_threads );
267
268    /*
269     *  See if we need a default timeout
270     */
271
272    if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
273        the_packet->timeout = _MPCI_table->default_timeout;
274
275    _Thread_queue_Enqueue( &_MPCI_Remote_blocked_threads, the_packet->timeout );
276
277    _Thread_Executing->current_state =
278      _States_Set( extra_state, _Thread_Executing->current_state );
279
280  _Thread_Enable_dispatch();
281
282  return _Thread_Executing->Wait.return_code;
283}
284
285/*
286 *  _MPCI_Send_response_packet
287 *
288 *  This subprogram sends a response packet by invoking the user provided
289 *  MPCI send callout.
290 */
291
292void _MPCI_Send_response_packet (
293  uint32_t            destination,
294  MP_packet_Prefix   *the_packet
295)
296{
297  the_packet->source_tid = _Thread_Executing->Object.id;
298
299  (*_MPCI_table->send_packet)( destination, the_packet );
300}
301
302/*
303 *  _MPCI_Receive_packet
304 *
305 *  This subprogram receives a packet by invoking the user provided
306 *  MPCI receive callout.
307 */
308
309MP_packet_Prefix  *_MPCI_Receive_packet ( void )
310{
311  MP_packet_Prefix  *the_packet;
312
313  (*_MPCI_table->receive_packet)( &the_packet );
314
315  return the_packet;
316}
317
318/*
319 *  _MPCI_Process_response
320 *
321 *  This subprogram obtains a packet by invoking the user provided
322 *  MPCI get packet callout.
323 */
324
325Thread_Control *_MPCI_Process_response (
326  MP_packet_Prefix  *the_packet
327)
328{
329  Thread_Control    *the_thread;
330  Objects_Locations  location;
331
332  the_thread = _Thread_Get( the_packet->id, &location );
333  switch ( location ) {
334    case OBJECTS_ERROR:
335#if defined(RTEMS_MULTIPROCESSING)
336    case OBJECTS_REMOTE:
337#endif
338      the_thread = NULL;          /* IMPOSSIBLE */
339      break;
340    case OBJECTS_LOCAL:
341      _Thread_queue_Extract( &_MPCI_Remote_blocked_threads, the_thread );
342      the_thread->Wait.return_code = the_packet->return_code;
343      _Thread_Unnest_dispatch();
344    break;
345  }
346
347  return the_thread;
348}
349
350/*
351 *  _MPCI_Receive_server
352 *
353 */
354
355Thread _MPCI_Receive_server(
356  uint32_t   ignored
357)
358{
359
360  MP_packet_Prefix         *the_packet;
361  MPCI_Packet_processor     the_function;
362  Thread_Control           *executing;
363
364  executing = _Thread_Executing;
365
366  for ( ; ; ) {
367
368    executing->receive_packet = NULL;
369
370    _Thread_Disable_dispatch();
371    _CORE_semaphore_Seize( &_MPCI_Semaphore, 0, true, WATCHDOG_NO_TIMEOUT );
372    _Thread_Enable_dispatch();
373
374    for ( ; ; ) {
375      the_packet = _MPCI_Receive_packet();
376
377      if ( !the_packet )
378        break;
379
380      executing->receive_packet = the_packet;
381
382      if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
383        break;
384
385      the_function = _MPCI_Packet_processors[ the_packet->the_class ];
386
387      if ( !the_function )
388        _Internal_error_Occurred(
389          INTERNAL_ERROR_CORE,
390          true,
391          INTERNAL_ERROR_BAD_PACKET
392        );
393
394        (*the_function)( the_packet );
395    }
396  }
397
398  return 0;   /* unreached - only to remove warnings */
399}
400
401/*
402 *  _MPCI_Announce
403 *
404 */
405
406void _MPCI_Announce ( void )
407{
408  _Thread_Disable_dispatch();
409  (void) _CORE_semaphore_Surrender( &_MPCI_Semaphore, 0, 0 );
410  _Thread_Enable_dispatch();
411}
412
413/*
414 *  _MPCI_Internal_packets_Send_process_packet
415 *
416 */
417
418void _MPCI_Internal_packets_Send_process_packet (
419   MPCI_Internal_Remote_operations operation
420)
421{
422  MPCI_Internal_packet *the_packet;
423
424  switch ( operation ) {
425
426    case MPCI_PACKETS_SYSTEM_VERIFY:
427
428      the_packet                    = _MPCI_Internal_packets_Get_packet();
429      the_packet->Prefix.the_class  = MP_PACKET_MPCI_INTERNAL;
430      the_packet->Prefix.length     = sizeof ( MPCI_Internal_packet );
431      the_packet->Prefix.to_convert = sizeof ( MPCI_Internal_packet );
432      the_packet->operation         = operation;
433
434      the_packet->maximum_nodes = _Objects_Maximum_nodes;
435
436      the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
437
438      _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
439      break;
440  }
441}
442
443/*
444 *  _MPCI_Internal_packets_Send_request_packet
445 *
446 *  This subprogram is not needed since there are no request
447 *  packets to be sent by this manager.
448 *
449 */
450
451/*
452 *  _MPCI_Internal_packets_Send_response_packet
453 *
454 *  This subprogram is not needed since there are no response
455 *  packets to be sent by this manager.
456 *
457 */
458
459/*
460 *
461 *  _MPCI_Internal_packets_Process_packet
462 *
463 */
464
465void _MPCI_Internal_packets_Process_packet (
466  MP_packet_Prefix  *the_packet_prefix
467)
468{
469  MPCI_Internal_packet *the_packet;
470  uint32_t                    maximum_nodes;
471  uint32_t                    maximum_global_objects;
472
473  the_packet = (MPCI_Internal_packet *) the_packet_prefix;
474
475  switch ( the_packet->operation ) {
476
477    case MPCI_PACKETS_SYSTEM_VERIFY:
478
479      maximum_nodes          = the_packet->maximum_nodes;
480      maximum_global_objects = the_packet->maximum_global_objects;
481      if ( maximum_nodes != _Objects_Maximum_nodes ||
482           maximum_global_objects != _Objects_MP_Maximum_global_objects ) {
483
484        _MPCI_Return_packet( the_packet_prefix );
485
486        _Internal_error_Occurred(
487          INTERNAL_ERROR_CORE,
488          true,
489          INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION
490        );
491      }
492
493      _MPCI_Return_packet( the_packet_prefix );
494
495      break;
496  }
497}
498
499/*
500 *  _MPCI_Internal_packets_Send_object_was_deleted
501 *
502 *  This subprogram is not needed since there are no objects
503 *  deleted by this manager.
504 *
505 */
506
507/*
508 *  _MPCI_Internal_packets_Send_extract_proxy
509 *
510 *  This subprogram is not needed since there are no objects
511 *  deleted by this manager.
512 *
513 */
514
515/*
516 *  _MPCI_Internal_packets_Get_packet
517 *
518 */
519
520MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
521{
522  return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
523}
524
525/* end of file */
Note: See TracBrowser for help on using the repository browser.