• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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