os_sem.c

共享资源的方法:关中断、关调度器、Sem、Mutex。
    关中断:任务与中断共享资源的唯一方法(CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); *****;  CPU_CRITICAL_EXIT();)。    
    关调度:当调度被关闭的时候,中断是开启的,当中断发生时,ISR会立即执行,执行完不管有没有高优先级的任务,都会回到被中断的任务。(OSSchedLock();  ***; OSSchedUnlock();)
    Sem:最初被用在控制共享资源(创建时初始值>0),现在也被用在同步上(创建时初始值=0)。
        binary semaphores:只能为0(Sem不可得,需要等待)或1(Sem可得,继续执行)。
        counting semaphores:0到OS_SEM_CTR对应的最大值(当资源可以被多个任务使用时,如缓冲池)。
    Mutex:一种特殊类型的binary semaphores,可以克服优先级翻转。


Sem在任务之间共享IO设备的时候非常有用,最好将处理和获取释放Sem封装起来。


优先级翻转:

L得到Sem,当H想要Sem时得不到,H被插入到等待List中,L被M终止,M执行完后,L继续执行释放Sem,H的到Sem运行。
Mutex可以解决这个问题(当高优先级任务H需要时,会将此时占用Mutex的低优先级的任务L优先级提高到和H相同)。




避免死锁的方法:
    1. 先获取所有的资源,然后在处理。
    2. 用同一个顺序获取资源。
    3. Pend操作使用timeout。


多个任务等待一个Sem,使多个任务同时运行。(广播Broadcast是同步多个任务同时运行的通用技术)
如果不使用Flag,但可能出现一种情况,在广播时有任务没有等待这个Sem,将Sem和Flag混合使用,可以解决此问题。



typedef  struct  os_sem              OS_SEM;

struct  os_sem {                                            /* Semaphore                                              */
                                                            /* ------------------ GENERIC  MEMBERS ------------------ */
    OS_OBJ_TYPE          Type;                              /* Should be set to OS_OBJ_TYPE_SEM                       */
    CPU_CHAR            *NamePtr;                           /* Pointer to Semaphore Name (NUL terminated ASCII)       */
    OS_PEND_LIST         PendList;                          /* List of tasks waiting on semaphore                     */
#if OS_CFG_DBG_EN > 0u
    OS_SEM              *DbgPrevPtr;
    OS_SEM              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
                                                            /* ------------------ SPECIFIC MEMBERS ------------------ */
    OS_SEM_CTR           Ctr;
    CPU_TS               TS;
};




void  OSSemCreate (OS_SEM      *p_sem,
                   CPU_CHAR    *p_name,
                   OS_SEM_CTR   cnt,
                   OS_ERR      *p_err):
    创建Sem。如果是资源共享cnt为资源的个数,如果是标志某个事件的发生则为0。

OS_OBJ_QTY  OSSemDel (OS_SEM  *p_sem,
                      OS_OPT   opt,
                      OS_ERR  *p_err):
    删除Sem。
    OS_OPT_DEL_NO_PEND:当没有任务等待时删除,调用OS_SemClr(),如果有任务则设置错误代码。
    OS_OPT_DEL_ALWAYS:即使有任务等待也删除,对等待列表中的将所有的任务调用OS_PendObjDel(),调用OS_SemClr(),启动调度。
    
void  OS_SemClr (OS_SEM  *p_sem):
    清空p_sem中的内容,OS内部函数,被OSQDel()调用。
    调用OS_PendListInit()清空p_sem的等待列表。

OS_SEM_CTR  OSSemPend (OS_SEM   *p_sem,
                       OS_TICK   timeout,
                       OS_OPT    opt,
                       CPU_TS   *p_ts,
                       OS_ERR   *p_err):
    等待一个Sem。
    查看p_sem->Ctr是否已经被标志,是OSTCBCurPtr->SemCtr--,任务继续执行,否调用OS_Pend(),启动调度器切换到别的任务执行,任务被再次唤醒时在此继续往下运行---->
---->判断OSTCBCurPtr->PendStatus:
            如果OS_STATUS_PEND_OK,*p_err = OS_ERR_NONE,返回继续执行
            如果OS_STATUS_PEND_ABORT、OS_STATUS_PEND_TIMEOUT、OS_STATUS_PEND_DEL设置错误代码。

OS_OBJ_QTY  OSSemPendAbort (OS_SEM  *p_sem,
                            OS_OPT   opt,
                            OS_ERR  *p_err):
    终止任务对p_sem的等待。
    根据opt对p_sem中等待列表中的任务调用OS_PendAbort(),根据opt是否启动调度。

OS_SEM_CTR  OSSemPost (OS_SEM  *p_sem,
                       OS_OPT   opt,
                       OS_ERR  *p_err):
    Post p_sem。
    如果OS_CFG_ISR_POST_DEFERRED_EN>0&&OSIntNestingCtr>0,调用OS_IntQPost()(Post到ISR Queue~OS_OBJ_TYPE_SEM),否则调用OS_SemPost()。

OS_SEM_CTR  OS_SemPost (OS_SEM  *p_sem,
                        OS_OPT   opt,
                        CPU_TS   ts,
                        OS_ERR  *p_err):
    Post一个Sem,OSSemPost ()调用。
    如果p_sem的等待列表中没有任务,p_sem->Ctr++。有任务则根据opt对等待链表中的任务调用OS_Post(),根据opt启动调度器

void  OSSemSet (OS_SEM      *p_sem,
                OS_SEM_CTR   cnt,
                OS_ERR      *p_err):
    设置p_sem->Ctr为cnt。
    如果p_sem->Ctr>0,则直接设为cnt,否则判断是否有任务等待,如果没有设为cnt,有则不允许。

void  OS_SemInit (OS_ERR  *p_err):
    初始化Sem管理,设置OSSemQty= 0,OS内部函数,OSInit()调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值