RTEMS线程调度算法(RMS)详解
RTEMS是以线程为基本调度单位的,调度算法基于优先级的抢占式线程调度,支持256个线程优先级。当然RTEMS值hi创建同等优先级线程,相同优先级的线程采用时间片轮转调度。调度器寻找下一个最高优先级就绪线程的时间是o(1),这是实时性得到保障的一个关键机制。
为了增强对用户应用需求的可扩展性,rtems实现了基于线程的任务扩展机制,可在创建任务、上下文切换或者删除任务等系统事件发生时插入用户指定的函数(称为钩子函数,hook函数),以完成用户设定的特殊功能。
对于RTEMS这样的基于抢占式和优先级策略调度的os而言,为保证硬实时特性,需要选择一个合适的调度算法,静态调度算法-速率单调调度RMS是为周期性任务解决多任务调度的一种很好的算法。
本文会先介绍核心层的thread handler组件与调度实现,然后对RMS算法在RTEMS上的实现进行分析。
核心层的thread handler组件:
RTEMS的调度相对于通用操作系统而言较为简单,主要是基于线程的优先级进行的,除了对于优先级反转问题需要在运行时改变线程的优先级外,其他情况下不会对线程的优先级修改。
thread handler组件提供了thread_control结构体和以此配套的一组基本线程管理数据结构和管理函数,涉及线程初始化,线程启动,线程暂停,线程恢复,线程切换等。不同的高层API接口实现只是对这些结构和函数进行封装,这样线程管理就可以分为两层,方便API接口进行拓展。
1.线程控制块(TCB)
thread control block是thread handler组件对线程的静态进本情况和动态运行变化过程的描述,其包含了与线程运行管理所需要的所有信息集合,是线程存在的唯一标志。线程的创建主要体现在为该线程生成一个TCB,而线程终止则体现在回收其TCB。
TCB定义在cpukit/score/include/rtems/score/thread.h中,如下:
/*** This structure defines the Thread Control Block (TCB).*/
struct Thread_Control_struct {/** This field is the object management structure for each thread. */Objects_Control Object;/** This field is used to enqueue the thread on RBTrees. */RBTree_Node RBNode;/** This field is the current execution state of this thread. */States_Control current_state;/** This field is the current priority state of this thread. */Priority_Control current_priority;/** This field is the base priority of this thread. */Priority_Control real_priority;/*** @brief Thread priority control.*/Thread_Priority_control Priority;/** This field is the number of mutexes currently held by this thread. */uint32_t resource_count;/** This field is the blocking information for this thread. */Thread_Wait_information Wait;/** This field is the Watchdog used to manage thread delays and timeouts. */Watchdog_Control Timer;
#if defined(RTEMS_MULTIPROCESSING)/** This field is the received response packet in an MP system. */MP_packet_Prefix *receive_packet;
#endif/*================= end of common block =================*/#if defined(RTEMS_SMP)/*** @brief Thread lock control.*/Thread_Lock_control Lock;
#endif#ifdef __RTEMS_STRICT_ORDER_MUTEX__/** This field is the head of queue of priority inheritance mutex* held by the thread.*/Chain_Control lock_mutex;
#endif
#if defined(RTEMS_SMP)/*** @brief Resource node to build a dependency tree in case this thread owns* resources or depends on a resource.*/Resource_Node Resource_node;
#endif
#if defined(RTEMS_MULTIPROCESSING)/** This field is true if the thread is offered globally */bool is_global;
#endif/** This field is true if the thread is preemptible. */bool is_preemptible;/*** @brief Scheduler related control.*/Thread_Scheduler_control Scheduler;#if __RTEMS_ADA__/** This field is the GNAT self context pointer. */void *rtems_ada_self;
#endif/** This field is the length of the time quantum that this thread is* allowed to consume. The algorithm used to manage limits on CPU usage* is specified by budget_algorithm.*/uint32_t cpu_time_budget;/** This field is the algorithm used to manage this thread's time* quantum. The algorithm may be specified as none which case,* no limit is in place.*/Thread_CPU_budget_algorithms budget_algorithm;/** This field is the method invoked with the budgeted time is consumed. */Thread_CPU_budget_algorithm_callout budget_callout;/** This field is the amount of CPU time consumed by this thread* since it was created.*/Thread_CPU_usage_t cpu_time_used;/** This field contains information about the starting state of* this thread.*/Thread_Start_information Start;Thread_Action_control Post_switch_actions;/** This field contains the context of this thread. */Context_Control Registers;
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )/** This field points to the floating point context for this thread.* If NULL, the thread is integer only.*/Context_Control_fp *fp_context;
#endif/** This field points to the newlib reentrancy structure for this thread. */struct _reent *libc_reent;/** This array contains the API extension area pointers. */void *API_Extensions[ THREAD_API_LAST + 1 ];#if !defined(RTEMS_SMP)/** This field points to the set of per task variables. */rtems_task_variable_t *task_variables;
#endif/*** This is the thread key value chain's control, which is used* to track all key value for specific thread, and when thread* exits, we can remove all key value for specific thread by* iterating this chain, or we have to search a whole rbtree,* which is inefficient.*/Chain_Control Key_Chain;/*** @brief Thread life-cycle control.** Control state changes triggered by thread restart and delete requests.*/Thread_Life_control Life;Thread_Capture_control Capture;/*** @brief Variable length array of user extension pointers.** The length is defined by the application via <rtems/confdefs.h>.*/void *extensions[ RTEMS_ZERO_LENGTH_ARRAY ];
};
其中解释几个重要的成员变量:
object是线程作为对象而存在的对象管理结构,也就是说TCB结构是作为一个对象。
real_priority和current_priority是线程的基础优先级和当前运行的优先级。
resource_count是代表线程获取到的资源(互斥量)数量,是为了实现优先级继承算法和优先级天花板算法而设计的。
cpu_time_budget是分配给线程的时间片,而budget_algorithm是用来管理该时间片的算法。RTEMS支持如下四种时间片算法配置:
a. THREAD_CPU_BUDGET_ALGORITHM_NONE //不使用budget算法
b. THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE //线程切换时重新设置时间片
c. THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE //线程时用完时间片才重置
d. THREAD_CPU_BUDGET_ALGORITHM_CALLOUT //时间片用完时调用回调函数
2.线程调度机制
3.线程上下文
运行的线程变为就绪或者阻塞时,都需要保存当前进程的上下文。线程的上下文是和硬件的体系结构密切相关,RTEMS中,ARM的上下文定义如下:
typedef struct {
#if defined(ARM_MULTILIB_ARCH_V4)uint32_t register_cpsr;uint32_t register_r4;uint32_t register_r5;uint32_t register_r6;uint32_t register_r7;uint32_t register_r8;uint32_t register_r9;uint32_t register_r10;uint32_t register_fp;uint32_t register_sp;uint32_t register_lr;
#elif defined(ARM_MULTILIB_ARCH_V6M) || defined(ARM_MULTILIB_ARCH_V7M)uint32_t register_r4;uint32_t register_r5;uint32_t register_r6;uint32_t register_r7;uint32_t register_r8;uint32_t register_r9;uint32_t register_r10;uint32_t register_r11;void *register_lr;void *register_sp;uint32_t isr_nest_level;
#elsevoid *register_sp;
#endif
#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTERuint32_t thread_id;
#endif
#ifdef ARM_MULTILIB_VFPuint64_t register_d8;uint64_t register_d9;uint64_t register_d10;uint64_t register_d11;uint64_t register_d12;uint64_t register_d13;uint64_t register_d14;uint64_t register_d15;
#endif
#ifdef RTEMS_SMPvolatile bool is_executing;
#endif
} Context_Control;
TCB中的Registers就是上下文的变量。
4.线程的优先级管理
每个优先级的就绪的线程都是一个FIFO链表,TCB中会包含该链表,便于线程调度时的操作。_thread_ready_chain就是由各个优先级的FIFO构成的数组,这是一个全局变量。
chain_control结构是对FIFO链表进行管理的数据结构,包含了链表的头和尾,这样可以很快确定每个优先级的第一个线程和最后一个。但问题在于,不容易确定下一个优先级最高的线程,如果切换出来的线程所在的优先级只有一个就绪线程,那么就需要在_thread_ready_chain数组中找到优先级最高的就绪线程,这是一个耗时的操作,因此RTEMS采用位图的方法解决了这个问题。它把256个优先级分为16*16,这样的话,就相当于两个16位整数就可以表示了,也就是两个16位长的二进制数组。这样提高了搜索速度。这样一个priority优先级可以分为major(priority/16)和minor(priority%16)两部分。major*16+minor.
RTEMS中的RMS实时调度
RMS速率单调调度算法基于以下假设:
a. 所有任务都是周期任务
b. 任务的相对截止时间等于任务周期
c.任务在每个周期的计算时间都相等
d.任务之间不进行通信,也不需要同步,是独立的
e.任何可以在计算的任何位置被抢占
任务的优先级和任务的周期表吓你为单调函数关系,任务周期越短,任务优先级越高。静态是指任务的优先级是事前确定的,在任务运行过程中不会改变。
关键数据结构
typedef struct {/** This field is the object management portion of a Period instance. */Objects_Control Object;/*** @brief Protects the rate monotonic period state.*/ISR_LOCK_MEMBER( Lock )/** This is the timer used to provide the unblocking mechanism. */Watchdog_Control Timer;/** This field indicates the current state of the period. */rtems_rate_monotonic_period_states state;/*** @brief A priority node for use by the scheduler job release and cancel* operations.*/Priority_Node Priority;/*** This field contains the length of the next period to be* executed.*/uint32_t next_length;/*** This field contains a pointer to the TCB for the thread* which owns and uses this period instance.*/Thread_Control *owner;/*** This field contains the cpu usage value of the owning thread when* the period was initiated. It is used to compute the period's* statistics.*/Timestamp_Control cpu_usage_period_initiated;/*** This field contains the wall time value when the period* was initiated. It is used to compute the period's statistics.*/Timestamp_Control time_period_initiated;/*** This field contains the statistics maintained for the period.*/Rate_monotonic_Statistics Statistics;/*** This field contains the number of postponed jobs.* When the watchdog timeout, this variable will be increased immediately.*/uint32_t postponed_jobs;/*** This field contains the tick of the latest deadline decided by the period* watchdog.*/uint64_t latest_deadline;
} Rate_monotonic_Control;
Watchdog_Control 是和这个结构体关联的定时器
rtems_rate_monotonic_period_states RMS的状态
关键实现函数
对于RMS,RTEMS提供了以下API:
rtems_rate_monotonic_create 创建一个RMS
rtems_rate_monotonic_cancel 取消一个RMS
rtems_rate_monotonic_delete 删除一个RMS
rtems_rate_monotonic_get_status 获得RMS状态
rtems_rate_monotonic_period 核心函数,用于启动一个周期,在这里发生RMS状态转换
RTEMS中RMS实现算法如下:
程序调用rtems_rate_monotonic_period ,此时系统认为线程开始一项周期任务,且周期长度为length,记这一时刻time_at_period。当线程的执行流到达下一个rtems_rate_monotonic_period语句时(在一般程序中,是回到之前调用的那句rtems_rate_monotonic_period ),系统会判断从time_at_period开始到现在是否经过了length个tick,如果超过了,重新开始一个周期。通常是不会超过的,此时这个线程会被阻塞,等待下一周期的开始,知道系统时刻确实到达time_at_period+length。线程会被唤醒。
应用举例:
RTMES/testsuites/sptests/sp32中包含了对RMS的测试用例。其功能是让任务运行五个确定的周期,在每个周期的开始和结束记录时间,然后相减,看是否与指定的周期长度相等。
RTEMS线程调度算法(RMS)详解相关推荐
- async spring 默认线程池_Spring boot注解@Async线程池实例详解
这篇文章主要介绍了Spring boot注解@Async线程池实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从Spring3开始提供了@A ...
- InheritableThreadLocal类原理简介使用 父子线程传递数据详解 多线程中篇(十八)...
上一篇文章中对ThreadLocal进行了详尽的介绍,另外还有一个类: InheritableThreadLocal 他是ThreadLocal的子类,那么这个类又有什么作用呢? 测试代码 publi ...
- openstack ice自定义调度算法项目详解(horizon、novaclient、api、scheduler、db、自定义数据库)
原文转自:openstack ice自定义调度算法项目详解(horizon.novaclient.api.scheduler.db.自定义数据库) 第一部分:页面层即horizon与novaclien ...
- C++11多线程第三篇:线程传参详解,detach()大坑,成员函数做线程参数
文章目录 3.1 传递临时对象作为线程参数 3.1.1 要避免的陷阱(解释1) 3.1.2 要避免的陷阱(解释2) 3.1.3 总结 3.2 临时对象作为线程参数进一步详解 3.2.1 线程id概念 ...
- python线程池原理_Python定时器线程池原理详解
这篇文章主要介绍了Python定时器线程池原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 定时器执行循环任务: 知识储备 Timer(int ...
- java 线程同步的list_java集合框架线程同步代码详解
List接口的大小可变数组的实现.实现了所有可选列表操作,并允许包括null在内的所有元素.除了实现List接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小.(此类大致上等同于Vector ...
- 线程池源代码详解,参数详解
线程池源代码详解,参数详解 ThreadPoolExecutor 构造函数源代码 public ThreadPoolExecutor(int corePoolSize, int maximumPool ...
- Java线程池ThreadPool详解
Java线程池ThreadPool详解 1. 线程池概述 1.1 线程池简介 1.2 线程池特点 1.3 线程池解决问题 2. 线程池原理分析 2.1 线程池总体设计 2.6 线程池流转状态 2.2 ...
- python 线程等待_详解python多线程之间的同步(一)
引言: 线程之间经常需要协同工作,通过某种技术,让一个线程访问某些数据时,其它线程不能访问这些数据,直到该线程完成对数据的操作.这些技术包括临界区(Critical Section),互斥量(Mute ...
最新文章
- 送书 | 2020年新一天,用这本书开启你的NLP学习之路!
- 中国黑客自揭黑色产业链条:做病毒一定要低调
- c语言编程任意矩阵相乘,c语言矩阵相乘
- Swift URL含有中文的处理
- 在代码中向ReportViewer动态添加数据源
- 计算机无法进入桌面怎么备份,无法进入系统如何正常备份数据?
- AIX 磁盘和文件系统
- [Java基础]字节,字符打印流
- 前端学习(2752):global全局设置
- mysql语句怎么记_Mysql常用语句(记一下,免得忘)
- 在系统中用etcd实现服务注册和发现
- LeetCode(404)——左叶子之和(JavaScript)
- Java并发编程:并发容器之ConcurrentHashMap(转载)
- php能做什么程序,PHP 能做什么?
- 软件设计文档国家标准—软件需求说明书(GB856T——88)
- 文献阅读笔记之 - - 48V锂电池管理系统的设计与实现(贾小龙)
- flash学习者不要错过-视频教程打包下载
- 使用ArcMap 生成TPK和geodatabase包
- shell命令以及运行原理和Linux权限
- 【IO专栏】Java OIO NIO通信对比分析【002】