关于目前架构的线程调度逻辑
1、线程优先级越大,优先级越高
RCLibThreadSched::RegisterTask(&userTask, 38);
40的优先级比38的高。
使用此逻辑其实是将各个函数加入链表中,按照优先级串行执行,并不是严格意义的并发。
相同优先级的线程函数安装添加顺序先后执行,而不是并发。
2、线程调度逻辑
int main(){
SRCI_SCHED_InitUserTask(&userTask); //初始化
userTask.loop_func = test1; //用户线程, for test
RCLibThreadSched::RegisterTask(&userTask, 30);
SRCI_SCHED_InitUserTask(&userTask); //初始化
userTask.loop_func = test2; //用户线程, for test
RCLibThreadSched::RegisterTask(&userTask, 30);
SRCI_SCHED_InitUserTask(&userTask); //初始化
userTask.loop_func = test3; //用户线程, for test
RCLibThreadSched::RegisterTask(&userTask, 35);
}
假设有如上三个等级的线程函数,程序会先依照函数写的顺序,执行一遍,然后按照优先级来执行,即:
test1 -> test2 -> test3 test3 -> test1-> tset2 循环下去
SRCI_HANDLE handle = (SRCI_HANDLE)arg;
SRCI_SCHED_Wait(handle); //等待调度
此线程等待实际是挂起, 之前测试过test1 2 3 均为死循环,但是3里加了usleep延时挂起, 发现usleep也不会卡死整个子线程,但是日志打印的时间会出现100ms的情况,所以最好用这个线程调度函数。
加上此函数后,日志打印时间正常,整个串行链表的程序运行一遍时间为20ms ,这个可以根据主线程运行时间调,若超出20ms可以把此时间加大。
只适用如上程序加线程调度函数,
res = SRCI_Thread_Init(CAlarmManager::AlarmResponse, this, 20, &_m_alarm_thread);
这个函数开的子线程不能用线程调度。
3、线程卡住情况测试
① 不加等待调度函数的情况下
void test1{
while(1){
log.......
}
}
void test2{
while(1){
log.......
}
}
void test3{
while(1){
log.......
}
}
高等级的test3会卡住test1,test1一直抢不到资源
②加线程调度加锁
void test1{
lock
while(1){
SRCI_SCHED_Wait(handle); //等待调度
log11111111111
}
}
void test3{
lock
while(1){
SRCI_SCHED_Wait(handle); //等待调度
log3333333333
}
}
加上线程调度的执行逻辑: 程序依照添加顺序先执行wait函数以上的代码,然后再安装优先级顺序执行wait函数之后的代码,相当于在wait处挂起。
运行结果是 一直打11111111111111111111
这也是低优先级程序会把高优先级程序卡住的一种情况,高优先级程序相当于挂起等待解锁,让出资源,并不会把低优先级程序卡死
③加线程调度不加锁
void test1{
while(1){
log11111111111
}
}
void test3{
while(1){
SRCI_SCHED_Wait(handle); //等待调度
log3333333333
}
}
上述函数为 test3 加了线程调度函数,而test1为死循环
这是另一种低优先级函数会把高优先级函数卡住的情况
④加解锁的测试情况
void test1(){
while(1){
lock
log 111111
sleep(1);
unlock;
log 111111122222
}
}
void test3(){
while(1){
lock
log 2222222;
unlock
}
}
程序在test1 unlock之后并不会运行log 1111111122222,因为在unlock的一瞬间,资源会被更高优先级的test3抢走,运行log222222,test3在test1 sleep 1秒的过程中阻塞了50个20ms,所以跑完50个test3后,才会运行log111111111111222222