• 2.7 时间片轮转机制
    • 概述
    • API讲解
    • 编程实例
    • 运行效果

    2.7 时间片轮转机制

    概述

    TencentOS tiny操作系统内核是一个抢占式内核,抢占式内核的特点是,如果最高优先级的任务不放弃CPU(调用tos_task_delay、tos_task_yeild等主动放权,或者任务间同步通信机制的pend接口等),那么CPU将会一直被此任务独占。

    假设这样一种场景:系统中包含多个同等优先级的任务,且这几个任务体中都没有放弃CPU的行为,则会出现的情况是,这几个任务始终只有第一个被得到调度的那个在运行,因为第一个得到调度的任务体中不会主动放弃CPU,而其他任务优先级上与其相等无法抢占。此种场景下,其他任务会因得不到CPU而陷入饥饿状态。

    时间片轮转机制提供了按时间片占用调度的策略,可以解决上述场景下的任务饥饿问题。

    API讲解

    编程实例

    1、在tos_config.h中,配置时间片轮转组件开关TOS_CFG_ROUND_ROBIN_EN:

    #define TOS_CFG_ROUND_ROBIN_EN 1u

    2、编写main.c示例代码:

    1. #include "tos.h"
    2. #include "mcu_init.h"
    3.  
    4. #define STK_SIZE_TASK_DEMO 512
    5. #define STK_SIZE_TASK_SAMPLE 512
    6.  
    7. /*
    8. 此代码中创建了两个同等优先级(PRIO_TASK_DEMO)的任务task_demo1、task_demo2,两个任务体中做的操作是不断对各自的计数器(demo1_counter、demo2_counter)做自增操作(没有放弃CPU的操作),时间片分别为timeslice_demo1、timeslice_demo2。
    9. 同时创建了一个优先级比task_demo1、task_demo2较高的采样任务task_sample,此任务不间歇的对两个计数器进行采样。在开启时间片轮转的情况下,task_demo1、task_demo2得到运行的时间比例应该是timeslice_demo1与timeslice_demo2的比例,那么demo1_counter和demo2_counter值的比例应该也差不多是timeslice_demo1与timeslice_demo2的比例。
    10. */
    11.  
    12. // task_demo1和task_demo2的优先级
    13. #define PRIO_TASK_DEMO 4
    14. // 采样任务的优先级
    15. #define PRIO_TASK_SAMPLE (PRIO_TASK_DEMO - 1)
    16.  
    17. // task_demo1的时间片,在tos_task_create时传入
    18. const k_timeslice_t timeslice_demo1 = 10;
    19. // task_demo2的时间片,在tos_task_create时传入
    20. const k_timeslice_t timeslice_demo2 = 20;
    21.  
    22. k_stack_t stack_task_demo1[STK_SIZE_TASK_DEMO];
    23. k_stack_t stack_task_demo2[STK_SIZE_TASK_DEMO];
    24. k_stack_t stack_task_sample[STK_SIZE_TASK_SAMPLE];
    25.  
    26. k_task_t task_demo1;
    27. k_task_t task_demo2;
    28. k_task_t task_sample;
    29.  
    30. extern void entry_task_demo1(void *arg);
    31. extern void entry_task_demo2(void *arg);
    32. extern void entry_task_sample(void *arg);
    33.  
    34. uint64_t demo1_counter = 0;
    35. uint64_t demo2_counter = 0;
    36.  
    37. void entry_task_demo1(void *arg)
    38. {
    39. while (K_TRUE) {
    40. ++demo1_counter;
    41. }
    42. }
    43.  
    44. void entry_task_demo2(void *arg)
    45. {
    46. while (K_TRUE) {
    47. ++demo2_counter;
    48. }
    49. }
    50.  
    51. void entry_task_sample(void *arg)
    52. {
    53. while (K_TRUE) {
    54. ++demo2_counter;
    55. printf("demo1_counter: %lld\n", demo1_counter);
    56. printf("demo2_counter: %lld\n", demo2_counter);
    57. printf("demo2_counter / demo1_counter = %f\n",
    58. (double)demo2_counter / demo1_counter);
    59. printf("should almost equals to:\n");
    60. printf("timeslice_demo2 / timeslice_demo1 = %f\n\n", (double)timeslice_demo2 / timeslice_demo1);
    61. tos_task_delay(1000);
    62. }
    63. }
    64.  
    65. int main(void)
    66. {
    67. board_init();
    68. tos_knl_init();
    69. // 配置robin机制参数
    70. tos_robin_config(TOS_ROBIN_STATE_ENABLED, (k_timeslice_t)500u);
    71. (void)tos_task_create(&task_demo1, "demo1", entry_task_demo1, NULL,
    72. PRIO_TASK_DEMO, stack_task_demo1, STK_SIZE_TASK_DEMO,
    73. timeslice_demo1);
    74. (void)tos_task_create(&task_demo2, "demo2", entry_task_demo2, NULL,
    75. PRIO_TASK_DEMO, stack_task_demo2, STK_SIZE_TASK_DEMO,
    76. timeslice_demo2);
    77. (void)tos_task_create(&task_sample, "sample", entry_task_sample, NULL,
    78. PRIO_TASK_SAMPLE, stack_task_sample, STK_SIZE_TASK_SAMPLE,
    79. 0);
    80. tos_knl_start();
    81. }

    运行效果

    demo1_counter: 0demo2_counter: 1demo2_counter / demo1_counter = 0.000000should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 1915369demo2_counter: 3720158demo2_counter / demo1_counter = 1.942267should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 3774985demo2_counter: 7493508demo2_counter / demo1_counter = 1.985043should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 5634601demo2_counter: 11266858demo2_counter / demo1_counter = 1.999584should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 7546896demo2_counter: 14987015demo2_counter / demo1_counter = 1.985852should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 9406512demo2_counter: 18759340demo2_counter / demo1_counter = 1.994293should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 11266128demo2_counter: 22531664demo2_counter / demo1_counter = 1.999947should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 13177398demo2_counter: 26251821demo2_counter / demo1_counter = 1.992185should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 15037014demo2_counter: 30023632demo2_counter / demo1_counter = 1.996649should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 16896630demo2_counter: 33795443demo2_counter / demo1_counter = 2.000129should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    demo1_counter: 18807900demo2_counter: 37515600demo2_counter / demo1_counter = 1.994672should almost equals to:timeslice_demo2 / timeslice_demo1 = 2.000000

    实例代码