同步官方代码,任务调度模块改动很大

    百图画鸿蒙 + 百文说内核 + 百万注源码  => 挖透鸿蒙内核源码
    鸿蒙研究站 | http://weharmonyos.com (国内)
              | https://weharmony.github.io (国外)
    oschina | https://my.oschina.net/weharmony
    博客园 | https://www.cnblogs.com/weharmony/
    知乎 | https://www.zhihu.com/people/weharmonyos
    csdn | https://blog.csdn.net/kuangyufei
    51cto | https://harmonyos.51cto.com/column/34
    掘金 | https://juejin.cn/user/756888642000808
    公众号 | 鸿蒙研究站 (weharmonyos)
上级 b6a46cc9
子曰:“里仁为美。择不处仁,焉得知?”《论语》:里仁篇
[![](https://gitee.com/weharmonyos/resources/raw/master/common/io.png)](http://weharmonyos.com/)
[![](http://weharmonyos.com/resources/common/io.png)](http://weharmonyos.com/)
**中文注解鸿蒙内核 | [kernel_liteos_a_note](https://gitee.com/weharmony/kernel_liteos_a_note)** 是在 `OpenHarmony`[kernel_liteos_a](https://gitee.com/openharmony/kernel_liteos_a) 基础上给内核源码加上中文注解的版本,同步官方代码迭代推进。
......@@ -26,7 +25,7 @@
* 如果把鸿蒙比作人,百图目的是要画出其骨骼系统。
* 百图系列每张图都是心血之作,耗时甚大,能用一张就绝不用两张,所以会画的比较复杂,高清图会很大,可在公众号中回复 **百图** 获取`3`倍超高清最新图。`v**.xx`代表图的版本,请留意图的更新。
* 例如: **双向链表** 是内核最重要的结构体,站长更愿意将它比喻成人的左右手,其意义是通过寄生在宿主结构体上来体现,可想象成在宿主结构体装上一对对勤劳的双手,它真的很会来事,超级活跃分子,为宿主到处拉朋友,建圈子。其插入 | 删除 | 遍历操作是它最常用的社交三大件,若不理解透彻在分析源码过程中很容易卡壳。虽在网上能找到很多它的图,但怎么看都不是自己想要的,干脆重画了它的主要操作。
* ![](https://gitee.com/weharmonyos/resources/raw/master/100pic/1_list.png)
* ![](http://weharmonyos.com/resources/100pic/1_list.png)
#### 二: 百文说内核 | 抓住主脉络 | 肌肉器官
......@@ -34,7 +33,7 @@
* 与代码需不断`debug`一样,文章内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,`v**.xx` 代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。
* 百文在 < 鸿蒙研究站 | 开源中国 | 博客园 | 51cto | csdn | 知乎 | 掘金 > 站点发布,公众号回复 **百文** 可方便阅读。
* ![](https://gitee.com/weharmonyos/resources/raw/master/common/cate.png)
* ![](http://weharmonyos.com/resources/common/cate.png)
**基础知识**
......@@ -77,20 +76,20 @@
* [v31.02 鸿蒙内核源码分析(内存规则) | 内存管理到底在管什么](http://weharmonyos.com/blog/31.html)
* [v32.04 鸿蒙内核源码分析(物理内存) | 真实的可不一定精彩](http://weharmonyos.com/blog/32.html)
* [v33.04 鸿蒙内核源码分析(虚拟内存) | 虚拟的也是真实的](http://weharmonyos.com/blog/33.html)
* [v34.03 鸿蒙内核源码分析(虚实映射) | 映射是种伟大的思想](http://weharmonyos.com/blog/34.html)
* [v35.03 鸿蒙内核源码分析(静态分配) | 内存有哪些分配方式](http://weharmonyos.com/blog/35.html)
* [v36.01 鸿蒙内核源码分析(动态分配) | 正在制作中 ... ](http://weharmonyos.com/blog/36.html)
* [v37.04 鸿蒙内核源码分析(原子操作) | 谁在为完整性保驾护航](http://weharmonyos.com/blog/37.html)
* [v38.02 鸿蒙内核源码分析(页表管理) | 谁是虚拟内存实现的基础](http://weharmonyos.com/blog/38.html)
* [v39.01 鸿蒙内核源码分析(I/O映射) | 正在制作中 ... ](http://weharmonyos.com/blog/39.html)
* [v34.03 鸿蒙内核源码分析(虚实映射) | 映射是伟大的发明](http://weharmonyos.com/blog/34.html)
* [v35.02 鸿蒙内核源码分析(页表管理) | 映射关系保存在哪](http://weharmonyos.com/blog/35.html)
* [v36.03 鸿蒙内核源码分析(静态分配) | 很简单的一位小朋友](http://weharmonyos.com/blog/36.html)
* [v37.01 鸿蒙内核源码分析(TLFS算法) | 用图解读TLFS原理 ](http://weharmonyos.com/blog/37.html)
* [v38.01 鸿蒙内核源码分析(内存池管理) | 如何高效切割合并内存块 ](http://weharmonyos.com/blog/38.html)
* [v39.04 鸿蒙内核源码分析(原子操作) | 谁在守护指令执行的完整性](http://weharmonyos.com/blog/39.html)
* [v40.01 鸿蒙内核源码分析(圆整对齐) | 正在制作中 ... ](http://weharmonyos.com/blog/40.html)
**通讯机制**
* [v41.04 鸿蒙内核源码分析(通讯总览) | 内核跟人一样都喜欢八卦](http://weharmonyos.com/blog/41.html)
* [v42.08 鸿蒙内核源码分析(自旋锁) | 死等丈夫归来的贞洁烈女](http://weharmonyos.com/blog/42.html)
* [v43.05 鸿蒙内核源码分析(互斥锁) | 同样是锁它却更丰满](http://weharmonyos.com/blog/43.html)
* [v44.02 鸿蒙内核源码分析(快锁使用) | 用户态下的快锁Futex(上)](http://weharmonyos.com/blog/44.html)
* [v45.02 鸿蒙内核源码分析(快锁实现) | 内核态下的快锁Futex(下)](http://weharmonyos.com/blog/45.html)
* [v43.05 鸿蒙内核源码分析(互斥锁) | 有你没她 相安无事](http://weharmonyos.com/blog/43.html)
* [v44.02 鸿蒙内核源码分析(快锁使用) | 用户态负责快锁逻辑](http://weharmonyos.com/blog/44.html)
* [v45.02 鸿蒙内核源码分析(快锁实现) | 内核态负责快锁调度](http://weharmonyos.com/blog/45.html)
* [v46.01 鸿蒙内核源码分析(读写锁) | 内核如何实现多读单写](http://weharmonyos.com/blog/46.html)
* [v47.05 鸿蒙内核源码分析(信号量) | 谁在解决任务间的同步](http://weharmonyos.com/blog/47.html)
* [v48.07 鸿蒙内核源码分析(事件机制) | 多对多任务如何同步](http://weharmonyos.com/blog/48.html)
......@@ -113,19 +112,19 @@
* [v63.03 鸿蒙内核源码分析(文件映射) | 正在制作中 ... ](http://weharmonyos.com/blog/63.html)
* [v64.01 鸿蒙内核源码分析(写时拷贝) | 正在制作中 ... ](http://weharmonyos.com/blog/64.html)
**软硬相接**
* [v65.03 鸿蒙内核源码分析(CPU结构) | 正在制作中 ... ](http://weharmonyos.com/blog/65.html)
* [v66.01 鸿蒙内核源码分析(协处理器) | 正在制作中 ... ](http://weharmonyos.com/blog/66.html)
* [v67.05 鸿蒙内核源码分析(工作模式) | 羡慕韦小宝这么多老婆](http://weharmonyos.com/blog/67.html)
* [v68.01 鸿蒙内核源码分析(异常处理) | 不如意事十之八九 ](http://weharmonyos.com/blog/68.html)
* [v69.06 鸿蒙内核源码分析(寄存器) | 真牛把世界玩出花来了](http://weharmonyos.com/blog/69.html)
* [v70.03 鸿蒙内核源码分析(多核管理) | 真正并发的基础](http://weharmonyos.com/blog/70.html)
* [v71.05 鸿蒙内核源码分析(中断概念) | 海公公的日常工作](http://weharmonyos.com/blog/71.html)
* [v72.04 鸿蒙内核源码分析(中断管理) | 没中断太可怕](http://weharmonyos.com/blog/72.html)
* [v73.01 鸿蒙内核源码分析(移值适配) | 正在制作中 ... ](http://weharmonyos.com/blog/73.html)
**硬件架构**
* [v65.01 鸿蒙内核源码分析(芯片模式) | 回顾芯片行业各位大佬](http://weharmonyos.com/blog/65.html)
* [v66.03 鸿蒙内核源码分析(ARM架构) | ARMv7 & Cortex(A|R|M)](http://weharmonyos.com/blog/66.html)
* [v67.01 鸿蒙内核源码分析(指令集) | CICS PK RICS](http://weharmonyos.com/blog/67.html)
* [v68.01 鸿蒙内核源码分析(协处理器) | CPU的好帮手 ](http://weharmonyos.com/blog/68.html)
* [v69.05 鸿蒙内核源码分析(工作模式) | 角色不同 责任不同](http://weharmonyos.com/blog/69.html)
* [v70.06 鸿蒙内核源码分析(寄存器) | 世界被它们玩出了花](http://weharmonyos.com/blog/70.html)
* [v71.03 鸿蒙内核源码分析(多核管理) | 并发真正的基础](http://weharmonyos.com/blog/71.html)
* [v72.05 鸿蒙内核源码分析(中断概念) | 海公公的日常工作](http://weharmonyos.com/blog/72.html)
* [v73.04 鸿蒙内核源码分析(中断管理) | 没中断太可怕](http://weharmonyos.com/blog/73.html)
**内核汇编**
* [v74.01 鸿蒙内核源码分析(汇编指令) | 正在制作中 ... ](http://weharmonyos.com/blog/74.html)
* [v74.01 鸿蒙内核源码分析(编码方式) | 机器指令是如何编码的 ](http://weharmonyos.com/blog/74.html)
* [v75.03 鸿蒙内核源码分析(汇编基础) | CPU上班也要打卡](http://weharmonyos.com/blog/75.html)
* [v76.04 鸿蒙内核源码分析(汇编传参) | 如何传递复杂的参数](http://weharmonyos.com/blog/76.html)
* [v77.01 鸿蒙内核源码分析(可变参数) | 正在制作中 ... ](http://weharmonyos.com/blog/77.html)
......@@ -158,24 +157,24 @@
* [v100.01 鸿蒙内核源码分析(测试用例) | 正在制作中 ... ](http://weharmonyos.com/blog/100.html)
**前因后果**
* [v101.03 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析](http://weharmonyos.com/blog/101.html)
* [v101.03 鸿蒙内核源码分析(总目录) | 精雕细琢 锤炼精品](http://weharmonyos.com/blog/101.html)
* [v102.05 鸿蒙内核源码分析(源码注释) | 每天死磕一点点](http://weharmonyos.com/blog/102.html)
* [v103.05 鸿蒙内核源码分析(静态站点) | 码农都不爱写注释和文档](http://weharmonyos.com/blog/103.html)
* [v104.01 鸿蒙内核源码分析(参考文档) | 阅读内核源码必备工具](http://weharmonyos.com/blog/104.html)
* [v104.01 鸿蒙内核源码分析(参考手册) | 阅读内核源码必备工具](http://weharmonyos.com/blog/104.html)
#### 三: 百万注内核 | 处处扣细节 | 细胞血管
* 百万汉字注解内核目的是要看清楚其毛细血管,细胞结构,等于在拿放大镜看内核。内核并不神秘,带着问题去源码中找答案是很容易上瘾的,你会发现很多文章对一些问题的解读是错误的,或者说不深刻难以自圆其说,你会慢慢形成自己新的解读,而新的解读又会碰到新的问题,如此层层递进,滚滚向前,拿着放大镜根本不愿意放手。
* 因鸿蒙内核6W+代码量,本身只有较少的注释, 中文注解以不对原有代码侵入为前提,源码中所有英文部分都是原有注释,所有中文部分都是中文版的注释,同时为方便同步官方版本的更新,尽量不去增加代码的行数,不破坏文件的结构,注释多类似以下的方式:
在重要模块的`.c/.h`文件开始位置先对模块功能做整体的介绍,例如异常接管模块注解如图所示:
![](https://gitee.com/weharmonyos/resources/raw/master/13/ycjg.png)
* 在重要模块的`.c/.h`文件开始位置先对模块功能做整体的介绍,例如异常接管模块注解如图所示:
![](http://weharmonyos.com/resources/13/ycjg.png)
注解过程中查阅了很多的资料和书籍,在具体代码处都附上了参考链接。
* 而函数级注解会详细到重点行,甚至每一行, 例如申请互斥锁的主体函数,不可谓不重要,而官方注释仅有一行,如图所示
![](https://gitee.com/weharmonyos/resources/raw/master/13/sop.png)
* 绘制字符图帮助理解模块 ,例如 虚拟内存区域分布没有图很难理解。
![](http://weharmonyos.com/resources/13/vm.png)
* 而函数级注解会详细到重点行,甚至每一行, 例如申请互斥锁的主体函数,不可谓不重要,而官方注释仅有一行,如图所示
![](http://weharmonyos.com/resources/13/sop.png)
* 注解创建了一些特殊记号,可直接搜索查看
- [x] 搜索 `@note_pic` 可查看绘制的全部字符图
......@@ -189,15 +188,16 @@
在中文加注版基础上构建了参考手册,如此可以看到毛细血管级的网络图,注解支持 [doxygen](https://www.doxygen.nl) 格式标准。
* 图为内核`main`的调用关系直观展现,如果没有这张图,光`main`一个函数就够喝一壶。 `main`本身是由汇编指令 `bl main`调用
![](https://gitee.com/weharmonyos/resources/raw/master/73/1.png)
![](http://weharmonyos.com/resources/73/1.png)
可前往 >> [鸿蒙研究站 | 参考手册 ](http://weharmonyos.com/doxygen/index.html) 体验
* 图为内核所有结构体索引,点击可查看每个结构变量细节
![](https://gitee.com/weharmonyos/resources/raw/master/73/6.png)
![](http://weharmonyos.com/resources/73/6.png)
可前往 >> [鸿蒙研究站 | 结构体索引 ](http://weharmonyos.com/doxygen/classes.html) 体验
### 四大码仓发布 | 源码同步官方
内核注解同时在 [gitee](https://gitee.com/weharmony/kernel_liteos_a_note) | [github](https://github.com/kuangyufei/kernel_liteos_a_note) | [coding](https://weharmony.coding.net/public/harmony/kernel_liteos_a_note/git/files) | [gitcode](https://gitcode.net/kuangyufei/kernel_liteos_a_note) 发布,并与官方源码按月保持同步,同步历史如下:
* `2022/04/16` -- 任务调度模块有很大更新
* `2022/03/23` -- 新增各CPU核自主管理中断, 定时器模块较大调整
* `2022/02/18` -- 官方无代码更新, 只有测试用例的完善
* `2022/01/20` -- 同步官方代码,本次官方对测试用例和MMU做了较大调整
......@@ -225,13 +225,13 @@
### 关于 zzz 目录
中文加注版比官方版无新增文件,只多了一个`zzz`的目录,里面放了一些加注所需文件,它与内核代码无关,可以忽略它,取名`zzz`是为了排在最后,减少对原有代码目录级的侵入,`zzz` 的想法源于微信中名称为`AAA`的那帮朋友,你的微信里应该也有他们熟悉的身影吧 :|P
* ![](https://gitee.com/weharmonyos/resources/raw/master/13/cate.png)
* ![](http://weharmonyos.com/resources/13/cate.png)
### 官方文档 | 静态站点呈现
* 研究鸿蒙需不断的翻阅资料,吸取别人的精华,其中官方文档必不可少, 为更好的呈现 **OpenHarmony开发者文档** , 特意做了静态站点 [ >> 鸿蒙研究站 | 官方文档](http://weharmonyos.com/openharmony) 来方便搜索,阅读官方资料。
* 左侧导航栏,右边索引区
![](https://gitee.com/weharmonyos/resources/raw/master/52/4.png)
![](http://weharmonyos.com/resources/52/4.png)
* [鸿蒙研究站](http://weharmonyos.com) 定位于做一个专注而靠谱的技术站, 没有广告,干净简洁,对鸿蒙研究会持续在上面输出。同时感谢资助鸿蒙研究和网站建设的小伙伴,很温暖。 [ >> 送温暖记录](http://weharmonyos.com/donate.html)
......@@ -240,7 +240,7 @@
### 关注不迷路 | 代码即人生
![](https://gitee.com/weharmonyos/resources/raw/master/common/so1so.png)
![](http://weharmonyos.com/resources/common/so1so.png)
原创不易,欢迎转载,请注明出处。
据说喜欢点赞分享的,后来都成了大神。:)
......@@ -32,13 +32,15 @@
#ifndef _SHELL_PRI_H
#define _SHELL_PRI_H
#include "shell.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern void *ShellEntry(void *argv);
extern void ShellEntry(ShellCB *shellCB);
extern void *ShellTask(void *argv);
#ifdef __cplusplus
......
......@@ -32,6 +32,7 @@
#ifndef _SHMSG_H
#define _SHMSG_H
#include "shell_list.h"
#include "shell.h"
#ifdef __cplusplus
......@@ -59,10 +60,9 @@ extern "C" {
#define COLOR_L_RED "\e[1;31m"
#define SHELL_PROMPT COLOR_L_RED"OHOS # "COLOR_NONE ///< shell 红色提示 OHOS #
typedef void (*OutputFunc)(const char *fmt, ...);
typedef void (* OutputFunc)(const char *fmt, ...);
extern int ShellTaskInit(ShellCB *shellCB);
extern int ShellEntryInit(ShellCB *shellCB);
extern void ChildExec(const char *cmdName, char *const paramArray[]);
extern void ChildExec(const char *cmdName, char *const paramArray[], bool foreground);
extern void ShellCmdLineParse(char c, OutputFunc outputFunc, ShellCB *shellCB);
extern int ShellNotify(ShellCB *shellCB);
......
......@@ -31,13 +31,16 @@
#define _GNU_SOURCE
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "show.h"
#include "shmsg.h"
#include "shcmd.h"
#include "shell_pri.h"
#include "semaphore.h"
#include "securec.h"
#include "unistd.h"
#include <sys/syscall.h>
ShellCB *g_shellCB = NULL; ///< 全部shell控制块
/// 获取shell控制块
......@@ -77,13 +80,8 @@ static int OsShellCreateTask(ShellCB *shellCB)
goto OUT;
}
ret = ShellEntryInit(shellCB);
if (ret != SH_OK) {
goto OUT;
}
(void)pthread_join(shellCB->shellTaskHandle, NULL);
(void)pthread_join(shellCB->shellEntryHandle, NULL);
shellCB->shellEntryHandle = pthread_self();
return 0;
OUT:
ShellDeinit(shellCB);
......@@ -98,7 +96,7 @@ static int DoShellExec(char **argv)
char *cmdLine = NULL;
if (strncmp(argv[0], SHELL_EXEC_COMMAND, SHELL_EXEC_COMMAND_BYTES) == 0) {
ChildExec(argv[1], argv + 1);
ChildExec(argv[1], argv + 1, FALSE);
}
for (i = 0; argv[i]; i++) {
len += strlen(argv[i]);
......@@ -124,12 +122,22 @@ static int DoShellExec(char **argv)
free(cmdLine);
return ret;
}
static void ShellSigChildHook(int sig)
{
(void)sig;
while (waitpid(-1, NULL, WNOHANG) > 0) {
continue;
}
}
/// shell进程的入口函数
int main(int argc, char **argv)
{
int ret = SH_NOK;
ShellCB *shellCB = NULL;
(void)signal(SIGCHLD, ShellSigChildHook);
if (argc > 1) {
ret = DoShellExec(argv + 1);
return ret;
......@@ -165,7 +173,12 @@ int main(int argc, char **argv)
sem_init(&shellCB->shellSem, 0, 0);//信号量初始化
g_shellCB = shellCB;//全局变量,说明鸿蒙同时只支持一个shell进程
return OsShellCreateTask(shellCB);//初始化两个任务
ret = OsShellCreateTask(shellCB);
if (ret != SH_OK) {
goto ERR_OUT3;
}
ShellEntry(shellCB);
ERR_OUT3:
(void)pthread_mutex_destroy(&shellCB->historyMutex);
......
......@@ -351,7 +351,7 @@ char *GetCmdName(const char *cmdline, unsigned int len)
return cmdName;
}
void ChildExec(const char *cmdName, char *const paramArray[])
void ChildExec(const char *cmdName, char *const paramArray[], bool foreground)
{
int ret;
pid_t gid;
......@@ -367,10 +367,12 @@ void ChildExec(const char *cmdName, char *const paramArray[])
exit(1);
}
ret = tcsetpgrp(STDIN_FILENO, gid);
if (ret != 0) {
printf("tcsetpgrp failed, errno %d\n", errno);
exit(1);
if (!foreground) {
ret = tcsetpgrp(STDIN_FILENO, gid);
if (ret != 0) {
printf("tcsetpgrp failed, errno %d\n", errno);
exit(1);
}
}
ret = execve(cmdName, paramArray, NULL);
......@@ -404,20 +406,30 @@ int CheckExit(const char *cmdName, const CmdParsed *cmdParsed)
exit(ret);
}
static void DoCmdExec(const char *cmdName, const char *cmdline, unsigned int len, const CmdParsed *cmdParsed)
static void DoCmdExec(const char *cmdName, const char *cmdline, unsigned int len, CmdParsed *cmdParsed)
{
bool foreground = FALSE;
int ret;
pid_t forkPid;
if (strncmp(cmdline, CMD_EXEC_COMMAND, CMD_EXEC_COMMAND_BYTES) == 0) {
if ((cmdParsed->paramCnt > 1) && (strcmp(cmdParsed->paramArray[cmdParsed->paramCnt - 1], "&") == 0)) {
free(cmdParsed->paramArray[cmdParsed->paramCnt - 1]);
cmdParsed->paramArray[cmdParsed->paramCnt - 1] = NULL;
cmdParsed->paramCnt--;
foreground = TRUE;
}
forkPid = fork();
if (forkPid < 0) {
printf("Faild to fork from shell\n");
return;
} else if (forkPid == 0) {
ChildExec(cmdParsed->paramArray[0], cmdParsed->paramArray);
ChildExec(cmdParsed->paramArray[0], cmdParsed->paramArray, foreground);
} else {
waitpid(forkPid, 0, 0);
if (!foreground) {
(void)waitpid(forkPid, 0, 0);
}
ret = tcsetpgrp(STDIN_FILENO, getpid());
if (ret != 0) {
printf("tcsetpgrp failed, errno %d\n", errno);
......@@ -567,20 +579,10 @@ static void ExecCmdline(const char *cmdline)
free(output);
}
void RecycleZombieChild(void)
{
while (waitpid(-1, NULL, WNOHANG) > 0) {
continue;
}
}
static void ShellCmdProcess(ShellCB *shellCB)
{
char *buf = NULL;
while (1) {
/* recycle zombine child process */
RecycleZombieChild();
buf = GetCmdline(shellCB);
char *buf = GetCmdline(shellCB);
if (buf == NULL) {
break;
}
......@@ -654,25 +656,19 @@ static int ShellKernelReg(unsigned int shellHandle)
return ioctl(STDIN_FILENO, CONSOLE_CONTROL_REG_USERTASK, shellHandle);//Shell Entry 任务将从标准输入中读取数据
}
void *ShellEntry(void *argv)
void ShellEntry(ShellCB *shellCB)
{
char ch;
int ret;
int n;
pid_t tid = syscall(__NR_gettid);//获取当前任务/线程ID, 即 "Shell Entry" 任务的ID
ShellCB *shellCB = (ShellCB *)argv;
if (shellCB == NULL) {
return NULL;
return;
}
(void)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);
ret = prctl(PR_SET_NAME, "ShellEntry");//将任务的名称设置成 ShellEntry
if (ret != SH_OK) {
return NULL;
}
ret = ShellKernelReg((int)tid);//向内核注册shell,和控制台捆绑在一块
if (ret != 0) {
printf("another shell is already running!\n");
......@@ -685,32 +681,5 @@ void *ShellEntry(void *argv)
ShellCmdLineParse(ch, (OutputFunc)printf, shellCB);//对命令行内容进行解析
}
}
return NULL;
}
int ShellEntryInit(ShellCB *shellCB)
{
int ret;
size_t stackSize = SHELL_ENTRY_STACKSIZE;
void *arg = NULL;
pthread_attr_t attr;
if (shellCB == NULL) {
return SH_NOK;
}
ret = pthread_attr_init(&attr);
if (ret != SH_OK) {
return SH_NOK;
}
pthread_attr_setstacksize(&attr, stackSize);
arg = (void *)shellCB;
ret = pthread_create(&shellCB->shellEntryHandle, &attr, &ShellEntry, arg);
if (ret != SH_OK) {
return SH_NOK;
}
return ret;
return;
}
......@@ -88,7 +88,7 @@ extern "C" {
#define MMU_DESCRIPTOR_L1_SECTION_ADDR(x) ((x) & MMU_DESCRIPTOR_L1_SMALL_FRAME)
#define MMU_DESCRIPTOR_L1_PAGE_TABLE_ADDR(x) ((x) & ~((1 << 10)-1))
#define MMU_DESCRIPTOR_L1_SMALL_L2_TABLES_PER_PAGE 4
#define MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS 0x4000U ///< 16Kb 小页页表条目(4096个页表项)
#define MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS 0x4000U ///< 页表必须按16Kb对齐,因为C2寄存器低14位得为0
#define MMU_DESCRIPTOR_L1_SMALL_DOMAIN_MASK (~(0x0f << 5)) /* 4k page section domain mask */
#define MMU_DESCRIPTOR_L1_SMALL_DOMAIN_CLIENT (MMU_DESCRIPTOR_DOMAIN_CLIENT << 5)
......@@ -131,10 +131,10 @@ extern "C" {
#define MMU_DESCRIPTOR_L1_AP_P_RO_U_NA (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_1)
#define MMU_DESCRIPTOR_L1_AP_MASK (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_3)
#define MMU_DESCRIPTOR_L2_SMALL_SIZE 0x1000
#define MMU_DESCRIPTOR_L2_SMALL_SIZE 0x1000 // L2 小页大小 4K
#define MMU_DESCRIPTOR_L2_SMALL_MASK (MMU_DESCRIPTOR_L2_SMALL_SIZE - 1)
#define MMU_DESCRIPTOR_L2_SMALL_FRAME (~MMU_DESCRIPTOR_L2_SMALL_MASK)
#define MMU_DESCRIPTOR_L2_SMALL_SHIFT 12
#define MMU_DESCRIPTOR_L2_SMALL_SHIFT 12 //小页偏移 12位
#define MMU_DESCRIPTOR_L2_NUMBERS_PER_L1 \
(MMU_DESCRIPTOR_L1_SMALL_SIZE >> MMU_DESCRIPTOR_L2_SMALL_SHIFT)
#define MMU_DESCRIPTOR_IS_L2_SIZE_ALIGNED(x) IS_ALIGNED(x, MMU_DESCRIPTOR_L2_SMALL_SIZE)
......
......@@ -1094,16 +1094,16 @@ STATUS_T LOS_ArchMmuDestroy(LosArchMmu *archMmu)
#endif
return LOS_OK;
}
/// 切换临时页表
STATIC VOID OsSwitchTmpTTB(VOID)
{
PTE_T *tmpTtbase = NULL;
errno_t err;
LosVmSpace *kSpace = LOS_GetKVmSpace();
/* ttbr address should be 16KByte align */
/* ttbr address should be 16KByte align | 页表应该 16Kb对齐,因为 TTB寄存器的低14位为 0 */
tmpTtbase = LOS_MemAllocAlign(m_aucSysMem0, MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS,
MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS);
MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS);//分配页表
if (tmpTtbase == NULL) {
VM_ERR("memory alloc failed");
return;
......@@ -1166,7 +1166,7 @@ STATIC VOID OsSetKSectionAttr(UINTPTR virtAddr, BOOL uncached)
UINT32 kmallocLength;
UINT32 flags;
/* use second-level mapping of default READ and WRITE */
/* use second-level mapping of default READ and WRITE | 使用二级映射*/
kSpace->archMmu.virtTtb = (PTE_T *)g_firstPageTable;//__attribute__((section(".bss.prebss.translation_table"))) UINT8 g_firstPageTable[MMU_DESCRIPTOR_L1_SMALL_ENTRY_NUMBERS];
kSpace->archMmu.physTtb = LOS_PaddrQuery(kSpace->archMmu.virtTtb);//通过TTB虚拟地址查询TTB物理地址
status = LOS_ArchMmuUnmap(&kSpace->archMmu, virtAddr,
......@@ -1266,8 +1266,8 @@ VOID OsInitMappingStartUp(VOID)
OsSwitchTmpTTB();//切换到临时TTB ,请想想为何要切换到临时 @note_thinking
OsSetKSectionAttr(KERNEL_VMM_BASE, FALSE);
OsSetKSectionAttr(UNCACHED_VMM_BASE, TRUE);
OsSetKSectionAttr(KERNEL_VMM_BASE, FALSE);//设置内核空间属性
OsSetKSectionAttr(UNCACHED_VMM_BASE, TRUE);//设置未缓存空间属性
OsKSectionNewAttrEnable();
}
#endif
......
......@@ -215,7 +215,7 @@ VOID OsInterrupt(UINT32 intNum)//中断实际处理函数
++g_hwiFormCnt[cpuid][intNum];
OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, intNum);
OsSchedIrqUpdateUsedTime();
OsSchedIrqUsedTimeUpdate();
#ifdef LOSCFG_CPUP_INCLUDE_IRQ
OsCpupIrqEnd(cpuid, intNum);
......
......@@ -159,7 +159,7 @@ STATIC VOID SetPthreadAttr(const _pthread_data *self, const pthread_attr_t *attr
}
if (outAttr->inheritsched == PTHREAD_INHERIT_SCHED) {
if (self->task == NULL) {
outAttr->schedparam.sched_priority = ((LosTaskCB *)(OsCurrTaskGet()))->priority;
outAttr->schedparam.sched_priority = LOS_TaskPriGet(OsCurrTaskGet()->taskID);
} else {
outAttr->schedpolicy = self->attr.schedpolicy;
outAttr->schedparam = self->attr.schedparam;
......
......@@ -29,10 +29,9 @@ endchoice
config BOOTENV_ADDR
int "Address of boot command line (KB)"
depends on PLATFORM_ROOTFS && (STORAGE_SPINOR || STORAGE_SPINAND || STORAGE_EMMC)
range 0 1024
default 512
help
Boot command line addr, range from 0 to 1MB.
Boot command line addr.
config BOOTENV_RAM
bool "Read bootenv from RAM"
......
......@@ -164,23 +164,23 @@ static VOID DoEpollClose(struct epoll_head *epHead)
}
/**
* epoll_create,
* epoll_create unsupported api
*
* epoll_create is implemented by calling epoll_create1, it's parameter 'size' is useless.
*
* epoll_create1,
* The simple version of epoll does not use red-black trees,
* so when fd is normal value (greater than 0),
* actually allocated epoll can manage num of EPOLL_DEFAULT_SIZE
*
* @param size: not actually used
* @param flags: not actually used
* @return epoll fd
*/
int epoll_create(int size)
int epoll_create1(int flags)
{
(void)flags;
int fd = -1;
if (size <= 0) {
set_errno(EINVAL);
return fd;
}
struct epoll_head *epHead = (struct epoll_head *)malloc(sizeof(struct epoll_head));
if (epHead == NULL) {
set_errno(ENOMEM);
......
......@@ -61,18 +61,18 @@ extern "C" {
#define EPOLL_CTL_MOD 3
typedef union epoll_data {
void *ptr;
int fd;
UINT32 u32;
UINT64 u64;
void *ptr;
int fd;
UINT32 u32;
UINT64 u64;
} epoll_data_t;
struct epoll_event {
UINT32 events;
epoll_data_t data;
UINT32 events;
epoll_data_t data;
};
int epoll_create(int size);
int epoll_create1(int flags);
int epoll_close(int epfd);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev);
int epoll_wait(int epfd, FAR struct epoll_event *evs, int maxevents, int timeout);
......
# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
# Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
......@@ -65,10 +65,12 @@ kernel_module(module_name) {
"mp/los_mp.c",
"mp/los_percpu.c",
"mp/los_spinlock.c",
"mp/los_stat.c",
"om/los_err.c",
"sched/sched_sq/los_sched.c",
"sched/sched_sq/los_sortlink.c",
"sched/los_idle.c",
"sched/los_priority.c",
"sched/los_sched.c",
"sched/los_sortlink.c",
"sched/los_statistics.c",
"vm/los_vm_boot.c",
"vm/los_vm_dump.c",
"vm/los_vm_fault.c",
......
......@@ -37,7 +37,7 @@ LOCAL_SRCS := $(wildcard ipc/*.c) $(wildcard core/*.c) $(wildcard mem/membox/*.
$(wildcard misc/*.c)\
$(wildcard mem/tlsf/*.c) \
$(wildcard mp/*.c) \
$(wildcard sched/sched_sq/*.c) \
$(wildcard sched/*.c) \
$(wildcard vm/*.c)
LOCAL_FLAGS := $(LITEOS_CFLAGS_INTERWORK)
......
......@@ -113,7 +113,7 @@ VOID OsDeleteTaskFromProcess(LosTaskCB *taskCB)
OsTaskInsertToRecycleList(taskCB);
}
UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB)
UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB, SchedParam *param)
{
UINT32 intSave;
UINT16 numCount;
......@@ -126,12 +126,14 @@ UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB)
if (OsProcessIsUserMode(processCB)) {
taskCB->taskStatus |= OS_TASK_FLAG_USER_MODE;
if (processCB->threadNumber > 0) {
taskCB->basePrio = OS_TCB_FROM_TID(processCB->threadGroupID)->basePrio;
LosTaskCB *task = OS_TCB_FROM_TID(processCB->threadGroupID);
task->ops->schedParamGet(task, param);
} else {
taskCB->basePrio = OS_USER_PROCESS_PRIORITY_HIGHEST;
OsSchedProcessDefaultSchedParamGet(param->policy, param);
}
} else {
taskCB->basePrio = OsCurrTaskGet()->basePrio;
LosTaskCB *runTask = OsCurrTaskGet();
runTask->ops->schedParamGet(runTask, param);
}
#ifdef LOSCFG_KERNEL_VM
......@@ -324,7 +326,7 @@ STATIC LosProcessCB *OsFindExitChildProcess(const LosProcessCB *processCB, INT32
VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID)
{
taskCB->waitID = wakePID;
OsSchedTaskWake(taskCB);
taskCB->ops->wake(taskCB);
#ifdef LOSCFG_KERNEL_SMP
LOS_MpSchedule(OS_MP_CPU_ALL);//向所有cpu发送调度指令
#endif
......@@ -956,7 +958,7 @@ STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 p
}
#ifdef LOSCFG_SECURITY_CAPABILITY //检查进程的安全许可证
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio)
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedParam *param, UINT16 prio)
{
LosProcessCB *runProcess = OsCurrProcessGet();//获得当前进程
......@@ -966,7 +968,7 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio)
}
/* user mode process can reduce the priority of itself */
if ((runProcess->processID == processCB->processID) && (prio > OsCurrTaskGet()->basePrio)) {
if ((runProcess->processID == processCB->processID) && (prio > param->basePrio)) {
return TRUE;
}
......@@ -980,31 +982,33 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio)
/// 设置进程调度计划
LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
{
LosProcessCB *processCB = NULL;
BOOL needSched = FALSE;
SchedParam param = { 0 };
UINT32 intSave;
INT32 ret;
ret = OsProcessSchedlerParamCheck(which, pid, prio, policy);//先参数检查
INT32 ret = OsProcessSchedlerParamCheck(which, pid, prio, policy);
if (ret != LOS_OK) {
return -ret;
}
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
SCHEDULER_LOCK(intSave);//持有调度自旋锁,多CPU情况下调度期间需要原子处理
processCB = OS_PCB_FROM_PID(pid);
if (OsProcessIsInactive(processCB)) {//进程未活动的处理
ret = LOS_ESRCH;
goto EXIT;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
if (!OsProcessCapPermitCheck(processCB, prio)) {//检查是否安全
if (!OsProcessCapPermitCheck(processCB, &param, prio)) {
ret = LOS_EPERM;
goto EXIT;
}
#endif
needSched = OsSchedModifyProcessSchedParam(pid, policy, prio);
LosTaskCB *taskCB = OS_TCB_FROM_TID(processCB->threadGroupID);
taskCB->ops->schedParamGet(taskCB, &param);
param.basePrio = prio;
BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
SCHEDULER_UNLOCK(intSave);//还锁
LOS_MpSchedule(OS_MP_CPU_ALL);//核间中断
......@@ -1052,6 +1056,7 @@ LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
{
INT32 prio;
UINT32 intSave;
SchedParam param = { 0 };
(VOID)which;
if (OS_PID_CHECK_INVALID(pid)) {
......@@ -1069,11 +1074,12 @@ LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
goto OUT;
}
prio = (INT32)OS_TCB_FROM_TID(processCB->threadGroupID)->basePrio;
LosTaskCB *taskCB = OS_TCB_FROM_TID(processCB->threadGroupID);
taskCB->ops->schedParamGet(taskCB, &param);
OUT:
SCHEDULER_UNLOCK(intSave);
return prio;
return param.basePrio;
}
/// 接口封装 - 获取指定进程优先级
LITE_OS_SEC_TEXT INT32 LOS_GetProcessPriority(INT32 pid)
......@@ -1113,8 +1119,7 @@ STATIC VOID OsWaitInsertWaitListInOrder(LosTaskCB *runTask, LosProcessCB *proces
/* if runTask->waitFlag == OS_PROCESS_WAIT_PRO,
* this node is inserted directly into the header of the waitList
*/
(VOID)OsSchedTaskWait(list->pstNext, LOS_WAIT_FOREVER, TRUE);
(VOID)runTask->ops->wait(runTask, list->pstNext, LOS_WAIT_FOREVER);
return;
}
/// 设置等待子进程退出方式方法
......@@ -1265,13 +1270,10 @@ STATIC INT32 OsWait(INT32 pid, USER INT32 *status, USER siginfo_t *info, UINT32
UINT32 ret;
UINT32 intSave;
LosProcessCB *childCB = NULL;
LosProcessCB *processCB = NULL;
LosTaskCB *runTask = NULL;
LosProcessCB *processCB = OsCurrProcessGet();
LosTaskCB *runTask = OsCurrTaskGet();
SCHEDULER_LOCK(intSave);
processCB = OsCurrProcessGet(); //获取当前进程
runTask = OsCurrTaskGet(); //获取当前任务
ret = OsWaitChildProcessCheck(processCB, pid, &childCB);//先检查下看能不能找到参数要求的退出子进程
if (ret != LOS_OK) {
pid = -ret;
......@@ -1798,48 +1800,39 @@ STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB)
#endif
return LOS_OK;
}
//任务初始化时拷贝任务信息
STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size,
TSK_INIT_PARAM_S *childPara)
//拷贝一个Task过程
STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size)
{
LosTaskCB *mainThread = NULL;
UINT32 intSave;
LosTaskCB *runTask = OsCurrTaskGet();
TSK_INIT_PARAM_S taskParam = { 0 };
UINT32 ret, taskID, intSave;
SchedParam param = { 0 };
SCHEDULER_LOCK(intSave);
mainThread = OsCurrTaskGet();//获取当前task,注意变量名从这里也可以看出 thread 和 task 是一个概念,只是内核常说task,上层应用说thread ,概念的映射.
if (OsProcessIsUserMode(childProcessCB)) {//用户态进程
childPara->pfnTaskEntry = mainThread->taskEntry;//拷贝当前任务入口地址
childPara->uwStackSize = mainThread->stackSize; //栈空间大小
childPara->userParam.userArea = mainThread->userArea; //用户态栈区栈顶位置
childPara->userParam.userMapBase = mainThread->userMapBase; //用户态栈底
childPara->userParam.userMapSize = mainThread->userMapSize; //用户态栈大小
taskParam.pfnTaskEntry = runTask->taskEntry;//拷贝当前任务入口地址
taskParam.uwStackSize = runTask->stackSize; //栈空间大小
taskParam.userParam.userArea = runTask->userArea; //用户态栈区栈顶位置
taskParam.userParam.userMapBase = runTask->userMapBase; //用户态栈底
taskParam.userParam.userMapSize = runTask->userMapSize; //用户态栈大小
} else {//注意内核态进程创建任务的入口由外界指定,例如 OsCreateIdleProcess 指定了OsIdleTask
childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;//参数(sp)为内核态入口地址
childPara->uwStackSize = size;//参数(size)为内核态栈大小
taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)entry;//参数(sp)为内核态入口地址
taskParam.uwStackSize = size;//参数(size)为内核态栈大小
}
childPara->pcName = (CHAR *)name; //进程名字
childPara->policy = mainThread->policy; //调度模式
childPara->usTaskPrio = mainThread->priority; //优先级
childPara->processID = childProcessCB->processID; //进程ID
if (mainThread->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
childPara->uwResved = LOS_TASK_ATTR_JOINABLE;
if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
taskParam.uwResved = LOS_TASK_ATTR_JOINABLE;
}
runTask->ops->schedParamGet(runTask, &param);
SCHEDULER_UNLOCK(intSave);
}
//拷贝一个Task过程
STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size)
{
LosTaskCB *runTask = OsCurrTaskGet();
TSK_INIT_PARAM_S childPara = { 0 };
UINT32 ret;
UINT32 intSave;
UINT32 taskID;
OsInitCopyTaskParam(childProcessCB, name, entry, size, &childPara);//初始化Task参数
taskParam.pcName = (CHAR *)name;
taskParam.policy = param.policy;
taskParam.usTaskPrio = param.priority;
taskParam.processID = childProcessCB->processID;
ret = LOS_TaskCreateOnly(&taskID, &childPara);//只创建任务,不调度
ret = LOS_TaskCreateOnly(&taskID, &taskParam);
if (ret != LOS_OK) {
if (ret == LOS_ERRNO_TSK_TCB_UNAVAILABLE) {
return LOS_EAGAIN;
......@@ -1849,7 +1842,7 @@ STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR
LosTaskCB *childTaskCB = OS_TCB_FROM_TID(taskID);
childTaskCB->taskStatus = runTask->taskStatus;//任务状态先同步,注意这里是赋值操作. ...01101001
childTaskCB->basePrio = runTask->basePrio;
childTaskCB->ops->schedParamModify(childTaskCB, &param);
if (childTaskCB->taskStatus & OS_TASK_STATUS_RUNNING) {//因只能有一个运行的task,所以如果一样要改4号位
childTaskCB->taskStatus &= ~OS_TASK_STATUS_RUNNING;//将四号位清0 ,变成 ...01100001
} else {//非运行状态下会发生什么?
......@@ -1957,6 +1950,7 @@ STATIC UINT32 OsChildSetProcessGroupAndSched(LosProcessCB *child, LosProcessCB *
UINT32 ret;
ProcessGroup *group = NULL;
LosTaskCB *taskCB = OS_TCB_FROM_TID(child->threadGroupID);
SCHEDULER_LOCK(intSave);
if (run->group->groupID == OS_USER_PRIVILEGE_PROCESS_GROUP) {//如果是有用户特权进程组
ret = OsSetProcessGroupIDUnsafe(child->processID, child->processID, &group);//设置组ID,存在不安全的风险
......@@ -1967,7 +1961,7 @@ STATIC UINT32 OsChildSetProcessGroupAndSched(LosProcessCB *child, LosProcessCB *
}
child->processStatus &= ~OS_PROCESS_STATUS_INIT;
OsSchedTaskEnQueue(OS_TCB_FROM_TID(child->threadGroupID));
taskCB->ops->enqueue(OsSchedRunqueue(), taskCB);
SCHEDULER_UNLOCK(intSave);
(VOID)LOS_MemFree(m_aucSysMem1, group);
......
......@@ -122,9 +122,10 @@ typedef struct {
SortLinkAttribute swtmrSortLink;
LosTaskCB *swtmrTask; /* software timer task id | 定时器任务ID */
LOS_DL_LIST swtmrHandlerQueue; /* software timer timeout queue id | 定时器超时队列*/
} SwtmrRunQue;
} SwtmrRunqueue;
STATIC SwtmrRunqueue g_swtmrRunqueue[LOSCFG_KERNEL_CORE_NUM];
STATIC SwtmrRunQue g_swtmrRunQue[LOSCFG_KERNEL_CORE_NUM];
#ifdef LOSCFG_SWTMR_DEBUG
#define OS_SWTMR_PERIOD_TO_CYCLE(period) (((UINT64)(period) * OS_NS_PER_TICK) / OS_NS_PER_CYCLE)
STATIC SwtmrDebugData *g_swtmrDebugData = NULL;
......@@ -244,7 +245,7 @@ STATIC INLINE VOID SwtmrHandler(SwtmrHandlerItemPtr swtmrHandle)
#endif
}
STATIC INLINE VOID SwtmrWake(SwtmrRunQue *srq, UINT64 startTime, SortLinkList *sortList)
STATIC INLINE VOID SwtmrWake(SwtmrRunqueue *srq, UINT64 startTime, SortLinkList *sortList)
{
UINT32 intSave;
SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
......@@ -278,7 +279,7 @@ STATIC INLINE VOID SwtmrWake(SwtmrRunQue *srq, UINT64 startTime, SortLinkList *s
SWTMR_UNLOCK(intSave);
}
STATIC INLINE VOID ScanSwtmrTimeList(SwtmrRunQue *srq)
STATIC INLINE VOID ScanSwtmrTimeList(SwtmrRunqueue *srq)
{
UINT32 intSave;
SortLinkAttribute *swtmrSortLink = &srq->swtmrSortLink;
......@@ -327,13 +328,13 @@ STATIC VOID SwtmrTask(VOID)
UINT32 intSave;
UINT64 waitTime;
SwtmrRunQue *srq = &g_swtmrRunQue[ArchCurrCpuid()];
SwtmrRunqueue *srq = &g_swtmrRunqueue[ArchCurrCpuid()];
LOS_DL_LIST *head = &srq->swtmrHandlerQueue;
for (;;) {//死循环获取队列item,一直读干净为止
waitTime = OsSortLinkGetNextExpireTime(OsGetCurrSchedTimeCycle(), &srq->swtmrSortLink);
if (waitTime != 0) {
SCHEDULER_LOCK(intSave);
OsSchedDelay(srq->swtmrTask, waitTime);
srq->swtmrTask->ops->delay(srq->swtmrTask, waitTime);
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, srq->swtmrTask);
SCHEDULER_UNLOCK(intSave);
}
......@@ -376,7 +377,7 @@ STATIC UINT32 SwtmrTaskCreate(UINT16 cpuid, UINT32 *swtmrTaskID)
UINT32 OsSwtmrTaskIDGetByCpuid(UINT16 cpuid)
{
return g_swtmrRunQue[cpuid].swtmrTask->taskID;
return g_swtmrRunqueue[cpuid].swtmrTask->taskID;
}
BOOL OsIsSwtmrTask(const LosTaskCB *taskCB)
......@@ -425,7 +426,7 @@ STATIC UINT32 SwtmrBaseInit(VOID)
}
for (UINT16 index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
SwtmrRunQue *srq = &g_swtmrRunQue[index];
SwtmrRunqueue *srq = &g_swtmrRunqueue[index];
/* The linked list of all cores must be initialized at core 0 startup for load balancing */
OsSortLinkInit(&srq->swtmrSortLink);
LOS_ListInit(&srq->swtmrHandlerQueue);
......@@ -456,7 +457,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID)
goto ERROR;
}
SwtmrRunQue *srq = &g_swtmrRunQue[cpuid];
SwtmrRunqueue *srq = &g_swtmrRunqueue[cpuid];
srq->swtmrTask = OsGetTaskCB(swtmrTaskID);
return LOS_OK;
......@@ -470,13 +471,13 @@ ERROR:
}
#ifdef LOSCFG_KERNEL_SMP
STATIC INLINE VOID FindIdleSwtmrRunQue(UINT16 *idleCpuid)
STATIC INLINE VOID FindIdleSwtmrRunqueue(UINT16 *idleCpuid)
{
SwtmrRunQue *idleRq = &g_swtmrRunQue[0];
SwtmrRunqueue *idleRq = &g_swtmrRunqueue[0];
UINT32 nodeNum = OsGetSortLinkNodeNum(&idleRq->swtmrSortLink);
UINT16 cpuid = 1;
do {
SwtmrRunQue *srq = &g_swtmrRunQue[cpuid];
SwtmrRunqueue *srq = &g_swtmrRunqueue[cpuid];
UINT32 temp = OsGetSortLinkNodeNum(&srq->swtmrSortLink);
if (nodeNum > temp) {
*idleCpuid = cpuid;
......@@ -489,7 +490,7 @@ STATIC INLINE VOID FindIdleSwtmrRunQue(UINT16 *idleCpuid)
STATIC INLINE VOID AddSwtmr2TimeList(SortLinkList *node, UINT64 responseTime, UINT16 cpuid)
{
SwtmrRunQue *srq = &g_swtmrRunQue[cpuid];
SwtmrRunqueue *srq = &g_swtmrRunqueue[cpuid];
OsAdd2SortLink(&srq->swtmrSortLink, node, responseTime, cpuid);
}
......@@ -500,7 +501,7 @@ STATIC INLINE VOID DeSwtmrFromTimeList(SortLinkList *node)
#else
UINT16 cpuid = 0;
#endif
SwtmrRunQue *srq = &g_swtmrRunQue[cpuid];
SwtmrRunqueue *srq = &g_swtmrRunqueue[cpuid];
OsDeleteFromSortLink(&srq->swtmrSortLink, node);
return;
}
......@@ -509,7 +510,7 @@ STATIC VOID SwtmrAdjustCheck(UINT16 cpuid, UINT64 responseTime)
{
UINT32 ret;
UINT32 intSave;
SwtmrRunQue *srq = &g_swtmrRunQue[cpuid];
SwtmrRunqueue *srq = &g_swtmrRunqueue[cpuid];
SCHEDULER_LOCK(intSave);
if ((srq->swtmrTask == NULL) || !OsTaskIsBlocked(srq->swtmrTask)) {
SCHEDULER_UNLOCK(intSave);
......@@ -521,14 +522,14 @@ STATIC VOID SwtmrAdjustCheck(UINT16 cpuid, UINT64 responseTime)
return;
}
ret = OsSchedAdjustTaskFromTimeList(srq->swtmrTask, responseTime);
ret = OsSchedTimeoutQueueAdjust(srq->swtmrTask, responseTime);
SCHEDULER_UNLOCK(intSave);
if (ret != LOS_OK) {
return;
}
if (cpuid == ArchCurrCpuid()) {
OsSchedUpdateExpireTime();
OsSchedExpireTimeUpdate();
} else {
LOS_MpSchedule(CPUID_TO_AFFI_MASK(cpuid));
}
......@@ -572,7 +573,7 @@ STATIC INLINE VOID SwtmrStart(SWTMR_CTRL_S *swtmr)
UINT64 responseTime;
UINT16 idleCpu = 0;
#ifdef LOSCFG_KERNEL_SMP
FindIdleSwtmrRunQue(&idleCpu);
FindIdleSwtmrRunqueue(&idleCpu);
#endif
swtmr->startTime = OsGetCurrSchedTimeCycle();
responseTime = SwtmrToStart(swtmr, idleCpu);
......@@ -609,7 +610,7 @@ STATIC INLINE VOID SwtmrRestart(UINT64 startTime, SortLinkList *sortList, UINT16
VOID OsSwtmrResponseTimeReset(UINT64 startTime)
{
UINT16 cpuid = ArchCurrCpuid();
SortLinkAttribute *swtmrSortLink = &g_swtmrRunQue[cpuid].swtmrSortLink;
SortLinkAttribute *swtmrSortLink = &g_swtmrRunqueue[cpuid].swtmrSortLink;
LOS_DL_LIST *listHead = &swtmrSortLink->sortLink;
LOS_DL_LIST *listNext = listHead->pstNext;
......@@ -627,7 +628,7 @@ VOID OsSwtmrResponseTimeReset(UINT64 startTime)
LOS_SpinUnlock(&swtmrSortLink->spinLock);
}
STATIC INLINE BOOL SwtmrRunQueFind(SortLinkAttribute *swtmrSortLink, SCHED_TL_FIND_FUNC checkFunc, UINTPTR arg)
STATIC INLINE BOOL SwtmrRunqueueFind(SortLinkAttribute *swtmrSortLink, SCHED_TL_FIND_FUNC checkFunc, UINTPTR arg)
{
LOS_DL_LIST *listObject = &swtmrSortLink->sortLink;
LOS_DL_LIST *list = listObject->pstNext;
......@@ -649,8 +650,8 @@ STATIC INLINE BOOL SwtmrRunQueFind(SortLinkAttribute *swtmrSortLink, SCHED_TL_FI
STATIC BOOL SwtmrTimeListFind(SCHED_TL_FIND_FUNC checkFunc, UINTPTR arg)
{
for (UINT16 cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
SortLinkAttribute *swtmrSortLink = &g_swtmrRunQue[ArchCurrCpuid()].swtmrSortLink;
if (SwtmrRunQueFind(swtmrSortLink, checkFunc, arg)) {
SortLinkAttribute *swtmrSortLink = &g_swtmrRunqueue[ArchCurrCpuid()].swtmrSortLink;
if (SwtmrRunqueueFind(swtmrSortLink, checkFunc, arg)) {
return TRUE;
}
}
......@@ -674,7 +675,7 @@ BOOL OsSwtmrWorkQueueFind(SCHED_TL_FIND_FUNC checkFunc, UINTPTR arg)
LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID)
{
UINT64 currTime = OsGetCurrSchedTimeCycle();
SwtmrRunQue *srq = &g_swtmrRunQue[ArchCurrCpuid()];
SwtmrRunqueue *srq = &g_swtmrRunqueue[ArchCurrCpuid()];
UINT64 time = (OsSortLinkGetNextExpireTime(currTime, &srq->swtmrSortLink) / OS_CYCLE_PER_TICK);
if (time > OS_INVALID_VALUE) {
time = OS_INVALID_VALUE;
......
......@@ -168,20 +168,23 @@ VOID OsSetMainTask()
{
UINT32 i;
CHAR *name = "osMain";//任务名称
SchedParam schedParam = { 0 };
schedParam.policy = LOS_SCHED_RR;
schedParam.basePrio = OS_PROCESS_PRIORITY_HIGHEST;
schedParam.priority = OS_TASK_PRIORITY_LOWEST;
//为每个CPU core 设置mainTask
for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
g_mainTask[i].taskStatus = OS_TASK_STATUS_UNUSED;
g_mainTask[i].taskID = LOSCFG_BASE_CORE_TSK_LIMIT;//128
g_mainTask[i].processID = OS_KERNEL_PROCESS_GROUP;
g_mainTask[i].basePrio = OS_TASK_PRIORITY_HIGHEST;
g_mainTask[i].priority = OS_TASK_PRIORITY_LOWEST;//31
#ifdef LOSCFG_KERNEL_SMP_LOCKDEP
g_mainTask[i].lockDep.lockDepth = 0;
g_mainTask[i].lockDep.waitLock = NULL;
#endif
(VOID)strncpy_s(g_mainTask[i].taskName, OS_TCB_NAME_LEN, name, OS_TCB_NAME_LEN - 1);
LOS_ListInit(&g_mainTask[i].lockList);//初始化任务锁链表,上面挂的是任务已申请到的互斥锁
(VOID)OsSchedParamInit(&g_mainTask[i], schedParam.policy, &schedParam, NULL);
}
}
///空闲任务,每个CPU都有自己的空闲任务
......@@ -212,7 +215,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB)
if (!LOS_ListEmpty(&taskCB->joinList)) {//注意到了这里 joinList中的节点身上都有阻塞标签
LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(taskCB->joinList)));//通过贴有JOIN标签链表的第一个节点找到Task
OsTaskWakeClearPendMask(resumedTask);//清除任务的挂起标记
OsSchedTaskWake(resumedTask);//唤醒任务
resumedTask->ops->wake(resumedTask);
}
}
taskCB->taskStatus |= OS_TASK_STATUS_EXIT;//贴上任务退出标签
......@@ -230,7 +233,8 @@ LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB)
if ((taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) && LOS_ListEmpty(&taskCB->joinList)) {
OsTaskWaitSetPendMask(OS_TASK_WAIT_JOIN, taskCB->taskID, LOS_WAIT_FOREVER);//设置任务的等待标记
return OsSchedTaskWait(&taskCB->joinList, LOS_WAIT_FOREVER, TRUE);//永久等待
LosTaskCB *runTask = OsCurrTaskGet();
return runTask->ops->wait(runTask, &taskCB->joinList, LOS_WAIT_FOREVER);
}
return LOS_EINVAL;
......@@ -290,7 +294,7 @@ EXIT:
///获取IdletaskId,每个CPU核都对Task进行了内部管理,做到真正的并行处理
UINT32 OsGetIdleTaskId(VOID)
{
return OsSchedGetRunQueIdle();
return OsSchedRunqueueIdleGet();
}
///创建一个空闲任务
LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
......@@ -303,6 +307,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;//入口函数
taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;//任务栈大小 2K
taskInitParam.pcName = "Idle";//任务名称 叫pcName有点怪怪的,不能换个撒
taskInitParam.policy = LOS_SCHED_IDLE;
taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;//默认最低优先级 31
taskInitParam.processID = OsGetIdleProcessID();//任务的进程ID绑定为空闲进程
#ifdef LOSCFG_KERNEL_SMP
......@@ -311,10 +316,9 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
ret = LOS_TaskCreateOnly(&idleTaskID, &taskInitParam);
LosTaskCB *idleTask = OS_TCB_FROM_TID(idleTaskID);
idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK; //标记为系统任务,idle任务是给CPU休息用的,当然是个系统任务
OsSchedRunQueIdleInit(idleTaskID);
OsSchedSetIdleTaskSchedParam(idleTask);//设置空闲任务的调度参数
OsSchedRunqueueIdleInit(idleTaskID);
return ret;
return LOS_TaskResume(idleTaskID);
}
/*
......@@ -556,10 +560,8 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskStackAlloc(VOID **topStack, UINT32 stack
}
///任务基本信息的初始化
LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
const VOID *stackPtr,
const VOID *topStack,
const TSK_INIT_PARAM_S *initParam)
STATIC VOID TaskCBBaseInit(LosTaskCB *taskCB, const VOID *stackPtr, const VOID *topStack,
const TSK_INIT_PARAM_S *initParam)
{
taskCB->stackPointer = (VOID *)stackPtr;//内核态SP位置
taskCB->args[0] = initParam->auwArgs[0]; /* 0~3: just for args array index */
......@@ -568,7 +570,6 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
taskCB->args[3] = initParam->auwArgs[3];
taskCB->topOfStack = (UINTPTR)topStack; //内核态栈顶
taskCB->stackSize = initParam->uwStackSize;//
taskCB->priority = initParam->usTaskPrio;
taskCB->taskEntry = initParam->pfnTaskEntry;
taskCB->signal = SIGNAL_NONE;
......@@ -577,7 +578,6 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
taskCB->cpuAffiMask = (initParam->usCpuAffiMask) ?
initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK;
#endif
taskCB->policy = (initParam->policy == LOS_SCHED_FIFO) ? LOS_SCHED_FIFO : LOS_SCHED_RR;//调度模式
taskCB->taskStatus = OS_TASK_STATUS_INIT;
if (initParam->uwResved & LOS_TASK_ATTR_JOINABLE) {
taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
......@@ -593,11 +593,14 @@ STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam,
{
UINT32 ret;
UINT32 numCount;
SchedParam schedParam = { 0 };
UINT16 policy = (initParam->policy == LOS_SCHED_NORMAL) ? LOS_SCHED_RR : initParam->policy;
OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam);//初始化任务的基本信息,
TaskCBBaseInit(taskCB, stackPtr, topStack, initParam);//初始化任务的基本信息,
//taskCB->stackPointer指向内核态栈 sp位置,该位置存着 任务初始上下文
numCount = OsProcessAddNewTask(initParam->processID, taskCB);
schedParam.policy = policy;
numCount = OsProcessAddNewTask(initParam->processID, taskCB, &schedParam);
#ifdef LOSCFG_KERNEL_VM
taskCB->futex.index = OS_INVALID_VALUE;
if (taskCB->taskStatus & OS_TASK_FLAG_USER_MODE) {
......@@ -609,6 +612,11 @@ STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam,
}
#endif
ret = OsSchedParamInit(taskCB, policy, &schedParam, initParam);
if (ret != LOS_OK) {
return ret;
}
if (initParam->pcName != NULL) {
ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE);
if (ret == LOS_OK) {
......@@ -653,8 +661,6 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S
{
UINT32 intSave, errRet;
VOID *topStack = NULL;
VOID *stackPtr = NULL;
LosTaskCB *taskCB = NULL;
VOID *pool = NULL;
errRet = OsTaskCreateParamCheck(taskID, initParam, &pool);//参数检查,获取内存池 *pool = (VOID *)m_aucSysMem1;
......@@ -662,7 +668,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S
return errRet;
}
taskCB = OsGetFreeTaskCB();//从g_losFreeTask中获取,还记得吗任务池中最多默认128个
LosTaskCB *taskCB = OsGetFreeTaskCB();//从g_losFreeTask中获取,还记得吗任务池中最多默认128个
if (taskCB == NULL) {
errRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
goto LOS_ERREND;
......@@ -679,7 +685,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S
goto LOS_ERREND_REWIND_SYNC;
}
stackPtr = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE);//初始化内核态任务栈,返回栈SP位置
VOID *stackPtr = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE);//初始化内核态任务栈,返回栈SP位置
errRet = OsTaskCBInit(taskCB, initParam, stackPtr, topStack);//初始化TCB,包括绑定进程等操作
if (errRet != LOS_OK) {
goto LOS_ERREND_TCB_INIT;
......@@ -733,7 +739,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in
LosTaskCB *taskCB = OS_TCB_FROM_TID(*taskID);
SCHEDULER_LOCK(intSave);
OsSchedTaskEnQueue(taskCB);
taskCB->ops->enqueue(OsSchedRunqueue(), taskCB);
SCHEDULER_UNLOCK(intSave);
/* in case created task not running on this core,
......@@ -750,13 +756,13 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
{
UINT32 intSave;
UINT32 errRet;
LosTaskCB *taskCB = NULL;
BOOL needSched = FALSE;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ERRNO_TSK_ID_INVALID;
}
taskCB = OS_TCB_FROM_TID(taskID);//拿到任务实体
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
/* clear pending signal */
......@@ -770,7 +776,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
OS_GOTO_ERREND();
}
BOOL needSched = OsSchedResume(taskCB);
errRet = taskCB->ops->resume(taskCB, &needSched);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
......@@ -778,7 +784,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
LOS_Schedule();
}
return LOS_OK;
return errRet;
LOS_ERREND:
SCHEDULER_UNLOCK(intSave);
......@@ -826,9 +832,7 @@ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UIN
LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB)
{
UINT32 errRet;
UINT16 tempStatus;
tempStatus = taskCB->taskStatus;
UINT16 tempStatus = taskCB->taskStatus;
if (tempStatus & OS_TASK_STATUS_UNUSED) {
return LOS_ERRNO_TSK_NOT_CREATED;
}
......@@ -842,8 +846,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB)
return errRet;
}
OsSchedSuspend(taskCB);
return LOS_OK;
return taskCB->ops->suspend(taskCB);
}
///外部接口,对OsTaskSuspend的封装
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
......@@ -944,11 +947,11 @@ LITE_OS_SEC_TEXT VOID OsInactiveTaskDelete(LosTaskCB *taskCB)
OsTaskReleaseHoldLock(taskCB);
OsSchedTaskExit(taskCB);
taskCB->ops->exit(taskCB);
if (taskStatus & OS_TASK_STATUS_PENDING) {
LosMux *mux = (LosMux *)taskCB->taskMux;
if (LOS_MuxIsValid(mux) == TRUE) {
OsMuxBitmapRestore(mux, taskCB, (LosTaskCB *)mux->owner);
OsMuxBitmapRestore(mux, NULL, taskCB);
}
}
......@@ -1035,17 +1038,16 @@ LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)
}
SCHEDULER_LOCK(intSave);
OsSchedDelay(runTask, OS_SCHED_TICK_TO_CYCLE(tick));
UINT32 ret = runTask->ops->delay(runTask, OS_SCHED_TICK_TO_CYCLE(tick));
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
return ret;
}
///获取任务的优先级
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
{
UINT32 intSave;
UINT16 priority;
SchedParam param = { 0 };
if (OS_TID_CHECK_INVALID(taskID)) {
return (UINT16)OS_INVALID;
......@@ -1058,14 +1060,15 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
return (UINT16)OS_INVALID;
}
priority = taskCB->priority;
taskCB->ops->schedParamGet(taskCB, &param);
SCHEDULER_UNLOCK(intSave);
return priority;
return param.priority;
}
///设置指定任务的优先级
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
{
UINT32 intSave;
SchedParam param = { 0 };
if (taskPrio > OS_TASK_PRIORITY_LOWEST) {
return LOS_ERRNO_TSK_PRIOR_ERROR;
......@@ -1086,11 +1089,15 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
return LOS_ERRNO_TSK_NOT_CREATED;
}
BOOL isReady = OsSchedModifyTaskSchedParam(taskCB, taskCB->policy, taskPrio);
taskCB->ops->schedParamGet(taskCB, &param);
param.priority = taskPrio;
BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
if (isReady && OS_SCHEDULER_ACTIVE) {
if (needSched && OS_SCHEDULER_ACTIVE) {
LOS_Schedule();
}
return LOS_OK;
......@@ -1120,8 +1127,8 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID)
}
SCHEDULER_LOCK(intSave);
/* reset timeslice of yeilded task */
OsSchedYield();
/* reset timeslice of yielded task */
runTask->ops->yield(runTask);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
......@@ -1151,7 +1158,7 @@ LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInfo)
{
UINT32 intSave;
LosTaskCB *taskCB = NULL;
SchedParam param = { 0 };
if (taskInfo == NULL) {
return LOS_ERRNO_TSK_PTR_NULL;
......@@ -1161,7 +1168,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInf
return LOS_ERRNO_TSK_ID_INVALID;
}
taskCB = OS_TCB_FROM_TID(taskID);
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
......@@ -1174,8 +1181,9 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInf
taskInfo->uwSP = ArchSPGet();
}
taskCB->ops->schedParamGet(taskCB, &param);
taskInfo->usTaskStatus = taskCB->taskStatus;
taskInfo->usTaskPrio = taskCB->priority;
taskInfo->usTaskPrio = param.priority;
taskInfo->uwStackSize = taskCB->stackSize; //内核态栈大小
taskInfo->uwTopOfStack = taskCB->topOfStack;//内核态栈顶位置
taskInfo->uwEventMask = taskCB->eventMask;
......@@ -1219,7 +1227,6 @@ LITE_OS_SEC_TEXT BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMas
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMask)
{
LosTaskCB *taskCB = NULL;
BOOL needSched = FALSE;
UINT32 intSave;
UINT16 currCpuMask;
......@@ -1232,7 +1239,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMa
return LOS_ERRNO_TSK_CPU_AFFINITY_MASK_ERR;
}
taskCB = OS_TCB_FROM_TID(taskID);//获取任务实体
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {//贴有未使用标签的处理
SCHEDULER_UNLOCK(intSave);
......@@ -1254,7 +1261,6 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
{
#ifdef LOSCFG_KERNEL_SMP
#define INVALID_CPU_AFFI_MASK 0
LosTaskCB *taskCB = NULL;
UINT16 cpuAffiMask;
UINT32 intSave;
......@@ -1262,7 +1268,7 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
return INVALID_CPU_AFFI_MASK;
}
taskCB = OS_TCB_FROM_TID(taskID);//获取任务实体
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { //任务必须在使用
SCHEDULER_UNLOCK(intSave);
......@@ -1368,19 +1374,19 @@ EXIT:
return err;
}
UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB)
INT32 OsUserTaskOperatePermissionsCheck(const LosTaskCB *taskCB)
{
return OsUserProcessOperatePermissionsCheck(taskCB, OsCurrProcessGet()->processID);
}
UINT32 OsUserProcessOperatePermissionsCheck(LosTaskCB *taskCB, UINT32 processID)
INT32 OsUserProcessOperatePermissionsCheck(const LosTaskCB *taskCB, UINT32 processID)
{
if (taskCB == NULL) {
return LOS_EINVAL;
}
if (processID == OS_INVALID_VALUE) {
return OS_INVALID_VALUE;
return LOS_EINVAL;
}
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
......@@ -1458,21 +1464,22 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S
LITE_OS_SEC_TEXT INT32 LOS_GetTaskScheduler(INT32 taskID)
{
UINT32 intSave;
LosTaskCB *taskCB = NULL;
INT32 policy;
SchedParam param = { 0 };
if (OS_TID_CHECK_INVALID(taskID)) {
return -LOS_EINVAL;
}
taskCB = OS_TCB_FROM_TID(taskID);//通过任务ID获得任务TCB
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {//状态不能是没有在使用
policy = -LOS_EINVAL;
OS_GOTO_ERREND();
}
policy = taskCB->policy;//任务的调度方式
taskCB->ops->schedParamGet(taskCB, &param);
policy = (INT32)param.policy;
LOS_ERREND:
SCHEDULER_UNLOCK(intSave);
......@@ -1482,8 +1489,8 @@ LOS_ERREND:
//设置任务的调度信息
LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 priority)
{
SchedParam param = { 0 };
UINT32 intSave;
BOOL needSched = FALSE;
if (OS_TID_CHECK_INVALID(taskID)) {
return LOS_ESRCH;
......@@ -1505,10 +1512,13 @@ LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
return LOS_EINVAL;
return LOS_EINVAL;
}
needSched = OsSchedModifyTaskSchedParam(taskCB, policy, priority);
taskCB->ops->schedParamGet(taskCB, &param);
param.policy = policy;
param.priority = priority;
BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
......@@ -1589,7 +1599,6 @@ UINT32 LOS_TaskDetach(UINT32 taskID)
{
UINT32 intSave;
LosTaskCB *runTask = OsCurrTaskGet();
LosTaskCB *taskCB = NULL;
UINT32 errRet;
if (OS_TID_CHECK_INVALID(taskID)) {
......@@ -1600,7 +1609,7 @@ UINT32 LOS_TaskDetach(UINT32 taskID)
return LOS_EINTR;
}
taskCB = OS_TCB_FROM_TID(taskID);
LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
SCHEDULER_UNLOCK(intSave);
......
......@@ -43,7 +43,7 @@ extern "C" {
#define OS_MUX_MAGIC 0xEBCFDEA0
extern VOID OsMuxBitmapRestore(const LosMux *mutex, const LosTaskCB *taskCB, LosTaskCB *owner);
extern VOID OsMuxBitmapRestore(const LosMux *mutex, const LOS_DL_LIST *list, const LosTaskCB *runTask);
extern UINT32 OsMuxLockUnsafe(LosMux *mutex, UINT32 timeout);
extern UINT32 OsMuxTrylockUnsafe(LosMux *mutex, UINT32 timeout);
extern UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched);
......
......@@ -301,11 +301,6 @@ STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
return (processCB->processMode == OS_USER_MODE);
}
#define LOS_SCHED_NORMAL 0U ///< 正常调度
#define LOS_SCHED_FIFO 1U ///< 先进先出,按顺序
#define LOS_SCHED_RR 2U ///< 抢占式调度,鸿蒙默认调度方式
#define LOS_SCHED_IDLE 3U ///< 空闲不调度
#define LOS_PRIO_PROCESS 0U ///< 进程标识
#define LOS_PRIO_PGRP 1U ///< 进程组标识
#define LOS_PRIO_USER 2U ///< 用户标识
......@@ -495,7 +490,7 @@ extern UINTPTR OsGetSigHandler(VOID);
extern VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID);
extern INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission);
extern INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission);
extern UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB);
extern UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB, SchedParam *param);
extern VOID OsDeleteTaskFromProcess(LosTaskCB *taskCB);
extern VOID OsProcessThreadGroupDestroy(VOID);
......
......@@ -41,7 +41,7 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_RWLOCK_MAGIC 0xBEFDCAU ///< 读写锁魔法数字
#define OS_RWLOCK_MAGIC 0xEFDCAU ///< 读写锁魔法数字
enum RwlockMode {
RWLOCK_NONE_MODE, ///< 自由模式: 读写链表都没有内容
......
......@@ -37,10 +37,11 @@
#include "los_hwi.h"
#include "hal_timer.h"
#ifdef LOSCFG_SCHED_DEBUG
#include "los_stat_pri.h"
#include "los_statistics_pri.h"
#endif
#include "los_stackinfo_pri.h"
#include "los_futex_pri.h"
#include "los_pm_pri.h"
#include "los_signal.h"
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
......@@ -66,6 +67,7 @@ extern UINT32 g_taskScheduled;
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))
#define OS_SCHEDULER_ALL_ACTIVE (g_taskScheduled == LOSCFG_KERNEL_CPU_MASK)
typedef struct TagTaskCB LosTaskCB;
typedef BOOL (*SCHED_TL_FIND_FUNC)(UINTPTR, UINTPTR);
//获取当前调度经历了多少个时间周期
STATIC INLINE UINT64 OsGetCurrSchedTimeCycle(VOID)
......@@ -79,52 +81,65 @@ typedef enum {
INT_PEND_TICK = 0x2, /* pending tick */
} SchedFlag;
#define OS_PRIORITY_QUEUE_NUM 32
typedef struct {
SortLinkAttribute taskSortLink; /* task sort link */
LOS_DL_LIST priQueList[OS_PRIORITY_QUEUE_NUM];
UINT32 readyTasks[OS_PRIORITY_QUEUE_NUM];
UINT32 queueBitmap;
} HPFQueue;
typedef struct {
HPFQueue queueList[OS_PRIORITY_QUEUE_NUM];
UINT32 queueBitmap;
} HPFRunqueue;
typedef struct {
SortLinkAttribute timeoutQueue; /* task timeout queue */
HPFRunqueue *hpfRunqueue;
UINT64 responseTime; /* Response time for current CPU tick interrupts */
UINT32 responseID; /* The response ID of the current CPU tick interrupt */
UINT32 idleTaskID; /* idle task id */
UINT32 taskLockCnt; /* task lock flag */
UINT32 schedFlag; /* pending scheduler flag */
} SchedRunQue;
} SchedRunqueue;
extern SchedRunQue g_schedRunQue[LOSCFG_KERNEL_CORE_NUM];
extern SchedRunqueue g_schedRunqueue[LOSCFG_KERNEL_CORE_NUM];
VOID OsSchedUpdateExpireTime(VOID);
VOID OsSchedExpireTimeUpdate(VOID);
STATIC INLINE SchedRunQue *OsSchedRunQue(VOID)
STATIC INLINE SchedRunqueue *OsSchedRunqueue(VOID)
{
return &g_schedRunQue[ArchCurrCpuid()];
return &g_schedRunqueue[ArchCurrCpuid()];
}
STATIC INLINE SchedRunQue *OsSchedRunQueByID(UINT16 id)
STATIC INLINE SchedRunqueue *OsSchedRunqueueByID(UINT16 id)
{
return &g_schedRunQue[id];
return &g_schedRunqueue[id];
}
STATIC INLINE UINT32 OsSchedLockCountGet(VOID)
{
return OsSchedRunQue()->taskLockCnt;
return OsSchedRunqueue()->taskLockCnt;
}
STATIC INLINE VOID OsSchedLockSet(UINT32 count)
{
OsSchedRunQue()->taskLockCnt = count;
OsSchedRunqueue()->taskLockCnt = count;
}
STATIC INLINE VOID OsSchedLock(VOID)
{
OsSchedRunQue()->taskLockCnt++;
OsSchedRunqueue()->taskLockCnt++;
}
STATIC INLINE VOID OsSchedUnlock(VOID)
{
OsSchedRunQue()->taskLockCnt--;
OsSchedRunqueue()->taskLockCnt--;
}
STATIC INLINE BOOL OsSchedUnlockResch(VOID)
{
SchedRunQue *rq = OsSchedRunQue();
SchedRunqueue *rq = OsSchedRunqueue();
if (rq->taskLockCnt > 0) {
rq->taskLockCnt--;
if ((rq->taskLockCnt == 0) && (rq->schedFlag & INT_PEND_RESCH) && OS_SCHEDULER_ACTIVE) {
......@@ -137,13 +152,13 @@ STATIC INLINE BOOL OsSchedUnlockResch(VOID)
STATIC INLINE BOOL OsSchedIsLock(VOID)
{
return (OsSchedRunQue()->taskLockCnt != 0);
return (OsSchedRunqueue()->taskLockCnt != 0);
}
/* Check if preemptible with counter flag */
STATIC INLINE BOOL OsPreemptable(VOID)
{
SchedRunQue *rq = OsSchedRunQue();
SchedRunqueue *rq = OsSchedRunqueue();
/*
* Unlike OsPreemptableInSched, the int may be not disabled when OsPreemptable
* is called, needs manually disable interrupt, to prevent current task from
......@@ -162,7 +177,7 @@ STATIC INLINE BOOL OsPreemptable(VOID)
STATIC INLINE BOOL OsPreemptableInSched(VOID)
{
BOOL preemptible = FALSE;
SchedRunQue *rq = OsSchedRunQue();
SchedRunqueue *rq = OsSchedRunqueue();
#ifdef LOSCFG_KERNEL_SMP
/*
......@@ -182,18 +197,61 @@ STATIC INLINE BOOL OsPreemptableInSched(VOID)
return preemptible;
}
STATIC INLINE UINT32 OsSchedGetRunQueIdle(VOID)
STATIC INLINE UINT32 OsSchedRunqueueIdleGet(VOID)
{
return OsSchedRunQue()->idleTaskID;
return OsSchedRunqueue()->idleTaskID;
}
STATIC INLINE VOID OsSchedRunQuePendingSet(VOID)
STATIC INLINE VOID OsSchedRunqueuePendingSet(VOID)
{
OsSchedRunQue()->schedFlag |= INT_PEND_RESCH;
OsSchedRunqueue()->schedFlag |= INT_PEND_RESCH;
}
VOID OsSchedRunQueIdleInit(UINT32 idleTaskID);
VOID OsSchedRunQueInit(VOID);
#define LOS_SCHED_NORMAL 0U
#define LOS_SCHED_FIFO 1U
#define LOS_SCHED_RR 2U
#define LOS_SCHED_IDLE 3U
typedef struct {
UINT16 policy;
UINT16 basePrio;
UINT16 priority;
UINT32 timeSlice;
} SchedParam;
typedef struct {
UINT16 policy; /* This field must be present for all scheduling policies and must be the first in the structure */
UINT16 basePrio;
UINT16 priority;
UINT32 initTimeSlice;
UINT32 priBitmap; /**< Bitmap for recording the change of task priority, the priority can not be greater than 31 */
} SchedHPF;
typedef struct {
union {
SchedHPF hpf;
} Policy;
} SchedPolicy;
typedef struct {
VOID (*dequeue)(SchedRunqueue *rq, LosTaskCB *taskCB);
VOID (*enqueue)(SchedRunqueue *rq, LosTaskCB *taskCB);
VOID (*start)(SchedRunqueue *rq, LosTaskCB *taskCB);
VOID (*exit)(LosTaskCB *taskCB);
UINT32 (*wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout);
VOID (*wake)(LosTaskCB *taskCB);
BOOL (*schedParamModify)(LosTaskCB *taskCB, const SchedParam *param);
UINT32 (*schedParamGet)(const LosTaskCB *taskCB, SchedParam *param);
UINT32 (*delay)(LosTaskCB *taskCB, UINT64 waitTime);
VOID (*yield)(LosTaskCB *taskCB);
UINT32 (*suspend)(LosTaskCB *taskCB);
UINT32 (*resume)(LosTaskCB *taskCB, BOOL *needSched);
UINT64 (*deadlineGet)(const LosTaskCB *taskCB);
VOID (*timeSliceUpdate)(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime);
INT32 (*schedParamCompare)(const SchedPolicy *sp1, const SchedPolicy *sp2);
VOID (*priorityInheritance)(LosTaskCB *owner, const SchedParam *param);
VOID (*priorityRestore)(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param);
} SchedOps;
/**
* @ingroup los_sched
......@@ -283,23 +341,31 @@ VOID OsSchedRunQueInit(VOID);
*/
#define OS_TASK_STATUS_EXIT 0x0100U
#define OS_TASK_STATUS_BLOCKED (OS_TASK_STATUS_INIT | OS_TASK_STATUS_PENDING | \
OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The delayed operation of this task is frozen.
*/
#define OS_TASK_STATUS_FROZEN 0x0200U
#define OS_TCB_NAME_LEN 32
typedef struct {
typedef struct TagTaskCB {
VOID *stackPointer; /**< Task stack pointer | 内核栈指针位置(SP) */
UINT16 taskStatus; /**< Task status | 各种状态标签,可以拥有多种标签,按位标识 */
/* The scheduling */
UINT16 basePrio;
UINT16 priority; /**< Task priority | 任务优先级[0:31],默认是31级 */
UINT16 policy; ///< 任务的调度方式(三种 .. LOS_SCHED_RR LOS_SCHED_FIFO .. )
UINT64 startTime; /**< The start time of each phase of task | 任务开始时间 */
UINT64 waitTime; /**< Task delay time, tick number | 设置任务调度延期时间 */
UINT64 irqStartTime; /**< Interrupt start time | 任务中断开始时间 */
UINT32 irqUsedTime; /**< Interrupt consumption time | 任务中断消耗时间 */
UINT32 initTimeSlice; /**< Task init time slice | 任务初始的时间片 */
INT32 timeSlice; /**< Task remaining time slice | 任务剩余时间片 */
SortLinkList sortList; /**< Task sortlink node | 跟CPU捆绑的任务排序链表节点,上面挂的是就绪队列的下一个阶段,进入CPU要执行的任务队列 */
const SchedOps *ops;
SchedPolicy sp;
UINT32 stackSize; /**< Task stack size | 内核态栈大小,内存来自内核空间 */
UINTPTR topOfStack; /**< Task stack top | 内核态栈顶 bottom = top + size */
UINT32 taskID; /**< Task ID | 任务ID,任务池本质是一个大数组,ID就是数组的索引,默认 < 128 */
......@@ -313,8 +379,6 @@ typedef struct {
LOS_DL_LIST threadList; /**< thread list | 挂到所属进程的线程链表上 */
UINT32 eventMask; /**< Event mask | 任务对哪些事件进行屏蔽 */
UINT32 eventMode; /**< Event mode | 事件三种模式(LOS_WAITMODE_AND,LOS_WAITMODE_OR,LOS_WAITMODE_CLR) */
UINT32 priBitMap; /**< BitMap for recording the change of task priority,the priority can not be greater than 31
| 任务在执行过程中优先级会经常变化,这个变量用来记录所有曾经变化过的优先级,例如 ..01001011 曾经有过 0,1,3,6 优先级 */
#ifdef LOSCFG_KERNEL_CPUP
OsCpupBase taskCpup; /**< task cpu usage | CPU 使用统计 */
#endif
......@@ -404,7 +468,7 @@ STATIC INLINE VOID OsCurrUserTaskSet(UINTPTR thread)
ArchCurrUserTaskSet(thread);
}
STATIC INLINE VOID OsSchedIrqUpdateUsedTime(VOID)
STATIC INLINE VOID OsSchedIrqUsedTimeUpdate(VOID)
{
LosTaskCB *runTask = OsCurrTaskGet();
runTask->irqUsedTime = OsGetCurrSchedTimeCycle() - runTask->irqStartTime;//获取时间差
......@@ -417,14 +481,14 @@ STATIC INLINE VOID OsSchedIrqStartTime(VOID)
}
#ifdef LOSCFG_KERNEL_SMP
STATIC INLINE VOID FindIdleRunQue(UINT16 *idleCpuid)
STATIC INLINE VOID IdleRunqueueFind(UINT16 *idleCpuid)
{
SchedRunQue *idleRq = OsSchedRunQueByID(0);
UINT32 nodeNum = OsGetSortLinkNodeNum(&idleRq->taskSortLink);
SchedRunqueue *idleRq = OsSchedRunqueueByID(0);
UINT32 nodeNum = OsGetSortLinkNodeNum(&idleRq->timeoutQueue);
UINT16 cpuid = 1;
do {
SchedRunQue *rq = OsSchedRunQueByID(cpuid);
UINT32 temp = OsGetSortLinkNodeNum(&rq->taskSortLink);
SchedRunqueue *rq = OsSchedRunqueueByID(cpuid);
UINT32 temp = OsGetSortLinkNodeNum(&rq->timeoutQueue);
if (nodeNum > temp) {
*idleCpuid = cpuid;
nodeNum = temp;
......@@ -434,20 +498,20 @@ STATIC INLINE VOID FindIdleRunQue(UINT16 *idleCpuid)
}
#endif
STATIC INLINE VOID OsSchedAddTask2TimeList(LosTaskCB *taskCB, UINT64 responseTime)
STATIC INLINE VOID OsSchedTimeoutQueueAdd(LosTaskCB *taskCB, UINT64 responseTime)
{
#ifdef LOSCFG_KERNEL_SMP
UINT16 cpuid = AFFI_MASK_TO_CPUID(taskCB->cpuAffiMask);
if (cpuid >= LOSCFG_KERNEL_CORE_NUM) {
cpuid = 0;
FindIdleRunQue(&cpuid);
IdleRunqueueFind(&cpuid);
}
#else
UINT16 cpuid = 0;
#endif
SchedRunQue *rq = OsSchedRunQueByID(cpuid);
OsAdd2SortLink(&rq->taskSortLink, &taskCB->sortList, responseTime, cpuid);
SchedRunqueue *rq = OsSchedRunqueueByID(cpuid);
OsAdd2SortLink(&rq->timeoutQueue, &taskCB->sortList, responseTime, cpuid);
#ifdef LOSCFG_KERNEL_SMP
if ((cpuid != ArchCurrCpuid()) && (responseTime < rq->responseTime)) {
rq->schedFlag |= INT_PEND_TICK;
......@@ -456,22 +520,22 @@ STATIC INLINE VOID OsSchedAddTask2TimeList(LosTaskCB *taskCB, UINT64 responseTim
#endif
}
STATIC INLINE VOID OsSchedDeTaskFromTimeList(LosTaskCB *taskCB)
STATIC INLINE VOID OsSchedTimeoutQueueDelete(LosTaskCB *taskCB)
{
SortLinkList *node = &taskCB->sortList;
#ifdef LOSCFG_KERNEL_SMP
SchedRunQue *rq = OsSchedRunQueByID(node->cpuid);
SchedRunqueue *rq = OsSchedRunqueueByID(node->cpuid);
#else
SchedRunQue *rq = OsSchedRunQueByID(0);
SchedRunqueue *rq = OsSchedRunqueueByID(0);
#endif
UINT64 oldResponseTime = GET_SORTLIST_VALUE(node);
OsDeleteFromSortLink(&rq->taskSortLink, node);
OsDeleteFromSortLink(&rq->timeoutQueue, node);
if (oldResponseTime <= rq->responseTime) {
rq->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
}
}
STATIC INLINE UINT32 OsSchedAdjustTaskFromTimeList(LosTaskCB *taskCB, UINT64 responseTime)
STATIC INLINE UINT32 OsSchedTimeoutQueueAdjust(LosTaskCB *taskCB, UINT64 responseTime)
{
UINT32 ret;
SortLinkList *node = &taskCB->sortList;
......@@ -480,14 +544,56 @@ STATIC INLINE UINT32 OsSchedAdjustTaskFromTimeList(LosTaskCB *taskCB, UINT64 res
#else
UINT16 cpuid = 0;
#endif
SchedRunQue *rq = OsSchedRunQueByID(cpuid);
ret = OsSortLinkAdjustNodeResponseTime(&rq->taskSortLink, node, responseTime);
SchedRunqueue *rq = OsSchedRunqueueByID(cpuid);
ret = OsSortLinkAdjustNodeResponseTime(&rq->timeoutQueue, node, responseTime);
if (ret == LOS_OK) {
rq->schedFlag |= INT_PEND_TICK;
}
return ret;
}
STATIC INLINE VOID SchedTaskFreeze(LosTaskCB *taskCB)
{
UINT64 responseTime;
if (!OsIsPmMode()) {
return;
}
if (!(taskCB->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY))) {
return;
}
responseTime = GET_SORTLIST_VALUE(&taskCB->sortList);
OsSchedTimeoutQueueDelete(taskCB);
SET_SORTLIST_VALUE(&taskCB->sortList, responseTime);
taskCB->taskStatus |= OS_TASK_STATUS_FROZEN;
return;
}
STATIC INLINE VOID SchedTaskUnfreeze(LosTaskCB *taskCB)
{
UINT64 currTime, responseTime;
if (!(taskCB->taskStatus & OS_TASK_STATUS_FROZEN)) {
return;
}
taskCB->taskStatus &= ~OS_TASK_STATUS_FROZEN;
currTime = OsGetCurrSchedTimeCycle();
responseTime = GET_SORTLIST_VALUE(&taskCB->sortList);
if (responseTime > currTime) {
OsSchedTimeoutQueueAdd(taskCB, responseTime);
return;
}
SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
LOS_ListDelete(&taskCB->pendList);
}
taskCB->taskStatus &= ~OS_TASK_STATUS_BLOCKED;
return;
}
/*
* Schedule flag, one bit represents one core.
* This flag is used to prevent kernel scheduling before OSStartToRun.
......@@ -500,24 +606,59 @@ STATIC INLINE UINT32 OsSchedAdjustTaskFromTimeList(LosTaskCB *taskCB, UINT64 res
g_taskScheduled &= ~(1U << (cpuid)); \
} while (0);
VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask);
VOID OsSchedResetSchedResponseTime(UINT64 responseTime);
STATIC INLINE LosTaskCB *HPFRunqueueTopTaskGet(HPFRunqueue *rq)
{
LosTaskCB *newTask = NULL;
UINT32 baseBitmap = rq->queueBitmap;
#ifdef LOSCFG_KERNEL_SMP
UINT32 cpuid = ArchCurrCpuid();
#endif
while (baseBitmap) {
UINT32 basePrio = CLZ(baseBitmap);
HPFQueue *queueList = &rq->queueList[basePrio];
UINT32 bitmap = queueList->queueBitmap;
while (bitmap) {
UINT32 priority = CLZ(bitmap);
LOS_DL_LIST_FOR_EACH_ENTRY(newTask, &queueList->priQueList[priority], LosTaskCB, pendList) {
#ifdef LOSCFG_KERNEL_SMP
if (newTask->cpuAffiMask & (1U << cpuid)) {
#endif
return newTask;
#ifdef LOSCFG_KERNEL_SMP
}
#endif
}
bitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - priority - 1));
}
baseBitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - basePrio - 1));
}
return NULL;
}
VOID HPFSchedPolicyInit(SchedRunqueue *rq);
VOID HPFTaskSchedParamInit(LosTaskCB *taskCB, UINT16 policy,
const SchedParam *parentParam, const TSK_INIT_PARAM_S *param);
VOID HPFProcessDefaultSchedParamGet(SchedParam *param);
VOID IdleTaskSchedParamInit(LosTaskCB *taskCB);
INT32 OsSchedParamCompare(const LosTaskCB *task1, const LosTaskCB *task2);
VOID OsSchedPriorityInheritance(LosTaskCB *owner, const SchedParam *param);
UINT32 OsSchedParamInit(LosTaskCB *taskCB, UINT16 policy,
const SchedParam *parentParam, const TSK_INIT_PARAM_S *param);
VOID OsSchedProcessDefaultSchedParamGet(UINT16 policy, SchedParam *param);
VOID OsSchedResponseTimeReset(UINT64 responseTime);
VOID OsSchedToUserReleaseLock(VOID);
VOID OsSchedTaskDeQueue(LosTaskCB *taskCB);
VOID OsSchedTaskEnQueue(LosTaskCB *taskCB);
UINT32 OsSchedTaskWait(LOS_DL_LIST *list, UINT32 timeout, BOOL needSched);
VOID OsSchedTaskWake(LosTaskCB *resumedTask);
BOOL OsSchedModifyTaskSchedParam(LosTaskCB *taskCB, UINT16 policy, UINT16 priority);
BOOL OsSchedModifyProcessSchedParam(UINT32 pid, UINT16 policy, UINT16 priority);
VOID OsSchedSuspend(LosTaskCB *taskCB);
BOOL OsSchedResume(LosTaskCB *taskCB);
VOID OsSchedDelay(LosTaskCB *runTask, UINT64 waitTime);
VOID OsSchedYield(VOID);
VOID OsSchedTaskExit(LosTaskCB *taskCB);
VOID OsSchedTick(VOID);
UINT32 OsSchedInit(VOID);
VOID OsSchedStart(VOID);
VOID OsSchedRunqueueIdleInit(UINT32 idleTaskID);
VOID OsSchedRunqueueInit(VOID);
/*
* This function simply picks the next task and switches to it.
* Current task needs to already be in the right state or the right
......@@ -532,13 +673,6 @@ VOID OsSchedIrqEndCheckNeedSched(VOID);
*/
LOS_DL_LIST *OsSchedLockPendFindPos(const LosTaskCB *runTask, LOS_DL_LIST *lockList);
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_TICK_DEBUG
VOID OsSchedDebugRecordData(VOID);
#endif
UINT32 OsShellShowTickRespo(VOID);
UINT32 OsShellShowSchedParam(VOID);
#endif
#ifdef __cplusplus
#if __cplusplus
}
......
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_STAT_PRI_H
#define __LOS_STAT_PRI_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
UINT64 runtime;
UINT32 contexSwitch;
} SchedPercpu;
typedef struct {
UINT64 allRuntime;
UINT64 runTime;
UINT64 switchCount; /* sched switch count */
UINT64 timeSliceRealTime; /* The actual usage time of each time slice */
UINT64 timeSliceTime;
UINT64 timeSliceCount; /* The number of time slices allocated */
UINT64 pendTime;
UINT64 pendCount;
UINT64 waitSchedTime; /* task status is ready to running times */
UINT64 waitSchedCount;
SchedPercpu schedPercpu[LOSCFG_KERNEL_CORE_NUM];
} SchedStat;
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_STAT_PRI_H */
\ No newline at end of file
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_STAT_PRI_H
#define __LOS_STAT_PRI_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
UINT64 allRuntime;
UINT64 runTime;
UINT64 switchCount; /* sched switch count */
UINT64 timeSliceRealTime; /* The actual usage time of each time slice */
UINT64 timeSliceTime;
UINT64 timeSliceCount; /* The number of time slices allocated */
UINT64 pendTime;
UINT64 pendCount;
UINT64 waitSchedTime; /* task status is ready to running times */
UINT64 waitSchedCount;
} SchedStat;
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_TICK_DEBUG
VOID OsSchedDebugRecordData(VOID);
UINT32 OsShellShowTickResponse(VOID);
UINT32 OsShellShowSchedStatistics(VOID);
UINT32 OsSchedDebugInit(VOID);
#endif
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_STAT_PRI_H */
......@@ -73,7 +73,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task control block is unused.
*/
#define OS_TASK_STATUS_UNUSED 0x0200U ///< 任务状态:未使用
#define OS_TASK_STATUS_UNUSED 0x0400U ///< 任务状态:未使用
/**
* @ingroup los_task
......@@ -81,7 +81,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is joinable.
*/
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U ///< 主task和子task连在一块不分离
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0800U ///< 主task和子task连在一块不分离
/**
* @ingroup los_task
......@@ -89,7 +89,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is user mode task.
*/
#define OS_TASK_FLAG_USER_MODE 0x0800U
#define OS_TASK_FLAG_USER_MODE 0x1000U
/**
* @ingroup los_task
......@@ -97,7 +97,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is system-level task, like idle, swtmr and etc.
*/
#define OS_TASK_FLAG_SYSTEM_TASK 0x1000U ///< 系统任务
#define OS_TASK_FLAG_SYSTEM_TASK 0x2000U ///< 系统任务
/**
* @ingroup los_task
......@@ -105,7 +105,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is no-delete system task, like resourceTask.
*/
#define OS_TASK_FLAG_NO_DELETE 0x2000U ///< 该任务是不可删除的系统任务,如资源回收任务
#define OS_TASK_FLAG_NO_DELETE 0x4000U ///< 该任务是不可删除的系统任务,如资源回收任务
/**
* @ingroup los_task
......@@ -113,15 +113,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* Kills the thread during process exit.
*/
#define OS_TASK_FLAG_EXIT_KILL 0x4000U ///< 在进程退出期间一同被干掉的任务
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The delayed operation of this task is frozen.
*/
#define OS_TASK_FLAG_FREEZE 0x8000U
#define OS_TASK_FLAG_EXIT_KILL 0x8000U ///< 在进程退出期间一同被干掉的任务
/**
* @ingroup los_task
......@@ -329,8 +321,8 @@ extern UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam);
extern INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName);
extern VOID OsTaskCBRecycleToFree(VOID);
extern VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status);
extern UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB);
extern UINT32 OsUserProcessOperatePermissionsCheck(LosTaskCB *taskCB, UINT32 processID);
extern INT32 OsUserTaskOperatePermissionsCheck(const LosTaskCB *taskCB);
extern INT32 OsUserProcessOperatePermissionsCheck(const LosTaskCB *taskCB, UINT32 processID);
extern INT32 OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info);
extern VOID OsWriteResourceEvent(UINT32 events);
extern VOID OsWriteResourceEventUnsafe(UINT32 events);
......
......@@ -79,6 +79,7 @@ struct page_mapping {
#endif
/* If the kernel malloc size is less than 16k, use heap, otherwise use physical pages */
#define KMALLOC_LARGE_SIZE (PAGE_SIZE << 2)
typedef struct VmMapRange {//线性区范围结构体
VADDR_T base; /**< vm region base addr | 线性区基地址*/
UINT32 size; /**< vm region size | 线性区大小*/
......
......@@ -200,7 +200,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventM
runTask->eventMode = mode; //事件模式
runTask->taskEvent = eventCB; //事件控制块
OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout);//任务进入等待状态,等待事件的到来并设置时长和掩码
ret = OsSchedTaskWait(&eventCB->stEventList, timeout, TRUE);//任务暂停,切换调度.
ret = runTask->ops->wait(runTask, &eventCB->stEventList, timeout);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
return LOS_ERRNO_EVENT_READ_TIMEOUT;
}
......@@ -238,7 +238,7 @@ LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT
resumedTask->taskEvent = NULL;
OsTaskWakeClearPendMask(resumedTask);
OsSchedTaskWake(resumedTask);
resumedTask->ops->wake(resumedTask);
}
return exitFlag;
......
......@@ -168,16 +168,16 @@ STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList)
LOS_DL_LIST *queueList = NULL;
tempNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
PRINTK("key(pid) : 0x%x(%d) : ->", tempNode->key, tempNode->pid);
PRINTK("key(pid) : 0x%x(%u) : ->", tempNode->key, tempNode->pid);
for (queueList = &tempNode->queueList; ;) {
lastNode = OS_FUTEX_FROM_QUEUELIST(queueList);
if (!LOS_ListEmpty(&(lastNode->pendList))) {
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(lastNode->pendList)));
PRINTK(" %d(%d) ->", taskCB->taskID, taskCB->priority);
PRINTK(" %u ->", taskCB->taskID);
} else {
taskCB = LOS_DL_LIST_ENTRY(lastNode, LosTaskCB, futex);
PRINTK(" %d(%d) ->", taskCB->taskID, -1);
PRINTK(" %u ->", taskCB->taskID);
}
queueList = queueList->pstNext;
if (queueList == &tempNode->queueList) {
......@@ -393,20 +393,19 @@ STATIC INT32 OsFutexInsertFindFormBackToFront(LOS_DL_LIST *queueList, const LosT
{
LOS_DL_LIST *listHead = queueList;
LOS_DL_LIST *listTail = queueList->pstPrev;
FutexNode *tempNode = NULL;
LosTaskCB *taskTail = NULL;
for (; listHead != listTail; listTail = listTail->pstPrev) {
tempNode = OS_FUTEX_FROM_QUEUELIST(listTail);
FutexNode *tempNode = OS_FUTEX_FROM_QUEUELIST(listTail);
tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
if (tempNode == NULL) {
return LOS_NOK;
}
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
if (runTask->priority >= taskTail->priority) {
LosTaskCB *taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
INT32 ret = OsSchedParamCompare(runTask, taskTail);
if (ret >= 0) {
LOS_ListHeadInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
} else if (runTask->priority < taskTail->priority) {
} else {
if (listTail->pstPrev == listHead) {
LOS_ListTailInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
......@@ -421,26 +420,25 @@ STATIC INT32 OsFutexInsertFindFromFrontToBack(LOS_DL_LIST *queueList, const LosT
{
LOS_DL_LIST *listHead = queueList;
LOS_DL_LIST *listTail = queueList->pstPrev;
FutexNode *tempNode = NULL;
LosTaskCB *taskHead = NULL;
for (; listHead != listTail; listHead = listHead->pstNext) {
tempNode = OS_FUTEX_FROM_QUEUELIST(listHead);
FutexNode *tempNode = OS_FUTEX_FROM_QUEUELIST(listHead);
tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
if (tempNode == NULL) {
return LOS_NOK;
}
taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
/* High priority comes before low priority,
* in the case of the same priority, after the current node
*/
if (runTask->priority >= taskHead->priority) {
INT32 ret = OsSchedParamCompare(runTask, taskHead);
if (ret >= 0) {
if (listHead->pstNext == listTail) {
LOS_ListHeadInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
}
continue;
} else if (runTask->priority < taskHead->priority) {
} else {
LOS_ListTailInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
}
......@@ -471,10 +469,9 @@ STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node,
{
LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));//获取阻塞链表首个任务
LOS_DL_LIST *queueList = &((*firstNode)->queueList);
FutexNode *tailNode = NULL;
LosTaskCB *taskTail = NULL;
if (run->priority < taskHead->priority) {//任务的优先级比较
INT32 ret1 = OsSchedParamCompare(run, taskHead);
if (ret1 < 0) {
/* The one with the highest priority is inserted at the top of the queue */
LOS_ListTailInsert(queueList, &(node->queueList));//查到queueList的尾部
OsFutexReplaceQueueListHeadNode(*firstNode, node);//同时交换futexList链表上的位置
......@@ -482,16 +479,16 @@ STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node,
return LOS_OK;
}
//如果等锁链表上没有任务或者当前任务大于链表首个任务
if (LOS_ListEmpty(queueList) && (run->priority >= taskHead->priority)) {
if (LOS_ListEmpty(queueList) && (ret1 >= 0)) {
/* Insert the next position in the queue with equal priority */
LOS_ListHeadInsert(queueList, &(node->queueList));//从头部插入当前任务,当前任务是要被挂起的
return LOS_OK;
}
tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));//获取尾部节点
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));//获取阻塞任务的最后一个
if ((run->priority >= taskTail->priority) ||//当前任务优先级比最后一个更高,或者 ... 没看懂, 为啥要这样 ? @notethinking
((run->priority - taskHead->priority) > (taskTail->priority - run->priority))) {//跟最后一个比较优先级
FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));//获取尾部节点
LosTaskCB *taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));//获取阻塞任务的最后一个
INT32 ret2 = OsSchedParamCompare(taskTail, run);
if ((ret2 <= 0) || (ret1 > ret2)) {
return OsFutexInsertFindFormBackToFront(queueList, run, node);//从后往前插入
}
......@@ -626,7 +623,7 @@ STATIC INT32 OsFutexInsertTaskToHash(LosTaskCB **taskCB, FutexNode **node, const
return LOS_OK;
}
/// 将当前任务挂入等待链表中
STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const UINT32 val, const UINT32 timeOut)
STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const UINT32 val, const UINT32 timeout)
{
INT32 futexRet;
UINT32 intSave, lockVal;
......@@ -657,9 +654,9 @@ STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const
}
SCHEDULER_LOCK(intSave);
OsTaskWaitSetPendMask(OS_TASK_WAIT_FUTEX, futexKey, timeOut);
OsSchedTaskWait(&(node->pendList), timeOut, FALSE);
OsSchedLock();
OsTaskWaitSetPendMask(OS_TASK_WAIT_FUTEX, futexKey, timeout);
taskCB->ops->wait(taskCB, &(node->pendList), timeout);
LOS_SpinUnlock(&g_taskSpin);
futexRet = OsFutexUnlock(&hashNode->listLock);//
......@@ -696,17 +693,17 @@ EXIT_UNLOCK_ERR:
INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
{
INT32 ret;
UINT32 timeOut = LOS_WAIT_FOREVER;
UINT32 timeout = LOS_WAIT_FOREVER;
ret = OsFutexWaitParamCheck(userVaddr, flags, absTime);//参数检查
if (ret) {
return ret;
}
if (absTime != LOS_WAIT_FOREVER) {//转换时间 , 内核的时间单位是 tick
timeOut = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); //转成 tick
timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); //转成 tick
}
return OsFutexWaitTask(userVaddr, flags, val, timeOut);//将任务挂起 timeOut 时长
return OsFutexWaitTask(userVaddr, flags, val, timeout);//将任务挂起 timeOut 时长
}
STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags)
......@@ -751,7 +748,7 @@ STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNum
node = *nextNode;
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(node->pendList)));
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
taskCB->ops->wake(taskCB);
*wakeAny = TRUE;
*nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&(node->queueList)));
if (node != headNode) {
......
......@@ -310,41 +310,37 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
return LOS_OK;
}
///设置互斥锁位图
STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask, LosTaskCB *owner)
{ //当前任务优先级高于锁持有task时的处理
if ((owner->priority > runTask->priority) && (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT)) {//协议用继承方式是怎么的呢?
LOS_BitmapSet(&(owner->priBitMap), owner->priority);//1.priBitMap是记录任务优先级变化的位图,这里把持有锁任务优先级记录在自己的priBitMap中
(VOID)OsSchedModifyTaskSchedParam(owner, owner->policy, runTask->priority);
}//注意任务优先级有32个, 是0最高,31最低!!!这里等于提高了持有锁任务的优先级,目的是让其在下次调度中提高选中的概率,从而快速的释放锁.您明白了吗? :|)
STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask)
{
if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
return;
}
SchedParam param = { 0 };
LosTaskCB *owner = (LosTaskCB *)mutex->owner;
INT32 ret = OsSchedParamCompare(owner, runTask);
if (ret > 0) {
runTask->ops->schedParamGet(runTask, &param);
owner->ops->priorityInheritance(owner, &param);
}
}
///恢复互斥锁位图
VOID OsMuxBitmapRestore(const LosMux *mutex, const LosTaskCB *taskCB, LosTaskCB *owner)
VOID OsMuxBitmapRestore(const LosMux *mutex, const LOS_DL_LIST *list, const LosTaskCB *runTask)
{
UINT16 bitMapPri;
if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
return;
}
if (owner->priority >= taskCB->priority) {
bitMapPri = LOS_LowBitGet(owner->priBitMap);
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
LOS_BitmapClr(&(owner->priBitMap), bitMapPri);
OsSchedModifyTaskSchedParam(owner, owner->policy, bitMapPri);
}
} else {
if (LOS_HighBitGet(owner->priBitMap) != taskCB->priority) {
LOS_BitmapClr(&(owner->priBitMap), taskCB->priority);
}
}
SchedParam param = { 0 };
LosTaskCB *owner = (LosTaskCB *)mutex->owner;
runTask->ops->schedParamGet(runTask, &param);
owner->ops->priorityRestore(owner, list, &param);
}
/// 最坏情况就是拿锁失败,让出CPU,变成阻塞任务,等别的任务释放锁后排到自己了接着执行.
STATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
{
UINT32 ret;
LOS_DL_LIST *node = NULL;
LosTaskCB *owner = NULL;
if ((mutex->muxList.pstPrev == NULL) || (mutex->muxList.pstNext == NULL)) {//列表为空时的处理
/* This is for mutex macro initialization. */
......@@ -357,9 +353,11 @@ STATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
mutex->muxCount++; //互斥锁计数器加1
mutex->owner = (VOID *)runTask; //当前任务拿到锁
LOS_ListTailInsert(&runTask->lockList, &mutex->holdList);
if ((mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) && (runTask->priority > mutex->attr.prioceiling)) {
LOS_BitmapSet(&runTask->priBitMap, runTask->priority);
(VOID)OsSchedModifyTaskSchedParam(runTask, runTask->policy, mutex->attr.prioceiling);
if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
SchedParam param = { 0 };
runTask->ops->schedParamGet(runTask, &param);
param.priority = mutex->attr.prioceiling;
runTask->ops->priorityInheritance(runTask, &param);
}
return LOS_OK;
}
......@@ -377,27 +375,23 @@ STATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
return LOS_EDEADLK;//返回错误,自旋锁被别的CPU core 持有
}
OsMuxBitmapSet(mutex, runTask, (LosTaskCB *)mutex->owner);//设置锁位图,尽可能的提高锁持有任务的优先级
OsMuxBitmapSet(mutex, runTask);//设置锁位图,尽可能的提高锁持有任务的优先级
owner = (LosTaskCB *)mutex->owner; //记录持有锁的任务
runTask->taskMux = (VOID *)mutex; //记下当前任务在等待这把锁
node = OsSchedLockPendFindPos(runTask, &mutex->muxList);
LOS_DL_LIST *node = OsSchedLockPendFindPos(runTask, &mutex->muxList);
if (node == NULL) {
ret = LOS_NOK;
return ret;
}
OsTaskWaitSetPendMask(OS_TASK_WAIT_MUTEX, (UINTPTR)mutex, timeout);
ret = OsSchedTaskWait(node, timeout, TRUE);
ret = runTask->ops->wait(runTask, node, timeout);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {//这行代码虽和OsTaskWait挨在一起,但要过很久才会执行到,因为在OsTaskWait中CPU切换了任务上下文
OsMuxBitmapRestore(mutex, NULL, runTask);
runTask->taskMux = NULL;// 所以重新回到这里时可能已经超时了
ret = LOS_ETIMEDOUT;//返回超时
}
if (timeout != LOS_WAIT_FOREVER) {//不是永远等待的情况
OsMuxBitmapRestore(mutex, runTask, owner);//恢复锁的位图
}
return ret;
}
......@@ -493,24 +487,6 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxTrylock(LosMux *mutex)
SCHEDULER_UNLOCK(intSave);
return ret;
}
///降低参数任务的优先级上限
STATIC VOID OsMuxPostOpSub(LosTaskCB *taskCB, LosMux *mutex)
{
LosTaskCB *pendedTask = NULL;
UINT16 bitMapPri;
//理解OsMuxPostOpSub之前要先理解一个task在运行过程中优先级会变化,这些变化都记录在taskCB->priBitMap中
if (!LOS_ListEmpty(&mutex->muxList)) {//还有任务在等锁
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);//获取参数任务bitmap中优先级下限(意思是最低优先级记录)
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, (&mutex->muxList), LosTaskCB, pendList) {//循环拿等锁任务
if (bitMapPri != pendedTask->priority) {//等锁任务优先级不等于参数任务优先级下限的情况
LOS_BitmapClr(&taskCB->priBitMap, pendedTask->priority);//在bitmap的pendedTask->priority位上置0
}
}
}
bitMapPri = LOS_LowBitGet(taskCB->priBitMap);//拿低位优先级,也就是最高优先级的记录
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);//把taskCB已知的最高优先级记录位清0,实际等于降低了taskCB优先级的上限
(VOID)OsSchedModifyTaskSchedParam((LosTaskCB *)mutex->owner, ((LosTaskCB *)mutex->owner)->policy, bitMapPri);
}
/*!
* @brief OsMuxPostOp
......@@ -525,30 +501,21 @@ STATIC VOID OsMuxPostOpSub(LosTaskCB *taskCB, LosMux *mutex)
*/
STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
{
LosTaskCB *resumedTask = NULL;
if (LOS_ListEmpty(&mutex->muxList)) {//如果互斥锁列表为空
LOS_ListDelete(&mutex->holdList);//把持有互斥锁的节点摘掉
mutex->owner = NULL;
return LOS_OK;
}
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));//拿到等待互斥锁链表的第一个任务实体,接下来要唤醒任务
if (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT) {//互斥锁属性协议是继承会怎么操作?
if (resumedTask->priority > taskCB->priority) {//拿到锁的任务优先级低于参数任务优先级
if (LOS_HighBitGet(taskCB->priBitMap) != resumedTask->priority) {//参数任务bitmap中最低的优先级不等于等待锁的任务优先级
LOS_BitmapClr(&taskCB->priBitMap, resumedTask->priority);//把等待任务锁的任务的优先级记录在参数任务的bitmap中
}
} else if (taskCB->priBitMap != 0) {//如果bitmap不等于0说明参数任务至少有任务调度的优先级
OsMuxPostOpSub(taskCB, mutex);//
}
}
LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));//拿到等待互斥锁链表的第一个任务实体,接下来要唤醒任务
OsMuxBitmapRestore(mutex, &mutex->muxList, resumedTask);
mutex->muxCount = 1;//互斥锁数量为1
mutex->owner = (VOID *)resumedTask;//互斥锁的持有人换了
LOS_ListDelete(&mutex->holdList);//自然要从等锁链表中把自己摘出去
LOS_ListTailInsert(&resumedTask->lockList, &mutex->holdList);//把锁挂到恢复任务的锁链表上,lockList是任务持有的所有锁记录
OsTaskWakeClearPendMask(resumedTask);
OsSchedTaskWake(resumedTask);
resumedTask->ops->wake(resumedTask);
resumedTask->taskMux = NULL;
if (needSched != NULL) {//如果不为空
*needSched = TRUE;//就走起再次调度流程
......@@ -559,8 +526,6 @@ STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
{
UINT16 bitMapPri;
if (mutex->magic != OS_MUX_MAGIC) {
return LOS_EBADF;
}
......@@ -582,11 +547,9 @@ UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
}
if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {//属性协议为保护时
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);//找priBitMap记录中最高的那个优先级
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);//找priBitMap记录中最高的那个优先级
(VOID)OsSchedModifyTaskSchedParam(taskCB, taskCB->policy, bitMapPri);
}
SchedParam param = { 0 };
taskCB->ops->schedParamGet(taskCB, &param);
taskCB->ops->priorityRestore(taskCB, NULL, &param);
}
/* Whether a task block the mutex lock. *///任务是否阻塞互斥锁
......
......@@ -275,6 +275,7 @@ STATIC VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *
PRINT_ERR("get msgdatasize failed\n");
return;
}
msgDataSize = (*bufferSize < msgDataSize) ? *bufferSize : msgDataSize;
if (memcpy_s(bufferAddr, *bufferSize, queueNode, msgDataSize) != EOK) {//2.读表示读走已有数据,所以相当于bufferAddr接着了queueNode的数据
PRINT_ERR("copy message to buffer failed\n");
return;
......@@ -301,9 +302,7 @@ STATIC UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 queueID
return LOS_ERRNO_QUEUE_NOT_CREATE;
}
if (OS_QUEUE_IS_READ(operateType) && (*bufferSize < (queueCB->queueSize - sizeof(UINT32)))) {//读时判断
return LOS_ERRNO_QUEUE_READ_SIZE_TOO_SMALL;//接走队列数据的buffer太小了,接不走整个消息数据
} else if (OS_QUEUE_IS_WRITE(operateType) && (*bufferSize > (queueCB->queueSize - sizeof(UINT32)))) {//写时判断
if (OS_QUEUE_IS_WRITE(operateType) && (*bufferSize > (queueCB->queueSize - sizeof(UINT32)))) {//写时判断
return LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG;//塞进来的数据太大,大于队列节点能承受的范围
}
return LOS_OK;
......@@ -322,15 +321,13 @@ STATIC UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 queueID
*/
UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeout)
{
LosQueueCB *queueCB = NULL;
LosTaskCB *resumedTask = NULL;
UINT32 ret;
UINT32 readWrite = OS_QUEUE_READ_WRITE_GET(operateType);//获取读/写操作标识
UINT32 intSave;
OsHookCall(LOS_HOOK_TYPE_QUEUE_READ, (LosQueueCB *)GET_QUEUE_HANDLE(queueID), operateType, *bufferSize, timeout);
SCHEDULER_LOCK(intSave);
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);//获取对应的队列控制块
LosQueueCB *queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);//获取对应的队列控制块
ret = OsQueueOperateParamCheck(queueCB, queueID, operateType, bufferSize);//参数检查
if (ret != LOS_OK) {
goto QUEUE_END;
......@@ -347,8 +344,9 @@ UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT
goto QUEUE_END;
}
//任务等待,这里很重要啊,将自己从就绪列表摘除,让出了CPU并发起了调度,并挂在readWriteList[readWrite]上,挂的都等待读/写消息的task
LosTaskCB *runTask = OsCurrTaskGet();
OsTaskWaitSetPendMask(OS_TASK_WAIT_QUEUE, queueCB->queueID, timeout);
ret = OsSchedTaskWait(&queueCB->readWriteList[readWrite], timeout, TRUE);
ret = runTask->ops->wait(runTask, &queueCB->readWriteList[readWrite], timeout);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {//唤醒后如果超时了,返回读/写消息失败
ret = LOS_ERRNO_QUEUE_TIMEOUT;
goto QUEUE_END;//
......@@ -360,9 +358,9 @@ UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT
OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);//发起读或写队列操作
if (!LOS_ListEmpty(&queueCB->readWriteList[!readWrite])) {//如果还有任务在排着队等待读/写入消息(当时不能读/写的原因有可能当时队列满了==)
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[!readWrite]));//取出要读/写消息的任务
LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[!readWrite]));//取出要读/写消息的任务
OsTaskWakeClearPendMask(resumedTask);
OsSchedTaskWake(resumedTask);
resumedTask->ops->wake(resumedTask);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);//让所有CPU发出调度申请,因为很可能那个要读/写消息的队列是由其他CPU执行
LOS_Schedule();//申请调度
......
......@@ -146,7 +146,7 @@ STATIC BOOL OsRwlockPriCompare(LosTaskCB *runTask, LOS_DL_LIST *rwList)
{
if (!LOS_ListEmpty(rwList)) {
LosTaskCB *highestTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(rwList));//首个写锁任务优先级是最高的
if (runTask->priority < highestTask->priority) {//如果当前任务优先级低于等待写锁任务
if (OsSchedParamCompare(runTask, highestTask) < 0) {//如果当前任务优先级低于等待写锁任务
return TRUE;
}
return FALSE;
......@@ -198,7 +198,7 @@ STATIC UINT32 OsRwlockRdPendOp(LosTaskCB *runTask, LosRwlock *rwlock, UINT32 tim
*/
LOS_DL_LIST *node = OsSchedLockPendFindPos(runTask, &(rwlock->readList));//找到要挂入的位置
//例如现有链表内任务优先级为 0 3 8 9 23 当前为 10 时, 返回的是 9 这个节点
ret = OsSchedTaskWait(node, timeout, TRUE);//从尾部插入读锁链表 由此变成了 0 3 8 9 10 23
ret = runTask->ops->wait(runTask, node, timeout);//从尾部插入读锁链表 由此变成了 0 3 8 9 10 23
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
return LOS_ETIMEDOUT;
}
......@@ -241,7 +241,7 @@ STATIC UINT32 OsRwlockWrPendOp(LosTaskCB *runTask, LosRwlock *rwlock, UINT32 tim
* write task will be pended. | 当 rwlock 为读模式或其他写任务获得该 rwlock 时,当前的写任务将被挂起。直到读模式下的锁释放
*/
LOS_DL_LIST *node = OsSchedLockPendFindPos(runTask, &(rwlock->writeList));//找到要挂入的位置
ret = OsSchedTaskWait(node, timeout, TRUE);//从尾部插入写锁链表
ret = runTask->ops->wait(runTask, node, timeout);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
ret = LOS_ETIMEDOUT;
}
......@@ -393,7 +393,7 @@ STATIC UINT32 OsRwlockGetMode(LOS_DL_LIST *readList, LOS_DL_LIST *writeList)
}
LosTaskCB *pendedReadTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(readList));
LosTaskCB *pendedWriteTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(writeList));
if (pendedWriteTask->priority <= pendedReadTask->priority) { //都有数据比优先级
if (OsSchedParamCompare(pendedWriteTask, pendedReadTask) <= 0) {
return RWLOCK_WRITEFIRST_MODE; //写的优先级高时,为写优先模式
}
return RWLOCK_READFIRST_MODE; //读的优先级高时,为读优先模式
......@@ -403,7 +403,6 @@ STATIC UINT32 OsRwlockPostOp(LosRwlock *rwlock, BOOL *needSched)
{
UINT32 rwlockMode;
LosTaskCB *resumedTask = NULL;
UINT16 pendedWriteTaskPri;
rwlock->rwCount = 0;
rwlock->writeOwner = NULL;
......@@ -416,30 +415,30 @@ STATIC UINT32 OsRwlockPostOp(LosRwlock *rwlock, BOOL *needSched)
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(rwlock->writeList)));//获取任务实体
rwlock->rwCount = -1;//直接干成-1,注意这里并不是 --
rwlock->writeOwner = (VOID *)resumedTask;//有锁了则唤醒等锁的任务(写模式)
OsSchedTaskWake(resumedTask);
resumedTask->ops->wake(resumedTask);
if (needSched != NULL) {
*needSched = TRUE;
}
return LOS_OK;
}
/* In this case, rwlock will wake the valid pended read task. 在这种情况下,rwlock 将唤醒有效的挂起读取任务。 */
if (rwlockMode == RWLOCK_READFIRST_MODE) { //如果是读优先模式
pendedWriteTaskPri = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(rwlock->writeList)))->priority;//取出写锁任务的最高优先级
}
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(rwlock->readList)));//获取最高优先级读锁任务
rwlock->rwCount = 1; //直接干成1,因为是释放操作
OsSchedTaskWake(resumedTask);//有锁了则唤醒等锁的任务(读模式)
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(rwlock->readList)));
resumedTask->ops->wake(resumedTask);
while (!LOS_ListEmpty(&(rwlock->readList))) {//遍历读链表,目的是要唤醒其他读模式的任务(优先级得要高于pendedWriteTaskPri才行)
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(rwlock->readList)));
if ((rwlockMode == RWLOCK_READFIRST_MODE) && (resumedTask->priority >= pendedWriteTaskPri)) {//低于写模式的优先级
if (rwlockMode == RWLOCK_READFIRST_MODE) {
LosTaskCB *pendedWriteTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(rwlock->writeList)));
if (OsSchedParamCompare(resumedTask, pendedWriteTask) >= 0) {
break;//跳出循环
}
}
if (rwlock->rwCount == INT8_MAX) {
return EINVAL;
}
rwlock->rwCount++;//读锁任务数量增加
OsSchedTaskWake(resumedTask);//不断唤醒读锁任务,由此实现了允许多个读操作并发,因为在多核情况下resumedTask很大可能
//与当前任务并不在同一个核上运行, 此处非常有意思,点赞! @note_good
resumedTask->ops->wake(resumedTask);//不断唤醒读锁任务,由此实现了允许多个读操作并发,因为在多核情况下resumedTask很大可能
//与当前任务并不在同一个核上运行, 此处非常有意思,点赞! @note_good
}
if (needSched != NULL) {
*needSched = TRUE;
......
......@@ -274,7 +274,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
OsHookCall(LOS_HOOK_TYPE_SEM_PEND, semPended, runTask, timeout);
OsTaskWaitSetPendMask(OS_TASK_WAIT_SEM, semPended->semID, timeout);
retErr = OsSchedTaskWait(&semPended->semList, timeout, TRUE);
retErr = runTask->ops->wait(runTask, &semPended->semList, timeout);
if (retErr == LOS_ERRNO_TSK_TIMEOUT) {//注意:这里是涉及到task切换的,把自己挂起,唤醒其他task
retErr = LOS_ERRNO_SEM_TIMEOUT;
}
......@@ -286,10 +286,8 @@ OUT:
///以不安全的方式释放指定的信号量,所谓不安全指的是不用自旋锁
LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
{
LosSemCB *semPosted = NULL;
LosTaskCB *resumedTask = NULL;
semPosted = GET_SEM(semHandle);
LosSemCB *semPosted = GET_SEM(semHandle);
if ((semPosted->semID != semHandle) || (semPosted->semStat == OS_SEM_UNUSED)) {
return LOS_ERRNO_SEM_INVALID;
}
......@@ -303,7 +301,7 @@ LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
if (!LOS_ListEmpty(&semPosted->semList)) {//当前有任务挂在semList上,要去唤醒任务
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));//semList上面挂的都是task->pendlist节点,取第一个task下来唤醒
OsTaskWakeClearPendMask(resumedTask);
OsSchedTaskWake(resumedTask);
resumedTask->ops->wake(resumedTask);
if (needSched != NULL) {//参数不为空,就返回需要调度的标签
*needSched = TRUE;//TRUE代表需要调度
}
......
......@@ -135,7 +135,7 @@ STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
OsMoveTmpInfoToUnbInfo(sigcb, signo);
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
taskCB->ops->wake(taskCB);
OsSigEmptySet(&sigcb->sigwaitmask);
}
}
......@@ -158,19 +158,19 @@ STATIC UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
break;
case OS_TASK_WAIT_JOIN:
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
taskCB->ops->wake(taskCB);
break;
case OS_TASK_WAIT_SIGNAL://等待普通信号
OsSigWaitTaskWake(taskCB, signo);
break;
case OS_TASK_WAIT_LITEIPC://等待liteipc信号
OsTaskWakeClearPendMask(taskCB);//重置任务的等待信息
OsSchedTaskWake(taskCB);//唤醒任务
taskCB->ops->wake(taskCB);
break;
case OS_TASK_WAIT_FUTEX://等待快锁信号
OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);//从哈希桶中删除快锁
OsTaskWakeClearPendMask(taskCB);//重置任务的等待信息
OsSchedTaskWake(taskCB);//唤醒任务
taskCB->ops->wake(taskCB);
break;
default:
break;
......@@ -589,7 +589,7 @@ int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
sigcb->sigwaitmask |= *set;//按位加到等待集上,也就是说sigwaitmask的信号来了都是要处理的.
OsTaskWaitSetPendMask(OS_TASK_WAIT_SIGNAL, sigcb->sigwaitmask, timeout);
ret = OsSchedTaskWait(&sigcb->waitList, timeout, TRUE);
ret = task->ops->wait(task, &sigcb->waitList, timeout);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
ret = -EAGAIN;
}
......
此差异已折叠。
......@@ -91,7 +91,7 @@ VOID OsMpScheduleHandler(VOID)
* set schedule flag to differ from wake function,
* so that the scheduler can be triggered at the end of irq.
*/
OsSchedRunQuePendingSet();
OsSchedRunqueuePendingSet();
}
///硬中断暂停处理函数
VOID OsMpHaltHandler(VOID)
......
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_task_pri.h"
// 文件作用:统计多CPU core下运行情况,打开开关必然消耗大量的性能
#ifdef LOSCFG_KERNEL_SCHED_STATISTICS
#define HIGHTASKPRI 16 //界定高优先级任务的标准
#define NS_PER_MS 1000000
#define DECIMAL_TO_PERCENTAGE 100
typedef struct { //每个cpu core 运行参数描述体
UINT64 idleRuntime;
UINT64 idleStarttime;
UINT64 highTaskRuntime;
UINT64 highTaskStarttime;
UINT64 spinWaitRuntime;
UINT64 sumPriority;
UINT32 prioritySwitch;
UINT32 highTaskSwitch;
UINT32 contexSwitch;
UINT32 hwiNum;
UINT32 ipiIrqNum;
} MpStatPercpu;
STATIC BOOL g_mpStaticStartFlag = FALSE;
STATIC UINT64 g_mpStaticStartTime;
STATIC MpStatPercpu g_mpStatPercpu[LOSCFG_KERNEL_SMP_CORE_NUM] = {0};
STATIC VOID OsMpSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
{
UINT32 cpuid;
UINT32 idleTaskID;
UINT64 now, runtime;
if (g_mpStaticStartFlag != TRUE) {
return;
}
cpuid = ArchCurrCpuid();
idleTaskID = OsGetIdleTaskId();
now = LOS_CurrNanosec();
g_mpStatPercpu[cpuid].contexSwitch++;
if ((runTask->taskID != idleTaskID) && (newTask->taskID == idleTaskID)) {
g_mpStatPercpu[cpuid].idleStarttime = now;
}
if ((runTask->taskID == idleTaskID) && (newTask->taskID != idleTaskID)) {
runtime = now - g_mpStatPercpu[cpuid].idleStarttime;
g_mpStatPercpu[cpuid].idleRuntime += runtime;
g_mpStatPercpu[cpuid].idleStarttime = 0;
}
if ((runTask->priority >= HIGHTASKPRI) && (newTask->priority < HIGHTASKPRI)) {
g_mpStatPercpu[cpuid].highTaskStarttime = now;
}
if ((runTask->priority < HIGHTASKPRI) && (newTask->priority >= HIGHTASKPRI)) {
runtime = now - g_mpStatPercpu[cpuid].highTaskStarttime;
g_mpStatPercpu[cpuid].highTaskRuntime += runtime;
g_mpStatPercpu[cpuid].highTaskStarttime = 0;
}
if (newTask->priority < HIGHTASKPRI) {
g_mpStatPercpu[cpuid].highTaskSwitch++;
}
if (newTask->taskID != idleTaskID) {
g_mpStatPercpu[cpuid].sumPriority += newTask->priority;
g_mpStatPercpu[cpuid].prioritySwitch++;
}
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
{
UINT64 runtime;
UINT32 cpuid = ArchCurrCpuid();
UINT64 now = LOS_CurrNanosec();
SchedStat *schedRun = &runTask->schedStat;
SchedStat *schedNew = &newTask->schedStat;
SchedPercpu *cpuRun = &schedRun->schedPercpu[cpuid];
SchedPercpu *cpuNew = &schedNew->schedPercpu[cpuid];
/* calculate one chance of running time */
runtime = now - schedRun->startRuntime;
/* add running timer to running task statistics */
cpuRun->runtime += runtime;
schedRun->allRuntime += runtime;
/* add context switch counters and schedule start time */
cpuNew->contexSwitch++;
schedNew->allContextSwitch++;
schedNew->startRuntime = now;
OsMpSchedStatistics(runTask, newTask);
}
LITE_OS_SEC_TEXT_MINOR VOID OsSpinWaitStatistics(UINT64 spinWaitRuntime)
{
UINT32 cpuid = ArchCurrCpuid();
g_mpStatPercpu[cpuid].spinWaitRuntime += spinWaitRuntime;
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum)
{
UINT32 cpuid = ArchCurrCpuid();
if ((g_mpStaticStartFlag != TRUE) || (intNum == OS_TICK_INT_NUM)) {
return;
}
g_mpStatPercpu[cpuid].hwiNum++;
/* 16: 0~15 is ipi interrupts */
if (intNum < 16) {
g_mpStatPercpu[cpuid].ipiIrqNum++;
}
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuid;
UINT32 affinity;
PRINTK("\n");
PRINTK("Task TID Total Time Total CST "
"CPU Time CST\n");
PRINTK("---- --- ------------------ ---------- -"
"--- ------------------ ----------\n");
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (OsTaskIsUnused(taskCB)) {
continue;
}
affinity = (UINT32)taskCB->cpuAffiMask;
PRINTK("%-30s0x%-6x%+16lf ms %10d\n", taskCB->taskName, taskCB->taskID,
(DOUBLE)(taskCB->schedStat.allRuntime) / NS_PER_MS,
taskCB->schedStat.allContextSwitch);
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
if (!((1U << cpuid) & affinity)) {
continue;
}
PRINTK(" "
"CPU%d %+16lf ms %12d\n", cpuid,
(DOUBLE)(taskCB->schedStat.schedPercpu[cpuid].runtime) / NS_PER_MS,
taskCB->schedStat.schedPercpu[cpuid].contexSwitch);
}
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStart(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuid = 0;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_mpStaticStartFlag) {
PRINT_WARN("mp static has started\n");
SCHEDULER_UNLOCK(intSave);
return;
}
g_mpStaticStartTime = LOS_CurrNanosec();
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#ifdef LOSCFG_KERNEL_SMP
cpuid = taskCB->currCpu;
#endif
if ((UINT32)(OS_TASK_INVALID_CPUID) == cpuid) {
continue;
}
if (!strcmp(taskCB->taskName, "Idle")) {
g_mpStatPercpu[cpuid].idleStarttime = g_mpStaticStartTime;
}
if (taskCB->priority < HIGHTASKPRI) {
g_mpStatPercpu[cpuid].highTaskStarttime = g_mpStaticStartTime;
g_mpStatPercpu[cpuid].highTaskSwitch++;
}
if (strcmp(taskCB->taskName, "Idle")) {
g_mpStatPercpu[cpuid].sumPriority += taskCB->priority;
g_mpStatPercpu[cpuid].prioritySwitch++;
}
}
}
g_mpStaticStartFlag = TRUE;
SCHEDULER_UNLOCK(intSave);
PRINTK("mp static start\n");
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsMpStaticShow(UINT64 mpStaticPastTime)
{
UINT32 cpuid;
PRINTK("\n");
PRINTK("Passed Time: %+16lf ms\n", (DOUBLE)mpStaticPastTime / NS_PER_MS);
PRINTK("--------------------------------\n");
PRINTK("CPU Idle(%%) schedule noTick Hwi MP Hwi MP Loss(%%) "
"avg PRI HiTSK(%%) HiTSK SCH HiTSK P(ms)\n");
PRINTK("---- --------- ---------- ---------- ---------- ---------- "
"---------- ---------- ---------- ----------\n");
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
PRINTK("CPU%d %+10lf%14d%14d%14d %+11lf %+11lf %+11lf%14d %+11lf\n", cpuid,
((DOUBLE)(g_mpStatPercpu[cpuid].idleRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
g_mpStatPercpu[cpuid].contexSwitch,
g_mpStatPercpu[cpuid].hwiNum,
g_mpStatPercpu[cpuid].ipiIrqNum,
((DOUBLE)(g_mpStatPercpu[cpuid].spinWaitRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
(g_mpStatPercpu[cpuid].prioritySwitch == 0) ? OS_TASK_PRIORITY_LOWEST :
((DOUBLE)(g_mpStatPercpu[cpuid].sumPriority) / (g_mpStatPercpu[cpuid].prioritySwitch)),
((DOUBLE)(g_mpStatPercpu[cpuid].highTaskRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
g_mpStatPercpu[cpuid].highTaskSwitch,
(g_mpStatPercpu[cpuid].highTaskSwitch == 0) ? 0 :
((DOUBLE)(g_mpStatPercpu[cpuid].highTaskRuntime) / (g_mpStatPercpu[cpuid].highTaskSwitch)) / NS_PER_MS);
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStop(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuid = 0;
UINT64 mpStaticStopTime;
UINT64 mpStaticPastTime;
UINT64 runtime;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_mpStaticStartFlag != TRUE) {
PRINT_WARN("Please set mp static start\n");
SCHEDULER_UNLOCK(intSave);
return;
}
g_mpStaticStartFlag = FALSE;
mpStaticStopTime = LOS_CurrNanosec();
mpStaticPastTime = mpStaticStopTime - g_mpStaticStartTime;
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#ifdef LOSCFG_KERNEL_SMP
cpuid = taskCB->currCpu;
#endif
if (cpuid == (UINT32)(OS_TASK_INVALID_CPUID)) {
continue;
}
if (!strcmp(taskCB->taskName, "Idle")) { //空闲任务情况下
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].idleStarttime;
g_mpStatPercpu[cpuid].idleRuntime += runtime;
g_mpStatPercpu[cpuid].idleStarttime = 0;
}
if (taskCB->priority < HIGHTASKPRI) {
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].highTaskStarttime;
g_mpStatPercpu[cpuid].highTaskRuntime += runtime;
g_mpStatPercpu[cpuid].highTaskStarttime = 0;
}
}
}
SCHEDULER_UNLOCK(intSave);
OsMpStaticShow(mpStaticPastTime);
(VOID)memset_s(g_mpStatPercpu, sizeof(g_mpStatPercpu), 0, sizeof(g_mpStatPercpu));
g_mpStaticStartTime = 0;
return;
}
#endif
/*
* Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_sched_pri.h"
#include "los_process_pri.h"
STATIC VOID IdleDequeue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC VOID IdleEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC UINT32 IdleWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks);
STATIC VOID IdleWake(LosTaskCB *resumedTask);
STATIC UINT32 IdleSchedParamGet(const LosTaskCB *taskCB, SchedParam *param);
STATIC VOID IdleYield(LosTaskCB *runTask);
STATIC VOID IdleStartToRun(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC UINT32 IdleResume(LosTaskCB *taskCB, BOOL *needSched);
STATIC UINT64 IdleTimeSliceGet(const LosTaskCB *taskCB);
STATIC VOID IdleTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime);
STATIC INT32 IdleParamCompare(const SchedPolicy *sp1, const SchedPolicy *sp2);
STATIC VOID IdlePriorityInheritance(LosTaskCB *owner, const SchedParam *param);
STATIC VOID IdlePriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param);
const STATIC SchedOps g_idleOps = {
.dequeue = IdleDequeue,
.enqueue = IdleEnqueue,
.wait = IdleWait,
.wake = IdleWake,
.schedParamModify = NULL,
.schedParamGet = IdleSchedParamGet,
.delay = NULL,
.yield = IdleYield,
.start = IdleStartToRun,
.exit = NULL,
.suspend = NULL,
.resume = IdleResume,
.deadlineGet = IdleTimeSliceGet,
.timeSliceUpdate = IdleTimeSliceUpdate,
.schedParamCompare = IdleParamCompare,
.priorityInheritance = IdlePriorityInheritance,
.priorityRestore = IdlePriorityRestore,
};
STATIC VOID IdleTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime)
{
(VOID)rq;
taskCB->startTime = currTime;
}
STATIC UINT64 IdleTimeSliceGet(const LosTaskCB *taskCB)
{
(VOID)taskCB;
return (OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION);
}
STATIC VOID IdleEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
(VOID)rq;
taskCB->taskStatus &= ~OS_TASK_STATUS_BLOCKED;
taskCB->taskStatus |= OS_TASK_STATUS_READY;
}
STATIC VOID IdleDequeue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
(VOID)rq;
taskCB->taskStatus &= ~OS_TASK_STATUS_READY;
}
STATIC VOID IdleStartToRun(SchedRunqueue *rq, LosTaskCB *taskCB)
{
IdleDequeue(rq, taskCB);
}
STATIC VOID IdleYield(LosTaskCB *runTask)
{
(VOID)runTask;
return;
}
STATIC UINT32 IdleWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks)
{
(VOID)runTask;
(VOID)list;
(VOID)ticks;
return LOS_NOK;
}
STATIC VOID IdleWake(LosTaskCB *resumedTask)
{
LOS_ListDelete(&resumedTask->pendList);
resumedTask->taskStatus &= ~OS_TASK_STATUS_PENDING;
if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
OsSchedTimeoutQueueDelete(resumedTask);
resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
}
if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
#ifdef LOSCFG_SCHED_DEBUG
resumedTask->schedStat.pendTime += OsGetCurrSchedTimeCycle() - resumedTask->startTime;
resumedTask->schedStat.pendCount++;
#endif
resumedTask->ops->enqueue(OsSchedRunqueue(), resumedTask);
}
}
STATIC UINT32 IdleResume(LosTaskCB *taskCB, BOOL *needSched)
{
*needSched = FALSE;
taskCB->taskStatus &= ~OS_TASK_STATUS_SUSPENDED;
if (!OsTaskIsBlocked(taskCB)) {
taskCB->ops->enqueue(OsSchedRunqueue(), taskCB);
*needSched = TRUE;
}
return LOS_OK;
}
STATIC UINT32 IdleSchedParamGet(const LosTaskCB *taskCB, SchedParam *param)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
param->policy = sched->policy;
param->basePrio = sched->basePrio;
param->priority = sched->priority;
param->timeSlice = 0;
return LOS_OK;
}
STATIC INT32 IdleParamCompare(const SchedPolicy *sp1, const SchedPolicy *sp2)
{
return 0;
}
STATIC VOID IdlePriorityInheritance(LosTaskCB *owner, const SchedParam *param)
{
(VOID)owner;
(VOID)param;
return;
}
STATIC VOID IdlePriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param)
{
(VOID)owner;
(VOID)list;
(VOID)param;
return;
}
VOID IdleTaskSchedParamInit(LosTaskCB *taskCB)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
sched->policy = LOS_SCHED_IDLE;
sched->basePrio = OS_PROCESS_PRIORITY_LOWEST;
sched->priority = OS_TASK_PRIORITY_LOWEST;
sched->initTimeSlice = 0;
taskCB->timeSlice = sched->initTimeSlice;
taskCB->taskStatus = OS_TASK_STATUS_SUSPENDED;
taskCB->ops = &g_idleOps;
}
/*
* Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_sched_pri.h"
#include "los_task_pri.h"
#include "los_process_pri.h"
#include "los_hook.h"
#include "los_tick_pri.h"
#include "los_mp.h"
#define OS_SCHED_FIFO_TIMEOUT 0x7FFFFFFF
#define PRIQUEUE_PRIOR0_BIT 0x80000000U
#define OS_SCHED_TIME_SLICES_MIN ((5000 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 5ms */
#define OS_SCHED_TIME_SLICES_MAX ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE)
#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN)
#define OS_SCHED_READY_MAX 30
#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
STATIC HPFRunqueue g_schedHPF;
STATIC VOID HPFDequeue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC VOID HPFEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC UINT32 HPFWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks);
STATIC VOID HPFWake(LosTaskCB *resumedTask);
STATIC BOOL HPFSchedParamModify(LosTaskCB *taskCB, const SchedParam *param);
STATIC UINT32 HPFSchedParamGet(const LosTaskCB *taskCB, SchedParam *param);
STATIC UINT32 HPFDelay(LosTaskCB *runTask, UINT64 waitTime);
STATIC VOID HPFYield(LosTaskCB *runTask);
STATIC VOID HPFStartToRun(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC VOID HPFExit(LosTaskCB *taskCB);
STATIC UINT32 HPFSuspend(LosTaskCB *taskCB);
STATIC UINT32 HPFResume(LosTaskCB *taskCB, BOOL *needSched);
STATIC UINT64 HPFTimeSliceGet(const LosTaskCB *taskCB);
STATIC VOID HPFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime);
STATIC INT32 HPFParamCompare(const SchedPolicy *sp1, const SchedPolicy *sp2);
STATIC VOID HPFPriorityInheritance(LosTaskCB *owner, const SchedParam *param);
STATIC VOID HPFPriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param);
const STATIC SchedOps g_priorityOps = {
.dequeue = HPFDequeue,
.enqueue = HPFEnqueue,
.wait = HPFWait,
.wake = HPFWake,
.schedParamModify = HPFSchedParamModify,
.schedParamGet = HPFSchedParamGet,
.delay = HPFDelay,
.yield = HPFYield,
.start = HPFStartToRun,
.exit = HPFExit,
.suspend = HPFSuspend,
.resume = HPFResume,
.deadlineGet = HPFTimeSliceGet,
.timeSliceUpdate = HPFTimeSliceUpdate,
.schedParamCompare = HPFParamCompare,
.priorityInheritance = HPFPriorityInheritance,
.priorityRestore = HPFPriorityRestore,
};
STATIC VOID HPFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
LOS_ASSERT(currTime >= taskCB->startTime);
INT32 incTime = (currTime - taskCB->startTime - taskCB->irqUsedTime);
LOS_ASSERT(incTime >= 0);
if (sched->policy == LOS_SCHED_RR) {
taskCB->timeSlice -= incTime;
#ifdef LOSCFG_SCHED_DEBUG
taskCB->schedStat.timeSliceRealTime += incTime;
#endif
}
taskCB->irqUsedTime = 0;
taskCB->startTime = currTime;
if (taskCB->timeSlice <= OS_TIME_SLICE_MIN) {
rq->schedFlag |= INT_PEND_RESCH;
}
#ifdef LOSCFG_SCHED_DEBUG
taskCB->schedStat.allRuntime += incTime;
#endif
}
STATIC UINT64 HPFTimeSliceGet(const LosTaskCB *taskCB)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
INT32 timeSlice = taskCB->timeSlice;
timeSlice = (timeSlice <= OS_TIME_SLICE_MIN) ? sched->initTimeSlice : timeSlice;
return (taskCB->startTime + timeSlice);
}
STATIC INLINE UINT32 TimeSliceCalculate(HPFRunqueue *rq, UINT16 basePrio, UINT16 priority)
{
UINT32 time;
UINT32 readyTasks;
HPFQueue *queueList = &rq->queueList[basePrio];
readyTasks = queueList->readyTasks[priority];
if (readyTasks > OS_SCHED_READY_MAX) {
return OS_SCHED_TIME_SLICES_MIN;
}
time = ((OS_SCHED_READY_MAX - readyTasks) * OS_SCHED_TIME_SLICES_DIFF) / OS_SCHED_READY_MAX;
return (time + OS_SCHED_TIME_SLICES_MIN);
}
STATIC INLINE VOID PriQueHeadInsert(HPFRunqueue *rq, UINT32 basePrio, LOS_DL_LIST *priQue, UINT32 priority)
{
HPFQueue *queueList = &rq->queueList[basePrio];
LOS_DL_LIST *priQueList = &queueList->priQueList[0];
UINT32 *bitmap = &queueList->queueBitmap;
/*
* Task control blocks are inited as zero. And when task is deleted,
* and at the same time would be deleted from priority queue or
* other lists, task pend node will restored as zero.
*/
LOS_ASSERT(priQue->pstNext == NULL);
if (*bitmap == 0) {
rq->queueBitmap |= PRIQUEUE_PRIOR0_BIT >> basePrio;
}
if (LOS_ListEmpty(&priQueList[priority])) {
*bitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
}
LOS_ListHeadInsert(&priQueList[priority], priQue);
queueList->readyTasks[priority]++;
}
STATIC INLINE VOID PriQueTailInsert(HPFRunqueue *rq, UINT32 basePrio, LOS_DL_LIST *priQue, UINT32 priority)
{
HPFQueue *queueList = &rq->queueList[basePrio];
LOS_DL_LIST *priQueList = &queueList->priQueList[0];
UINT32 *bitmap = &queueList->queueBitmap;
/*
* Task control blocks are inited as zero. And when task is deleted,
* and at the same time would be deleted from priority queue or
* other lists, task pend node will restored as zero.
*/
LOS_ASSERT(priQue->pstNext == NULL);
if (*bitmap == 0) {
rq->queueBitmap |= PRIQUEUE_PRIOR0_BIT >> basePrio;
}
if (LOS_ListEmpty(&priQueList[priority])) {
*bitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
}
LOS_ListTailInsert(&priQueList[priority], priQue);
queueList->readyTasks[priority]++;
}
STATIC INLINE VOID PriQueDelete(HPFRunqueue *rq, UINT32 basePrio, LOS_DL_LIST *priQue, UINT32 priority)
{
HPFQueue *queueList = &rq->queueList[basePrio];
LOS_DL_LIST *priQueList = &queueList->priQueList[0];
UINT32 *bitmap = &queueList->queueBitmap;
LOS_ListDelete(priQue);
queueList->readyTasks[priority]--;
if (LOS_ListEmpty(&priQueList[priority])) {
*bitmap &= ~(PRIQUEUE_PRIOR0_BIT >> priority);
}
if (*bitmap == 0) {
rq->queueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> basePrio);
}
}
STATIC INLINE VOID PriQueInsert(HPFRunqueue *rq, LosTaskCB *taskCB)
{
LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
switch (sched->policy) {
case LOS_SCHED_RR: {
if (taskCB->timeSlice > OS_TIME_SLICE_MIN) {
PriQueHeadInsert(rq, sched->basePrio, &taskCB->pendList, sched->priority);
} else {
sched->initTimeSlice = TimeSliceCalculate(rq, sched->basePrio, sched->priority);
taskCB->timeSlice = sched->initTimeSlice;
PriQueTailInsert(rq, sched->basePrio, &taskCB->pendList, sched->priority);
#ifdef LOSCFG_SCHED_DEBUG
taskCB->schedStat.timeSliceTime = taskCB->schedStat.timeSliceRealTime;
taskCB->schedStat.timeSliceCount++;
#endif
}
break;
}
case LOS_SCHED_FIFO: {
/* The time slice of FIFO is always greater than 0 unless the yield is called */
if ((taskCB->timeSlice > OS_TIME_SLICE_MIN) && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
PriQueHeadInsert(rq, sched->basePrio, &taskCB->pendList, sched->priority);
} else {
sched->initTimeSlice = OS_SCHED_FIFO_TIMEOUT;
taskCB->timeSlice = sched->initTimeSlice;
PriQueTailInsert(rq, sched->basePrio, &taskCB->pendList, sched->priority);
}
break;
}
default:
LOS_ASSERT(0);
break;
}
taskCB->taskStatus &= ~OS_TASK_STATUS_BLOCKED;
taskCB->taskStatus |= OS_TASK_STATUS_READY;
}
STATIC VOID HPFEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
#ifdef LOSCFG_SCHED_DEBUG
if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
taskCB->startTime = OsGetCurrSchedTimeCycle();
}
#endif
PriQueInsert(rq->hpfRunqueue, taskCB);
}
STATIC VOID HPFDequeue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
PriQueDelete(rq->hpfRunqueue, sched->basePrio, &taskCB->pendList, sched->priority);
taskCB->taskStatus &= ~OS_TASK_STATUS_READY;
}
}
STATIC VOID HPFStartToRun(SchedRunqueue *rq, LosTaskCB *taskCB)
{
HPFDequeue(rq, taskCB);
}
STATIC VOID HPFExit(LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
HPFDequeue(OsSchedRunqueue(), taskCB);
} else if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
LOS_ListDelete(&taskCB->pendList);
taskCB->taskStatus &= ~OS_TASK_STATUS_PENDING;
}
if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) {
OsSchedTimeoutQueueDelete(taskCB);
taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
}
}
STATIC VOID HPFYield(LosTaskCB *runTask)
{
SchedRunqueue *rq = OsSchedRunqueue();
runTask->timeSlice = 0;
runTask->startTime = OsGetCurrSchedTimeCycle();
HPFEnqueue(rq, runTask);
OsSchedResched();
}
STATIC UINT32 HPFDelay(LosTaskCB *runTask, UINT64 waitTime)
{
runTask->taskStatus |= OS_TASK_STATUS_DELAY;
runTask->waitTime = waitTime;
OsSchedResched();
return LOS_OK;
}
STATIC UINT32 HPFWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks)
{
runTask->taskStatus |= OS_TASK_STATUS_PENDING;
LOS_ListTailInsert(list, &runTask->pendList);
if (ticks != LOS_WAIT_FOREVER) {
runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME;
runTask->waitTime = OS_SCHED_TICK_TO_CYCLE(ticks);
}
if (OsPreemptableInSched()) {
OsSchedResched();
if (runTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
return LOS_ERRNO_TSK_TIMEOUT;
}
}
return LOS_OK;
}
STATIC VOID HPFWake(LosTaskCB *resumedTask)
{
LOS_ListDelete(&resumedTask->pendList);
resumedTask->taskStatus &= ~OS_TASK_STATUS_PENDING;
if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
OsSchedTimeoutQueueDelete(resumedTask);
resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
}
if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
#ifdef LOSCFG_SCHED_DEBUG
resumedTask->schedStat.pendTime += OsGetCurrSchedTimeCycle() - resumedTask->startTime;
resumedTask->schedStat.pendCount++;
#endif
HPFEnqueue(OsSchedRunqueue(), resumedTask);
}
}
STATIC BOOL BasePriorityModify(SchedRunqueue *rq, LosTaskCB *taskCB, UINT16 priority)
{
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
BOOL needSched = FALSE;
LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &processCB->threadSiblingList, LosTaskCB, threadList) {
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
taskCB->ops->dequeue(rq, taskCB);
sched->basePrio = priority;
taskCB->ops->enqueue(rq, taskCB);
} else {
sched->basePrio = priority;
}
if (taskCB->taskStatus & (OS_TASK_STATUS_READY | OS_TASK_STATUS_RUNNING)) {
needSched = TRUE;
}
}
return needSched;
}
STATIC BOOL HPFSchedParamModify(LosTaskCB *taskCB, const SchedParam *param)
{
SchedRunqueue *rq = OsSchedRunqueue();
BOOL needSched = FALSE;
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
if (sched->policy != param->policy) {
sched->policy = param->policy;
taskCB->timeSlice = 0;
}
if (sched->basePrio != param->basePrio) {
needSched = BasePriorityModify(rq, taskCB, param->basePrio);
}
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
HPFDequeue(rq, taskCB);
sched->priority = param->priority;
HPFEnqueue(rq, taskCB);
return TRUE;
}
sched->priority = param->priority;
OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, sched->priority);
if (taskCB->taskStatus & OS_TASK_STATUS_INIT) {
HPFEnqueue(rq, taskCB);
return TRUE;
}
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
return TRUE;
}
return needSched;
}
STATIC UINT32 HPFSchedParamGet(const LosTaskCB *taskCB, SchedParam *param)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
param->policy = sched->policy;
param->basePrio = sched->basePrio;
param->priority = sched->priority;
param->timeSlice = sched->initTimeSlice;
return LOS_OK;
}
STATIC UINT32 HPFSuspend(LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
HPFDequeue(OsSchedRunqueue(), taskCB);
}
SchedTaskFreeze(taskCB);
taskCB->taskStatus |= OS_TASK_STATUS_SUSPENDED;
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);
if (taskCB == OsCurrTaskGet()) {
OsSchedResched();
}
return LOS_OK;
}
STATIC UINT32 HPFResume(LosTaskCB *taskCB, BOOL *needSched)
{
*needSched = FALSE;
SchedTaskUnfreeze(taskCB);
taskCB->taskStatus &= ~OS_TASK_STATUS_SUSPENDED;
if (!OsTaskIsBlocked(taskCB)) {
HPFEnqueue(OsSchedRunqueue(), taskCB);
*needSched = TRUE;
}
return LOS_OK;
}
STATIC INT32 HPFParamCompare(const SchedPolicy *sp1, const SchedPolicy *sp2)
{
SchedHPF *param1 = (SchedHPF *)sp1;
SchedHPF *param2 = (SchedHPF *)sp2;
if (param1->basePrio != param2->basePrio) {
return (param1->basePrio - param2->basePrio);
}
return (param1->priority - param2->priority);
}
STATIC VOID HPFPriorityInheritance(LosTaskCB *owner, const SchedParam *param)
{
SchedHPF *sp = (SchedHPF *)&owner->sp;
if ((param->policy != LOS_SCHED_RR) && (param->policy != LOS_SCHED_FIFO)) {
return;
}
if (sp->priority <= param->priority) {
return;
}
LOS_BitmapSet(&sp->priBitmap, sp->priority);
sp->priority = param->priority;
}
STATIC VOID HPFPriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param)
{
UINT16 priority;
LosTaskCB *pendedTask = NULL;
if ((param->policy != LOS_SCHED_RR) && (param->policy != LOS_SCHED_FIFO)) {
return;
}
SchedHPF *sp = (SchedHPF *)&owner->sp;
if (sp->priority < param->priority) {
if (LOS_HighBitGet(sp->priBitmap) != param->priority) {
LOS_BitmapClr(&sp->priBitmap, param->priority);
}
return;
}
if (sp->priBitmap == 0) {
return;
}
if ((list != NULL) && !LOS_ListEmpty((LOS_DL_LIST *)list)) {
priority = LOS_HighBitGet(sp->priBitmap);
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, list, LosTaskCB, pendList) {
SchedHPF *pendSp = (SchedHPF *)&pendedTask->sp;
if ((pendedTask->ops == owner->ops) && (priority != pendSp->priority)) {
LOS_BitmapClr(&sp->priBitmap, pendSp->priority);
}
}
}
priority = LOS_LowBitGet(sp->priBitmap);
if (priority != LOS_INVALID_BIT_INDEX) {
LOS_BitmapClr(&sp->priBitmap, priority);
sp->priority = priority;
}
}
VOID HPFTaskSchedParamInit(LosTaskCB *taskCB, UINT16 policy,
const SchedParam *parentParam,
const TSK_INIT_PARAM_S *param)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
sched->policy = policy;
if (param != NULL) {
sched->priority = param->usTaskPrio;
} else {
sched->priority = parentParam->priority;
}
sched->basePrio = parentParam->basePrio;
sched->initTimeSlice = 0;
taskCB->timeSlice = sched->initTimeSlice;
taskCB->ops = &g_priorityOps;
}
VOID HPFProcessDefaultSchedParamGet(SchedParam *param)
{
param->basePrio = OS_USER_PROCESS_PRIORITY_HIGHEST;
}
VOID HPFSchedPolicyInit(SchedRunqueue *rq)
{
if (ArchCurrCpuid() > 0) {
rq->hpfRunqueue = &g_schedHPF;
return;
}
for (UINT16 index = 0; index < OS_PRIORITY_QUEUE_NUM; index++) {
HPFQueue *queueList = &g_schedHPF.queueList[index];
LOS_DL_LIST *priQue = &queueList->priQueList[0];
for (UINT16 prio = 0; prio < OS_PRIORITY_QUEUE_NUM; prio++) {
LOS_ListInit(&priQue[prio]);
}
}
rq->hpfRunqueue = &g_schedHPF;
}
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_sched_pri.h"
#include "los_hw_pri.h"
#include "los_task_pri.h"
#include "los_swtmr_pri.h"
#include "los_process_pri.h"
#include "los_arch_mmu.h"
#include "los_hook.h"
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
#include "los_hw_tick_pri.h"
#include "los_tick_pri.h"
#ifdef LOSCFG_BASE_CORE_TSK_MONITOR
#include "los_stackinfo_pri.h"
#endif
#include "los_mp.h"
SchedRunqueue g_schedRunqueue[LOSCFG_KERNEL_CORE_NUM];
STATIC INLINE VOID SchedNextExpireTimeSet(UINT32 responseID, UINT64 taskEndTime, UINT32 oldResponseID)
{
SchedRunqueue *rq = OsSchedRunqueue();
BOOL isTimeSlice = FALSE;
UINT64 currTime = OsGetCurrSchedTimeCycle();
UINT64 nextExpireTime = OsGetSortLinkNextExpireTime(&rq->timeoutQueue, currTime, OS_TICK_RESPONSE_PRECISION);
rq->schedFlag &= ~INT_PEND_TICK;
if (rq->responseID == oldResponseID) {
/* This time has expired, and the next time the theory has expired is infinite */
rq->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
}
/* The current thread's time slice has been consumed, but the current system lock task cannot
* trigger the schedule to release the CPU
*/
if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > OS_SCHED_MINI_PERIOD)) {
nextExpireTime = taskEndTime;
isTimeSlice = TRUE;
}
if ((rq->responseTime <= nextExpireTime) ||
((rq->responseTime - nextExpireTime) < OS_TICK_RESPONSE_PRECISION)) {
return;
}
if (isTimeSlice) {
/* The expiration time of the current system is the thread's slice expiration time */
rq->responseID = responseID;
} else {
rq->responseID = OS_INVALID_VALUE;
}
UINT64 nextResponseTime = nextExpireTime - currTime;
rq->responseTime = currTime + HalClockTickTimerReload(nextResponseTime);
}
VOID OsSchedExpireTimeUpdate(VOID)
{
UINT32 intSave;
if (!OS_SCHEDULER_ACTIVE || OS_INT_ACTIVE) {
OsSchedRunqueuePendingSet();
return;
}
LosTaskCB *runTask = OsCurrTaskGet();
SCHEDULER_LOCK(intSave);
UINT64 deadline = runTask->ops->deadlineGet(runTask);
SCHEDULER_UNLOCK(intSave);
SchedNextExpireTimeSet(runTask->taskID, deadline, runTask->taskID);
}
STATIC INLINE VOID SchedTimeoutTaskWake(SchedRunqueue *rq, UINT64 currTime, LosTaskCB *taskCB, BOOL *needSched)
{
#ifndef LOSCFG_SCHED_DEBUG
(VOID)currTime;
#endif
LOS_SpinLock(&g_taskSpin);
UINT16 tempStatus = taskCB->taskStatus;
if (tempStatus & (OS_TASK_STATUS_PENDING | OS_TASK_STATUS_DELAY)) {
taskCB->taskStatus &= ~(OS_TASK_STATUS_PENDING | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY);
if (tempStatus & OS_TASK_STATUS_PENDING) {
taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
LOS_ListDelete(&taskCB->pendList);
taskCB->taskMux = NULL;
OsTaskWakeClearPendMask(taskCB);
}
if (!(tempStatus & OS_TASK_STATUS_SUSPENDED)) {
#ifdef LOSCFG_SCHED_DEBUG
taskCB->schedStat.pendTime += currTime - taskCB->startTime;
taskCB->schedStat.pendCount++;
#endif
taskCB->ops->enqueue(rq, taskCB);
*needSched = TRUE;
}
}
LOS_SpinUnlock(&g_taskSpin);
}
STATIC INLINE BOOL SchedTimeoutQueueScan(SchedRunqueue *rq)
{
BOOL needSched = FALSE;
SortLinkAttribute *timeoutQueue = &rq->timeoutQueue;
LOS_DL_LIST *listObject = &timeoutQueue->sortLink;
/*
* When task is pended with timeout, the task block is on the timeout sortlink
* (per cpu) and ipc(mutex,sem and etc.)'s block at the same time, it can be waken
* up by either timeout or corresponding ipc it's waiting.
*
* Now synchronize sortlink procedure is used, therefore the whole task scan needs
* to be protected, preventing another core from doing sortlink deletion at same time.
*/
LOS_SpinLock(&timeoutQueue->spinLock);
if (LOS_ListEmpty(listObject)) {
LOS_SpinUnlock(&timeoutQueue->spinLock);
return needSched;
}
SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
UINT64 currTime = OsGetCurrSchedTimeCycle();
while (sortList->responseTime <= currTime) {
LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);
OsDeleteNodeSortLink(timeoutQueue, &taskCB->sortList);
LOS_SpinUnlock(&timeoutQueue->spinLock);
SchedTimeoutTaskWake(rq, currTime, taskCB, &needSched);
LOS_SpinLock(&timeoutQueue->spinLock);
if (LOS_ListEmpty(listObject)) {
break;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
}
LOS_SpinUnlock(&timeoutQueue->spinLock);
return needSched;
}
VOID OsSchedTick(VOID)
{
SchedRunqueue *rq = OsSchedRunqueue();
if (rq->responseID == OS_INVALID_VALUE) {
if (SchedTimeoutQueueScan(rq)) {
LOS_MpSchedule(OS_MP_CPU_ALL);
rq->schedFlag |= INT_PEND_RESCH;
}
}
rq->schedFlag |= INT_PEND_TICK;
rq->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
}
VOID OsSchedResponseTimeReset(UINT64 responseTime)
{
OsSchedRunqueue()->responseTime = responseTime;
}
VOID OsSchedRunqueueInit(VOID)
{
if (ArchCurrCpuid() != 0) {
return;
}
for (UINT16 index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
SchedRunqueue *rq = OsSchedRunqueueByID(index);
OsSortLinkInit(&rq->timeoutQueue);
rq->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
}
}
VOID OsSchedRunqueueIdleInit(UINT32 idleTaskID)
{
SchedRunqueue *rq = OsSchedRunqueue();
rq->idleTaskID = idleTaskID;
}
UINT32 OsSchedInit(VOID)
{
for (UINT16 cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) {
HPFSchedPolicyInit(OsSchedRunqueueByID(cpuId));
}
#ifdef LOSCFG_SCHED_TICK_DEBUG
UINT32 ret = OsSchedDebugInit();
if (ret != LOS_OK) {
return ret;
}
#endif
return LOS_OK;
}
/*
* If the return value greater than 0, task1 has a lower priority than task2.
* If the return value less than 0, task1 has a higher priority than task2.
* If the return value is 0, task1 and task2 have the same priority.
*/
INT32 OsSchedParamCompare(const LosTaskCB *task1, const LosTaskCB *task2)
{
SchedHPF *rp1 = (SchedHPF *)&task1->sp;
SchedHPF *rp2 = (SchedHPF *)&task2->sp;
if (rp1->policy == rp2->policy) {
return task1->ops->schedParamCompare(&task1->sp, &task2->sp);
}
if (rp1->policy == LOS_SCHED_IDLE) {
return 1;
} else if (rp2->policy == LOS_SCHED_IDLE) {
return -1;
}
return 0;
}
UINT32 OsSchedParamInit(LosTaskCB *taskCB, UINT16 policy, const SchedParam *parentParam, const TSK_INIT_PARAM_S *param)
{
switch (policy) {
case LOS_SCHED_FIFO:
case LOS_SCHED_RR:
HPFTaskSchedParamInit(taskCB, policy, parentParam, param);
break;
case LOS_SCHED_IDLE:
IdleTaskSchedParamInit(taskCB);
break;
default:
return LOS_NOK;
}
return LOS_OK;
}
VOID OsSchedProcessDefaultSchedParamGet(UINT16 policy, SchedParam *param)
{
switch (policy) {
case LOS_SCHED_FIFO:
case LOS_SCHED_RR:
HPFProcessDefaultSchedParamGet(param);
break;
case LOS_SCHED_IDLE:
default:
PRINT_ERR("Invalid process-level scheduling policy, %u\n", policy);
break;
}
return;
}
STATIC LosTaskCB *TopTaskGet(SchedRunqueue *rq)
{
LosTaskCB *newTask = HPFRunqueueTopTaskGet(rq->hpfRunqueue);
if (newTask == NULL) {
newTask = OS_TCB_FROM_TID(rq->idleTaskID);
}
newTask->ops->start(rq, newTask);
return newTask;
}
VOID OsSchedStart(VOID)
{
UINT32 cpuid = ArchCurrCpuid();
UINT32 intSave;
PRINTK("cpu %d entering scheduler\n", cpuid);
SCHEDULER_LOCK(intSave);
OsTickStart();
SchedRunqueue *rq = OsSchedRunqueue();
LosTaskCB *newTask = TopTaskGet(rq);
newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
#ifdef LOSCFG_KERNEL_SMP
/*
* attention: current cpu needs to be set, in case first task deletion
* may fail because this flag mismatch with the real current cpu.
*/
newTask->currCpu = cpuid;
#endif
OsCurrTaskSet((VOID *)newTask);
newTask->startTime = OsGetCurrSchedTimeCycle();
OsSwtmrResponseTimeReset(newTask->startTime);
/* System start schedule */
OS_SCHEDULER_SET(cpuid);
rq->responseID = OS_INVALID;
UINT64 deadline = newTask->ops->deadlineGet(newTask);
SchedNextExpireTimeSet(newTask->taskID, deadline, OS_INVALID);
OsTaskContextLoad(newTask);
}
#ifdef LOSCFG_KERNEL_SMP
VOID OsSchedToUserReleaseLock(VOID)
{
/* The scheduling lock needs to be released before returning to user mode */
LOCKDEP_CHECK_OUT(&g_taskSpin);
ArchSpinUnlock(&g_taskSpin.rawLock);
OsSchedUnlock();
}
#endif
#ifdef LOSCFG_BASE_CORE_TSK_MONITOR
STATIC VOID TaskStackCheck(LosTaskCB *runTask, LosTaskCB *newTask)
{
if (!OS_STACK_MAGIC_CHECK(runTask->topOfStack)) {
LOS_Panic("CURRENT task ID: %s:%d stack overflow!\n", runTask->taskName, runTask->taskID);
}
if (((UINTPTR)(newTask->stackPointer) <= newTask->topOfStack) ||
((UINTPTR)(newTask->stackPointer) > (newTask->topOfStack + newTask->stackSize))) {
LOS_Panic("HIGHEST task ID: %s:%u SP error! StackPointer: %p TopOfStack: %p\n",
newTask->taskName, newTask->taskID, newTask->stackPointer, newTask->topOfStack);
}
}
#endif
STATIC INLINE VOID SchedSwitchCheck(LosTaskCB *runTask, LosTaskCB *newTask)
{
#ifdef LOSCFG_BASE_CORE_TSK_MONITOR
TaskStackCheck(runTask, newTask);
#endif /* LOSCFG_BASE_CORE_TSK_MONITOR */
OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN, newTask, runTask);
}
STATIC VOID SchedTaskSwitch(SchedRunqueue *rq, LosTaskCB *runTask, LosTaskCB *newTask)
{
SchedSwitchCheck(runTask, newTask);
runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;
newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
#ifdef LOSCFG_KERNEL_SMP
/* mask new running task's owner processor */
runTask->currCpu = OS_TASK_INVALID_CPUID;
newTask->currCpu = ArchCurrCpuid();
#endif
OsCurrTaskSet((VOID *)newTask);
#ifdef LOSCFG_KERNEL_VM
if (newTask->archMmu != runTask->archMmu) {
LOS_ArchMmuContextSwitch((LosArchMmu *)newTask->archMmu);
}
#endif
#ifdef LOSCFG_KERNEL_CPUP
OsCpupCycleEndStart(runTask->taskID, newTask->taskID);
#endif
#ifdef LOSCFG_SCHED_DEBUG
UINT64 waitStartTime = newTask->startTime;
#endif
if (runTask->taskStatus & OS_TASK_STATUS_READY) {
/* When a thread enters the ready queue, its slice of time is updated */
newTask->startTime = runTask->startTime;
} else {
/* The currently running task is blocked */
newTask->startTime = OsGetCurrSchedTimeCycle();
/* The task is in a blocking state and needs to update its time slice before pend */
runTask->ops->timeSliceUpdate(rq, runTask, newTask->startTime);
if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) {
OsSchedTimeoutQueueAdd(runTask, runTask->startTime + runTask->waitTime);
}
}
UINT64 deadline = newTask->ops->deadlineGet(newTask);
SchedNextExpireTimeSet(newTask->taskID, deadline, runTask->taskID);
#ifdef LOSCFG_SCHED_DEBUG
newTask->schedStat.waitSchedTime += newTask->startTime - waitStartTime;
newTask->schedStat.waitSchedCount++;
runTask->schedStat.runTime = runTask->schedStat.allRuntime;
runTask->schedStat.switchCount++;
#endif
/* do the task context switch */
OsTaskSchedule(newTask, runTask);
}
VOID OsSchedIrqEndCheckNeedSched(VOID)
{
SchedRunqueue *rq = OsSchedRunqueue();
LosTaskCB *runTask = OsCurrTaskGet();
runTask->ops->timeSliceUpdate(rq, runTask, OsGetCurrSchedTimeCycle());
if (OsPreemptable() && (rq->schedFlag & INT_PEND_RESCH)) {
rq->schedFlag &= ~INT_PEND_RESCH;
LOS_SpinLock(&g_taskSpin);
runTask->ops->enqueue(rq, runTask);
LosTaskCB *newTask = TopTaskGet(rq);
if (runTask != newTask) {
SchedTaskSwitch(rq, runTask, newTask);
LOS_SpinUnlock(&g_taskSpin);
return;
}
LOS_SpinUnlock(&g_taskSpin);
}
if (rq->schedFlag & INT_PEND_TICK) {
OsSchedExpireTimeUpdate();
}
}
VOID OsSchedResched(VOID)
{
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
SchedRunqueue *rq = OsSchedRunqueue();
#ifdef LOSCFG_KERNEL_SMP
LOS_ASSERT(rq->taskLockCnt == 1);
#else
LOS_ASSERT(rq->taskLockCnt == 0);
#endif
rq->schedFlag &= ~INT_PEND_RESCH;
LosTaskCB *runTask = OsCurrTaskGet();
LosTaskCB *newTask = TopTaskGet(rq);
if (runTask == newTask) {
return;
}
SchedTaskSwitch(rq, runTask, newTask);
}
VOID LOS_Schedule(VOID)
{
UINT32 intSave;
LosTaskCB *runTask = OsCurrTaskGet();
SchedRunqueue *rq = OsSchedRunqueue();
if (OS_INT_ACTIVE) {
OsSchedRunqueuePendingSet();
return;
}
if (!OsPreemptable()) {
return;
}
/*
* trigger schedule in task will also do the slice check
* if necessary, it will give up the timeslice more in time.
* otherwise, there's no other side effects.
*/
SCHEDULER_LOCK(intSave);
runTask->ops->timeSliceUpdate(rq, runTask, OsGetCurrSchedTimeCycle());
/* add run task back to ready queue */
runTask->ops->enqueue(rq, runTask);
/* reschedule to new thread */
OsSchedResched();
SCHEDULER_UNLOCK(intSave);
}
STATIC INLINE LOS_DL_LIST *SchedLockPendFindPosSub(const LosTaskCB *runTask, const LOS_DL_LIST *lockList)
{
LosTaskCB *pendedTask = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, lockList, LosTaskCB, pendList) {
INT32 ret = OsSchedParamCompare(pendedTask, runTask);
if (ret < 0) {
continue;
} else if (ret > 0) {
return &pendedTask->pendList;
} else {
return pendedTask->pendList.pstNext;
}
}
return NULL;
}
LOS_DL_LIST *OsSchedLockPendFindPos(const LosTaskCB *runTask, LOS_DL_LIST *lockList)
{
if (LOS_ListEmpty(lockList)) {
return lockList;
}
LosTaskCB *pendedTask1 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(lockList));
INT32 ret = OsSchedParamCompare(pendedTask1, runTask);
if (ret > 0) {
return lockList->pstNext;
}
LosTaskCB *pendedTask2 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_LAST(lockList));
ret = OsSchedParamCompare(pendedTask2, runTask);
if (ret <= 0) {
return lockList;
}
return SchedLockPendFindPosSub(runTask, lockList);
}
......@@ -30,7 +30,6 @@
*/
#include "los_sortlink_pri.h"
#include "los_mp.h"
/// 排序链表初始化
VOID OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
{
......
/*
* Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_statistics_pri.h"
#include "los_task_pri.h"
#include "los_process_pri.h"
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_TICK_DEBUG
typedef struct {
UINT64 responseTime;
UINT64 responseTimeMax;
UINT64 count;
} SchedTickDebug;
STATIC SchedTickDebug *g_schedTickDebug = NULL;
UINT32 OsSchedDebugInit(VOID)
{
UINT32 size = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM;
g_schedTickDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem0, size);
if (g_schedTickDebug == NULL) {
return LOS_ERRNO_TSK_NO_MEMORY;
}
(VOID)memset_s(g_schedTickDebug, size, 0, size);
return LOS_OK;
}
VOID OsSchedDebugRecordData(VOID)
{
SchedRunqueue *rq = OsSchedRunqueue();
SchedTickDebug *schedDebug = &g_schedTickDebug[ArchCurrCpuid()];
UINT64 currTime = OsGetCurrSchedTimeCycle();
LOS_ASSERT(currTime >= rq->responseTime);
UINT64 usedTime = currTime - rq->responseTime;
schedDebug->responseTime += usedTime;
if (usedTime > schedDebug->responseTimeMax) {
schedDebug->responseTimeMax = usedTime;
}
schedDebug->count++;
}
UINT32 OsShellShowTickResponse(VOID)
{
UINT32 intSave;
UINT16 cpu;
UINT32 tickSize = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM;
SchedTickDebug *schedDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem1, tickSize);
if (schedDebug == NULL) {
return LOS_NOK;
}
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s((CHAR *)schedDebug, tickSize, (CHAR *)g_schedTickDebug, tickSize);
SCHEDULER_UNLOCK(intSave);
PRINTK("cpu ATRTime(us) ATRTimeMax(us) TickCount\n");
for (cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
SchedTickDebug *schedData = &schedDebug[cpu];
UINT64 averTime = 0;
if (schedData->count > 0) {
averTime = schedData->responseTime / schedData->count;
averTime = (averTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
}
UINT64 timeMax = (schedData->responseTimeMax * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
PRINTK("%3u%14llu%15llu%11llu\n", cpu, averTime, timeMax, schedData->count);
}
(VOID)LOS_MemFree(m_aucSysMem1, schedDebug);
return LOS_OK;
}
#endif
STATIC VOID SchedDataGet(const LosTaskCB *taskCB, UINT64 *runTime, UINT64 *timeSlice,
UINT64 *pendTime, UINT64 *schedWait)
{
if (taskCB->schedStat.switchCount >= 1) {
UINT64 averRunTime = taskCB->schedStat.runTime / taskCB->schedStat.switchCount;
*runTime = (averRunTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
}
if (taskCB->schedStat.timeSliceCount > 1) {
UINT64 averTimeSlice = taskCB->schedStat.timeSliceTime / (taskCB->schedStat.timeSliceCount - 1);
*timeSlice = (averTimeSlice * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
}
if (taskCB->schedStat.pendCount > 1) {
UINT64 averPendTime = taskCB->schedStat.pendTime / taskCB->schedStat.pendCount;
*pendTime = (averPendTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
}
if (taskCB->schedStat.waitSchedCount > 0) {
UINT64 averSchedWait = taskCB->schedStat.waitSchedTime / taskCB->schedStat.waitSchedCount;
*schedWait = (averSchedWait * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
}
}
UINT32 OsShellShowSchedStatistics(VOID)
{
UINT32 taskLinkNum[LOSCFG_KERNEL_CORE_NUM];
UINT32 intSave;
LosTaskCB task;
SCHEDULER_LOCK(intSave);
for (UINT16 cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
SchedRunqueue *rq = OsSchedRunqueueByID(cpu);
taskLinkNum[cpu] = OsGetSortLinkNodeNum(&rq->timeoutQueue);
}
SCHEDULER_UNLOCK(intSave);
for (UINT16 cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
PRINTK("cpu: %u Task SortMax: %u\n", cpu, taskLinkNum[cpu]);
}
PRINTK(" Tid AverRunTime(us) SwitchCount AverTimeSlice(us) TimeSliceCount AverReadyWait(us) "
"AverPendTime(us) TaskName \n");
for (UINT32 tid = 0; tid < g_taskMaxNum; tid++) {
LosTaskCB *taskCB = g_taskCBArray + tid;
SCHEDULER_LOCK(intSave);
if (OsTaskIsUnused(taskCB) || (taskCB->processID == OsGetIdleProcessID())) {
SCHEDULER_UNLOCK(intSave);
continue;
}
(VOID)memcpy_s(&task, sizeof(LosTaskCB), taskCB, sizeof(LosTaskCB));
SCHEDULER_UNLOCK(intSave);
UINT64 averRunTime = 0;
UINT64 averTimeSlice = 0;
UINT64 averPendTime = 0;
UINT64 averSchedWait = 0;
SchedDataGet(&task, &averRunTime, &averTimeSlice, &averPendTime, &averSchedWait);
PRINTK("%5u%19llu%15llu%19llu%18llu%19llu%18llu %-32s\n", taskCB->taskID,
averRunTime, taskCB->schedStat.switchCount,
averTimeSlice, taskCB->schedStat.timeSliceCount - 1,
averSchedWait, averPendTime, taskCB->taskName);
}
return LOS_OK;
}
#endif
此差异已折叠。
......@@ -70,7 +70,7 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 EarliestInit(VOID)
/* Must be placed at the beginning of the boot process *///必须放在启动过程的开头
OsSetMainTask();//为每个CPU核设置临时主任务
OsCurrTaskSet(OsGetMainTask());//设置当前任务
OsSchedRunQueInit();
OsSchedRunqueueInit();
g_sysClock = OS_SYS_CLOCK;
g_tickPerSecond = LOSCFG_BASE_CORE_TICK_PER_SECOND;
......
......@@ -272,6 +272,15 @@ extern UINT32 __heap_end; ///< 堆区结束地址
#define LOSCFG_BASE_IPC_MUX
#endif
/****************************** rwlock module configuration ******************************/
/**
* @ingroup los_config
* Configuration item for rwlock module tailoring
*/
#ifndef LOSCFG_BASE_IPC_RWLOCK
#define LOSCFG_BASE_IPC_RWLOCK
#endif
/****************************** Queue module configuration ********************************/
/**
* @ingroup los_config
......
......@@ -32,6 +32,7 @@
#include "los_magickey.h"
#include "console.h"
#include "los_task_pri.h"
#include "los_process_pri.h"
/// 魔法键依赖于宏LOSCFG_ENABLE_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”:
/// Debug ---> Enable MAGIC KEY;若关闭该选项,则魔法键失效。
......@@ -99,9 +100,7 @@ STATIC VOID OsMagicHelp(VOID)//遍历一下 g_magicOpTable
///执行 shell task -a 命令
STATIC VOID OsMagicTaskShow(VOID)
{
const CHAR *arg = "-a";
(VOID)OsShellCmdDumpTask(1, &arg);
(VOID)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL);
return;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
git add -A
git commit -m ' cp15 协处理代码注解
git commit -m ' 同步官方代码,任务调度模块改动很大
百图画鸿蒙 + 百文说内核 + 百万注源码 => 挖透鸿蒙内核源码
鸿蒙研究站 | http://weharmonyos.com (国内)
| https://weharmony.github.io (国外)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册