CN103995743B - 基于资源预约的两级混合任务调度方法 - Google Patents
基于资源预约的两级混合任务调度方法 Download PDFInfo
- Publication number
- CN103995743B CN103995743B CN201410215702.1A CN201410215702A CN103995743B CN 103995743 B CN103995743 B CN 103995743B CN 201410215702 A CN201410215702 A CN 201410215702A CN 103995743 B CN103995743 B CN 103995743B
- Authority
- CN
- China
- Prior art keywords
- task
- processor
- variable
- current
- sched
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Landscapes
- Debugging And Monitoring (AREA)
Abstract
本发明公开了一种基于资源预约的两级混合任务调度方法,实施步骤为:为各处理器建立各自的局部队列、抢先计数器、抢先允许状态,抢先允许状态反映处理器的中断/抢先的开放/禁止情况;为全系统建立全局队列;为任务创建抢先列表;被唤醒任务先存于全局队列,再为其寻找局部队列,若找到的处理器已临时关闭抢先,则增加其抢先计数器,并将其加入此任务的抢先列表,否则将任务移入相应局部队列;处理器在调度时根据其抢先计数器状态决定候选任务来自哪些队列;若被调度执行的任务抢先列表非空,则减少该表所登记处理器的抢先计数器。本发明能够防止操作系统决定抢先“不能马上实施抢先的优先权”,具有调度合理、可靠性好、执行效率高的优点。
Description
技术领域
本发明涉及计算机操作系统领域,具体涉及一种操作系统用来决定在哪个处理器上运行实时任务的基于资源预约的两级混合任务调度方法。
背景技术
操作系统是计算机系统的基础软件。计算机系统开机后,首先执行的软件就是操作系统。操作系统首先会进行系统的初始化(包括启动各个处理器),然后创建默认要创建的任务(如各种服务)。在系统运行过程中,用户还可以动态要求系统新创建一些任务。
由于系统中同时存在的任务数量一般会超过处理器数量,故这些任务需要按照某种方式来共享使用有限的物理处理器。在计算机系统中,由操作系统的调度算法来决定“某个处理器当前应该执行哪个任务”和“某个任务应该由哪个处理器运行”。当外部中断发生、或当前执行的任务主动放弃使用处理器时,调度算法决定“当前处理器应运行哪个任务”,在当前正执行的任务通知操作系统“另外某个任务现在可以运行了”时,调度算法决定由哪个处理器运行这个刚刚可以运行的任务。
任务在运行时,用户应用逻辑所需要的某些功能(如获取当前时间、打开一个文件、从网络接收数据),需要通过执行操作系统代码完成。操作系统在为任务执行某些功能时,会要求暂时禁止处理器响应外部中断(后文称作disable_intr),或暂时禁止“操作系统将当前任务换下去,由另外一个任务使用当前处理器”(后文称作preempt_disable)。
在实时计算机系统中,用户期望任务能够在预期的时刻按照自己预期的方式执行。由于用户对不同任务的执行时间、执行速度的预期不同,当在某个时刻同时有多个任务需要运行时,需要有一种方法保证系统行为尽可能地符合用户的预期。基于实时优先权的调度就是这样一种方式。为说明方便,下文假设实时优先权的取值为整数,且两个不同的实时优先权在数值上最少相差1,且当两个任务同时竞争同一个处理器资源时,操作系统认为高实时优先权的任务应获得处理器。
在基于实时优先权调度的系统中,操作系统实现的调度器会尽力按照任务实时优先权的高低来决定哪个任务先运行。考虑如下情形:T0时刻高实时优先权任务TASKhigh(以下简称TASKhigh)等待接收某事件event,低实时优先权任务TASKlow(以下简称TASKlow)满足运行条件,故调度器决定运行任务TASKlow;在晚于T0的某时刻T1,发生了事件event,但此时TASKlow仍在运行。在T1时刻,因需要运行TASKhigh,按照实时系统对用户的保证,调度器应剥夺实时优先权低于TASKhigh的任务所拥有的处理器资源,让TASKhigh任务运行。比如:调度器可能会决定剥夺Tasklow的执行权,由TASKhigh使用处理器。若调度器做出了这样的决定,则称作TASKhigh抢先TASKlow运行,或者说,TASKlow被TASKhigh抢先运行。
在逻辑上,抢先一般被分为两步来完成:
步骤一:将高实时优先权任务放入待运行队列,并通知期望运行此任务的处理器执行步骤二(若是本处理器,则无需通知,本处理器会在合适的时机自行执行步骤二);
步骤二:综合考虑本处理器当前正在运行任务和本处理器对应的待运行队列中的所有任务,选取一个当前最应该在本处理器上执行的任务。
在一般实现抢先时,只会有一个处理器会执行上述的步骤二,以运行我们关心的高实时优先权任务。而步骤一的功能是:决定需要在哪个处理器上执行步骤二。
在一个计算机系统中,很可能会同时运行多个具有不同实时优先权的任务。当上一个任务TASKprio(以下简称TASKprio)由“不需要运行”变为“需要运行”时,步骤一会试图找出符合条件CONDA的某个低实时优先权任务TASKlowest(以下简称TASKlowest),然后让TASKprio抢先TASKlowest。条件CONDA如下:①、当前正在某个“允许TASKprio使用”的处理器上运行;②、实时优先权低于任务TASKprio的实时优先权;③、在所有满足性质①和②的任务中,TASKlowest的实时优先权最低。
在具体实现上,待运行任务队列有全局队列和局部队列两种实现形式。早期操作系统为全局队列实现方式,所有的处理器都从单一的全局队列中获取任务运行。由于从全局任务队列中获取任务需要使用互斥操作,故此种实现方式在处理器数量较多时性能较差。当前操作系统一般采用局部队列。此时,每个处理器在本地都对应一个局部队列,处理器只从自己对应的局部队列中选取任务运行。
在多处理器系统上,这种实现方式有时会造成无效调度,影响任务及时运行。原因为:1、操作系统在实现上往往要求任务在执行某段内核代码时不能被抢先;2、操作系统在执行某些功能时会把中断关闭。若低实时优先权任务TASKlowest在某处理器上执行1或2对应的代码时,步骤一可能看到TASKlowest符合条件CONDA,决定让高实时优先权任务TASKprio抢先TASKlowest,而不会抢先实时优先权低于TASKprio、但高于TASKlowest、正在运行、且可立即被抢先的任务TASKcanpr。由于任务TASKprio没有被放入运行TASKcanpr的处理器的调度队列中,这可能会造成TASKprio被迫等待较长时间才能获得运行。
发明内容
本发明解决的技术问题是提供一种能够防止操作系统决定抢先低实时优先权任务执行不能被抢先的代码,调度合理、可靠性好、执行效率高的基于资源预约的两级混合任务调度方法。
为了解决上述技术问题,本发明采用的技术方案为:
一种基于资源预约的两级混合任务调度方法,其实施步骤如下:
1)在操作系统系统初始化启动各个处理器时,为各个处理器建立用于存放确定将在该处理器上运行任务的局部队列、用于记录试图被抢先次数的抢先计数器以及抢先允许状态,所述抢先允许状态用于表示处理器的中断或抢先的开放/禁止情况;建立用于存放暂时没有找到合适处理器运行任务的全局队列;所述在操作系统系统初始化启动各个处理器时,分别为每一个处理器分配sched_cnt、sched_cnt_rwl、try_pr_cnt、pr_dis_cnt、intr_mask_st信息的存储空间,其中,sched_cnt用于记录了从开机至今在此处理器上调度函数的执行次数,sched_cnt_rwl为一个读写锁,处理器在修改自己对应的sched_cnt信息前,需要以“写”的方式获得自己对应的sched_cnt_rwl,处理器在查看其它处理器对应的sched_cnt信息前,需要以“读”的方式获得相应处理器对应的sched_cnt_rwl;try_pr_cnt用于记录从本处理器上次执行调度函数至今,中间有试图抢先本处理器上的当前任务的任务数量;pr_dis_cnt用于记录此处理器上正在运行的任务目前净累积的“禁止抢先请求”次数,若任务先执行了N次“禁止抢先请求”,接下来执行了N-1次“允许抢先请求”,则此任务pr_dis_cnt的值为1;若在pr_dis_cnt为0时,任务仍然执行“允许抢先请求”,则pr_dis_cnt仍然为0;intr_mask_st为一个枚举类型变量,值域为{DIS,ENA},其值仅受任务执行时的“打开对中断的响应”、“关闭对中断的响应”两类操作的影响,任务在本处理器上执行“关闭对中断的响应”操作后,则intr_mask_st值变为DIS;任务在本处理器上执行“打开对中断的响应”操作后,则intr_mask_st值变为ENA;
2)将新创建或刚被唤醒的当前任务暂存到全局队列中,在当前任务在全局队列被调度运行时遍历所有的处理器选择在哪个处理器上运行当前任务,且在选择处理器时检查各个处理器的抢先允许状态,避开抢先允许状态标明中断或抢先已禁止而不能马上实施抢先的处理器,若能找到合适的处理器,则将当前任务放入所找到处理器的局部队列中并跳转执行步骤3);否则,将当前任务继续停留在全局队列,并通过抢先计数器记录不能马上实施抢先的处理器的试图被抢先次数,然后等待下一次在全局队列被调度运行;
3)各个处理器分别执行选择在当前处理器上运行的任务,在执行任务过程中,如果遇到不允许插入执行中断处理程序的代码,则通过执行“关闭对中断的响应”操作修改抢先允许状态标明中断已禁止,返回执行所述不允许插入执行中断处理程序的代码,最终通过执行“打开对中断的响应”操作修改抢先允许状态标明中断已开放;如果遇到不允许插入执行的代码,则修改抢先允许状态标明抢先已禁止,返回执行所述不允许插入执行的代码,最终修改抢先允许状态标明抢先已开放。
优选地,所述步骤1)中建立用于存放暂时没有找到合适处理器运行任务的全局队列具体是指启动一个虚拟处理器,针对该虚拟处理器建立一个用于缓存任务的任务调度队列作为用于存放暂时没有找到合适处理器运行任务的全局队列。
优选地,所述步骤2)中将新创建或刚被唤醒的当前任务暂存到全局队列中之前,还包括为当前任务初始化分配ctab、sched_lock,sched_st,vlistn信息的存储空间的步骤;其中,ctab为一个列表,用于记录本任务所试图抢先、但因对方禁止了抢先,而没有抢先成功的信息,由于系统中同时运行的任务个数不超过在线处理器的数量,故ctab最多包含的元素个数不大于在线处理器数量,ctab记录的每一项可用<tried_cpu,snapshot>来表示,其含义为此任务试图抢先在处理器tried_cpu上运行的任务,但抢先失败了,且在失败时处理器tried_cpu对应的sched_cnt值为snapshot;sched_lock为一个读写锁,在需清除ctab中信息时,应先获得写锁;在需向ctab中添加信息时,应先获得读锁,在需为某任务寻找合适的处理器运行时,应先获得写锁;vlistn为一个指向全局队列中下一个待调度任务的指针;sched_st为一个枚举类型的变量,用于描述此任务的执行状态,其值域为{ RUN,PRD,INL,ING,SLEP},其中RUN表示该任务正在运行,PRD表示该任务原本在运行,但刚刚被抢先,还未放入到待运行队列中,INL表示该任务在局部队列中等待调度运行,ING表示该任务在全局队列中等待调度运行,SLEP表示该任务目前还在等待除CPU之外的其它运行条件获得满足,新创建的任务的sched_st默认为SLEP;所述步骤2)的详细步骤如下:
2.1)令预先建立的用于临时存储抢先列表ctab的临时抢先列表R为空,令当前任务T的抢先列表ctab为空,令变量first_try的值为true、变量low的值为系统所允许的最低优先权、变量high的值为当前任务T的实时优先权减1,将当前任务T对应的sched_st信息设置为ING,其中变量first_try用于指示是不是第一次就找到了被抢先任务,若变量first_try为true,则说明第一次就找到的任务没有禁止掉抢先,传统的处理逻辑不会影响系统响应,若变量first_try为false,则说明是当前正在运行的最低优先级的任务禁止掉了抢先,系统决定抢先非最低优先级任务;变量low是本次循环中当前任务T考虑可以抢先的任务最低应具有优先级;变量high是本次循环中当前任务T考虑可以抢先的任务最高应具有优先级;设置用于指定执行当前任务T的处理器的变量proc的值为所述虚拟处理器;
2.2)将当前任务T放入全局队列中;
2.3)为当前任务T在指定的处理器集合中筛选出所有可运行用户任务的处理器集合S,并将筛选得到的处理器集合S保存;
2.4)判断处理器集合S是否为空集,如果为空集则跳转执行步骤2.22);否则,跳转执行下一步;
2.5)获得当前任务T应当抢先的处理器,将得到的处理器放入变量proc中,然后获得变量proc对应处理器上当前正在运行的任务X;
2.6)试图获取当前任务T对应的sched_lock读锁,若获取失败,则令变量proc的值为虚拟处理器、临时抢先列表R的值为空,跳转执行步骤2.22);否则跳转执行下一步;
2.7)获取当前任务T的sched_st信息,若当前任务T对应的sched_st不是ING,则首先令变量proc的值为虚拟处理器、变量first_try的值为true、临时抢先列表R的值为空,然后跳转执行步骤2.15);否则,跳转执行下一步;
2.8)获得变量proc对应处理器的sched_cnt_rwl读锁;
2.9)读取变量proc对应处理器的sched_cnt信息,将读取的sched_cnt信息、变量proc对应处理器两者作为一条记录存入临时抢先列表R;
2.10)获得变量proc对应处理器的try_pr_cnt信息增1;
2.11)释放变量proc对应处理器的sched_cnt_rwl读锁;
2.12)判断变量proc对应处理器的pr_dis_cnt信息为0、intr_mask_st信息为ENA两个条件是否同时成立,如果同时成立则跳转执行步骤2.13);否则如果不能同时成立,则释放当前任务T对应的sched_lock读锁,从处理器集合S中去掉变量proc对应的处理器,然后判断处理器集合S是否变为空集,如果处理器集合S不是空集则跳转执行步骤2.5);如果处理器集合S是空集,则令变量first_try的值为false、变量low的值为变量proc对应的处理器的当前实时优先权加1、变量proc的值为所述虚拟处理器,跳转执行步骤2.3);
2.13)将当前任务T对应的sched_st信息设为INL;
2.14)将当前任务T从全局队列中删除,并将当前任务T添加至变量proc对应处理器的局部队列中;
2.15)释放当前任务T对应的sched_lock读锁;
2.16)判断变量first_try的值,若first_try的值为true,则跳转执行步骤2.22),否则跳转执行步骤2.17);
2.17)获得变量proc对应处理器上当前正在运行的任务X对应的sched_lock的读锁;
2.18)检查所述任务X的sched_st信息,若所述任务X对应的sched_st信息不是RUN状态,则从处理器集合S中去掉变量proc对应的处理器,然后判断处理器集合S是否变为空集,如果处理器集合S不是空集则跳转执行步骤2.5);如果处理器集合S是空集,则令变量first_try的值为false、变量low的值为变量proc对应的处理器的当前实时优先权加1、变量proc的值为所述虚拟处理器,跳转执行步骤2.3);若任务X对应的sched_st信息是RUN状态,则跳转执行下一步;
2.19)将所述任务X对应的sched_st信息设为PRD状态;
2.20)将临时抢先列表R的内容填写到所述任务X的抢先列表ctab中,再令临时抢先列表R为空;
2.21)释放所述任务X对应的sched_lock读锁;
2.22)将临时抢先列表R复制到当前任务T的抢先列表ctab中,返回变量proc对应处理器即为被选中用于运行当前任务T的处理器。
优选地,所述步骤3)中各个处理器分别执行选择在当前处理器上运行的任务的详细步骤如下:
3.1)获得当前处理器的sched_cnt_rwl写锁;
3.2)将当前处理器的sched_cnt信息增1、try_pr_cnt信息设为0;
3.3)释放当前处理器的sched_cnt_rwl写锁;
3.4)获取当前处理器本地的局部队列中最高实时优先权的任务放在变量next中,获取当前处理器上正在运行的任务放在变量curr中;
3.5)获取变量curr对应任务的sched_lock写锁;
3.6)判断变量curr对应任务的sched_st信息,若变量curr对应任务的sched_st信息为PRD,则根据变量curr对应任务从全局队列中获取一个任务Tg放在变量next中,且获取的任务Tg满足下述条件④~⑥,④任务Tg的实时优先权高于变量curr对应任务的实时优先权;⑤任务Tg的抢先列表ctab中,当前处理器编号对应的tried_cpu项中包含有效内容;⑥在所有满足条件④和⑤的所有任务中,任务Tg的实时优先权最高;
3.7)判断变量next和变量curr是否相同,若变量next和变量curr相同,则释放变量curr对应任务的sched_lock写锁,并返回继续执行变量curr对应的任务;否则跳转执行下一步;
3.8)判断变量curr对应任务的sched_st信息是否为PRD,若curr对应任务的sched_st信息为PRD,则将变量curr对应任务从当前处理器的局部队列中删除,并将变量curr对应任务添加至全局队列,然后设置变量curr对应任务的sched_st信息为ING;
3.9)判断变量curr对应任务是否需要继续运行,如果不需要继续运行,则设置变量curr对应任务的sched_st信息为SLEP,将变量curr对应任务从当前处理器的局部队列中删除,将变量curr对应的任务作为待清除任务,删除待清除任务的相关记录信息,然后跳转执行步骤3.10);如果需要继续运行,则直接跳转执行步骤3.10);
3.10)设置当前处理器正在运行的任务为变量next对应的任务;
3.11)释放变量curr对应任务的sched_lock写锁;
3.12)判断变量next对应任务当前的sched_lock状态,若sched_lock状态为无锁或读锁,则跳转执行步骤3.13);否则,设置当前处理器当前运行的任务为空闲任务,获取当前处理器本地的局部队列中最高实时优先权的任务放在变量next中,以变量next对应的任务作为查找失败的默认返回值从全局队列中获取一个任务Tg放在变量next中,且获取的任务Tg满足下述条件④~⑥,④任务Tg的实时优先权高于变量curr对应任务的实时优先权;⑤任务Tg的抢先列表ctab中,当前处理器编号对应的tried_cpu项中包含有效内容;⑥在所有满足条件④和⑤的所有任务中,任务Tg的实时优先权最高;设置当前运行的任务为变量next对应的任务,跳转重新执行步骤3.12);
3.13)试图获取变量next对应任务的sched_lock写锁,若失败则跳转执行步骤3.12);否则,跳转执行步骤3.14);
3.14)读取变量next对应任务的sched_st信息,若变量next对应任务的sched_st信息不是PRD,跳转执行步骤3.17),否则跳转执行步骤3.15);
3.15)判断变量next对应的任务是否在全局队列中,如果在全局队列中,则设置变量next对应任务的sched_st信息为ING,否则设置变量next对应任务的sched_st信息为INL;
3.16)释放变量next对应任务的sched_lock写锁,跳转执行步骤3.12);
3.17)将变量next对应的任务作为待清除任务,删除待清除任务的相关记录信息;
3.18)判断变量next对应的任务是否在全局队列中,如果在全局队列中,则将变量next对应的任务从全局队列中删除,并将变量next对应的任务添加至当前处理器的局部队列,然后跳转执行步骤3.19);否则如果不在全局队列中,则直接跳转执行步骤3.19);
3.19)设置变量next对应的任务的sched_st信息为RUN;
3.20)释放变量next对应的任务的sched_lock写锁,开始执行变量next对应的任务。
优选地,所述步骤3.9)和步骤3.17)中删除待清除任务的相关记录信息的详细步骤如下:
3.9.1)检查待清除任务的抢先列表ctab中是否包含有效记录,若待清除任务的抢先列表ctab中不包含有效记录,则返回;否则,跳转执行步骤3.9.2);
3.9.2)获取待清除任务的抢先列表ctab中的第一个有效记录,首先将所述有效记录删除;
3.9.3)判断已删除有效记录中的tried_cpu信息是否与本处理器相同,如果是则跳转执行步骤3.9.1);否则,跳转执行步骤3.9.4);
3.9.4)获取已删除有效记录中的tried_cpu信息对应处理器的sched_cnt_rwl读锁;
3.9.5)读取已删除有效记录中的tried_cpu信息对应处理器的sched_cnt信息,如果所述sched_cnt信息的值与已删除有效记录中的snapshot的值相同,则将已删除有效记录中的tried_cpu信息对应处理器的try_pr_cnt信息的值以原子方式减1;
3.9.6)释放已删除有效记录中的tried_cpu信息对应处理器的sched_cnt_rwl读锁;跳转执行步骤3.9.1)。
优选地,所述步骤3)中通过执行“关闭对中断的响应”操作修改抢先允许状态标明中断已禁止的详细步骤包括:
3.21)将当前处理器的intr_mask_st信息设置为DIS完成执行“关闭对中断的响应”操作,修改抢先允许状态标明中断已禁止;
3.22)判断当前处理器的pr_dis_cnt信息为1、try_pr_cnt不为0两个条件是否同时不成立,如果两个条件不能同时成立,则关闭当前处理器对物理中断的响应,当前处理器返回执行当前处理器上运行的任务;否则如果两个条件同时成立,则跳转执行下一步;
3.23)将当前处理器的intr_mask_st信息设置为ENA完成执行“打开对中断的响应”操作,修改抢先允许状态标明中断已打开;
3.24)当前处理器执行选择在当前处理器上运行的任务,跳转执行步骤3.21);
优选地,所述步骤3)中通过执行“打开对中断的响应”操作修改抢先允许状态标明中断已开放的详细步骤包括:
3.25)打开当前处理器对物理中断的响应;
3.26)将当前处理器的intr_mask_st信息设置为ENA完成执行“打开对中断的响应”操作,修改抢先允许状态标明中断已打开;
3.27)判断当前处理器的pr_dis_cnt信息为0、try_pr_cnt不为0两个条件是否同时不成立,如果两个条件不能同时成立,当前处理器返回执行当前处理器上运行的任务;否则如果两个条件同时成立,则当前处理器执行选择在当前处理器上运行的任务。
优选地,所述步骤3)中修改抢先允许状态标明抢先已禁止的详细步骤如下:
3.28)将当前处理器的pr_dis_cnt信息的值增1;
3.29)判断当前处理器的pr_dis_cnt信息的值为1、try_pr_cnt信息的值不为0、intr_mask_st信息的值为ENA三个条件是否同时成立,如果同时成立则跳转执行步骤3.30);否则,当前处理器返回执行当前处理器上运行的任务;
3.30)将当前处理器的pr_dis_cnt信息的值设置为0;
3.31)当前处理器执行选择在当前处理器上运行的任务,跳转执行步骤3.28);
所述步骤3)中修改抢先允许状态标明抢先已开放的详细步骤如下:
3.32)将当前处理器的pr_dis_cnt信息的值减1;
3.33)判断当前处理器的pr_dis_cnt信息的值为0、try_pr_cnt信息的值不为0、intr_mask_st信息的值为ENA三个条件是否同时成立,如果三个条件同时成立,则跳转执行步骤3.34);否则,当前处理器返回执行当前处理器上运行的任务;
3.34)当前处理器执行选择在当前处理器上运行的任务。
本发明基于资源预约的两级混合任务调度方法具有下述技术效果:与传统调度算法只有一个全局队列或完全分布的局部队列不同,本发明采取局部队列与全局队列相结合,各处理器对应的局部队列中存放确定将在该处理器上运行的任务,全局队列存放暂时没有找到合适处理器运行的任务,形成两级混合任务调度,在此两级混合任务调度的基础上,根据抢先允许状态为任务选择处理器,各个处理器分别执行选择在当前处理器上运行的任务,则根据处理器的抢先允许状态以及任务的优先级别等状态信息对任务进行中断或抢先操作,能够防止操作系统决定抢先低实时优先权任务执行不能被抢先的代码,具有调度合理、可靠性好、执行效率高的优点。
附图说明
图1为本发明实施例方法的基本实施流程示意图。
图2为本发明实施例步骤2)的实施流程示意图。
图3为本发明实施例步骤3)中各个处理器执行任务的实施流程示意图。
图4为本发明实施例中删除待清除任务的相关记录信息的实施流程示意图。
图5为本发明实施例中disable_intr函数的实施流程示意图。
图6为本发明实施例中enable_intr函数的实施流程示意图。
图7为本发明实施例中preempt_disable函数的实施流程示意图。
图8为本发明实施例中preempt_enable函数的实施流程示意图。
图9为本发明实施例中sched_st信息的状态变迁示意图。
图10为本发明实施例中各个接口的调用流程示意图。
具体实施方式
如图1所示,本实施例基于资源预约的两级混合任务调度方法的实施步骤如下:
1)在操作系统系统初始化启动各个处理器时,为各个处理器建立用于存放确定将在该处理器上运行任务的局部队列、用于记录试图被抢先次数的抢先计数器以及抢先允许状态,所述抢先允许状态用于表示处理器的中断或抢先的开放/禁止情况;建立用于存放暂时没有找到合适处理器运行任务的全局队列;
2)将新创建或刚被唤醒的当前任务暂存到全局队列中,在当前任务在全局队列被调度运行时遍历所有的处理器选择在哪个处理器上运行当前任务,且在选择处理器时检查各个处理器的抢先允许状态,避开抢先允许状态标明中断或抢先已禁止而不能马上实施抢先的处理器,若能找到合适的处理器,则将当前任务放入所找到处理器的局部队列中并跳转执行步骤3);否则,将当前任务继续停留在全局队列,并通过抢先计数器记录不能马上实施抢先的处理器的试图被抢先次数,然后等待下一次在全局队列被调度运行;
3)各个处理器分别执行选择在当前处理器上运行的任务,在执行任务过程中,如果遇到不允许插入执行中断处理程序的代码,则通过执行“关闭对中断的响应”操作修改抢先允许状态标明中断已禁止,返回执行所述不允许插入执行中断处理程序的代码,最终通过执行“打开对中断的响应”操作修改抢先允许状态标明中断已开放;如果遇到不允许插入执行的代码,则修改抢先允许状态标明抢先已禁止,返回执行所述不允许插入执行的代码,最终修改抢先允许状态标明抢先已开放。
本实施例按照模块包括初始化模块、本地调度模块,中断状态切换模块,抢先状态改变模块,被抢先任务选取模块。其中,初始化模块包括提供init_cpu、init_rt_task、init_rt_intr三个接口,init_cpu接口供操作系统添加可用处理器资源时使用,init_rt_task供操作系统在创建实时任务、或将任务从非实时任务改变为实时任务时使用、init_rt_intr供用户将实时相关中断绑定到预留处理器上,这个处理器仅被用于响应中断信号,而不执行用户任务和中断的具体处理逻辑。在一般的实现中,可以预留系统内编号最大的处理器做此用途。系统为此处理器分配中断完成缓冲区,用于供其它处理器通知此处理器已处理完成的中断。
本实施例中,init_rt_intr的处理流程为:步骤1、为本处理器安装中断转发处理程序;步骤2、为本处理器安装中断完成处理程序;步骤3、调用操作系统功能,将物理中断都绑定到被预留的处理器上。当此处理器接收到外部设备的中断后,执行中断转发处理程序,其流程为:步骤1、关闭处理器对物理中断的响应;步骤2、若中断为电平式的,则在本处理器禁止此中断源;步骤3、向用户设定的处理器集合转发此中断;步骤4、开放处理器对物理中断的响应。当其它处理器完成中断处理后,执行“中断完成”通知流程:步骤1、向中断完成缓冲区中写入完成的中断号;步骤2、向预留处理器发送“中断处理完成”中断。当预留处理器接收到其它处理器发来的中断处理完成中断后,执行中断处理完成处理程序,其流程为:步骤1、关闭处理器对物理中断的响应;步骤2、若中断完成缓冲区为空,则转到步骤6;步骤3、获得一个已完成中断号;步骤4、开放处理器对于此中断号对应中断的响应;步骤5、转到步骤2;步骤6、放开处理器对物理中断的响应;步骤7、处理结束。
本实施例中,步骤1)中具体是调用init_cpu、init_rt_intr两个接口进行操作,用于对各个处理器进行初始化(init_cpu)、对实时中断处理相关例程进行设置(init_rt_intr)。步骤2)在通过调用init_rt_task接口完成,用于对实时任务进行初始化。init_cpu的处理流程为:步骤1、为本处理器分配sched_cnt、sched_cnt_rwl、try_pr_cnt、pr_dis_cnt、intr_mask_st信息的存储空间;步骤2、将sched_cnt_rwl设置为“未上锁”,将intr_mask_st设置为ENA,将sched_cnt、try_pr_cnt、pr_dis_cnt均设置为0;步骤3、返回。init_rt_task的处理流程为:步骤1、为本任务分配ctab、sched_lock,sched_st,vlistn这些变量所需的空间;步骤2、将ctab初始化为“不包含任何有效记录”,sched_lock设置为“未上锁”,sched_st设置为SLEP,vlistn设置为空;步骤3:返回。
本实施例中,步骤1)中建立用于存放暂时没有找到合适处理器运行任务的全局队列具体是指启动一个虚拟处理器,其编号为VIRT,针对该虚拟处理器建立一个用于缓存任务的任务调度队列作为用于存放暂时没有找到合适处理器运行任务的全局队列virtual_q。全局队列virtual_q为所有处理器都可以从中取任务的全局队列,全局队列初始不包含任何任务。
本实施例中,步骤1)中在操作系统系统初始化启动各个处理器时,分别为每一个处理器分配sched_cnt、sched_cnt_rwl、try_pr_cnt、pr_dis_cnt、intr_mask_st信息的存储空间,本实施例要求操作系统为每个处理器都维护上述信息并保持全系统可见,处理器通过访问这些信息来获得其他处理器的状态,并视情况修改其它处理器所对应的信息,以影响其它处理器的调度行为。上述各个信息的说明如下:
1.1)sched_cnt用于记录了从开机至今在此处理器上调度函数的执行次数。本实施例中sched_cnt使用64位表示,当使用64位表示此变量、且初始值设置为0时,可认为此变量具有单调递增性质。
1.2)sched_cnt_rwl为一个读写锁,处理器在修改自己对应的sched_cnt信息前,需要以“写”的方式获得自己对应的sched_cnt_rwl,处理器在查看其它处理器对应的sched_cnt信息前,需要以“读”的方式获得相应处理器对应的sched_cnt_rwl。
1.3)try_pr_cnt用于记录从本处理器上次执行调度函数至今,中间有试图抢先本处理器上的当前任务的任务数量。
1.4)pr_dis_cnt用于记录此处理器上正在运行的任务目前净累积的“禁止抢先请求”次数,若任务先执行了N次“禁止抢先请求”,接下来执行了N-1次“允许抢先请求”,则此任务pr_dis_cnt的值为1;若在pr_dis_cnt为0时,任务仍然执行“允许抢先请求”,则pr_dis_cnt仍然为0。
1.5)intr_mask_st为一个枚举类型变量,值域为{DIS,ENA},其值仅受任务执行时的“打开对中断的响应”、“关闭对中断的响应”两类操作的影响,任务在本处理器上执行“关闭对中断的响应”操作后,则intr_mask_st值变为DIS;任务在本处理器上执行“打开对中断的响应”操作后,则intr_mask_st值变为ENA。
本实施例中,步骤2)中将新创建或刚被唤醒的当前任务暂存到全局队列中之前,还包括为当前任务初始化分配ctab、sched_lock,sched_st,vlistn信息的存储空间的步骤通过调用init_rt_task接口完成,用于对实时任务进行初始化。本实施例要求操作系统为每个有实时要求任务维护上述信息,且上述信息的具体说明如下:
2.1)ctab为一个列表,用于记录本任务所试图抢先、但因对方禁止了抢先,而没有抢先成功的信息,由于系统中同时运行的任务个数不超过在线处理器的数量,故ctab最多包含的元素个数不大于在线处理器数量,ctab记录的每一项可用<tried_cpu,snapshot>来表示,其含义为此任务试图抢先在处理器tried_cpu上运行的任务,但抢先失败了,且在失败时处理器tried_cpu对应的sched_cnt值为snapshot。
2.2)sched_lock为一个读写锁,在需清除ctab中信息时,应先获得写锁;在需向ctab中添加信息时,应先获得读锁,在需为某任务寻找合适的处理器运行时,应先获得写锁。
2.3)vlistn为一个指向全局队列中下一个待调度任务的指针。
2.4)sched_st为一个枚举类型的变量,用于描述此任务的执行状态,其值域为{ RUN,PRD,INL,ING,SLEP},其中RUN表示该任务正在运行,PRD表示该任务原本在运行,但刚刚被抢先,还未放入到待运行队列中,INL表示该任务在局部队列中等待调度运行,ING表示该任务在全局队列中等待调度运行,SLEP表示该任务目前还在等待除CPU之外的其它运行条件获得满足,新创建的任务的sched_st默认为SLEP。
本实施例中,步骤2)则作为被抢先任务选取模块封装在select_fittest_cpu接口供调用,在调度任务运行时,使用select_fittest_cpu确定任务将在哪个调度队列中排队等待运行。被抢先任务选取模块负责实现当有任务刚被唤醒时“选择在哪个处理器上运行此任务”的问题,因正在运行的任务与处理器之间存在一一对应关系,故可将“选取被抢先的任务”与“选取抢先哪个处理器上的任务”视为等价。本实施例中解决“选取抢先哪个处理器上的任务”问题时,定义处理器的当前实时优先权与当前正在其上运行的任务的实时优先权相等。被抢先任务选取模块对外提供select_fittest_cpu接口,其输入参数包括刚被唤醒的待运行的高优先权任务T、用户实现声明的、允许任务T可以使用的处理器的集合AFFINITY。本接口供操作系统的调度相关代码选择最适宜运行高优先权任务T的处理器。
如图2所示,本实施例中步骤2)(select_fittest_cpu接口函数)的详细步骤如下:
2.1)执行R←Φ令预先建立的用于临时存储抢先列表ctab的临时抢先列表R为空,执行ctab←Φ令当前任务T的抢先列表ctab为空,令变量first_try的值为true、变量low的值为系统所允许的最低优先权MIN_PRIO、变量high的值为当前任务T的实时优先权减1(即first_try←true, low←MIN_PRIO,high←PRIO(T)-1),将当前任务T对应的sched_st信息设置为ING,其中变量first_try用于指示是不是第一次就找到了被抢先任务,若变量first_try为true,则说明第一次就找到的任务没有禁止掉抢先,传统的处理逻辑不会影响系统响应,若变量first_try为false,则说明是当前正在运行的最低优先级的任务禁止掉了抢先,系统决定抢先非最低优先级任务;变量low是本次循环中当前任务T考虑可以抢先的任务最低应具有优先级;变量high是本次循环中当前任务T考虑可以抢先的任务最高应具有优先级;执行proc←VIRT设置用于指定执行当前任务T的处理器的变量proc的值为虚拟处理器;R与ctab的含义相同,由于在本函数执行完成前,不能确定到底是修改哪个任务的ctab,故此时先将ctab的内容放到R,待到确定了具体的任务后,再将R的值复制到此任务的ctab。first_try指示是不是第一次就找到了被抢先任务。若first_try为true,则说明第一次就找到的任务没有禁止掉抢先,传统的处理逻辑不会影响系统响应;若first_try为false,则说明是“当前正在运行的最低优先级的任务禁止掉了抢先,系统决定抢先非最低优先级任务”。low和high是本次循环中,任务T考虑可以抢先的任务最低应具有优先级low,最高应具有优先级high。 proc为最终决定在哪个处理器上运行任务T,若找不到合适的处理器,则其值为VIRT,表示应将此任务放入全局队列中。若找到了,则任务T会被放入此处理器的局部队列中。
2.2)执行enqueue_virt(T)将当前任务T放入全局队列中。
2.3)执行S←get_cands(AFFINITY,low,high)为当前任务T在指定的处理器集合AFFINITY中筛选出所有可运行用户任务的处理器集合S,并将筛选得到的处理器集合S保存。
2.4)判断处理器集合S是否为空集,如果为空集则跳转执行步骤2.22);否则,跳转执行下一步。
2.5)执行proc←get_fittest(S)获得当前任务T应当抢先的处理器,将得到的处理器放入变量proc中,然后执行X←get_cur(proc)获得变量proc对应处理器上当前正在运行的任务X。
2.6)试图获取当前任务T对应的sched_lock读锁(T.sched_lock),若获取失败,则执行proc←VIRT、R←Φ,令变量proc的值为虚拟处理器(proc←VIRT)、临时抢先列表R的值为空(R←Φ),跳转执行步骤2.22);否则跳转执行下一步。
2.7)获取当前任务T的sched_st信息,若当前任务T对应的sched_st(T.sched_st)不是ING,则首先令变量proc的值为虚拟处理器(proc←VIRT)、变量first_try的值为true(first_try←true)、临时抢先列表R的值为空(R←Φ),然后跳转执行步骤2.15);否则,跳转执行下一步。
2.8)获得变量proc对应处理器的sched_cnt_rwl读锁(proc.sched_cnt_rwl)。
2.9)读取变量proc对应处理器的sched_cnt信息(proc.sched_cnt)作为变量snap_cnt,将读取的sched_cnt信息(变量snap_cnt)、变量proc对应处理器两者作为一条记录存入临时抢先列表R(R←R+{<proc,snap_cnt>})。
2.10)获得变量proc对应处理器的try_pr_cnt信息增1。
2.11)释放变量proc对应处理器的sched_cnt_rwl读锁(proc.sched_cnt_rwl)。
2.12)判断变量proc对应处理器的pr_dis_cnt信息(proc.pr_dis_cnt)为0、intr_mask_st信息(proc.intr_mask_st)为ENA两个条件是否同时成立,如果同时成立则跳转执行步骤2.13);否则如果不能同时成立,则释放当前任务T对应的sched_lock读锁(T.sched_lock),从处理器集合S中去掉变量proc对应的处理器(S←S-{proc}),然后判断处理器集合S是否变为空集,如果处理器集合S不是空集则跳转执行步骤2.5);如果处理器集合S是空集,则令变量first_try的值为false(first_try←false)、变量low的值为变量proc对应的处理器的当前实时优先权加1(low←PRIOC(proc)+1)、变量proc的值为虚拟处理器(proc←VIRT),跳转执行步骤2.3)。
2.13)将当前任务T对应的sched_st信息设为INL。
2.14)执行dequeue_virt(T)将当前任务T从全局队列中删除,并执行enqueue_local(T)将当前任务T添加至变量proc对应处理器的局部队列中。
2.15)释放当前任务T对应的sched_lock读锁。
2.16)判断变量first_try的值,若first_try的值为true,则跳转执行步骤2.22),否则跳转执行步骤2.17)。
2.17)获得变量proc对应处理器上当前正在运行的任务X对应的sched_lock的读锁;
2.18)检查任务X的sched_st信息,若任务X对应的sched_st信息不是RUN状态,则从处理器集合S中去掉变量proc对应的处理器(S←S-{proc}),然后判断处理器集合S是否变为空集,如果处理器集合S不是空集则跳转执行步骤2.5);如果处理器集合S是空集,则令变量first_try的值为false(first_try←false)、变量low的值为变量proc对应的处理器的当前实时优先权加1(low←PRIOC(proc)+1)、变量proc的值为虚拟处理器(proc←VIRT),跳转执行步骤2.3);若任务X对应的sched_st信息是RUN状态,则跳转执行下一步。
2.19)将任务X对应的sched_st信息设为PRD状态。
2.20)将临时抢先列表R的内容填写到任务X的抢先列表ctab中,再令临时抢先列表R为空(R←Φ)。
2.21)释放任务X对应的sched_lock读锁。
2.22)将临时抢先列表R复制到当前任务T的抢先列表ctab中,返回变量proc对应处理器即为被选中用于运行当前任务T的处理器。
本实施例中,步骤2.1)~2.22)应通过关闭抢先等方式,保证以上步骤2.1)~2.22)在执行时不会被另外的任务打断。其中,函数PRIO(TASKx)返回任务TASKx的实时优先权,函数PRIOC(CPUx) 返回处理器CPUx的当前实时优先权。函数get_cands(TASK_AFFINITY,PRIO_LOW,PRIO_HIGH)返回一个处理器的集合,函数get_cands要求这个集合包含、且仅包含所有满足如下条件的处理器core:1) core在集合TASK_AFFINITY中;2) PRIOC(core) >= PRIO_LOW,且PRIOC(core) <= PRIO_HIGH;3)对于任意满足以上性质1)和性质2)的处理器core’,不等式PRIOC(core’)>= PRIOC(core)成立。函数get_fittest(S)的输入为处理器集合S,输出为一个在S中的处理器,函数get_fittest为从处理器集合S中选择一个处理器所使用的传统方法。函数get_cur(p)返回当前正在处理器p上运行的任务。需要说明的是,上述函数的实现均为本领的公知手段,因此本实施例不再对其进行详细说明。
本实施例中,步骤3)则作为本地调度模块封装在new_schedule接口供调用,该接口用于实现调度器中“选取哪个任务在当前处理器上运行”的功能。此外,任务在执行过程中,可能需要暂时的关闭中断,以防止中断处理程序干扰任务运行,此时则需要调用中断状态切换模块;任务也有可能需要暂时禁止任务抢先机制,以执行不允许其它任务插入执行的代码,此时则需要调用抢先状态改变模块。
设系统中有P0~P3共4个处理器。任务A实时优先权为80,可以在处理器P2和处理器P3上运行;任务C实时优先权为70,可以在处理器P3、处理器P2、处理器P0上运行,当前正运行于处理器P3;任务D实时优先权为60,可以在处理器P2和处理器P3上运行,当前正运行于处理器P2;任务B的实时优先权为75,可以在处理器P1上运行;任务A当前正睡眠;处理器P0上当前正在运行的任务优先权为90;任务B现在要唤醒任务A。下面针对四种不同情形,对本实施例中select_fittest_cpu接口函数的进行举例说明:
场景1:处理器P2允许抢先、中断开放。此时为标准情形,无论是否采用本实施例中的select_fittest_cpu接口函数的方法,任务A都将抢先处理器P2上的任务。
场景2:处理器P2不允许抢先,或中断被关闭,处理器P3允许抢先、中断开放。该场景下,如果不采用本实施例中的select_fittest_cpu接口函数的方法,任务A将试图抢先处理器P2上的当前任务,由于不能成功,任务A被迫等待;如果采用本实施例中的select_fittest_cpu接口函数的方法,则任务A将增加处理器P2的抢先计数,将处理器P2加入任务A的抢先列表,然后考察处理器P3,发现处理器P3上运行的任务C可被抢先,则将任务A的抢先任务列表表项移动到任务C的抢先列表;然后任务A抢先处理器P3上的当前任务,从而可以立即执行。当处理器P2允许抢先时,它发现自己的抢先计数不为0,从全局队列和局部队列中选取最应该执行的任务,假设为任务C,调度运行之。另一种可能是:在处理器P2允许抢先前,处理器P0上的任务放弃使用CPU,或者降低优先权,拉取高优先权任务C,调度执行之,任务C在被调度时减少处理器P2的抢先计数,从而处理器P2在允许抢先时不再检查是否需要进行调度。
场景3:处理器P2、处理器P3均不允许抢先,或中断被关闭;处理器P2先开放抢先,处理器P3紧接着开放抢先。该场景下,如果不采用本实施例中的select_fittest_cpu接口函数的方法,任务A将试图抢先处理器P2上的当前任务,由于不能成功,任务A被迫等待;如果采用本实施例中的select_fittest_cpu接口函数的方法,任务A被唤醒时发现无法抢先处理器P2和处理器P3,增加处理器P2和处理器P3的抢先计数器值,并将处理器P2和处理器P3放入任务A的抢先列表中,然后被放入全局队列中;在处理器P2开放抢先时,发现自己的抢先计数器的计数不为0,从全局队列和局部队列中选取最应该在本处理器上运行的任务,假设该任务为任务A,任务A抢先处理器P2上的任务,并根据抢先列表,减小处理器P3的抢先计数。这样在处理器P3开放抢先时,不会发现有人试图抢先,从而不会运行额外的调度处理。
场景4:处理器P2、处理器P3均不允许抢先,或中断被关闭;处理器P3先开放抢先,处理器P2紧接着开放抢先。该场景下,采用本实施例中的select_fittest_cpu接口函数的方法时,任务A被唤醒时发现无法抢先处理器P2和处理器P3,增加处理器P2和处理器P3的抢先计数器值,并将处理器P2和处理器P3放入任务A的抢先列表中,然后被放入全局队列中;在处理器P3开放抢先时,发现自己的 抢先计数不为0,从全局队列和局部队列中选取最应该在本处理器上运行的任务,假设为任务A,任务A抢先处理器P3上的任务,并根据抢先列表,减小处理器P2的抢先计数,然后为根据任务C的抢先列表,增加列表中处理器的抢先计数,这样当处理器P2开放抢先时,任务C可获得执行。
如图3所示,本实施例中步骤3)中各个处理器分别执行选择在当前处理器上运行的任务的详细步骤如下:
3.1)获得当前处理器的sched_cnt_rwl写锁。
3.2)将当前处理器的sched_cnt信息增1、try_pr_cnt信息设为0(try_pr_cnt←0)。
3.3)释放当前处理器的sched_cnt_rwl写锁。
3.4)执行next←get_local()获取当前处理器本地的局部队列中最高实时优先权的任务放在变量next中,执行curr←get_curp()获取当前处理器上正在运行的任务放在变量curr中;其中,“←”表示赋值操作,下文中的含义相同。
3.5)获取变量curr对应任务的sched_lock写锁。
3.6)判断变量curr对应任务的sched_st信息curr.sched_st,若变量curr对应任务的sched_st信息curr.sched_st为PRD,则执行next←get_global(next)根据变量curr对应任务从全局队列中获取一个任务Tg放在变量next中,且获取的任务Tg满足下述条件④~⑥,④任务Tg的实时优先权高于变量curr对应任务的实时优先权;⑤任务Tg的抢先列表ctab中,当前处理器编号对应的tried_cpu项中包含有效内容;⑥在所有满足条件④和⑤的所有任务中,任务Tg的实时优先权最高。
3.7)判断变量next和变量curr是否相同,若变量next和变量curr相同,则释放变量curr对应任务的sched_lock写锁,并返回继续执行变量curr对应的任务;否则跳转执行下一步。
3.8)判断变量curr对应任务的sched_st信息是否为PRD,若curr对应任务的sched_st信息为PRD,则执行dequeue_local(cur)将变量curr对应任务从当前处理器的局部队列中删除,并执行enqueue_virt(cur)将变量curr对应任务添加至全局队列,然后设置变量curr对应任务的sched_st信息为ING。
3.9)判断变量curr对应任务是否需要继续运行,如果不需要继续运行,则设置变量curr对应任务的sched_st信息为SLEP,执行dequeue_local(curr)将变量curr对应任务从当前处理器的局部队列中删除,将变量curr对应的任务作为待清除任务,执行clear_record(curr)删除待清除任务的相关记录信息,然后跳转执行步骤3.10);如果需要继续运行,则直接跳转执行步骤3.10)。
3.10)设置当前处理器正在运行的任务为变量next对应的任务。
3.11)释放变量curr对应任务的sched_lock写锁。
3.12)判断变量next对应任务当前的sched_lock状态,若sched_lock状态为无锁或读锁,则跳转执行步骤3.13);否则,设置当前处理器当前运行的任务为空闲任务idle,执行next←get_local()获取当前处理器本地的局部队列中最高实时优先权的任务放在变量next中,执行next←get_global(next)以变量next对应的任务作为查找失败的默认返回值从全局队列中获取一个任务Tg放在变量next中,且获取的任务Tg满足下述条件④~⑥,④任务Tg的实时优先权高于变量curr对应任务的实时优先权;⑤任务Tg的抢先列表ctab中,当前处理器编号对应的tried_cpu项中包含有效内容;⑥在所有满足条件④和⑤的所有任务中,任务Tg的实时优先权最高;设置当前运行的任务为变量next对应的任务,跳转重新执行步骤3.12)。
3.13)试图获取变量next对应任务的sched_lock写锁,若失败则跳转执行步骤3.12);否则,跳转执行步骤3.14)。
3.14)读取变量next对应任务的sched_st信息next.sched_st,若变量next对应任务的sched_st信息next.sched_st不是PRD,跳转执行步骤3.17),否则跳转执行步骤3.15)。
3.15)判断变量next对应的任务是否在全局队列中,如果在全局队列中,则设置变量next对应任务的sched_st信息为ING,否则设置变量next对应任务的sched_st信息为INL;
3.16)释放变量next对应任务的sched_lock写锁,跳转执行步骤3.12)。
3.17)将变量next对应的任务作为待清除任务,执行clear_record(next)删除待清除任务的相关记录信息。
3.18)判断变量next对应的任务是否在全局队列中,如果在全局队列中,则执行dequeue_virt(next)将变量next对应的任务从全局队列中删除,并执行enqueue_local(next)将变量next对应的任务添加至当前处理器的局部队列,然后跳转执行步骤3.19);否则如果不在全局队列中,则直接跳转执行步骤3.19)。
3.19)设置变量next对应的任务的sched_st信息为RUN。
3.20)释放变量next对应的任务的sched_lock写锁,开始执行变量next对应的任务。
上述步骤3.1)~3.20)中,函数get_local为获取本地的局部队列中最高实时优先权的任务。函数enqueue_local(Tg)为将任务Tg从添加到局部队列,函数dequeue_local(TL)为将任务TL从局部队列删除。函数enqueue_virt(TASKx)为将TASKx放入全局队列virtual_q;函数dequeue_virt(TASKk)为将TASKk任务从全局队列virtual_q中删除,函数enqueue_virt(TASKx)和dequeue_virt(TASKk)一般可以将其实现为单向链表,通过原子执行“比较交换”操作来达到对于链表的无锁插入和删除。函数get_global(TASKstd)为获取全局队列virtual_q队列中的一个满足条件CONDB的任务Tg,若没有找到这样的Tg,则get_global返回任务TASKstd。条件CONDB:① 实时优先权高于任务TASKstd的实时优先权;② 此任务对应的ctab中,当前处理器编号对应的项中包含有效内容;③ 在所有满足性质①②的任务中,Tg的实时优先权最高。函数get_curp()返回当前处理器上正在运行的任务。需要说明的是,上述函数的实现均为本领的公知手段,因此本实施例不再对其进行详细说明。
如图4所示,本实施例中步骤3.9)和步骤3.17)中执行clear_record函数删除待清除任务的相关记录信息的详细步骤如下:
3.9.1)检查待清除任务task的抢先列表ctabtask.ctab中是否包含有效记录,若待清除任务的抢先列表ctabtask.ctab中不包含有效记录,则返回;否则,跳转执行步骤3.9.2);
3.9.2)获取待清除任务的抢先列表ctab中的第一个有效记录(有效记录的表现形式为<tried_cpu,snapshot>,其含义为此任务试图抢先在处理器tried_cpu上运行的任务,但抢先失败了,且在失败时处理器tried_cpu对应的sched_cnt值为snapshot),首先将有效记录删除。
3.9.3)判断已删除有效记录中的tried_cpu信息是否与本处理器相同,如果是则跳转执行步骤3.9.1);否则,跳转执行步骤3.9.4)。
3.9.4)获取已删除有效记录中的tried_cpu信息对应处理器的sched_cnt_rwl读锁tried_cpu.sched_cnt_rwl。
3.9.5)读取已删除有效记录中的tried_cpu信息对应处理器的sched_cnt信息tried_cpu. sched_cnt,如果sched_cnt信息的值与已删除有效记录中的snapshot的值相同,则将已删除有效记录中的tried_cpu信息对应处理器的try_pr_cnt信息的值以原子方式减1。
3.9.6)释放已删除有效记录中的tried_cpu信息对应处理器的sched_cnt_rwl读锁;跳转执行步骤3.9.1)。
本实施例通过中断状态切换模块对外提供enable_intr和disable_intr两个接口。当任务在执行时需要暂时关闭处理器对于中断的响应时,应调用本模块的disable_intr接口;当任务执行完不能被中断程打断的代码后,应调用本模块的enable_intr接口,使得处理器重新可以随时对中断做出响应。
如图5所示,本实施例中步骤3)中通过执行“关闭对中断的响应”操作修改抢先允许状态标明中断已禁止(调用disable_intr接口函数实现)的详细步骤包括:
3.21)将当前处理器的intr_mask_st信息this.intr_mask_st设置为DIS完成执行“关闭对中断的响应”操作,修改抢先允许状态标明中断已禁止。
3.22)判断当前处理器的pr_dis_cnt信息(this.pr_dis_cnt)为1、try_pr_cnt(this.try_pr_cnt)不为0两个条件是否同时不成立,如果两个条件不能同时成立,则关闭当前处理器对物理中断的响应,当前处理器返回执行当前处理器上运行的任务,“关闭对中断的响应”操作执行完毕,退出;否则如果两个条件同时成立,则跳转执行下一步。
3.23)将当前处理器的intr_mask_st信息this.intr_mask_st设置为ENA完成执行“打开对中断的响应”操作,修改抢先允许状态标明中断已打开。
3.24)当前处理器执行选择在当前处理器上运行的任务(即调用new_schedule),跳转执行步骤3.21)。
如图6所示,本实施例中步骤3)中通过执行“打开对中断的响应”操作修改抢先允许状态标明中断已开放(调用enable_intr接口函数实现)的详细步骤包括:
3.25)打开当前处理器对物理中断的响应。
3.26)执行this.intr_mask_st←ENA将当前处理器的intr_mask_st信息this.intr_mask_st设置为ENA,完成执行“打开对中断的响应”操作,修改抢先允许状态标明中断已打开。
3.27)判断当前处理器的pr_dis_cnt信息this.pr_dis_cnt为0、try_pr_cnt(this.try_pr_cnt)不为0两个条件是否同时不成立,如果两个条件不能同时成立,当前处理器返回执行当前处理器上运行的任务;否则如果两个条件同时成立,则当前处理器执行选择在当前处理器上运行的任务(即调用new_schedule)。
本实施例通过抢先状态改变模块提供preempt_enable和preempt_disable两个接口。当任务在执行不能被抢先的代码前,应使用preempt_disable禁止抢先;当任务执行完不能被抢先的代码后,应调用本模块的preempt_enable接口。
如图7所示,本实施例中步骤3)中修改抢先允许状态标明抢先已禁止(调用preempt_disable接口函数实现)的详细步骤如下:
3.28)将当前处理器的pr_dis_cnt信息this.pr_dis_cnt的值增1。
3.29)判断当前处理器的pr_dis_cnt信息this.pr_dis_cnt的值为1、try_pr_cnt信息this.try_pr_cnt的值不为0、intr_mask_st信息this.intr_mask_st的值为ENA三个条件是否同时成立,如果同时成立则跳转执行步骤3.30);否则,当前处理器返回执行当前处理器上运行的任务;
3.30)将当前处理器的pr_dis_cnt信息this.pr_dis_cnt的值设置为0。
3.31)当前处理器执行选择在当前处理器上运行的任务(即调用new_schedule),跳转执行步骤3.28);
如图8所示,本实施例中步骤3)中修改抢先允许状态标明抢先已开放(调用preempt_enable接口函数实现)的详细步骤如下:
3.32)将当前处理器的pr_dis_cnt信息this.pr_dis_cnt的值减1。
3.33)判断当前处理器的pr_dis_cnt信息this.pr_dis_cnt的值为0、try_pr_cnt信息this.try_pr_cnt的值不为0、intr_mask_st信息this.intr_mask_st的值为ENA三个条件是否同时成立,如果三个条件同时成立,则跳转执行步骤3.34);否则,当前处理器返回执行当前处理器上运行的任务;
3.34)当前处理器执行选择在当前处理器上运行的任务(调用new_schedule)。
如图9所示,本实施例要求操作系统为每个有实时要求任务维护的sched_st信息为枚举类型的变量,用于描述此任务的执行状态。其值域为{ RUN,PRD,INL,ING, SLEP}。RUN表示该任务正在运行;PRD表示该任务原本在运行,但刚刚被抢先,还未放入到待运行队列中;INL表示该任务在局部队列中等待调度运行;ING表示该任务在全局队列中等待调度运行;SLEP表示该任务目前还在等待除CPU之外的其它运行条件获得满足。当任务不需要运行时,处于SLEP状态;某些外部事件会将该任务唤醒,将其首先放入全局队列中,从而转变为ING状态。此时调度器会寻找在哪个处理器上运行此任务,有四种情况:a)确定应立即运行此任务,且顺利运行,则此任务进入RUN状态;b)确定应立即运行此任务,但在运行之前就被其它更高优先级的任务抢先,则它进入PRD状态;c)确定当前应由另外的某个处理器运行此任务,将此任务放入对应处理器的局部队列,任务进入INL状态。d)没有找到合适的处理器运行此任务,此时任务停留在ING状态。INL状态的任务若被成功调度,则转入RUN状态,开始运行,也有可能在运行前就被抢先,进入PRD状态;new_schedule在运行时,发现刚调度上来的任务进入了PRD状态,就知道调度失败了,将这个任务重新放入此任务原来所在的调度队列,并将其状态更新为相应值(ING或INL);处于运行状态的任务若被抢先,则进入PRD状态;若此任务暂时不需要处理器,则进入SLEP状态。
如图10所示,本实施例在操作系统启动各个处理器后,各个接口调用步骤如下:Ⅰ)调用init_cpu,初始化各个处理器的状态信息。Ⅱ)调用init_rt_intr,对实时中断处理相关例程进行设置。Ⅲ)创建任务,调用init_rt_task,对实时任务进行初始化。Ⅳ)任务激活后调度任务运行,首先调用select_fittest_cpu确定任务将在哪个调度队列中排队等待运行。Ⅴ)各个处理器分别执行分配的任务。任务在执行过程中,可能需要暂时的关闭中断,以防止中断处理程序干扰任务运行;任务也有可能需要暂时禁止任务抢先机制,以执行不允许其它任务插入执行的代码。在运行不允许插入执行中断处理程序的代码前,调用disable_intr接口,在运行不允许插入执行中断处理程序的代码后,调用enable_intr接口。在运行不允许其它任务插入执行的代码前,调用preempt_disable接口,在运行不允许其它任务插入执行的代码后,调用preempt_enable接口。在执行内核中与任务相关的其它功能的时候,则允许抢先和中断。
本实施例与传统调度算法只有一个全局队列或完全分布的局部队列不同,本发明采取局部队列与全局队列相结合的方法。其中,各处理器对应的局部队列中存放确定将在该处理器上运行的任务;全局队列存放暂时没有找到合适处理器运行的任务。本实施例在为高优先权任务选取运行的处理器时,先把任务暂存到全局队列中,然后检查处理器状态信息,避开该表中标明不能马上实施抢先的处理器(即:中断或抢先已临时关闭),若能找到合适的处理器,则将其放入此处理器的局部队列中,否则任务停留在全局队列,并将不能马上实施抢先的处理器的试图被抢先计数器增1。本实施例任务在关闭/打开对中断的响应时,将此中断的关闭、打开信息记录到全系统可见的位置(intr_mask_st信息); 任务在打开/关闭对抢先的支持时,将此抢先的打开、关闭信息记录到全系统可见的位置(pr_dis_cnt信息);任务在关闭对中断的响应前和打开对中断的响应后,若发现自己的试图被抢先计数器值不为0,则检查全局队列中是否有任务要抢先自己;任务在关闭对抢先的支持前,或打开对抢先的支持后,若发现本处理器被标记为候选处理器,则会检查当前全局队列中是否有任务要抢先自己;当任务被运行时,若调度器曾经增加了某个处理器的试图被抢先计数器,则此时将对应处理器的试图被抢先计数器减1。
本实施例中,操作系统中保留系统内编号最大的处理器,该处理器仅被系统用于接收实时相关中断,不能用于调度用户任务,所有处理器均可运行中断状态切换模块。在传统的操作系统中的任务调度方法中,调度器为某个新唤醒的任务选取处理器时仅考虑各个处理器上当前任务的实时优先级,不考虑这些处理器是否已通过“关中断”、“关抢先”等方式禁止了被派发到其上的高优先级任务立即获得执行权。本实施例中,每当处理器需要暂时禁止抢先时,它都通过修改禁止抢先计数和中断关闭状态变量,让其它处理器可以查询此处理器的状态,从而主动避免“因将任务派发到不能立刻实施抢先的处理器上而导致任务被延迟处理”。比如,在实时优先级数值越大,就越优先执行时,正在处理器1上运行的任务T1的实时优先级为10,但它当前关闭了中断或抢先;正在处理器2上运行任务T2的实时优先权为20,它没有关闭中断或抢先,T2当前唤醒了一个实时优先权为30的任务T3。在传统的实现中,处理器2上的调度器可能会决定由处理器1来运行任务T3。但这会导致任务T3被迫等T1执行,直到其把中断或抢先打开。此外,本实施例中,为每个处理器维护一个调度函数执行次数信息—sched_cnt。处理器2在为任务T3选取处理器时,会发现处理器1运行的任务T1虽具有较低的优先级,但不能马上实施抢先,就不会选择有处理器1运行T3,而是仅增加此处理器的试图被抢先计数器的值,并获得处理器1当前的sched_cnt值作为变量SCHED_CNT,然后选择其它的处理器,如处理器2,运行任务T3。后文假设选择的是处理器2。调度器会登记“若T2运行了,且处理器1上的调度函数执行次数为变量SCHED_CNT时,则减少处理器1的试图被抢先计数器”。此时,本实施例事实上会造成“低优先级的任务T1能够运行,高优先级的任务T2不能运行”,为了避免这种情况,当低优先级的任务T1结束禁止抢先状态后,会检查自己的试图被抢先计数,若发现其不为0,就综合全局队列和局部队列,选取出一个任务,比如是任务T2,并运行之。在任务T1结束禁止抢先状态之前,任务T2也有可能被另外的处理器,如处理器3,调度运行。此时它会试图减小处理器1的试图被抢先计数器,以使得任务T1结束禁止抢先状态之后不进行调度队列的检查工作。若处理器1在此时仍然没有运行过调度函数,则其sched_cnt必然等于变量SCHED_CNT,故系统会减少处理器1的试图被抢先计数器;若从试图抢先处理器1上的任务,到现在,处理器1已经运行过调度函数,则说明其已考虑过任务抢先问题,故“减小处理器1的试图被抢先计数器”会被视为过时信息,而被丢弃。处理器每执行一次“选取哪个任务在本处理器上运行”的调度函数,就会更新一下自己的调度函数执行次数变量,并将试图被抢先计数器清零,以向外界宣告:本处理器已进入新的历史时代,之前基于老的调度函数执行次数变量的所做的一切决策都作废(这些决策比如:当某任务运行时,减小此处理器的试图被抢先计数器值)。在此函数执行时,若发现当前任务是被抢先了,则会把它放入全局队列中(这样其它的处理器在检查完试图被抢先计数器后,在检查全局队列中的任务时会发现这个被抢先的任务)。
以上所述仅是本发明的优选实施方式,本发明的保护范围并不仅局限于上述实施例,凡属于本发明思路下的技术方案均属于本发明的保护范围。应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理前提下的若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。
Claims (7)
1.一种基于资源预约的两级混合任务调度方法,其特征在于实施步骤如下:
1)在操作系统系统初始化启动各个处理器时,为各个处理器建立用于存放确定将在该处理器上运行任务的局部队列、用于记录试图被抢先次数的抢先计数器以及抢先允许状态,所述抢先允许状态用于表示处理器的中断或抢先的开放/禁止情况;建立用于存放暂时没有找到合适处理器运行任务的全局队列;所述在操作系统系统初始化启动各个处理器时,分别为每一个处理器分配sched_cnt、sched_cnt_rwl、try_pr_cnt、pr_dis_cnt、intr_mask_st信息的存储空间,其中,sched_cnt用于记录了从开机至今在此处理器上调度函数的执行次数,sched_cnt_rwl为一个读写锁,处理器在修改自己对应的sched_cnt信息前,需要以“写”的方式获得自己对应的sched_cnt_rwl,处理器在查看其它处理器对应的sched_cnt信息前,需要以“读”的方式获得相应处理器对应的sched_cnt_rwl;try_pr_cnt用于记录从本处理器上次执行调度函数至今,中间有试图抢先本处理器上的当前任务的任务数量;pr_dis_cnt用于记录此处理器上正在运行的任务目前净累积的“禁止抢先请求”次数,若任务先执行了N次“禁止抢先请求”,接下来执行了N-1次“允许抢先请求”,则此任务pr_dis_cnt的值为1;若在pr_dis_cnt为0时,任务仍然执行“允许抢先请求”,则pr_dis_cnt仍然为0;intr_mask_st为一个枚举类型变量,值域为{DIS,ENA},其值仅受任务执行时的“打开对中断的响应”、“关闭对中断的响应”两类操作的影响,任务在本处理器上执行“关闭对中断的响应”操作后,则intr_mask_st值变为DIS;任务在本处理器上执行“打开对中断的响应”操作后,则intr_mask_st值变为ENA;
2)将新创建或刚被唤醒的当前任务暂存到全局队列中,在当前任务在全局队列被调度运行时遍历所有的处理器选择在哪个处理器上运行当前任务,且在选择处理器时检查各个处理器的抢先允许状态,避开抢先允许状态标明中断或抢先已禁止而不能马上实施抢先的处理器,若能找到合适的处理器,则将当前任务放入所找到处理器的局部队列中并跳转执行步骤3);否则,将当前任务继续停留在全局队列,并通过抢先计数器记录不能马上实施抢先的处理器的试图被抢先次数,然后等待下一次在全局队列被调度运行;
3)各个处理器分别执行选择在当前处理器上运行的任务,在执行任务过程中,如果遇到不允许插入执行中断处理程序的代码,则通过执行“关闭对中断的响应”操作修改抢先允许状态标明中断已禁止,返回执行所述不允许插入执行中断处理程序的代码,最终通过执行“打开对中断的响应”操作修改抢先允许状态标明中断已开放;如果遇到不允许插入执行的代码,则修改抢先允许状态标明抢先已禁止,返回执行所述不允许插入执行的代码,最终修改抢先允许状态标明抢先已开放。
2.根据权利要求1所述的基于资源预约的两级混合任务调度方法,其特征在于:所述步骤1)中建立用于存放暂时没有找到合适处理器运行任务的全局队列具体是指启动一个虚拟处理器,针对该虚拟处理器建立一个用于缓存任务的任务调度队列作为用于存放暂时没有找到合适处理器运行任务的全局队列。
3.根据权利要求2所述的基于资源预约的两级混合任务调度方法,其特征在于,所述步骤2)中将新创建或刚被唤醒的当前任务暂存到全局队列中之前,还包括为当前任务初始化分配ctab、sched_lock,sched_st,vlistn信息的存储空间的步骤;其中,ctab为抢先列表,用于记录本任务所试图抢先、但因对方禁止了抢先,而没有抢先成功的信息,由于系统中同时运行的任务个数不超过在线处理器的数量,故ctab最多包含的元素个数不大于在线处理器数量,ctab记录的每一项可用<tried_cpu,snapshot>来表示,其含义为此任务试图抢先在处理器tried_cpu上运行的任务,但抢先失败了,且在失败时处理器tried_cpu对应的sched_cnt值为snapshot;sched_lock为一个读写锁,在需清除ctab中信息时,应先获得写锁;在需向ctab中添加信息时,应先获得读锁,在需为某任务寻找合适的处理器运行时,应先获得写锁;vlistn为一个指向全局队列中下一个待调度任务的指针;sched_st为一个枚举类型的变量,用于描述此任务的执行状态,其值域为{ RUN,PRD,INL,ING,SLEP},其中RUN表示该任务正在运行,PRD表示该任务原本在运行,但刚刚被抢先,还未放入到待运行队列中,INL表示该任务在局部队列中等待调度运行,ING表示该任务在全局队列中等待调度运行,SLEP表示该任务目前还在等待除CPU之外的其它运行条件获得满足,新创建的任务的sched_st默认为SLEP;所述步骤2)的详细步骤如下:
2.1)令预先建立的用于临时存储抢先列表ctab的临时抢先列表R为空,令当前任务T的抢先列表ctab为空,令变量first_try的值为true、变量low的值为系统所允许的最低优先权、变量high的值为当前任务T的实时优先权减1,将当前任务T对应的sched_st信息设置为ING,其中变量first_try用于指示是不是第一次就找到了被抢先任务,若变量first_try为true,则说明第一次就找到的任务没有禁止掉抢先,传统的处理逻辑不会影响系统响应,若变量first_try为false,则说明是当前正在运行的最低优先级的任务禁止掉了抢先,系统决定抢先非最低优先级任务;变量low是本次循环中当前任务T考虑可以抢先的任务最低应具有优先级;变量high是本次循环中当前任务T考虑可以抢先的任务最高应具有优先级;设置用于指定执行当前任务T的处理器的变量proc的值为所述虚拟处理器;
2.2)将当前任务T放入全局队列中;
2.3)为当前任务T在指定的处理器集合中筛选出所有可运行用户任务的处理器集合S,并将筛选得到的处理器集合S保存;
2.4)判断处理器集合S是否为空集,如果为空集则跳转执行步骤2.22);否则,跳转执行下一步;
2.5)获得当前任务T应当抢先的处理器,将得到的处理器放入变量proc中,然后获得变量proc对应处理器上当前正在运行的任务X;
2.6)试图获取当前任务T对应的sched_lock读锁,若获取失败,则令变量proc的值为虚拟处理器、临时抢先列表R的值为空,跳转执行步骤2.22);否则跳转执行下一步;
2.7)获取当前任务T的sched_st信息,若当前任务T对应的sched_st不是ING,则首先令变量proc的值为虚拟处理器、变量first_try的值为true、临时抢先列表R的值为空,然后跳转执行步骤2.15);否则,跳转执行下一步;
2.8)获得变量proc对应处理器的sched_cnt_rwl读锁;
2.9)读取变量proc对应处理器的sched_cnt信息,将读取的sched_cnt信息、变量proc对应处理器两者作为一条记录存入临时抢先列表R;
2.10)获得变量proc对应处理器的try_pr_cnt信息增1;
2.11)释放变量proc对应处理器的sched_cnt_rwl读锁;
2.12)判断变量proc对应处理器的pr_dis_cnt信息为0、intr_mask_st信息为ENA两个条件是否同时成立,如果同时成立则跳转执行步骤2.13);否则如果不能同时成立,则释放当前任务T对应的sched_lock读锁,从处理器集合S中去掉变量proc对应的处理器,然后判断处理器集合S是否变为空集,如果处理器集合S不是空集则跳转执行步骤2.5);如果处理器集合S是空集,则令变量first_try的值为false、变量low的值为变量proc对应的处理器的当前实时优先权加1、变量proc的值为所述虚拟处理器,跳转执行步骤2.3);
2.13)将当前任务T对应的sched_st信息设为INL;
2.14)将当前任务T从全局队列中删除,并将当前任务T添加至变量proc对应处理器的局部队列中;
2.15)释放当前任务T对应的sched_lock读锁;
2.16)判断变量first_try的值,若first_try的值为true,则跳转执行步骤2.22),否则跳转执行步骤2.17);
2.17)获得变量proc对应处理器上当前正在运行的任务X对应的sched_lock的读锁;
2.18)检查所述任务X的sched_st信息,若所述任务X对应的sched_st信息不是RUN状态,则从处理器集合S中去掉变量proc对应的处理器,然后判断处理器集合S是否变为空集,如果处理器集合S不是空集则跳转执行步骤2.5);如果处理器集合S是空集,则令变量first_try的值为false、变量low的值为变量proc对应的处理器的当前实时优先权加1、变量proc的值为所述虚拟处理器,跳转执行步骤2.3);若任务X对应的sched_st信息是RUN状态,则跳转执行下一步;
2.19)将所述任务X对应的sched_st信息设为PRD状态;
2.20)将临时抢先列表R的内容填写到所述任务X的抢先列表ctab中,再令临时抢先列表R为空;
2.21)释放所述任务X对应的sched_lock读锁;
2.22)将临时抢先列表R复制到当前任务T的抢先列表ctab中,返回变量proc对应处理器即为被选中用于运行当前任务T的处理器。
4.根据权利要求3所述的基于资源预约的两级混合任务调度方法,其特征在于,所述步骤3)中各个处理器分别执行选择在当前处理器上运行的任务的详细步骤如下:
3.1)获得当前处理器的sched_cnt_rwl写锁;
3.2)将当前处理器的sched_cnt信息增1、try_pr_cnt信息设为0;
3.3)释放当前处理器的sched_cnt_rwl写锁;
3.4)获取当前处理器本地的局部队列中最高实时优先权的任务放在变量next中,获取当前处理器上正在运行的任务放在变量curr中;
3.5)获取变量curr对应任务的sched_lock写锁;
3.6)判断变量curr对应任务的sched_st信息,若变量curr对应任务的sched_st信息为PRD,则根据变量curr对应任务从全局队列中获取一个任务Tg放在变量next中,且获取的任务Tg满足下述条件④~⑥,④任务Tg的实时优先权高于变量curr对应任务的实时优先权;⑤任务Tg的抢先列表ctab中,当前处理器编号对应的tried_cpu项中包含有效内容;⑥在所有满足条件④和⑤的所有任务中,任务Tg的实时优先权最高;
3.7)判断变量next和变量curr是否相同,若变量next和变量curr相同,则释放变量curr对应任务的sched_lock写锁,并返回继续执行变量curr对应的任务;否则跳转执行下一步;
3.8)判断变量curr对应任务的sched_st信息是否为PRD,若curr对应任务的sched_st信息为PRD,则将变量curr对应任务从当前处理器的局部队列中删除,并将变量curr对应任务添加至全局队列,然后设置变量curr对应任务的sched_st信息为ING;
3.9)判断变量curr对应任务是否需要继续运行,如果不需要继续运行,则设置变量curr对应任务的sched_st信息为SLEP,将变量curr对应任务从当前处理器的局部队列中删除,将变量curr对应的任务作为待清除任务,删除待清除任务的相关记录信息,然后跳转执行步骤3.10);如果需要继续运行,则直接跳转执行步骤3.10);
3.10)设置当前处理器正在运行的任务为变量next对应的任务;
3.11)释放变量curr对应任务的sched_lock写锁;
3.12)判断变量next对应任务当前的sched_lock状态,若sched_lock状态为无锁或读锁,则跳转执行步骤3.13);否则,设置当前处理器当前运行的任务为空闲任务,获取当前处理器本地的局部队列中最高实时优先权的任务放在变量next中,以变量next对应的任务作为查找失败的默认返回值从全局队列中获取一个任务Tg放在变量next中,且获取的任务Tg满足下述条件④~⑥,④任务Tg的实时优先权高于变量curr对应任务的实时优先权;⑤任务Tg的抢先列表ctab中,当前处理器编号对应的tried_cpu项中包含有效内容;⑥在所有满足条件④和⑤的所有任务中,任务Tg的实时优先权最高;设置当前运行的任务为变量next对应的任务,跳转重新执行步骤3.12);
3.13)试图获取变量next对应任务的sched_lock写锁,若失败则跳转执行步骤3.12);否则,跳转执行步骤3.14);
3.14)读取变量next对应任务的sched_st信息,若变量next对应任务的sched_st信息不是PRD,跳转执行步骤3.17),否则跳转执行步骤3.15);
3.15)判断变量next对应的任务是否在全局队列中,如果在全局队列中,则设置变量next对应任务的sched_st信息为ING,否则设置变量next对应任务的sched_st信息为INL;
3.16)释放变量next对应任务的sched_lock写锁,跳转执行步骤3.12);
3.17)将变量next对应的任务作为待清除任务,删除待清除任务的相关记录信息;
3.18)判断变量next对应的任务是否在全局队列中,如果在全局队列中,则将变量next对应的任务从全局队列中删除,并将变量next对应的任务添加至当前处理器的局部队列,然后跳转执行步骤3.19);否则如果不在全局队列中,则直接跳转执行步骤3.19);
3.19)设置变量next对应的任务的sched_st信息为RUN;
3.20)释放变量next对应的任务的sched_lock写锁,开始执行变量next对应的任务。
5.根据权利要求4所述的基于资源预约的两级混合任务调度方法,其特征在于,所述步骤3.9)和步骤3.17)中删除待清除任务的相关记录信息的详细步骤如下:
3.9.1)检查待清除任务的抢先列表ctab中是否包含有效记录,若待清除任务的抢先列表ctab中不包含有效记录,则返回;否则,跳转执行步骤3.9.2);
3.9.2)获取待清除任务的抢先列表ctab中的第一个有效记录,首先将所述有效记录删除;
3.9.3)判断已删除有效记录中的tried_cpu信息是否与本处理器相同,如果是则跳转执行步骤3.9.1);否则,跳转执行步骤3.9.4);
3.9.4)获取已删除有效记录中的tried_cpu信息对应处理器的sched_cnt_rwl读锁;
3.9.5)读取已删除有效记录中的tried_cpu信息对应处理器的sched_cnt信息,如果所述sched_cnt信息的值与已删除有效记录中的snapshot的值相同,则将已删除有效记录中的tried_cpu信息对应处理器的try_pr_cnt信息的值以原子方式减1;
3.9.6)释放已删除有效记录中的tried_cpu信息对应处理器的sched_cnt_rwl读锁;跳转执行步骤3.9.1)。
6.根据权利要求5所述的基于资源预约的两级混合任务调度方法,其特征在于,所述步骤3)中通过执行“关闭对中断的响应”操作修改抢先允许状态标明中断已禁止的详细步骤包括:
3.21)将当前处理器的intr_mask_st信息设置为DIS完成执行“关闭对中断的响应”操作,修改抢先允许状态标明中断已禁止;
3.22)判断当前处理器的pr_dis_cnt信息为1、try_pr_cnt不为0两个条件是否同时不成立,如果两个条件不能同时成立,则关闭当前处理器对物理中断的响应,当前处理器返回执行当前处理器上运行的任务;否则如果两个条件同时成立,则跳转执行下一步;
3.23)将当前处理器的intr_mask_st信息设置为ENA完成执行“打开对中断的响应”操作,修改抢先允许状态标明中断已打开;
3.24)当前处理器执行选择在当前处理器上运行的任务,跳转执行步骤3.21);
所述步骤3)中通过执行“打开对中断的响应”操作修改抢先允许状态标明中断已开放的详细步骤包括:
3.25)打开当前处理器对物理中断的响应;
3.26)将当前处理器的intr_mask_st信息设置为ENA完成执行“打开对中断的响应”操作,修改抢先允许状态标明中断已打开;
3.27)判断当前处理器的pr_dis_cnt信息为0、try_pr_cnt不为0两个条件是否同时不成立,如果两个条件不能同时成立,当前处理器返回执行当前处理器上运行的任务;否则如果两个条件同时成立,则当前处理器执行选择在当前处理器上运行的任务。
7.根据权利要求6所述的基于资源预约的两级混合任务调度方法,其特征在于,所述步骤3)中修改抢先允许状态标明抢先已禁止的详细步骤如下:
3.28)将当前处理器的pr_dis_cnt信息的值增1;
3.29)判断当前处理器的pr_dis_cnt信息的值为1、try_pr_cnt信息的值不为0、intr_mask_st信息的值为ENA三个条件是否同时成立,如果同时成立则跳转执行步骤3.30);否则,当前处理器返回执行当前处理器上运行的任务;
3.30)将当前处理器的pr_dis_cnt信息的值设置为0;
3.31)当前处理器执行选择在当前处理器上运行的任务,跳转执行步骤3.28);
所述步骤3)中修改抢先允许状态标明抢先已开放的详细步骤如下:
3.32)将当前处理器的pr_dis_cnt信息的值减1;
3.33)判断当前处理器的pr_dis_cnt信息的值为0、try_pr_cnt信息的值不为0、intr_mask_st信息的值为ENA三个条件是否同时成立,如果三个条件同时成立,则跳转执行步骤3.34);否则,当前处理器返回执行当前处理器上运行的任务;
3.34)当前处理器执行选择在当前处理器上运行的任务。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201410215702.1A CN103995743B (zh) | 2014-05-21 | 2014-05-21 | 基于资源预约的两级混合任务调度方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201410215702.1A CN103995743B (zh) | 2014-05-21 | 2014-05-21 | 基于资源预约的两级混合任务调度方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN103995743A CN103995743A (zh) | 2014-08-20 |
CN103995743B true CN103995743B (zh) | 2015-04-29 |
Family
ID=51309917
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201410215702.1A Active CN103995743B (zh) | 2014-05-21 | 2014-05-21 | 基于资源预约的两级混合任务调度方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN103995743B (zh) |
Families Citing this family (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN105260234A (zh) * | 2015-09-22 | 2016-01-20 | 浙江工商大学 | 基于独立任务列表的过程动态执行优化方法 |
CN106095696B (zh) * | 2016-07-26 | 2018-11-09 | 上海航天测控通信研究所 | 一种基于自适应路由及调度策略的高速缓存装置 |
CN111708639A (zh) * | 2020-06-22 | 2020-09-25 | 中国科学技术大学 | 任务调度系统及方法、存储介质及电子设备 |
Family Cites Families (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US9063796B2 (en) * | 2012-08-02 | 2015-06-23 | GM Global Technology Operations LLC | Method and apparatus for improving processing performance of a multi-core processor |
CN103676727A (zh) * | 2013-11-27 | 2014-03-26 | 南京国电南自美卓控制系统有限公司 | 基于嵌入式芯片的可抢占、可嵌套中断控制方法 |
-
2014
- 2014-05-21 CN CN201410215702.1A patent/CN103995743B/zh active Active
Also Published As
Publication number | Publication date |
---|---|
CN103995743A (zh) | 2014-08-20 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US20220214930A1 (en) | Systems and Methods for Performing Concurrency Restriction and Throttling over Contended Locks | |
US9430388B2 (en) | Scheduler, multi-core processor system, and scheduling method | |
US5274809A (en) | Task execution control method for a multiprocessor system with enhanced post/wait procedure | |
CN100481009C (zh) | 根据客户软件的特许级向虚拟机转移的系统、装置和方法 | |
US8959515B2 (en) | Task scheduling policy for limited memory systems | |
KR100934533B1 (ko) | 연산 처리 시스템, 컴퓨터 시스템 상에서의 태스크 제어 방법, 및 컴퓨터 프로그램을 기록한 컴퓨터 판독 가능한 기록 매체 | |
CN109828833B (zh) | 一种神经网络训练任务的排队系统及其方法 | |
US7370326B2 (en) | Prerequisite-based scheduler | |
CN104272256B (zh) | 任务处理装置 | |
TWI729003B (zh) | 用於在存在衝突時進行高效任務排程的方法、設備及處理器可讀儲存媒體 | |
US6754736B1 (en) | Information processing apparatus, data inputting/outputting method, and program storage medium therefor | |
CN112306699B (zh) | 访问临界资源的方法及装置、计算机设备及可读存储介质 | |
CN103995743B (zh) | 基于资源预约的两级混合任务调度方法 | |
JPWO2011096163A1 (ja) | 情報処理システム、排他制御方法および排他制御用プログラム | |
CN112363812B (zh) | 基于任务分类的数据库连接队列管理方法及存储介质 | |
EP0343646B1 (en) | Task execution control method for a multiprocessor system with enhanced post/wait procedure | |
WO2023241307A1 (zh) | 管理线程的方法及装置 | |
CN111989651A (zh) | 在多核系统中管理内核服务的方法和装置 | |
CN115309531A (zh) | 基于实时任务队列的高并发多任务调度管理方法 | |
JP2008225641A (ja) | コンピュータシステム、割り込み制御方法及びプログラム | |
JPH01297760A (ja) | タスク制御方式及びオンライン・トランザクション・システム | |
CN113961364A (zh) | 一种大规模锁系统实现方法、装置、存储介质和服务器 | |
JPH1027122A (ja) | データベース管理システム | |
CN115509713A (zh) | 一种任务处理方法、系统、装置、电子设备及存储介质 | |
JP2023091314A (ja) | 半導体装置、半導体装置の制御方法及びプログラム |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
C14 | Grant of patent or utility model | ||
GR01 | Patent grant |