Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreScheduler
0007  *
0008  * @brief This header file provides interfaces of the
0009  *   @ref RTEMSScoreScheduler related to scheduler nodes which are only used by
0010  *   the implementation.
0011  */
0012 
0013 /*
0014  * Copyright (C) 2014, 2017 embedded brains GmbH & Co. KG
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifndef _RTEMS_SCORE_SCHEDULERNODEIMPL_H
0039 #define _RTEMS_SCORE_SCHEDULERNODEIMPL_H
0040 
0041 #include <rtems/score/schedulernode.h>
0042 #include <rtems/score/priorityimpl.h>
0043 
0044 /**
0045  * @addtogroup RTEMSScoreScheduler
0046  *
0047  * @{
0048  */
0049 
0050 struct _Scheduler_Control;
0051 
0052 #ifdef __cplusplus
0053 extern "C" {
0054 #endif /* __cplusplus */
0055 
0056 #define SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node ) \
0057   RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Priority.Node.Node.Chain )
0058 
0059 #define SCHEDULER_NODE_OF_WAIT_PRIORITY( node ) \
0060   RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Priority )
0061 
0062 /**
0063  * @brief Maps a priority value to support the append indicator.
0064  */
0065 #define SCHEDULER_PRIORITY_MAP( priority ) ( ( priority ) << 1 )
0066 
0067 /**
0068  * @brief Returns the plain priority value.
0069  */
0070 #define SCHEDULER_PRIORITY_UNMAP( priority ) ( ( priority ) >> 1 )
0071 
0072 /**
0073  * @brief Clears the priority append indicator bit.
0074  */
0075 #define SCHEDULER_PRIORITY_PURIFY( priority )  \
0076   ( ( priority ) & ~( (Priority_Control) PRIORITY_GROUP_LAST ) )
0077 
0078 /**
0079  * @brief Returns the priority control with the append indicator bit set.
0080  */
0081 #define SCHEDULER_PRIORITY_APPEND( priority )  \
0082   ( ( priority ) | ( (Priority_Control) PRIORITY_GROUP_LAST ) )
0083 
0084 /**
0085  * @brief Returns true, if the item should be appended to its priority group,
0086  * otherwise returns false and the item should be prepended to its priority
0087  * group.
0088  */
0089 #define SCHEDULER_PRIORITY_IS_APPEND( priority ) \
0090   ( ( ( priority ) & ( (Priority_Control) PRIORITY_GROUP_LAST ) ) != 0 )
0091 
0092 /**
0093  * @brief Initializes the node.
0094  *
0095  * @param scheduler is the scheduler of the node.
0096  *
0097  * @param[out] node is the node to initialize.
0098  *
0099  * @param[in, out] the_thread is the thread of the node.
0100  *
0101  * @param priority is the initial priority of the node.
0102  */
0103 static inline void _Scheduler_Node_do_initialize(
0104   const struct _Scheduler_Control *scheduler,
0105   Scheduler_Node                  *node,
0106   Thread_Control                  *the_thread,
0107   Priority_Control                 priority
0108 )
0109 {
0110   node->owner = the_thread;
0111 
0112   node->Priority.value = priority;
0113 
0114 #if defined(RTEMS_SMP)
0115   _Chain_Initialize_node( &node->Thread.Wait_node );
0116   node->Wait.Priority.scheduler = scheduler;
0117   node->user = the_thread;
0118   node->idle = NULL;
0119 #if CPU_SIZEOF_POINTER != 8
0120   _ISR_lock_Initialize( &node->Priority.Lock, "Scheduler Node Priority" );
0121 #endif
0122 #else
0123   (void) scheduler;
0124   (void) the_thread;
0125 #endif
0126 }
0127 
0128 /**
0129  * @brief Destroys the node.
0130  *
0131  * @param scheduler is the scheduler of the node.
0132  *
0133  * @param[in, out] node is the node to destroy.
0134  */
0135 static inline void _Scheduler_Node_do_destroy(
0136   const struct _Scheduler_Control *scheduler,
0137   Scheduler_Node                  *node
0138 )
0139 {
0140   (void) scheduler;
0141 
0142 #if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER != 8
0143   _ISR_lock_Destroy( &node->Priority.Lock );
0144 #else
0145   (void) node;
0146 #endif
0147 }
0148 
0149 /**
0150  * @brief Gets the scheduler of the node.
0151  *
0152  * @param node The node to get the scheduler of.
0153  *
0154  * @return The scheduler of the node.
0155  */
0156 static inline const Scheduler_Control *_Scheduler_Node_get_scheduler(
0157   const Scheduler_Node *node
0158 )
0159 {
0160   return _Priority_Get_scheduler( &node->Wait.Priority );
0161 }
0162 
0163 /**
0164  * @brief Gets the owner of the node.
0165  *
0166  * @param node The node to get the owner of.
0167  *
0168  * @return The owner of the node.
0169  */
0170 static inline Thread_Control *_Scheduler_Node_get_owner(
0171   const Scheduler_Node *node
0172 )
0173 {
0174   return node->owner;
0175 }
0176 
0177 /**
0178  * @brief Gets the priority of the node.
0179  *
0180  * @param node The node to get the priority of.
0181  *
0182  * @return The priority of the node.
0183  */
0184 static inline Priority_Control _Scheduler_Node_get_priority(
0185   Scheduler_Node *node
0186 )
0187 {
0188   Priority_Control priority;
0189 
0190 #if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
0191   priority = _Atomic_Fetch_add_ulong(
0192     &node->Priority.value,
0193     0,
0194     ATOMIC_ORDER_RELAXED
0195   );
0196 #else
0197   ISR_lock_Context lock_context;
0198 
0199   _ISR_lock_Acquire( &node->Priority.Lock, &lock_context );
0200   priority = node->Priority.value;
0201   _ISR_lock_Release( &node->Priority.Lock, &lock_context );
0202 #endif
0203 
0204   return priority;
0205 }
0206 
0207 /**
0208  * @brief Sets the priority of the node.
0209  *
0210  * @param[in, out] node is the scheduler node.
0211  *
0212  * @param new_priority is the priority to set.
0213  *
0214  * @param group_order is the priority group order, see #PRIORITY_GROUP_FIRST
0215  *   and #PRIORITY_GROUP_LAST.
0216  */
0217 static inline void _Scheduler_Node_set_priority(
0218   Scheduler_Node      *node,
0219   Priority_Control     new_priority,
0220   Priority_Group_order group_order
0221 )
0222 {
0223 #if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
0224   _Atomic_Store_ulong(
0225     &node->Priority.value,
0226     new_priority | (Priority_Control) group_order,
0227     ATOMIC_ORDER_RELAXED
0228   );
0229 #else
0230   ISR_lock_Context lock_context;
0231 
0232   _ISR_lock_Acquire( &node->Priority.Lock, &lock_context );
0233   node->Priority.value = new_priority | ( (Priority_Control) group_order );
0234   _ISR_lock_Release( &node->Priority.Lock, &lock_context );
0235 #endif
0236 }
0237 
0238 #if defined(RTEMS_SMP)
0239 /**
0240  * @brief Gets the user of the node.
0241  *
0242  * @param node The node to get the user of.
0243  *
0244  * @return The user of the node.
0245  */
0246 static inline Thread_Control *_Scheduler_Node_get_user(
0247   const Scheduler_Node *node
0248 )
0249 {
0250   return node->user;
0251 }
0252 
0253 /**
0254  * @brief Sets the user of the node.
0255  *
0256  * @param[out] node The node to set the user of.
0257  * @param user The new user for @a node.
0258  */
0259 static inline void _Scheduler_Node_set_user(
0260   Scheduler_Node *node,
0261   Thread_Control *user
0262 )
0263 {
0264   node->user = user;
0265 }
0266 
0267 /**
0268  * @brief Gets the idle thread of the node.
0269  *
0270  * @param node The node to get the idle thread of.
0271  *
0272  * @return The idle thread of @a node.
0273  */
0274 static inline Thread_Control *_Scheduler_Node_get_idle(
0275   const Scheduler_Node *node
0276 )
0277 {
0278   return node->idle;
0279 }
0280 
0281 /**
0282  * @brief Sets the scheduler node's user to the idle thread.
0283  *
0284  * @param[in, out] node is the node to receive an idle thread.
0285  *
0286  * @param idle is the idle thread to use.
0287  */
0288 static inline void _Scheduler_Node_set_idle_user(
0289   Scheduler_Node *node,
0290   Thread_Control *idle
0291 )
0292 {
0293   _Assert( _Scheduler_Node_get_idle( node ) == NULL );
0294   _Assert(
0295     _Scheduler_Node_get_owner( node ) == _Scheduler_Node_get_user( node )
0296   );
0297 
0298   _Scheduler_Node_set_user( node, idle );
0299   node->idle = idle;
0300 }
0301 #endif
0302 
0303 #ifdef __cplusplus
0304 }
0305 #endif /* __cplusplus */
0306 
0307 /** @} */
0308 
0309 #endif /* _RTEMS_SCORE_SCHEDULERNODEIMPL_H */