手写RTOS嵌入式操作系统(5)

事件控制块信号量邮箱事件标志组互斥信号量等的基础组件

解决以下问题

1、同步两个任务的运行

2、处理多个任务共享资源的冲突问题

3、任务间消息的传递

4、中断向任务传递事件标志,以唤醒任务执行

1、事件控制块

事件控制块的结构
typedef struct _tEvent{
    tEventType type;        //事件类型
    tList waitList;         //事件等待链表
}tEvent;
初始化事件控制块
void tEventInit(tEvent *event, tEventType type)
{
    event->type=type;
    tListInit(&event->waitList);
}
事件的等待
void tEventWait(tEvent *event,tTask * task,void *msg,uint32_t state,uint32_t timeout)
{
    uint32_t status = tTaskEnterCritical();
    task->waitEvent=event;
    task->eventMsg=msg;
    task->state|=state; 
    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);
        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;         
}

2、计数信号量(不支持嵌套)

计数信号量的结构
typedef struct _tSem{
    tEvent event;
    uint32 count;
    uint32 maxCount;
}tSem;
计数信号量的初始化
void tSemInit(tSem *sem,uint32_t startCount,uint32_t maxCount)
{
    
    sem->maxCount=maxCount;
    if(maxCount==0)
    {    
        sem->count=startCount;
    }
    else
    {
        sem->count=(startCount>maxCount)?maxCount:startCount;
    }
}
计数信号量的获取
uint32_t tSemwait(tSem *sem,uint32_t waitTicks)
{
    uint32_t status = tTaskEnterCritical();
    if(sem->count > 0)
    {
        sem->count--;
        tTaskExitCritical(status); 
    	return tErrorNoError;
    }
    else
    {
        tEventWait(&sem->event,currentTask,(void *)0,tEventTypeSem,waitTicks);
        tTaskExitCritical(status); 
        tTaskSched();                        //任务调度
        return currentTask->waitEventResult;
    }   
}
计数信号量的释放
void tSemNotify (tSem * sem)
{
    uint32_t status = tTaskEnterCritical();        
    if (tEventWaitCount(&sem->event) > 0)
    {
        tTask * task = tEventWakeUp(&sem->event, (void *)0, tErrorNoError );
        if (task->prio < currentTask->prio)
        {
            tTaskSched(); 
    	}
    }
    else
    {
    	++sem->count;
    	if ((sem->maxCount != 0) && (sem->count > sem->maxCount)) 
    	{	
    		sem->count = sem->maxCount;
    	}
    }
    tTaskExitCritical(status);
}

3、邮箱

邮箱的结构
typedef struct _tMbox
{
	tEvent event;
    uint32_t count;
    uint32_t read;
    uint32_t write;
    uint32_t maxCount;
    void ** msgBuffer;
}tMbox;
邮箱的初始化
void tMboxInit (tMbox * mbox, void ** msgBuffer, uint32_t maxCount) 
{
	tEventInit(&mbox->event, tEventTypeMbox);

	mbox->msgBuffer = msgBuffer;
	mbox->maxCount = maxCount;
	mbox->read = 0;
	mbox->write = 0;
	mbox->count = 0;
}

邮箱的获取
uint32_t tMboxWait (tMbox * mbox, void **msg, uint32_t waitTicks) 
{
    uint32_t status = tTaskEnterCritical();
    if (mbox->count > 0)
    {
        --mbox->count;
        *msg = mbox->msgBuffer[mbox->read++];        //取出消息
        if (mbox->read >= mbox->maxCount) 
        {
        	mbox->read = 0;
        }
    	tTaskExitCritical(status); 
    	return tErrorNoError;
    }
    else                                                                
    { 
        tEventWait(&mbox->event, currentTask, (void *)0,  tEventTypeMbox, waitTicks);    //将任务插入到事件队列
        tTaskExitCritical(status);
        tTaskSched();
        *msg = currentTask->eventMsg;
        return currentTask->waitEventResult;
    }
}
邮箱的释放
uint32_t tMboxNotify (tMbox * mbox, void * msg, uint32_t notifyOption)
{
    uint32_t status = tTaskEnterCritical();        
    if (tEventWaitCount(&mbox->event) > 0)
    {
        tTask * task = tEventWakeUp(&mbox->event, (void *)msg, tErrorNoError );    //唤醒任务
        if (task->prio < currentTask->prio)
        {
            tTaskSched(); 
    	}
    }
    else
    {
    	if (mbox->count >= mbox->maxCount) 
    	{
		    tTaskExitCritical(status);
		    return tErrorResourceFull;
    	}
		if (notifyOption & tMBOXSendFront)        //优先获取该消息
		{
			if (mbox->read <= 0) 
			{
				mbox->read = mbox->maxCount - 1;
			} 
			else 
			{
				--mbox->read;
			}
			mbox->msgBuffer[mbox->read] = msg;
		}
		else 
		{
			mbox->msgBuffer[mbox->write++] = msg;
			if (mbox->write >= mbox->maxCount)
			{
				mbox->write = 0;
			}
		}
		mbox->count++;        //消息计数
   	}
	tTaskExitCritical(status);
	return tErrorNoError;
}

4、事件标志组

事件标志组的结构
typedef struct _tFlagGroup
{
    tEvent event;
    uint32_t flags;
}tFlagGroup;
事件标志组的初始化
void tFlagGroupInit (tFlagGroup * flagGroup, uint32_t flags)
{
	tEventInit(&flagGroup->event, tEventTypeFlagGroup);
	flagGroup->flags = flags;
}

检查并消耗掉事件标志

static uint32_t tFlagGroupCheckAndConsume (tFlagGroup * flagGroup, uint32_t type, uint32_t * flags)
{
    uint32_t srcFlags = *flags;
	uint32_t isSet = type & TFLAGGROUP_SET;
	uint32_t isAll = type & TFLAGGROUP_ALL;
	uint32_t isConsume = type & TFLAGGROUP_CONSUME;
	uint32_t calcFlag = isSet ? (flagGroup->flags & srcFlags) : (~flagGroup->flags & srcFlags);
	if (((isAll != 0) && (calcFlag == srcFlags)) || ((isAll == 0) && (calcFlag != 0)))
	{
		if (isConsume)
		{
			if (isSet)
			{
				flagGroup->flags &= ~srcFlags;
			}
			else 
			{
				flagGroup->flags |= srcFlags;
			}
		}
		*flags = calcFlag;
		return tErrorNoError;
	}
	*flags = calcFlag;
	return tErrorResourceUnavaliable;
}
事件标志组的等待
uint32_t tFlagGroupWait (tFlagGroup * flagGroup, uint32_t waitType, uint32_t requestFlag,
						uint32_t * resultFlag, uint32_t waitTicks)
{
    uint32_t result;
    uint32_t flags = requestFlag;

    uint32_t status = tTaskEnterCritical();
    result = tFlagGroupCheckAndConsume(flagGroup, waitType, &flags);
    if (result != tErrorNoError)
    {
		currentTask->waitFlagsType = waitType;    	    // 不满足条件,插入到等待队列
		currentTask->eventFlags = requestFlag;
		tEventWait(&flagGroup->event, currentTask, (void *)0,  tEventTypeFlagGroup, waitTicks);
        tTaskExitCritical(status);
		tTaskSched();
        *resultFlag = currentTask->eventFlags;
        result = currentTask->waitEventResult;
	}
    else
    {
        *resultFlag = flags;
        tTaskExitCritical(status);
    }
	return result;
}
事件标志组的通知
void tFlagGroupNotify (tFlagGroup * flagGroup, uint8_t isSet, uint32_t flags)
{
    tList *waitList;
    tNode * node;
    tNode * nextNode;
    uint8_t sched = 0;

    uint32_t status = tTaskEnterCritical();

    if (isSet) {
        flagGroup->flags |= flags;     // 置1
    } else {
        flagGroup->flags &= ~flags;    // 清0
    }
    waitList = &flagGroup->event.waitList;
    for (node = waitList->headNode.nextNode; node != &(waitList->headNode); node = nextNode) {
        uint32_t result;
        tTask *task = tNodeParent(node, tTask, linkNode);
        uint32_t flags = task->eventFlags;
        nextNode = node->nextNode;
        result = tFlagGroupCheckAndConsume(flagGroup, task->waitFlagsType, &flags);
        if (result == tErrorNoError) {
            task->eventFlags = flags;
            tEventWakeUpTask(&flagGroup->event, task, (void *)0, tErrorNoError);    // 唤醒任务
            sched = 1;
        }
    }
    if (sched)
    {
        tTaskSched();
    }
    tTaskExitCritical(status);
}

5、互斥信号量(支持嵌套)

互斥信号量的结构
typedef struct  _tMutex
{
    tEvent event;
    uint32_t lockedCount;          // 已被锁定的次数
    tTask * owner;                 // 拥有者
    uint32_t ownerOriginalPrio;    // 拥有者原始的优先级
}tMutex;
互斥信号量的初始化
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 tMutexNotify (tMutex * mutex)
{
    uint32_t status = tTaskEnterCritical();
    if (mutex->lockedCount <= 0)
    {
        tTaskExitCritical(status);
        return tErrorNoError;
    }
    if (mutex->owner != currentTask)
    {
        tTaskExitCritical(status);
        return tErrorOwner;
    }
    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;
            tTaskSchedRdy(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;
}

拥有者不加入到等待列表中,所以可实现嵌套

实现优先级继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值