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

4.115
Last change on this file since d7c3883 was 28352fae, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/29/09 at 13:51:53

Whitespace removal.

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