The Master said, “If you speak eloquence, you flatter yourself, and respect your feet, you will see shame on your left qiu, and shame on your own Qiu. If you are a friend with a grudge, you should be ashamed of yourself and ashamed of yourself.” “The Analects of Confucius” : Gong Ye chang
A hundred blog series. This is: the v03. Xx HongMeng kernel source code analysis task (clock), whose biggest contribution | trigger scheduling
Task management related articles are:
- V03. Xx HongMeng kernel source code analysis (the clock) whose biggest contribution | trigger scheduling
- V04. Xx HongMeng kernel source code analysis (scheduling) | is the kernel task scheduling unit
- V05. Xx HongMeng kernel source code analysis (task management) | pool of task is how to manage
- V06. Xx HongMeng kernel source code analysis (scheduling queue) | how many scheduling are the kernel queue
- V07. Xx HongMeng kernel source code analysis (scheduling) scheduler | task is how to
- V21. Xx HongMeng kernel source code analysis concept (thread) | who is constantly with the CPU
- V25. Xx HongMeng kernel source code analysis (concurrent parallel) | heard countless times two concepts
- V37. Xx HongMeng kernel source code analysis (system calls) | forever mantra
- V41. Xx HongMeng kernel source code analysis (task switching) switch | see how assembly task
The clock concept
-
Time is a very important concept, and one thing that is very important throughout our student life is the school bell. It controls the rhythm of class, dismissal, eating, and sleeping. Without it, the management of the school would be chaotic. The teacher would drag the class for as long as he wanted to. That can’t do, the bell rang after class is to tell the teacher that it is time to stop and let the students HAPPY.
-
The operating system also needs time to perform tasks. The smallest unit of time in an operating system is the OS Tick. Any operating system needs to provide a clock beat so that the system can handle all time-related events, such as thread delay, thread time slice rotation scheduling, and timer timeout. Ticks are specific periodic interruptions, heartbeat, the interrupt is seen as a system interrupt the time interval between depends on the different application, the general is 1 ms – 100 ms, the faster the rate of ticks, the faster the real-time response of the system, but the greater the overhead of system, start from the system began to count the number of ticks is called the system time.
-
In the Hung Moon kernel, the length of the clock beat can be adjusted according to the definition of LOSCFG_BASE_CORE_TICK_PER_SECOND, which is equal to 1/LOSCFG_BASE_CORE_TICK_PER_SECOND.
The implementation of clock beats
The clock beat is generated by a hardware timer configured for interrupt-triggered mode. When an interrupt occurs, the following void OsTickHandler(void) is called to notify the operating system that a system clock has passed. Different hardware timer interrupt implementation is different,
/** * @ingroup los_config * Number of Ticks in one second */
#ifndef LOSCFG_BASE_CORE_TICK_PER_SECOND
#define LOSCFG_BASE_CORE_TICK_PER_SECOND 100 // The default is 100 times per second, but this can be changed
#endif
Copy the code
100 ticks per second, the time unit is 10 milliseconds, that is, call the clock interrupt handler 100 times per second.
/* * Description : Tick interruption handler */// Beat interrupt processing function, hongming default 10ms trigger once
LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
{
/ /...
OsTimesliceCheck(a);// Time slice checks for processes and tasks
OsTaskScan(a);/* task timeout scan */// Task scan
#if (LOSCFG_BASE_CORE_SWTMR == YES)
OsSwtmrScan(a);// Scan the timer to see if there is a timeout timer
#endif
}
Copy the code
It does three main things
First: check the time slice of the current task. How much time is allocated for each task execution? The answer is 2 time slices, i.e. 20ms.
#ifndef LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT
#define LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT 2 //2 time slices,20ms
#endif
// Check the time slice of the process and task, if there is no time slice directly schedule
LITE_OS_SEC_TEXT VOID OsTimesliceCheck(VOID)
{
LosTaskCB *runTask = NULL;
LosProcessCB *runProcess = OsCurrProcessGet(a);// Get the current process
if(runProcess->policy ! = LOS_SCHED_RR) {// Whether the process scheduling algorithm is preemptive
goto SCHED_TASK;// The process is not preemptively scheduled to check the time slice of the task directly
}
if(runProcess->timeSlice ! =0) {// Does the process still have time slices?
runProcess->timeSlice--;// The process time slice is reduced once
if (runProcess->timeSlice == 0) {// There are no more time slots
LOS_Schedule(a);// The process runs out of time
}
}
SCHED_TASK:
runTask = OsCurrTaskGet(a);// Get the current task
if(runTask->policy ! = LOS_SCHED_RR) {// Whether the task scheduling algorithm is preemptive
return;// Tasks are not preemptively scheduled to end the check directly
}
if(runTask->timeSlice ! =0) {// Will there be a time slot for the mission?
runTask->timeSlice--;// The task time slice is also reduced once
if (runTask->timeSlice == 0) {// There are no more time slots
LOS_Schedule(a);// The task time slice is used up}}}Copy the code
Second: scanning tasks, mainly to check whether blocked tasks can be rescheduled
LITE_OS_SEC_TEXT VOID OsTaskScan(VOID)
{
SortLinkList *sortList = NULL;
LosTaskCB *taskCB = NULL;
BOOL needSchedule = FALSE;
UINT16 tempStatus;
LOS_DL_LIST *listObject = NULL;
SortLinkAttribute *taskSortLink = NULL;
taskSortLink = &OsPercpuGet()->taskSortLink;// Get the sorted list of tasks
taskSortLink->cursor = (taskSortLink->cursor + 1) & OS_TSK_SORTLINK_MASK;
listObject = taskSortLink->sortLink + taskSortLink->cursor;// Process only the linked list on this cursor, because the system already lists timeout tasks.
// When a task is suspended due to timeout, the task block is on the timeout sort link, and the blocks (per CPU) and IPC (mutex, SEM, etc.) are woken up at the same time
/* It is waiting for either a timeout or the corresponding IPC. Now use Synchronize SortLink PRECEDure, so the entire task scan needs protection to prevent another core from deleting sortLink at the same time. * 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 preocedure is used, therefore the whole task scan needs * to be protected, preventing another core from doing sortlink deletion at same time. */
LOS_SpinLock(&g_taskSpin);
if (LOS_ListEmpty(listObject)) {
LOS_SpinUnlock(&g_taskSpin);
return;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);// Tick the first node of SortLinkList sortLinkNode
ROLLNUM_DEC(sortList->idxRollNum);// Roll count --
while (ROLLNUM(sortList->idxRollNum) == 0) {// Find the time is up node, note that these nodes are generated by the timer,
LOS_ListDelete(&sortList->sortLinkNode);
taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);// Take the tasks, where the tasks are timeout tasks
taskCB->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
tempStatus = taskCB->taskStatus;
if (tempStatus & OS_TASK_STATUS_PEND) {
taskCB->taskStatus &= ~OS_TASK_STATUS_PEND;
#if (LOSCFG_KERNEL_LITEIPC == YES)
taskCB->ipcStatus &= ~IPC_THREAD_STATUS_PEND;
#endif
taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
LOS_ListDelete(&taskCB->pendList);
taskCB->taskSem = NULL;
taskCB->taskMux = NULL;
} else {
taskCB->taskStatus &= ~OS_TASK_STATUS_DELAY;
}
if(! (tempStatus & OS_TASK_STATUS_SUSPEND)) {OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, OS_PROCESS_STATUS_PEND);
needSchedule = TRUE;
}
if (LOS_ListEmpty(listObject)) {
break;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
}
LOS_SpinUnlock(&g_taskSpin);
if(needSchedule ! = FALSE) {// Need scheduling
LOS_MpSchedule(OS_MP_CPU_ALL);// Intercore communication, send scheduling signal to all cpus
LOS_Schedule(a);// Start scheduling}}Copy the code
Third: timer scan to see if there is a timeout timer
/* * Description: Tick interrupt interface module of software timer * Return : LOS_OK on success or error code on failure */OsSwtmrScan is called by the system clock interrupt handler
LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID)// Scan timer, if encounter timeout, put into the timeout queue
{
SortLinkList *sortList = NULL;
SWTMR_CTRL_S *swtmr = NULL;
SwtmrHandlerItemPtr swtmrHandler = NULL;
LOS_DL_LIST *listObject = NULL;
SortLinkAttribute* swtmrSortLink = &OsPercpuGet()->swtmrSortLink;// Get the current CPU timer list
swtmrSortLink->cursor = (swtmrSortLink->cursor + 1) & OS_TSK_SORTLINK_MASK;
listObject = swtmrSortLink->sortLink + swtmrSortLink->cursor;
// Since SWTMR is in a specific sortlink, it needs to be handled very carefully, but other CPU cores still have a chance to handle it, such as stopping timers
/* * it needs to be carefully coped with, since the swtmr is in specific sortlink * while other cores still has the chance to process it, like stop the timer. */
LOS_SpinLock(&g_swtmrSpin);
if (LOS_ListEmpty(listObject)) {
LOS_SpinUnlock(&g_swtmrSpin);
return;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
ROLLNUM_DEC(sortList->idxRollNum);
while (ROLLNUM(sortList->idxRollNum) == 0) {
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
LOS_ListDelete(&sortList->sortLinkNode);
swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
swtmrHandler = (SwtmrHandlerItemPtr)LOS_MemboxAlloc(g_swtmrHandlerPool);// Retrieves an available soft clock handler
if(swtmrHandler ! =NULL) {
swtmrHandler->handler = swtmr->pfnHandler;
swtmrHandler->arg = swtmr->uwArg;
if (LOS_QueueWrite(OsPercpuGet()->swtmrHandlerQueue, swtmrHandler, sizeof(CHAR *), LOS_NO_WAIT)) {
(VOID)LOS_MemboxFree(g_swtmrHandlerPool, swtmrHandler); }}if (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) {
OsSwtmrDelete(swtmr);
if (swtmr->usTimerID < (OS_SWTMR_MAX_TIMERID - LOSCFG_BASE_CORE_SWTMR_LIMIT)) {
swtmr->usTimerID += LOSCFG_BASE_CORE_SWTMR_LIMIT;
} else{ swtmr->usTimerID %= LOSCFG_BASE_CORE_SWTMR_LIMIT; }}else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) {
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
} else {
swtmr->ucOverrun++;
OsSwtmrStart(swtmr);
}
if (LOS_ListEmpty(listObject)) {
break;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
}
LOS_SpinUnlock(&g_swtmrSpin);
}
Copy the code
Finally, the implementation of the scheduling algorithm
// Implementation of the scheduling algorithm
VOID OsSchedResched(VOID)
{
LosTaskCB *runTask = NULL;
LosTaskCB *newTask = NULL;
LosProcessCB *runProcess = NULL;
LosProcessCB *newProcess = NULL;
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));// The task spinlock must be held. The spinlock is not a process-level fight for the lock, but a fight between CPU cores
if (!OsPreemptableInSched()) {// Whether the rescheduling flag bit is set
return;
}
runTask = OsCurrTaskGet(a);// Get the current task
newTask = OsGetTopTask(a);// Get the highest priority task
/* always be able to get one task */
LOS_ASSERT(newTask ! =NULL);// Can't have no tasks to schedule
if (runTask == newTask) {// The current task is the highest task.
return;
}
runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;// The current task status is not running
newTask->taskStatus |= OS_TASK_STATUS_RUNNING;// The highest task status position is in the running state
runProcess = OS_PCB_FROM_PID(runTask->processID);// Retrieve the process entity from the process ID index
newProcess = OS_PCB_FROM_PID(newTask->processID);/ / same as above
OsSchedSwitchProcess(runProcess, newProcess);// Switch the process, which mainly involves the process space switch, that is, MMU context switch.
#if (LOSCFG_KERNEL_SMP == YES)// Multiple CPU cores
/* mask new running task's owner processor */
runTask->currCpu = OS_TASK_INVALID_CPUID;// The current task consumes no CPU
newTask->currCpu = ArchCurrCpuid(a);// Make the new task consume CPU
#endif
(VOID)OsTaskSwitchCheck(runTask, newTask);// Switch the task check
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
OsSchedStatistics(runTask, newTask);
#endif
if ((newTask->timeSlice == 0) && (newTask->policy == LOS_SCHED_RR)) {// No time slice and preemptive scheduling. Note that non-preemptive scheduling does not require time slices.
newTask->timeSlice = LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT;// Give the new task time slice default 20ms
}
OsCurrTaskSet((VOID*)newTask);// Set the new task to the current task of the CPU core
if (OsProcessIsUserMode(newProcess)) {// What happens in user mode?
OsCurrUserTaskSet(newTask->userArea);// Set the task stack space
}
/* do the task context switch */
OsTaskSchedule(newTask, runTask);// Switch the task context, noting that OsTaskSchedule is an assembly function seen in los_dispatch.s
}
Copy the code
Intensive reading of the kernel source code
Four code stores synchronous annotation kernel source code, >> view the Gitee repository
Analysis of 100 blogs. Dig deep into the core
Add comments to hongmeng kernel source code process, sort out the following article. Content based on the source code, often in life scene analogy as much as possible into the kernel knowledge of a scene, with a pictorial sense, easy to understand memory. It’s important to speak in a way that others can understand! The 100 blogs are by no means a bunch of ridiculously difficult concepts being put forward by Baidu. That’s not interesting. More hope to make the kernel become lifelike, feel more intimate. It’s hard, it’s hard, but there’s no turning back. 😛 and code bugs need to be constantly debug, there will be many mistakes and omissions in the article and annotation content, please forgive, but will be repeatedly amended, continuous update. Xx represents the number of modifications, refined, concise and comprehensive, and strive to create high-quality content.
Compile build | The fundamental tools | Loading operation | Process management |
---|---|---|---|
Compile environment The build process Environment script Build tools Designed.the gn application Ninja ninja |
Two-way linked list Bitmap management In the stack way The timer Atomic operation Time management |
The ELF format The ELF parsing Static link relocation Process image |
Process management Process concept Fork Special process Process recycling Signal production Signal consumption Shell editor Shell parsing |
Process of communication | Memory management | Ins and outs | Task management |
spinlocks The mutex Process of communication A semaphore Incident control The message queue |
Memory allocation Memory management Memory assembly The memory mapping Rules of memory Physical memory |
Total directory Scheduling the story Main memory slave The source code comments Source structure Static site |
The clock task Task scheduling Task management The scheduling queue Scheduling mechanism Thread concept Concurrent parallel The system calls Task switching |
The file system | Hardware architecture | ||
File concept The file system The index node Mount the directory Root file system Character device VFS File handle Pipeline file |
Compilation basis Assembly and the cords Working mode register Anomaly over Assembly summary Interrupt switch Interrupt concept Interrupt management |
HongMeng station | into a little bit every day, the original is not easy, welcome to reprint, please indicate the source.