Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup POSIXAPI
0007  *
0008  * @brief Function sets scheduling policy and parameters of the thread
0009  */
0010 
0011 /*
0012  *  13.5.2 Dynamic Thread Scheduling Parameters Access,
0013  *         P1003.1c/Draft 10, p. 124
0014  */
0015 
0016 /*  COPYRIGHT (c) 1989-2014.
0017  *  On-Line Applications Research Corporation (OAR).
0018  *
0019  * Redistribution and use in source and binary forms, with or without
0020  * modification, are permitted provided that the following conditions
0021  * are met:
0022  * 1. Redistributions of source code must retain the above copyright
0023  *    notice, this list of conditions and the following disclaimer.
0024  * 2. Redistributions in binary form must reproduce the above copyright
0025  *    notice, this list of conditions and the following disclaimer in the
0026  *    documentation and/or other materials provided with the distribution.
0027  *
0028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0029  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0030  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0031  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0032  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0033  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0034  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0035  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0036  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0037  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0038  * POSSIBILITY OF SUCH DAMAGE.
0039  */
0040 
0041 #ifdef HAVE_CONFIG_H
0042 #include "config.h"
0043 #endif
0044 
0045 #include <pthread.h>
0046 #include <string.h>
0047 #include <errno.h>
0048 
0049 #include <rtems/posix/pthreadimpl.h>
0050 #include <rtems/posix/priorityimpl.h>
0051 #include <rtems/score/threadimpl.h>
0052 
0053 static int _POSIX_Set_sched_param(
0054   Thread_Control             *the_thread,
0055   int                         policy,
0056   const struct sched_param   *param,
0057   const Thread_Configuration *config,
0058   Thread_queue_Context       *queue_context
0059 )
0060 {
0061   const Scheduler_Control            *scheduler;
0062   int                                 normal_prio;
0063   bool                                valid;
0064   Priority_Control                    core_normal_prio;
0065   const Thread_CPU_budget_operations *cpu_budget_operations;
0066 #if defined(RTEMS_POSIX_API)
0067   POSIX_API_Control                  *api;
0068   int                                 low_prio;
0069   Priority_Control                    core_low_prio;
0070 #endif
0071 
0072   normal_prio = param->sched_priority;
0073 
0074   scheduler = _Thread_Scheduler_get_home( the_thread );
0075 
0076   core_normal_prio = _POSIX_Priority_To_core( scheduler, normal_prio, &valid );
0077   if ( !valid ) {
0078     return EINVAL;
0079   }
0080 
0081 #if defined(RTEMS_SCORE_THREAD_HAS_SCHEDULER_CHANGE_INHIBITORS)
0082   the_thread->is_scheduler_change_inhibited = ( policy == SCHED_SPORADIC );
0083 #endif
0084 
0085 #if defined(RTEMS_POSIX_API)
0086   if ( policy == SCHED_SPORADIC ) {
0087     low_prio = param->sched_ss_low_priority;
0088   } else {
0089     low_prio = normal_prio;
0090   }
0091 
0092   core_low_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
0093   if ( !valid ) {
0094     return EINVAL;
0095   }
0096 
0097   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
0098 
0099   _Watchdog_Per_CPU_remove_ticks( &api->Sporadic.Timer );
0100 #endif
0101 
0102   _Priority_Node_set_priority( &the_thread->Real_priority, core_normal_prio );
0103 
0104 #if defined(RTEMS_POSIX_API)
0105   if ( !_Priority_Node_is_active( &the_thread->Real_priority ) ) {
0106     _Thread_Priority_add(
0107       the_thread,
0108       &the_thread->Real_priority,
0109       queue_context
0110     );
0111     _Thread_Priority_remove(
0112       the_thread,
0113       &api->Sporadic.Low_priority,
0114       queue_context
0115     );
0116   } else {
0117 #endif
0118     _Thread_Priority_changed(
0119       the_thread,
0120       &the_thread->Real_priority,
0121       PRIORITY_GROUP_LAST,
0122       queue_context
0123     );
0124 #if defined(RTEMS_POSIX_API)
0125   }
0126 #endif
0127 
0128   cpu_budget_operations = config->cpu_budget_operations;
0129   the_thread->CPU_budget.operations = cpu_budget_operations;
0130 
0131   if ( cpu_budget_operations != NULL ) {
0132     ( *cpu_budget_operations->initialize )( the_thread );
0133   }
0134 
0135 #if defined(RTEMS_POSIX_API)
0136   _Priority_Node_set_priority( &api->Sporadic.Low_priority, core_low_prio );
0137   api->Sporadic.sched_ss_repl_period = param->sched_ss_repl_period;
0138   api->Sporadic.sched_ss_init_budget = param->sched_ss_init_budget;
0139   api->Sporadic.sched_ss_max_repl = param->sched_ss_max_repl;
0140 
0141   if ( policy == SCHED_SPORADIC ) {
0142     _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
0143   }
0144 #endif
0145 
0146   return 0;
0147 }
0148 
0149 int pthread_setschedparam(
0150   pthread_t                 thread,
0151   int                       policy,
0152 #ifdef HAVE_PTHREAD_SETSCHEDPARAM_CONST
0153   const struct sched_param *param
0154 #else
0155   struct sched_param       *param
0156 #endif
0157 )
0158 {
0159   Thread_Configuration config;
0160   Thread_Control      *the_thread;
0161   Per_CPU_Control     *cpu_self;
0162   Thread_queue_Context queue_context;
0163   int                  error;
0164 
0165   if ( param == NULL ) {
0166     return EINVAL;
0167   }
0168 
0169   memset( &config, 0, sizeof( config ) );
0170   error = _POSIX_Thread_Translate_sched_param( policy, param, &config );
0171   if ( error != 0 ) {
0172     return error;
0173   }
0174 
0175   _Thread_queue_Context_initialize( &queue_context );
0176   _Thread_queue_Context_clear_priority_updates( &queue_context );
0177   the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
0178 
0179   if ( the_thread == NULL ) {
0180     return ESRCH;
0181   }
0182 
0183   _Thread_Wait_acquire_critical( the_thread, &queue_context );
0184   error = _POSIX_Set_sched_param(
0185     the_thread,
0186     policy,
0187     param,
0188     &config,
0189     &queue_context
0190   );
0191   cpu_self = _Thread_queue_Dispatch_disable( &queue_context );
0192   _Thread_Wait_release( the_thread, &queue_context );
0193   _Thread_Priority_update( &queue_context );
0194   _Thread_Dispatch_enable( cpu_self );
0195   return error;
0196 }