source: rtems/cpukit/score/src/smpmulticastaction.c @ 7f616dd

5
Last change on this file since 7f616dd was 7f616dd, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 25, 2016 at 12:45:50 PM

score: Fix for RTEMS_DEBUG

  • Property mode set to 100644
File size: 3.9 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  cpu_set_t *recipients;
23  size_t setsize;
24  Atomic_Ulong done;
25} SMP_Multicast_action;
26
27typedef struct {
28  SMP_lock_Control Lock;
29  Chain_Control List;
30} SMP_Multicast_action_context;
31
32static SMP_Multicast_action_context _SMP_Multicast_action_context = {
33  .Lock = SMP_LOCK_INITIALIZER("SMP Multicast Action"),
34  .List = CHAIN_INITIALIZER_EMPTY(_SMP_Multicast_action_context.List)
35};
36
37void
38_SMP_Multicast_actions_process(void)
39{
40  SMP_lock_Context lock_context;
41  SMP_Multicast_action *node;
42  SMP_Multicast_action *next;
43  uint32_t cpu_self_idx;
44
45  _SMP_lock_ISR_disable_and_acquire( &_SMP_Multicast_action_context.Lock,
46      &lock_context );
47  cpu_self_idx = _SMP_Get_current_processor();
48
49  node = (SMP_Multicast_action*)_Chain_First(
50      &_SMP_Multicast_action_context.List );
51  while ( !_Chain_Is_tail( &_SMP_Multicast_action_context.List, &node->Node ) ) {
52    next = (SMP_Multicast_action*)_Chain_Next( &node->Node );
53    if ( CPU_ISSET_S ( cpu_self_idx, node->setsize, node->recipients ) ) {
54      CPU_CLR_S ( cpu_self_idx, node->setsize, node->recipients );
55
56      node->handler( node->arg );
57
58      if ( CPU_COUNT_S( node->setsize, node->recipients ) == 0 ) {
59        _Chain_Extract_unprotected( &node->Node );
60        _Atomic_Store_ulong( &node->done, 1, ATOMIC_ORDER_RELEASE );
61      }
62    }
63    node = next;
64  }
65
66  _SMP_lock_Release_and_ISR_enable( &_SMP_Multicast_action_context.Lock,
67      &lock_context );
68}
69
70static void
71_SMP_Multicast_actions_try_process( void )
72{
73  unsigned long message;
74  Per_CPU_Control *cpu_self;
75  ISR_Level isr_level;
76
77  _ISR_Local_disable( isr_level );
78
79  cpu_self = _Per_CPU_Get();
80
81  message = _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED );
82
83  if ( message & SMP_MESSAGE_MULTICAST_ACTION ) {
84    if ( _Atomic_Compare_exchange_ulong( &cpu_self->message, &message,
85        message & ~SMP_MESSAGE_MULTICAST_ACTION, ATOMIC_ORDER_RELAXED,
86        ATOMIC_ORDER_RELAXED ) ) {
87      _SMP_Multicast_actions_process();
88    }
89  }
90
91  _ISR_Local_enable( isr_level );
92}
93
94void _SMP_Multicast_action(
95  const size_t setsize,
96  const cpu_set_t *cpus,
97  SMP_Action_handler handler,
98  void *arg
99)
100{
101  uint32_t i;
102  SMP_Multicast_action node;
103  size_t set_size = CPU_ALLOC_SIZE( _SMP_Get_processor_count() );
104  char cpu_set_copy[set_size];
105  SMP_lock_Context lock_context;
106
107  if ( ! _System_state_Is_up( _System_state_Get() ) ) {
108    handler( arg );
109    return;
110  }
111
112  memset( cpu_set_copy, 0, set_size );
113  if( cpus == NULL ) {
114    for( i=0; i<_SMP_Get_processor_count(); ++i )
115      CPU_SET_S( i, set_size, (cpu_set_t *)cpu_set_copy );
116  } else {
117    for( i=0; i<_SMP_Get_processor_count(); ++i )
118      if( CPU_ISSET_S( i, set_size, cpus ) )
119        CPU_SET_S( i, set_size, (cpu_set_t *)cpu_set_copy );
120  }
121
122  node.handler = handler;
123  node.arg = arg;
124  node.setsize = set_size;
125  node.recipients = (cpu_set_t *)cpu_set_copy;
126  _Atomic_Store_ulong( &node.done, 0, ATOMIC_ORDER_RELAXED );
127
128
129  _SMP_lock_ISR_disable_and_acquire( &_SMP_Multicast_action_context.Lock,
130      &lock_context );
131  _Chain_Initialize_node( &node.Node );
132  _Chain_Prepend_unprotected( &_SMP_Multicast_action_context.List, &node.Node );
133  _SMP_lock_Release_and_ISR_enable( &_SMP_Multicast_action_context.Lock,
134      &lock_context );
135
136  _SMP_Send_message_multicast( set_size, node.recipients,
137      SMP_MESSAGE_MULTICAST_ACTION );
138
139  _SMP_Multicast_actions_try_process();
140
141  while ( !_Atomic_Load_ulong( &node.done, ATOMIC_ORDER_ACQUIRE ) );
142}
Note: See TracBrowser for help on using the repository browser.