source: rtems/cpukit/rtems/src/schedulerremoveprocessor.c @ 05ca53d

5
Last change on this file since 05ca53d was 05ca53d, checked in by Sebastian Huber <sebastian.huber@…>, on 10/31/16 at 12:08:33

rtems: Add scheduler processor add/remove

Update #2797.

  • Property mode set to 100644
File size: 4.2 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_Wait_acquire( the_thread, &queue_context );
45  _Thread_State_acquire_critical( the_thread, &state_context );
46
47  if ( _Thread_Scheduler_get_home( the_thread ) == iter_context->scheduler ) {
48    iter_context->status = RTEMS_RESOURCE_IN_USE;
49  }
50
51  _Thread_State_release_critical( the_thread, &state_context );
52  _Thread_Wait_release( the_thread, &queue_context );
53  return iter_context->status != RTEMS_SUCCESSFUL;
54}
55#endif
56
57rtems_status_code rtems_scheduler_remove_processor(
58  rtems_id scheduler_id,
59  uint32_t cpu_index
60)
61{
62  const Scheduler_Control             *scheduler;
63#if defined(RTEMS_SMP)
64  uint32_t                             processor_count;
65  Scheduler_Processor_removal_context  iter_context;
66  ISR_lock_Context                     lock_context;
67  Scheduler_Context                   *scheduler_context;
68  Per_CPU_Control                     *cpu;
69  Per_CPU_Control                     *cpu_self;
70#endif
71
72  scheduler = _Scheduler_Get_by_id( scheduler_id );
73  if ( scheduler == NULL ) {
74    return RTEMS_INVALID_ID;
75  }
76
77  if ( cpu_index >= rtems_configuration_get_maximum_processors() ) {
78    return RTEMS_INVALID_NUMBER;
79  }
80
81#if defined(RTEMS_SMP)
82  iter_context.scheduler = scheduler;
83  iter_context.status = RTEMS_SUCCESSFUL;
84  scheduler_context = _Scheduler_Get_context( scheduler );
85  cpu = _Per_CPU_Get_by_index( cpu_index );
86
87  _Objects_Allocator_lock();
88
89  if ( cpu->Scheduler.control != scheduler ) {
90    _Objects_Allocator_unlock();
91    return RTEMS_INVALID_NUMBER;
92  }
93
94  /*
95   * This prevents the selection of this scheduler instance by new threads in
96   * case the processor count changes to zero.
97   */
98  _ISR_lock_ISR_disable( &lock_context );
99  _Scheduler_Acquire_critical( scheduler, &lock_context );
100  processor_count = scheduler_context->processor_count - 1;
101  scheduler_context->processor_count = processor_count;
102  _Scheduler_Release_critical( scheduler, &lock_context );
103  _ISR_lock_ISR_enable( &lock_context );
104
105  if ( processor_count == 0 ) {
106    _Thread_Iterate( _Scheduler_Check_processor_removal, &iter_context );
107  }
108
109  _ISR_lock_ISR_disable( &lock_context );
110  _Scheduler_Acquire_critical( scheduler, &lock_context );
111
112  if ( iter_context.status == RTEMS_SUCCESSFUL ) {
113    Thread_Control *idle;
114    Scheduler_Node *scheduler_node;
115
116    cpu->Scheduler.control = NULL;
117    cpu->Scheduler.context = NULL;
118    idle = ( *scheduler->Operations.remove_processor )( scheduler, cpu );
119    cpu->Scheduler.idle_if_online_and_unused = idle;
120
121    scheduler_node = _Thread_Scheduler_get_home_node( idle );
122    _Priority_Plain_extract(
123      &scheduler_node->Wait.Priority,
124      &idle->Real_priority
125    );
126    _Assert( _Priority_Is_empty( &scheduler_node->Wait.Priority ) );
127    _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node );
128    _Assert( _Chain_Is_empty( &idle->Scheduler.Wait_nodes ) );
129    _Chain_Extract_unprotected( &scheduler_node->Thread.Scheduler_node.Chain );
130    _Assert( _Chain_Is_empty( &idle->Scheduler.Scheduler_nodes ) );
131  } else {
132    ++scheduler_context->processor_count;
133  }
134
135  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
136  _Scheduler_Release_critical( scheduler, &lock_context );
137  _ISR_lock_ISR_enable( &lock_context );
138  _Thread_Dispatch_enable( cpu_self );
139  _Objects_Allocator_unlock();
140  return iter_context.status;
141#else
142  return RTEMS_RESOURCE_IN_USE;
143#endif
144}
Note: See TracBrowser for help on using the repository browser.