source: rtems/cpukit/score/src/smpmulticastaction.c @ 0daa8ab

5
Last change on this file since 0daa8ab was 76d1198, checked in by Sebastian Huber <sebastian.huber@…>, on 07/07/17 at 05:45:57

score: Introduce _SMP_Get_online_processors()

Update #3059.

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/*
2 * Copyright (c) 2014 Aeroflex Gaisler AB.  All rights reserved.
3 *
4 * The license and distribution terms for this file may be
5 * found in the file LICENSE in this distribution or at
6 * http://www.rtems.org/license/LICENSE.
7 */
8
9#ifdef HAVE_CONFIG_H
10  #include "config.h"
11#endif
12
13#include <rtems/score/smpimpl.h>
14#include <rtems/score/smplock.h>
15#include <rtems/score/chainimpl.h>
16#include <rtems/score/sysstate.h>
17
18typedef struct {
19  Chain_Node          Node;
20  SMP_Action_handler  handler;
21  void               *arg;
22  Processor_mask      targets;
23  Atomic_Ulong        done;
24} SMP_Multicast_action;
25
26typedef struct {
27  SMP_lock_Control Lock;
28  Chain_Control    Actions;
29} SMP_Multicast_context;
30
31static SMP_Multicast_context _SMP_Multicast = {
32  .Lock = SMP_LOCK_INITIALIZER( "SMP Multicast Action" ),
33  .Actions = CHAIN_INITIALIZER_EMPTY( _SMP_Multicast.Actions )
34};
35
36void _SMP_Multicast_actions_process( void )
37{
38  SMP_lock_Context      lock_context;
39  uint32_t              cpu_self_index;
40  SMP_Multicast_action *node;
41  SMP_Multicast_action *next;
42
43  _SMP_lock_ISR_disable_and_acquire( &_SMP_Multicast.Lock, &lock_context );
44  cpu_self_index = _SMP_Get_current_processor();
45  node = (SMP_Multicast_action *) _Chain_First( &_SMP_Multicast.Actions );
46
47  while ( !_Chain_Is_tail( &_SMP_Multicast.Actions, &node->Node ) ) {
48    next = (SMP_Multicast_action *) _Chain_Next( &node->Node );
49
50    if ( _Processor_mask_Is_set( &node->targets, cpu_self_index ) ) {
51      _Processor_mask_Clear( &node->targets, cpu_self_index );
52
53      ( *node->handler )( node->arg );
54
55      if ( _Processor_mask_Is_zero( &node->targets ) ) {
56        _Chain_Extract_unprotected( &node->Node );
57        _Atomic_Store_ulong( &node->done, 1, ATOMIC_ORDER_RELEASE );
58      }
59    }
60
61    node = next;
62  }
63
64  _SMP_lock_Release_and_ISR_enable( &_SMP_Multicast.Lock, &lock_context );
65}
66
67static void
68_SMP_Multicasts_try_process( void )
69{
70  unsigned long message;
71  Per_CPU_Control *cpu_self;
72  ISR_Level isr_level;
73
74  _ISR_Local_disable( isr_level );
75
76  cpu_self = _Per_CPU_Get();
77
78  message = _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED );
79
80  if ( message & SMP_MESSAGE_MULTICAST_ACTION ) {
81    if ( _Atomic_Compare_exchange_ulong( &cpu_self->message, &message,
82        message & ~SMP_MESSAGE_MULTICAST_ACTION, ATOMIC_ORDER_RELAXED,
83        ATOMIC_ORDER_RELAXED ) ) {
84      _SMP_Multicast_actions_process();
85    }
86  }
87
88  _ISR_Local_enable( isr_level );
89}
90
91void _SMP_Multicast_action(
92  const size_t setsize,
93  const cpu_set_t *cpus,
94  SMP_Action_handler handler,
95  void *arg
96)
97{
98  SMP_Multicast_action node;
99  Processor_mask       targets;
100  SMP_lock_Context     lock_context;
101  uint32_t             i;
102
103  if ( ! _System_state_Is_up( _System_state_Get() ) ) {
104    ( *handler )( arg );
105    return;
106  }
107
108  if( cpus == NULL ) {
109    _Processor_mask_Assign( &targets, _SMP_Get_online_processors() );
110  } else {
111    _Processor_mask_Zero( &targets );
112
113    for ( i = 0; i < _SMP_Get_processor_count(); ++i ) {
114      if ( CPU_ISSET_S( i, setsize, cpus ) ) {
115        _Processor_mask_Set( &targets, i );
116      }
117    }
118  }
119
120  _Chain_Initialize_node( &node.Node );
121  node.handler = handler;
122  node.arg = arg;
123  _Processor_mask_Assign( &node.targets, &targets );
124  _Atomic_Store_ulong( &node.done, 0, ATOMIC_ORDER_RELAXED );
125
126  _SMP_lock_ISR_disable_and_acquire( &_SMP_Multicast.Lock, &lock_context );
127  _Chain_Prepend_unprotected( &_SMP_Multicast.Actions, &node.Node );
128  _SMP_lock_Release_and_ISR_enable( &_SMP_Multicast.Lock, &lock_context );
129
130  _SMP_Send_message_multicast( &targets, SMP_MESSAGE_MULTICAST_ACTION );
131  _SMP_Multicasts_try_process();
132
133  while ( _Atomic_Load_ulong( &node.done, ATOMIC_ORDER_ACQUIRE ) == 0 ) {
134    /* Wait */
135  };
136}
Note: See TracBrowser for help on using the repository browser.