A detailed Ucos task scheduling mechanism
One operating system kernel provides the most core function is the task scheduling mechanism, the operating system kernel scheduling mechanism there are basically two, one is the time slice turns scheduling, is to divide a system cycle into several paragraphs, the first time to perform the first task, the second time to perform the second task .... Perform the appropriate tasks for each period of time. One is the preemptive real-time kernel, that is, the highest priority task to run, whenever, as long as there is a task in readiness than the currently executing task priority, pause the current task to perform the highest priority task. Ucos_ii is the preemptive real-time kernel.
The variables associated with task scheduling in Ucos are as follows:
Os_ext int8u osrdygrp;
Os_ext int8u osrdytbl[64];
UCOS supports a total of 64 tasks, the lower priority of the priority book of the task, the higher the level. We divided 64 tasks into 8 groups, with 8 priorities per group.
Priority 0->7 is Priority group 0
Priority 8->15 is Priority Group 1
Priority 16->23 to Priority Group 2
Priority 3 for Priority Group->31
Priority->39 to Priority Group 4
Priority 40->47 to Priority Group 5
Priority->55 to Priority Group 6
Priority 56->63 is the priority Group 7 OSRDYGRP is int8u type, and each of the bits in the OSRDYGRP represents whether a task in each group has entered a ready state.
If any one task in group No. 0 enters the ready state-------->osrdygrp |= 00000001;
If any one task in group 1th enters the ready state-------->osrdygrp |= 00000010;
If any one task in group 2nd enters the ready state-------->osrdygrp |= 00000100;
If any one task in group 3rd enters the ready state-------->osrdygrp |= 00001000;
If any one task in group 4th enters the ready state-------->osrdygrp |= 00010000;
If any one task in group 5th enters the ready state-------->osrdygrp |= 00100000;
If any one task in group 6th enters the ready state-------->osrdygrp |= 01000000;
If any one task in group 7th enters the ready state-------->osrdygrp |= 10000000;
Summarize the law namely: Osrdygrp |= 1<< (group);
OSRDYTBL[8] is an array, and each of the bits in the Osrdytbl[n] represents the first task in the nth group into the ready state.
If the first task in group No. 0 enters the ready state-------> Osrdytbl[0] |= 00000001
If the seventh task in group No. 0 enters the ready state-------> Osrdytbl[0] |= 10000000
If the third task in group 2nd enters the ready state-------> osrdytbl[2] |= 00001000
If the sixth task in group 7th enters the ready state-------> Osrdytbl[7] |= 01000000
osrdytbl[Group] |=1<< (priority of Task &0x07)
The reason why this is difficult to understand is that the following table of the array is 0->7, so the prio/8 gets the scope of the priority group is 0->7,
But a bitwise operation on the int8u is the first to eighth bit, to be converted so it is difficult to understand the
So the process of getting a task into the Ready state is (Prio is the priority of the task):
x = Piro & 0X07; Position of the task in the priority group 0----->7
y = P >> 3; Priority group where the task is located 0----->7
bitx = 1<<x;
Bity = 1<<y;
Osrdygrp |= bity; Position of the corresponding priority group 1
osrdytbl[y] |= bitx; Put the corresponding priority unit in the corresponding position 1
Take the task of priority 22 as an example:
x = & 0X07 = 6;
y = >>3 = 2;
BITX = 1<<6; 01000000
Bity = 1<<2; 00000100
Osrdygrp |= 00000100; 2nd Priority Group has a task in the Ready state
OSRDYTBL[2] |= 01000000; The 7th task in the 2nd Priority group is in a ready state
In contrast to the above, the process of leaving a task out of the ready state is as follows:
Osrdytbl[y] &= ~bixx;
if (osrdytbl[y]==0)
{
osrdygrp &= ~bity;
}
OSRDYGRP altogether has 8 bits, so a total of 256 in a combination, assuming osrdygrp = 11011000, at this time the OSRDYGRP means: Priority group 3,4,6,7 has a task into the ready state. Since we only have to deal with the highest priority tasks, let's just osrdygrp the position of the first bits 1, the current highest priority task in group 3rd. Let's do this in all 256 cases. Build a table that directly checks the table for the group that contains the highest-priority task currently in place.
int8u Const OSUNMAPTBL[256] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x00 to 0x0F
*/4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x10 to 0x1F */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x20 to 0x2F */4, 0, 1, 0, 2 , 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x30 to 0x3F */6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x40 to 0X4F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5f */5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x60 to 0x6F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x70 to 0x7F */7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x80 to 0x8F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0x90 to 0x9F */5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0 , 2, 0, 1, 0,/* 0xA0 to 0xAF */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xb0 to 0xBF */6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0xC0 to 0xC F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0xD0 to 0xDF
*/5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 0xE0 to 0xEF */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0/* 0xF0 to 0xFF */};
Prioritize the highest priority tasks by identifying the group that contains the highest priority tasks and then identifying the highest priority tasks in the reorganization (first 1 bits):
y = osunmaptbl[osrdygrp]; The group that gets the highest priority task
x = osunmaptbl[osrdytbl[y]];///////The highest priority bit
Prio = y<<3 + x in the group; Highest priority level
Functions related to task scheduling are dispatched in the Os_core.c file with the following specific functions:
The function is to find the highest-priority task in the Ready table
void os_sched (void)
{
#if Os_critical_method = = 3
Os_cpu_sr cpu_sr = 0; Allocating space for the CPU status register
#endif
Os_enter_critical ();
if (osintnesting = = 0)//Interrupt Service program cannot dispatch
{
if (oslocknesting = = 0)//scheduler cannot be dispatched when locked
{
Os_schednew (); Find the highest-priority tasks in the Ready table
if (Ospriohighrdy! = ospriocur)//The highest-priority task is not scheduled until the current task
{
Ostcbhighrdy = Ostcbpriotbl[ospriohighrdy];
#if os_task_profile_en > 0
ostcbhighrdy->ostcbctxswctr++; Count the number of tasks to switch
#endif
osctxswctr++; Statistics system all task switching times
OS_TASK_SW (); Perform task switching
}
}
}
Os_exit_critical ();
}