source: rtems/cpukit/rtems/src/schedulerremoveprocessor.c @ 6b5f22dc

Last change on this file since 6b5f22dc was 6b5f22dc, checked in by Sebastian Huber <sebastian.huber@…>, on 11/26/20 at 10:45:47

rtems: Canonicalize Doxygen @file comments

Use common phrases for the file brief descriptions.

Update #3706.

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