在实时操作系统中,task是有优先级的,这里的优先级体现的是对CPU的使用权。按理说为了保证关键任务的执行,不光CPU,其他的系统资源,比如内存,也应该优先为这些任务提供服务才对。
操作系统可以保证关键任务对内存的需求,比如在中断上下文,或者持有spinlock的任务(两者都属于atomic上下文),通过GFP_ATOMIC标志位向内核申请内存,在系统内存不足的情况下,可以使用内核预留的内存(参考这篇文章)。
现在处理器的高速cache越来越大,常用的内存数据都是放在cache中的,CPU主要和cache打交道,而操作系统是没法让cache优先为某个任务服务的。
为此,intel从Xeon E5 v4系列处理器开始,提供了一种叫Cache Allocation Technology(CAT)的技术,可以让系统软件(OS或者虚拟化中的hypervisor)为某个应用划定可以使用的最外层的cache(LLC - Last Level Cache,通常为L3)空间的大小,后续新的处理器甚至支持对L2的划分。
在CAT技术中,任务对cache使用的优先级是通过classes of service (COS)来标定的,而cache的空间根据划分,比如一个有32个cache line的4-wat set associative的cache,其含有的set就是8个。
软件对CAT的配着和使用过程是这样的:
OS初始化的时候通过CPUID指令查询得到当前的处理器支持的COS级数和L2/L3的cache sets数目,然后OS为每级COS配置对应的cache sets。假设当前处理器支持4级COS,COS 0优先级最高,COS 3最低。
如果每个COS级别的任务对所有cache都有相同的访问权(相当于没有使用CAT),其配置关系就是这样的(横向代表cache set,纵向代表COS,A代表可以Allocate):
让高优先级的任务可以访问的cache sets多于低优先级的任务,但某些cache sets可以被高优先级和低优先级的任务共享(overlap),则是这样的:
如果把高优先级和低优先级的任务对cache的使用完全隔离,则是这样的:
当发生context switch时,OS会为即将执行的task分配一个COS级别(系统启动后所有任务默认都是COS 0级的)。那这个task运行起来后怎么知道OS是怎么配置cache空间的,或者说哪些cache sets是它可以访问的?
获得cache使用权靠的是tag比对,前面的文章介绍过,比如VIPT,就是以物理地址做tag同cache line中的tag做匹配的,匹配的上就可以使用可以这个cache line。同样的,task会带上OS给它的代表COS的tag去匹配该COS级别对应的cache空间。
COS的分配是动态的,也就是说OS可以为同一个task在两次调度运行时分配不同的COS优先级,但是更换了COS级别,很可能就更换了cache sets(如果是overlap的配置则不一定),这样新的cache sets里就没有这个task常用的数据和代码,所以一般不推荐这样做。
如果想进一步细化不同task对代码和数据的使用,还可以利用基于CAT的扩展技术Code and Data Prioritization(CDP)。CDP默认是关闭的,如果开启,由于每个COS级别都分为Code和Data,所以系统支持的COS级别将减半。
原创文章,转载请注明出处。