1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: Task schedule implementation
14 */
15 #include "prt_task_internal.h"
16
17 #if defined(OS_OPTION_TASK_YIELD)
OsTaskYieldProc(TskHandle nextTaskId,U32 taskPrio,TskHandle * yieldTo,struct TagTskCb * currTask,struct TagListObject * tskPriorRdyList)18 OS_SEC_ALW_INLINE INLINE U32 OsTaskYieldProc(TskHandle nextTaskId, U32 taskPrio, TskHandle *yieldTo,
19 struct TagTskCb *currTask,
20 struct TagListObject *tskPriorRdyList)
21 {
22 struct TagTskCb *nextTask = NULL;
23 /* there is no task that user particularly wishes */
24 /* therefore second task will become ready */
25 if (nextTaskId == OS_TSK_NULL_ID) {
26 if (yieldTo != NULL) {
27 *yieldTo = (GET_TCB_PEND(OS_LIST_FIRST(&currTask->pendList)))->taskPid;
28 }
29 OsTskReadyDel(currTask); // 从当前就绪队列删除
30 OsTskReadyAdd(currTask); // 添加到就绪队列末尾
31 } else {
32 if (yieldTo != NULL) {
33 *yieldTo = nextTaskId;
34 }
35
36 nextTask = GET_TCB_HANDLE(nextTaskId);
37 if ((nextTask->priority == taskPrio) && TSK_STATUS_TST(nextTask, OS_TSK_READY)) {
38 ListDelete(&nextTask->pendList);
39 ListAdd(&nextTask->pendList, tskPriorRdyList);
40 } else { /* task is illegal */
41 return OS_ERRNO_TSK_YIELD_INVALID_TASK;
42 }
43 }
44
45 return OS_OK;
46 }
47
48 /*
49 * 描述:调整指定优先级的任务调度顺序。调用者负责关中断
50 */
OsTaskYield(TskPrior taskPrio,TskHandle nextTaskId,TskHandle * yieldTo)51 static OS_SEC_L2_TEXT U32 OsTaskYield(TskPrior taskPrio, TskHandle nextTaskId, TskHandle *yieldTo)
52 {
53 U32 ret;
54 U32 tskCount = 0;
55 struct TagTskCb *currTask = NULL;
56 struct TagListObject *tskPriorRdyList = NULL;
57 struct TagListObject *currNode = NULL;
58
59 tskPriorRdyList = &g_runQueue.readyList[taskPrio];
60 /* In case there are more then one ready tasks at */
61 /* this priority, remove first task and add it */
62 /* to the end of the queue */
63 currTask = GET_TCB_PEND(OS_LIST_FIRST(tskPriorRdyList));
64
65 for (currNode = tskPriorRdyList->next; currNode != tskPriorRdyList; currNode = currNode->next) {
66 tskCount++;
67 }
68
69 if (tskCount > 1) {
70 ret = OsTaskYieldProc(nextTaskId, taskPrio, yieldTo, currTask, tskPriorRdyList);
71 if (ret != OS_OK) {
72 return ret;
73 }
74
75 // 如果是当前的running任务
76 if (TSK_STATUS_TST(currTask, OS_TSK_RUNNING)) {
77 OsTskScheduleFast();
78
79 return OS_OK;
80 }
81 } else { /* There is only one task or none */
82 OS_REPORT_ERROR(OS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK);
83 return OS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK;
84 }
85
86 return OS_OK;
87 }
88 #endif
89
90 /*
91 * 描述:延迟当前运行任务的执行
92 */
PRT_TaskDelay(U32 tick)93 OS_SEC_L0_TEXT U32 PRT_TaskDelay(U32 tick)
94 {
95 U32 ret;
96 uintptr_t intSave;
97 struct TagTskCb *runTask = NULL;
98
99 intSave = OsIntLock();
100 if (UNI_FLAG == 0) {
101 OsIntRestore(intSave);
102 // 初始化过程中不允许切换
103 return OS_ERRNO_TSK_DELAY_IN_INT;
104 }
105
106 if (OS_INT_ACTIVE) {
107 OS_REPORT_ERROR(OS_ERRNO_TSK_DELAY_IN_INT);
108 OsIntRestore(intSave);
109 return OS_ERRNO_TSK_DELAY_IN_INT;
110 }
111
112 if (OS_TASK_LOCK_DATA != 0) {
113 OsIntRestore(intSave);
114 return OS_ERRNO_TSK_DELAY_IN_LOCK;
115 }
116 runTask = RUNNING_TASK;
117 if (tick > 0) {
118 OsTskReadyDel(runTask);
119 TSK_STATUS_SET(runTask, OS_TSK_DELAY);
120 OsTskTimerAdd(runTask, tick);
121 OsTskScheduleFastPs(intSave);
122 OsIntRestore(intSave);
123
124 return OS_OK;
125 }
126
127 #if defined(OS_OPTION_TASK_YIELD)
128 ret = OsTaskYield(runTask->priority, OS_TSK_NULL_ID, NULL);
129 #else
130 ret = OS_OK;
131 #endif
132 OsIntRestore(intSave);
133
134 return ret;
135 }
136
137 /*
138 * 描述:锁任务调度
139 */
PRT_TaskLock(void)140 OS_SEC_L0_TEXT void PRT_TaskLock(void)
141 {
142 uintptr_t intSave;
143
144 intSave = OsIntLock();
145
146 if (g_uniTaskLock == 0) {
147 UNI_FLAG &= (~OS_FLG_TSK_REQ);
148 }
149
150 OS_TSK_LOCK();
151 OsIntRestore(intSave);
152 }
153
154 /*
155 * 描述:解锁锁任务调度
156 */
PRT_TaskUnlock(void)157 OS_SEC_L0_TEXT void PRT_TaskUnlock(void)
158 {
159 uintptr_t intSave = OsIntLock();
160
161 if (g_uniTaskLock == 1) {
162 // 参照osTskUnlock注释,热点函数特殊实现
163 g_uniTaskLock = 0;
164 if ((OS_FLG_BGD_ACTIVE & UNI_FLAG) != 0) {
165 OsTskScheduleFastPs(intSave);
166 OsIntRestore(intSave);
167 }
168 return;
169 }
170 // 冷分支
171 if (g_uniTaskLock > 1) {
172 g_uniTaskLock--;
173 OsIntRestore(intSave);
174 return;
175 }
176 // unlock时 已为0,说明lock unlock不配对,记录错误
177 OS_REPORT_ERROR(OS_ERRNO_TSK_UNLOCK_NO_LOCK);
178 OsIntRestore(intSave);
179 }
180