source: rtems/cpukit/rtems/src/schedulerremoveprocessor.c @ 7851555

5
Last change on this file since 7851555 was 7da78cf, checked in by Sebastian Huber <sebastian.huber@…>, on 12/02/16 at 10:51:16

rtems: Use _Thread_Dispatch_direct()

Update #2797.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/rtems/tasks.h>
20#include <rtems/score/schedulerimpl.h>
21#include <rtems/config.h>
22
23#if defined(RTEMS_SMP)
24typedef struct {
25  const Scheduler_Control *scheduler;
26  rtems_status_code        status;
27} Scheduler_Processor_removal_context;
28
29static bool _Scheduler_Check_processor_removal(
30  Thread_Control *the_thread,
31  void           *arg
32)
33{
34  Scheduler_Processor_removal_context *iter_context;
35  Thread_queue_Context                 queue_context;
36  ISR_lock_Context                     state_context;
37
38  if ( the_thread->is_idle ) {
39    return false;
40  }
41
42  iter_context = arg;
43
44  _Thread_queue_Context_initialize( &queue_context );
45  _Thread_Wait_acquire( the_thread, &queue_context );
46  _Thread_State_acquire_critical( the_thread, &state_context );
47
48  if ( _Thread_Scheduler_get_home( the_thread ) == iter_context->scheduler ) {
49    iter_context->status = RTEMS_RESOURCE_IN_USE;
50  }
51
52  _Thread_State_release_critical( the_thread, &state_context );
53  _Thread_Wait_release( the_thread, &queue_context );
54  return iter_context->status != RTEMS_SUCCESSFUL;
55}
56#endif
57
58rtems_status_code rtems_scheduler_remove_processor(
59  rtems_id scheduler_id,
60  uint32_t cpu_index
61)
62{
63  const Scheduler_Control             *scheduler;
64#if defined(RTEMS_SMP)
65  uint32_t                             processor_count;
66  Scheduler_Processor_removal_context  iter_context;
67  ISR_lock_Context                     lock_context;
68  Scheduler_Context                   *scheduler_context;
69  Per_CPU_Control                     *cpu;
70  Per_CPU_Control                     *cpu_self;
71#endif
72
73  scheduler = _Scheduler_Get_by_id( scheduler_id );
74  if ( scheduler == NULL ) {
75    return RTEMS_INVALID_ID;
76  }
77
78  if ( cpu_index >= rtems_configuration_get_maximum_processors() ) {
79    return RTEMS_INVALID_NUMBER;
80  }
81
82#if defined(RTEMS_SMP)
83  iter_context.scheduler = scheduler;
84  iter_context.status = RTEMS_SUCCESSFUL;
85  scheduler_context = _Scheduler_Get_context( scheduler );
86  cpu = _Per_CPU_Get_by_index( cpu_index );
87
88  _Objects_Allocator_lock();
89
90  if ( cpu->Scheduler.control != scheduler ) {
91    _Objects_Allocator_unlock();
92    return RTEMS_INVALID_NUMBER;
93  }
94
95  /*
96   * This prevents the selection of this scheduler instance by new threads in
97   * case the processor count changes to zero.
98   */
99  _ISR_lock_ISR_disable( &lock_context );
100  _Scheduler_Acquire_critical( scheduler, &lock_context );
101  processor_count = scheduler_context->processor_count - 1;
102  scheduler_context->processor_count = processor_count;
103  _Scheduler_Release_critical( scheduler, &lock_context );
104  _ISR_lock_ISR_enable( &lock_context );
105
106  if ( processor_count == 0 ) {
107    _Thread_Iterate( _Scheduler_Check_processor_removal, &iter_context );
108  }
109
110  _ISR_lock_ISR_disable( &lock_context );
111  _Scheduler_Acquire_critical( scheduler, &lock_context );
112
113  if ( iter_context.status == RTEMS_SUCCESSFUL ) {
114    Thread_Control *idle;
115    Scheduler_Node *scheduler_node;
116
117    cpu->Scheduler.control = NULL;
118    cpu->Scheduler.context = NULL;
119    idle = ( *scheduler->Operations.remove_processor )( scheduler, cpu );
120    cpu->Scheduler.idle_if_online_and_unused = idle;
121
122    scheduler_node = _Thread_Scheduler_get_home_node( idle );
123    _Priority_Plain_extract(
124      &scheduler_node->Wait.Priority,
125      &idle->Real_priority
126    );
127    _Assert( _Priority_Is_empty( &scheduler_node->Wait.Priority ) );
128    _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node );
129    _Assert( _Chain_Is_empty( &idle->Scheduler.Wait_nodes ) );
130    _Chain_Extract_unprotected( &scheduler_node->Thread.Scheduler_node.Chain );
131    _Assert( _Chain_Is_empty( &idle->Scheduler.Scheduler_nodes ) );
132  } else {
133    ++scheduler_context->processor_count;
134  }
135
136  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
137  _Scheduler_Release_critical( scheduler, &lock_context );
138  _ISR_lock_ISR_enable( &lock_context );
139  _Thread_Dispatch_direct( cpu_self );
140  _Objects_Allocator_unlock();
141  return iter_context.status;
142#else
143  return RTEMS_RESOURCE_IN_USE;
144#endif
145}
Note: See TracBrowser for help on using the repository browser.