RTEMS
schedulerremoveprocessor.c
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 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #include <rtems/rtems/tasks.h>
21 #include <rtems/config.h>
22 
23 #if defined(RTEMS_SMP)
24 typedef struct {
25  const Scheduler_Control *scheduler;
26  rtems_status_code status;
28 
29 static bool _Scheduler_Check_processor_removal(
30  Thread_Control *the_thread,
31  void *arg
32 )
33 {
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 (
49  _Thread_Scheduler_get_home( the_thread ) == iter_context->scheduler
51  &the_thread->Scheduler.Affinity,
52  _Scheduler_Get_processors( iter_context->scheduler )
53  )
54  ) {
55  iter_context->status = RTEMS_RESOURCE_IN_USE;
56  }
57 
58  _Thread_State_release_critical( the_thread, &state_context );
59  _Thread_Wait_release( the_thread, &queue_context );
60  return iter_context->status != RTEMS_SUCCESSFUL;
61 }
62 #endif
63 
65  rtems_id scheduler_id,
66  uint32_t cpu_index
67 )
68 {
69  const Scheduler_Control *scheduler;
70 #if defined(RTEMS_SMP)
72  ISR_lock_Context lock_context;
73  Scheduler_Context *scheduler_context;
74  Per_CPU_Control *cpu;
75  Per_CPU_Control *cpu_self;
76 #endif
77 
78  scheduler = _Scheduler_Get_by_id( scheduler_id );
79  if ( scheduler == NULL ) {
80  return RTEMS_INVALID_ID;
81  }
82 
83  if ( cpu_index >= rtems_configuration_get_maximum_processors() ) {
84  return RTEMS_INVALID_NUMBER;
85  }
86 
87 #if defined(RTEMS_SMP)
88  iter_context.scheduler = scheduler;
89  iter_context.status = RTEMS_SUCCESSFUL;
90  scheduler_context = _Scheduler_Get_context( scheduler );
91  cpu = _Per_CPU_Get_by_index( cpu_index );
92 
94 
95  if ( cpu->Scheduler.control != scheduler ) {
97  return RTEMS_INVALID_NUMBER;
98  }
99 
100  /*
101  * This prevents the selection of this scheduler instance by new threads in
102  * case the processor count changes to zero.
103  */
104  _ISR_lock_ISR_disable( &lock_context );
105  _Scheduler_Acquire_critical( scheduler, &lock_context );
106  _Processor_mask_Clear( &scheduler_context->Processors, cpu_index );
107  _Scheduler_Release_critical( scheduler, &lock_context );
108  _ISR_lock_ISR_enable( &lock_context );
109 
110  _Thread_Iterate( _Scheduler_Check_processor_removal, &iter_context );
111 
112  _ISR_lock_ISR_disable( &lock_context );
113  _Scheduler_Acquire_critical( scheduler, &lock_context );
114 
115  if ( iter_context.status == RTEMS_SUCCESSFUL ) {
116  Thread_Control *idle;
117  Scheduler_Node *scheduler_node;
118 
119  cpu->Scheduler.control = NULL;
120  cpu->Scheduler.context = NULL;
121  idle = ( *scheduler->Operations.remove_processor )( scheduler, cpu );
122  cpu->Scheduler.idle_if_online_and_unused = idle;
123 
124  scheduler_node = _Thread_Scheduler_get_home_node( idle );
126  &scheduler_node->Wait.Priority,
127  &idle->Real_priority
128  );
129  _Assert( _Priority_Is_empty( &scheduler_node->Wait.Priority ) );
130  _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node );
132  _Chain_Extract_unprotected( &scheduler_node->Thread.Scheduler_node.Chain );
134  } else {
135  _Processor_mask_Set( &scheduler_context->Processors, cpu_index );
136  }
137 
138  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
139  _Scheduler_Release_critical( scheduler, &lock_context );
140  _ISR_lock_ISR_enable( &lock_context );
141  _Thread_Dispatch_direct( cpu_self );
143  return iter_context.status;
144 #else
145  return RTEMS_RESOURCE_IN_USE;
146 #endif
147 }
static __inline__ void _Objects_Allocator_unlock(void)
Unlocks the object allocator mutex.
Definition: objectimpl.h:846
static __inline__ void _Scheduler_Acquire_critical(const Scheduler_Control *scheduler, ISR_lock_Context *lock_context)
Acquires the scheduler instance inside a critical section (interrupts disabled).
Scheduler context.
Definition: scheduler.h:247
Thread queue context for the thread queue methods.
Definition: threadq.h:198
void _Thread_Dispatch_direct(Per_CPU_Control *cpu_self)
Directly do a thread dispatch.
static __inline__ void _Thread_State_release_critical(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Release the lock context in a critical section.
Definition: threadimpl.h:578
static __inline__ void _Thread_State_acquire_critical(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Acquires the lock context in a critical section.
Definition: threadimpl.h:528
static __inline__ const Scheduler_Control * _Thread_Scheduler_get_home(const Thread_Control *the_thread)
Gets the home scheduler of the thread.
Definition: threadimpl.h:1419
struct _Thread_Control * idle_if_online_and_unused
The idle thread for this processor in case it is online and currently not used by a scheduler instanc...
Definition: percpu.h:528
This status code indicates that the object still had resources in use.
Definition: status.h:149
Inlined Routines Associated with the Manipulation of the Scheduler.
static __inline__ void _Thread_queue_Context_initialize(Thread_queue_Context *queue_context)
Initializes a thread queue context.
Definition: threadqimpl.h:152
RTEMS_INLINE_ROUTINE void _Processor_mask_Clear(Processor_mask *mask, uint32_t index)
Clears the specified index bit of the mask.
This header file defines parts of the application configuration information API.
#define _ISR_lock_ISR_enable(_context)
Restores the saved interrupt state of the ISR lock context.
Definition: isrlock.h:416
Thread_Scheduler_control Scheduler
Scheduler related control.
Definition: thread.h:764
const struct Scheduler_Context * context
The scheduler context of the scheduler owning this processor.
Definition: percpu.h:522
This status code indicates that a specified number was invalid.
Definition: status.h:138
static __inline__ void _Priority_Plain_extract(Priority_Aggregation *aggregation, Priority_Node *node)
Extracts the priority node from the aggregation.
Definition: priorityimpl.h:433
struct Scheduler_Node::@19 Thread
Block to register and manage this scheduler node in the thread control block of the owner of this sch...
static __inline__ void _Objects_Allocator_lock(void)
Locks the object allocator mutex.
Definition: objectimpl.h:834
Thread_Control *(* remove_processor)(const Scheduler_Control *scheduler, struct Per_CPU_Control *cpu)
Remove processor operation.
Definition: scheduler.h:186
RTEMS_INLINE_ROUTINE bool _Processor_mask_Has_overlap(const Processor_mask *a, const Processor_mask *b)
Checks if the intersection of the processor sets a and b is non-empty.
Chain_Node Wait_node
Node to add this scheduler node to Thread_Control::Scheduler::Wait_nodes.
Processor_mask Affinity
The thread processor affinity set.
Definition: thread.h:343
This status code indicates successful completion.
Definition: status.h:86
static __inline__ void _Scheduler_Release_critical(const Scheduler_Control *scheduler, ISR_lock_Context *lock_context)
Releases the scheduler instance inside a critical section (interrupts disabled).
static __inline__ Per_CPU_Control * _Thread_Dispatch_disable_critical(const ISR_lock_Context *lock_context)
Disables thread dispatching inside a critical section (interrupts disabled).
rtems_status_code
This enumeration provides status codes for directives of the Classic API.
Definition: status.h:82
Per CPU Core Structure.
Definition: percpu.h:347
static __inline__ Scheduler_Node * _Thread_Scheduler_get_home_node(const Thread_Control *the_thread)
Gets the scheduler&#39;s home node.
Definition: threadimpl.h:1438
static __inline__ void _Thread_Wait_acquire(Thread_Control *the_thread, Thread_queue_Context *queue_context)
Acquires the thread wait default lock and disables interrupts.
Definition: threadimpl.h:1868
Processor_mask Processors
Lock to protect this scheduler instance.
Definition: scheduler.h:257
static __inline__ const Processor_mask * _Scheduler_Get_processors(const Scheduler_Control *scheduler)
Gets the processors of the scheduler.
This header file defines the main parts of the Tasks Manager API.
static __inline__ void _Chain_Extract_unprotected(Chain_Node *the_node)
Extracts this node (unprotected).
Definition: chainimpl.h:558
const struct _Scheduler_Control * control
The scheduler control of the scheduler owning this processor.
Definition: percpu.h:514
void _Thread_Iterate(Thread_Visitor visitor, void *arg)
Calls the visitor with all threads and the given argument until it is done.
Definition: threaditerate.c:21
static __inline__ bool _Priority_Is_empty(const Priority_Aggregation *aggregation)
Checks if the priority aggregation is empty.
Definition: priorityimpl.h:256
Chain_Control Scheduler_nodes
Scheduler nodes immediately available to the schedulers for this thread.
Definition: thread.h:294
struct Scheduler_Node::@20 Wait
Thread wait support block.
This status code indicates that an object identifier was invalid.
Definition: status.h:106
Objects_Id rtems_id
Values of this type identify an RTEMS object.
Definition: types.h:99
rtems_status_code rtems_scheduler_remove_processor(rtems_id scheduler_id, uint32_t cpu_index)
Removes a processor from set of processors owned by the scheduler instance.
Scheduler_Operations Operations
The scheduler operations.
Definition: scheduler.h:273
Scheduler control.
Definition: scheduler.h:264
Scheduler node for per-thread data.
Definition: schedulernode.h:79
static __inline__ Scheduler_Context * _Scheduler_Get_context(const Scheduler_Control *scheduler)
Gets the context of the scheduler.
Definition: schedulerimpl.h:85
#define _ISR_lock_ISR_disable(_context)
Disables interrupts and saves the previous interrupt state in the ISR lock context.
Definition: isrlock.h:392
Chain_Control Wait_nodes
Scheduler nodes immediately available to the thread by its home scheduler and due to thread queue own...
Definition: thread.h:279
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
static __inline__ void _Thread_Wait_release(Thread_Control *the_thread, Thread_queue_Context *queue_context)
Releases the thread wait lock and restores the previous interrupt status.
Definition: threadimpl.h:1929
#define rtems_configuration_get_maximum_processors()
Returns the maximum number of processors which are configured for this application.
Definition: config.h:194
static __inline__ bool _Chain_Is_empty(const Chain_Control *the_chain)
Checks if the chain is empty.
Definition: chainimpl.h:393
Priority_Node Real_priority
The base priority of this thread in its home scheduler instance.
Definition: thread.h:754
union Scheduler_Node::@19::@22 Scheduler_node
Node to add this scheduler node to Thread_Control::Scheduler::Scheduler_nodes or a temporary remove l...
static __inline__ const Scheduler_Control * _Scheduler_Get_by_id(Objects_Id id)
Gets the scheduler from the given object build id.
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG.
Definition: assert.h:100
bool is_idle
Definition: thread.h:789
RTEMS_INLINE_ROUTINE void _Processor_mask_Set(Processor_mask *mask, uint32_t index)
Sets the specified index bit of the mask.