目录
等待互斥信号量
信号量未被占用
信号量被自己占用
信号量被高优先级任务占用
信号量被低优先级任务占用
释放互斥信号量
未发生优先级继承
发生优先级继承
等待互斥信号量
信号量未被占用
- 标记为已经被占用
- 锁定计数+1
信号量被自己占用
- 锁定计数+1
信号量被高优先级任务占用
- 低优先级任务插入事件控制块的等待队列中
信号量被低优先级任务占用
- 高优先级任务插入到等待队列中
- 低优先级任务设置成高优先级任务一样的优先级
释放互斥信号量
未发生优先级继承
- 释放信号量
- 从等待队列中唤醒一个任务占用信号量
发生优先级继承
- 低优先级任务从信号量中释放,不再占用信号量,同时低优先级任务优先级改为原有的优先级
- 从等待队列中唤醒一个任务占用信号量
tMutex.c
#include "tinyOS.h"
/* 互斥信号量初始化函数 */
void tMutexInit(tMutex *mutex)
{
tEventInit(&mutex->event, tEventTypeMutex);
mutex->lockedCount = 0;
mutex->owner = (tTask *)0;
mutex->ownerOriginalPrio = TINYOS_PRO_COUNT;//初始设为无效值
}
/* 等待互斥信号量函数 */
//参数:互斥信号量,超时时间
uint32_t tMutexWait(tMutex *mutex, uint32_t waitTicks)
{
uint32_t status = tTaskEnterCritical();
//互斥信号量是否被锁定
if(mutex->lockedCount <= 0)
{
//未锁定:当前任务可以占用互斥信号量
mutex->owner = currentTask;
mutex->ownerOriginalPrio = currentTask->prio;
mutex->lockedCount++;
tTaskExitCritical(status);
return tErrorNoError;
}
else
{
//已锁定:
//判断是否是当前任务锁定的
if(mutex->owner == currentTask)
{
mutex->lockedCount++;
tTaskExitCritical(status);
return tErrorNoError;
}
else
{
//不是当前任务锁定:
//判断当前任务优先级和互斥信号量占有者优先级哪个高
if(currentTask->prio < mutex->owner->prio)
{
//当前任务优先级高:
//任务优先级继承机制
tTask *owner = mutex->owner;
//判断当前任务是否为就绪状态
if(owner->state == TINYOS_TASK_STATE_RDY)
{
//当前任务为就绪状态:
tTaskSchedUnRdy(owner);//从原有就绪队列中移出
owner->prio = currentTask->prio;//更改所有者优先级
tTaskSchedRdy(owner);//插入新的队列
}
else
{
owner->prio = currentTask->prio;
}
}
tEventWait(&mutex->event, currentTask, (void *)0, tEventTypeMutex, waitTicks);//当前任务插入事件控制块中
tTaskExitCritical(status);
tTaskSched();
return currentTask->waitEventResult;
}
}
}
/* 无等待获取互斥信号量函数 */
//仅需检查互斥信号量能否被当前任务获取到
uint32_t tMutexNoWaitGet(tMutex *mutex)
{
uint32_t status = tTaskEnterCritical();
//判断互斥信号量是否被锁定
if(mutex->lockedCount <= 0)
{
//没有被锁定:由当前任务锁定
mutex->owner = currentTask;
mutex->ownerOriginalPrio = currentTask->prio;
mutex->lockedCount++;
tTaskExitCritical(status);
return tErrorNoError;
}
else
{
//被锁定:
//判断互斥信号量所有者是否是当前任务
if(mutex->owner == currentTask)
{
mutex->lockedCount++;
tTaskExitCritical(status);
return tErrorNoError;
}
tTaskExitCritical(status);
return tErrorResourceUnavailable;
}
}
/* 释放互斥信号量函数 */
uint32_t tMutexNotify(tMutex *mutex)
{
uint32_t status = tTaskEnterCritical();
//判断信号量是否被锁定
if(mutex->lockedCount <= 0)
{
tTaskExitCritical(status);
return tErrorNoError;
}
//判断信号量所有者
if(mutex->owner != currentTask)
{
tTaskExitCritical(status);
return tErrorOwner;
}
//对锁定计数--仍大于0:没有到最终释放任务的过程
if(--mutex->lockedCount > 0)
{
tTaskExitCritical(status);
return tErrorNoError;
}
//判断是否发生优先级继承
if(mutex->ownerOriginalPrio != mutex->owner->prio)
{
//发生优先级继承:
//判断任务是否在就绪状态
if(mutex->owner->state == TINYOS_TASK_STATE_RDY)
{
//更改任务所在就绪列表位置及优先级
tTaskSchedUnRdy(mutex->owner);
currentTask->prio = mutex->ownerOriginalPrio;
tTaskSchedUnRdy(mutex->owner);
}
else
{
currentTask->prio = mutex->ownerOriginalPrio;
}
}
//判断当前等待队列中是否有任务
if(tEventWaitCount(&mutex->event) > 0)
{
tTask *task = tEventWakeUp(&mutex->event, (void *)0, tErrorNoError);//取出一个任务
//信号量的所有者设置为新任务
mutex->owner = task;
mutex->ownerOriginalPrio = task->prio;
mutex->lockedCount++;
//判断任务的优先级是否比当前任务的优先级高
if(task->prio < currentTask->prio)
{
tTaskSched();
}
}
tTaskExitCritical(status);
return tErrorNoError;
}
tMutex.h
#ifndef __TMUTEX_H
#define __TMUTEX_H
#include "tEvent.h"
/* 互斥信号量结构 */
typedef struct _tMutex
{
tEvent event; //事件控制块
uint32_t lockedCount; //锁定计数器
tTask *owner; //当前互斥信号量所有者
uint32_t ownerOriginalPrio; //所有者原始优先级
}tMutex;
void tMutexInit(tMutex *mutex);
uint32_t tMutexWait(tMutex *mutex, uint32_t waitTicks);
uint32_t tMutexNoWaitGet(tMutex *mutex);
uint32_t tMutexNotify(tMutex *mutex);
#endif
tintOS.h
#ifndef __TINYOS_H
#define __TINYOS_H
#include <stdint.h>
#include "tLib.h"
#include "tConfig.h"
#include "tTask.h"
#include "tEvent.h"
#include "tSem.h"
#include "tMbox.h"
#include "tMemBlock.h"
#include "tFlagGroup.h"
#include "tMutex.h"
/* 错误码 */
typedef enum _tError{
tErrorNoError = 0, //没有错误发生
tErrorTimeout, //超时
tErrorResourceUnavailable,//资源不可用
tErrorDel, //被删除
tErrorResourceFull, //资源已满
tErrorOwner, //拥有者错误
}tError;
extern tTask *currentTask;
extern tTask *nextTask;
uint32_t tTaskEnterCritical(void);
void tTaskExitCritical(uint32_t status);
void tTaskSwitch(void); //和CPU相关,写在switch.c
void tTaskRunFirst(void);
void tTaskSchedInit(void);
void tTaskSchedDisable(void);
void tTaskSchedEnable(void);
void tTaskSchedRdy(tTask *task);
void tTaskSchedUnRdy(tTask *task);
void tTaskSchedRemove(tTask *task);
void tTaskSched(void);
void tTimeTaskWait(tTask *task, uint32_t ticks);
void tTimeTaskWakeUp(tTask *task);
void tTimeTaskRemove(tTask *task);
void tTaskSystemTickHandler(void);
void tTaskDelay(uint32_t delay);
void tSetSysTickPeriod(uint32_t ms);
void tInitApp(void);
#endif
tEvent.c
#include "tinyOS.h"
/* 事件控制块初始化函数 */
void tEventInit(tEvent *event, tEventType type)
{
event->type = tEventTypeUnknow;
tListInit(&event->waitList);
}
/* 事件控制块等待函数 */
//参数:事件控制块,任务,消息(传入消息来源,在事件发生以后存放具体的消息),等待的状态,超时时间
void tEventWait(tEvent *event, tTask *task, void *msg, uint32_t state, uint32_t timeout)
{
uint32_t status = tTaskEnterCritical();
task->state |= state << 16;
task->waitEvent = event;
task->eventMsg = msg;
task->waitEventResult = tErrorNoError;
tTaskSchedUnRdy(task);//移出就绪队列
tListAddLast(&event->waitList, &task->linkNode);//插入事件控制块等待队列的尾部
if(timeout)
{
tTimeTaskWait(task, timeout);//设置了超时事件,插入延时队列
}
tTaskExitCritical(status);
}
/* 事件控制块通知函数(将任务从事件控制块中唤醒,唤醒队列首部任务) */
//参数:事件控制块,消息,唤醒结果
tTask *tEventWakeUp(tEvent *event, void *msg, uint32_t result)
{
tNode *node;
tTask *task = (tTask *)0;
uint32_t status = tTaskEnterCritical();
if((node = tListRemoveFirst(&event->waitList)) != (tNode *)0)
{
task = (tTask *)tNodeParent(node, tTask, linkNode);//插入到事件控制块是用linknode
task->waitEvent = (tEvent *)0;//不等待任何事件
task->eventMsg = msg;
task->waitEventResult = result;
task->state &= ~TINYOS_TASK_WAIT_MASK;
if(task->delayTicks != 0)//有延时
{
tTimeTaskWakeUp(task);//强制将任务从延时队列中移除
}
tTaskSchedRdy(task);//插入就绪队列
}
tTaskExitCritical(status);
return task;
}
/* 事件控制块通知函数(将任务从事件控制块中唤醒,唤醒队列中的指定任务) */
//参数:事件控制块,指定唤醒的任务,消息,唤醒结果
tTask *tEventWakeUpTask(tEvent *event, tTask *task, void *msg, uint32_t result)
{
uint32_t status = tTaskEnterCritical();
tListRemove(&event->waitList, &task->linkNode);//直接将任务移出队列
task->waitEvent = (tEvent *)0;//不等待任何事件
task->eventMsg = msg;
task->waitEventResult = result;
task->state &= ~TINYOS_TASK_WAIT_MASK;
if(task->delayTicks != 0)//有延时
{
tTimeTaskWakeUp(task);//强制将任务从延时队列中移除
}
tTaskSchedRdy(task);//插入就绪队列
tTaskExitCritical(status);
return task;
}
/* 事件控制块移除函数 */
void tEventRemoveTask(tTask *task, void *msg, uint32_t result)
{
uint32_t status = tTaskEnterCritical();
tListRemove(&task->waitEvent->waitList, &task->linkNode);
task->waitEvent = (tEvent *)0;
task->eventMsg = msg;
task->waitEventResult = result;
task->state &= ~TINYOS_TASK_WAIT_MASK;
tTaskExitCritical(status);
}
/* 事件控制块清空函数 */
//返回值:事件任务块被清空时,它的等待队列中有多少任务
uint32_t tEventRemoveAll(tEvent *event, void *msg, uint32_t result)
{
tNode *node;
uint32_t count = 0;
uint32_t status = tTaskEnterCritical();
count = tListCount(&event->waitList);//等待队列中有多少任务
while((node = tListRemoveFirst(&event->waitList)) != (tNode *)0)//移除等待队列头部任务
{
tTask *task = (tTask *)tNodeParent(node, tTask, linkNode);//获取task结构
task->waitEvent = (tEvent *)0;//不再等待事件
task->eventMsg = msg;
task->waitEventResult = result;
task->state &= ~TINYOS_TASK_WAIT_MASK;
if(task->delayTicks != 0)//任务有延时
{
tTimeTaskWakeUp(task);//移出延时队列
}
tTaskSchedRdy(task);
}
tTaskExitCritical(status);
return count;
}
/* 获取事件控制块中等待任务函数 */
uint32_t tEventWaitCount(tEvent *event)
{
uint32_t count = 0;
uint32_t status = tTaskEnterCritical();
count = tListCount(&event->waitList);
tTaskExitCritical(status);
return count;
}
app.c
#include "tinyOS.h"
#include "string.h"
//定义任务,分别为它们配备独立的堆栈空间
tTask tTask1;
tTask tTask2;
tTask tTask3;
tTask tTask4;
tTaskStack task1Env[1024];
tTaskStack task2Env[1024];
tTaskStack task3Env[1024];
tTaskStack task4Env[1024];
tMutex mutex;
//定义任务要执行的功能
int task1Flag;
void task1Entry(void *param)
{
tSetSysTickPeriod(10);//初始化
tMutexInit(&mutex);
for(;;)//任务里是for的死循环
{
//嵌套的申请互斥信号量再释放
tMutexWait(&mutex, 0);
tMutexWait(&mutex, 0);
task1Flag = 0;
tTaskDelay(1);
task1Flag = 1;
tTaskDelay(1);
tMutexNotify(&mutex);
tMutexNotify(&mutex);
}
}
int task2Flag;
void task2Entry(void *param)
{
for(;;)
{
tMutexWait(&mutex, 0);
tMutexWait(&mutex, 0);
task2Flag = 0;
tTaskDelay(1);
task2Flag = 1;
tTaskDelay(1);
tMutexNotify(&mutex);
tMutexNotify(&mutex);
}
}
int task3Flag;
void task3Entry(void *param)
{
for(;;)
{
task3Flag = 0;
tTaskDelay(1);
task3Flag = 1;
tTaskDelay(1);
}
}
int task4Flag;
void task4Entry(void *param)
{
for(;;)
{
task4Flag = 0;
tTaskDelay(1);
task4Flag = 1;
tTaskDelay(1);
}
}
/* 应用任务初始化函数 */
void tInitApp(void)
{
//最后一个参数:传堆栈末端地址,因为堆栈是向下生长的,初始堆栈地址是堆栈空间最后一个单元地址的末端
tTaskInit(&tTask1, task1Entry, (void *)0x11111111, 0, &task1Env[1024]);
tTaskInit(&tTask2, task2Entry, (void *)0x22222222, 1, &task2Env[1024]);
tTaskInit(&tTask3, task3Entry, (void *)0x22222222, 1, &task3Env[1024]);
tTaskInit(&tTask4, task4Entry, (void *)0x22222222, 1, &task4Env[1024]);
}