第二十讲 任务的挂起和恢复

  1、任务处于一系列的列表中,比如某个优先级的就绪列表等。任务挂起的时候,就是把任务的node从这些列表中删除。

  2、任务可能会被多次挂起,所以需要定义一个挂起计数器。

  3、处于delay状态中的函数不要挂起。

  主要实现两个函数,挂起和唤醒。

  

void tTaskSchedUnRdy (tTask * task)
{
    tListRemove(&taskTable[task->prio], &(task->linkNode));

    // 队列中可能存在多个任务。只有当没有任务时,才清除位图标记
    if (tListCount(&taskTable[task->prio]) == 0) 
    {
        tBitmapClear(&taskPrioBitmap, task->prio);
    }
}

void tTaskSchedRdy (tTask * task)
{
    tListAddLast(&taskTable[task->prio], &(task->linkNode));
    tBitmapSet(&taskPrioBitmap, task->prio);
}

void tTaskSuspend (tTask * task) 
{
    // 进入临界区
    uint32_t status = tTaskEnterCritical();

    // 不允许对已经进入延时状态的任务挂起
    if (!(task->state & TINYOS_TASK_STATE_DELAYED)) 
    {
        // 增加挂起计数,仅当该任务被执行第一次挂起操作时,才考虑是否
        // 要执行任务切换操作
        if (++task->suspendCount <= 1)
        {
            // 设置挂起标志
            task->state |= TINYOS_TASK_STATE_SUSPEND;

            // 挂起方式很简单,就是将其从就绪队列中移除,这样调度器就不会发现他
            // 也就没法切换到该任务运行
            tTaskSchedUnRdy(task);

            // 当然,这个任务可能是自己,那么就切换到其它任务
            if (task == currentTask)
            {
                tTaskSched();
            }
        }
    }

    // 退出临界区
    tTaskExitCritical(status); 
}

/**********************************************************************************************************
** Function name        :   tTaskWakeUp
** Descriptions         :   唤醒被挂起的任务
** parameters           :   task        待唤醒的任务
** Returned value       :   无
***********************************************************************************************************/
void tTaskWakeUp (tTask * task)
{
    // 进入临界区
    uint32_t status = tTaskEnterCritical();

     // 检查任务是否处于挂起状态
    if (task->state & TINYOS_TASK_STATE_SUSPEND)
    {
        // 递减挂起计数,如果为0了,则清除挂起标志,同时设置进入就绪状态
        if (--task->suspendCount == 0) 
        {
            // 清除挂起标志
            task->state &= ~TINYOS_TASK_STATE_SUSPEND;

            // 同时将任务放回就绪队列中
            tTaskSchedRdy(task);

            // 唤醒过程中,可能有更高优先级的任务就绪,执行一次任务调度
            tTaskSched();
        }
    }

    // 退出临界区
    tTaskExitCritical(status); 
}

 

转载于:https://www.cnblogs.com/nasduc/p/8570526.html

实验报告三:(1)设计 Task0、Task1 两个任务任务 Task0 不断地挂起自己,再被任务 Task1 解挂,两个任务不断地切换执行,并输出两个任务在各个时刻的状态。Task0 的主要功能是显示 Task1 的状态,Task1 的主要功能是显示 Task0 的状态。整个应用的运行流程如图 1 所示,其描述如下:在 main 函数创建起始任务 TaskStart,其优先级为 0。TaskStart 任务主要成创建 2 个应用任务 Task0、Task1,并挂起自己(不再被其它任务唤醒)。之后整个系统的运行流程如下:t1 时刻,Task0 开始执行,它运行到 t2 时刻挂起自己;t2 时刻,系统调度处于就绪状态的优先级最高任务 Task1 执行,它在 t3 时刻唤醒 Task0,后者由于优先级较高而抢占 CPU;Task0 执行到 t4 时刻又挂起自己,内核调度 Task1执行;Task1 运行至 t5 时刻再度唤醒 Task0; 注意:图中的栅格并不代表严格的时间刻度,而仅仅表现各任务启动和执行的相对先后关系。 (2)设计 MyTask、YouTask、KeyTask 三个任务:MyTask 任务输出 M;YouTask 任务输出 Y,并输出 MyTask 任务的状态;KeyTask 任务从键盘接收字符 Y 或 N,当接收 Y 时挂起 MyTask 任务,当接收 N 时恢复 MyTask 任务。 (3)设计 KeyTask 任务,当从键盘输入+号时动态创建任务,最多可以创建 10 个任务,这 10个任务都执行一个函数 MyTask,要求优先级是(PRIO_BASE+0,1,2,3,4,5,6,7,8,9),还要向不同的任务传递不同的参数(0,1,2,3,4,5,6,7,8,9)给 MyTask 函数,优先级为(PRIO_BASE+0,1,2,3,4,5,6,7,8,9)的任务分别输出数字(0,1,2,3,4,5,6,7,8,9)。当从键盘输入-号时动态的删除刚创建的一个任务,最多可删除 10 个任务。提示:多个任务可以执行一个函数。运行结果如下图所示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值