锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

SylixOS里的事件控制块儿

时间:2023-01-29 15:00:01 24ppcb板公整套连接器

概念

SylixOS线程间的同步工具,如信号量、信息队列、标志组等,统称为事件(event),所有这些都取决于事件控制块。因此,理解事件控制块的数据结构和基本操作是理解信号量、信息队列和标志组的重要基础和保证。

数据结构

/********************************************************************************************************* 事件控制块 (可用于计数和二进制信号量、互斥信号量、消息队列、PART内存池) *********************************************************************************************************/ #define EVENT_RW_STATUS_R 0 #define EVENT_RW_STATUS_W 1  #define EVENT_SEM_Q 0      #define EVENT_RW_Q_R 0 #define EVENT_RW_Q_W 1  #define EVENT_MSG_Q_R 0 #define EVENT_MSG_Q_S 1  typedef struct { 
             LW_LIST_MONO          EVENT_monoResrcList;                          /* 空闲资源表 */     UINT8                 EVENT_ucType;                                 /* 事件类型 */     PVOID                 EVENT_pvTcbOwn;                               /* 占有资源的TCB指针 */                                                                         /* 加入死检测机制 */     ULONG                 EVENT_ulCounter;                              /* 计数器值 */     ULONG                 EVENT_ulMaxCounter;                           /* 最大技术值 */          INT                   EVENT_iStatus;     ULONG                 EVENT_ulOption;                               /* 事件选项 */     UINT8                 EVENT_ucCeilingPriority;                      /* 天花板优先级 */     PVOID                 EVENT_pvPtr;                                  /* 多用途指针 */                                                                         /* 包括二进制信号量消息, */                                                                         /* 子控制块包括消息队列, */                                                                         /* 内存等 */     LW_CLASS_WAITQUEUE    EVENT_wqWaitQ[2];                             /* 双等待队列 */     UINT16                EVENT_usIndex;                                /* 下标缓冲区 */     CHAR                  EVENT_cEventName[LW_CFG_OBJECT_NAME_SIZE];    /* 事件名 */ } LW_CLASS_EVENT; typedef LW_CLASS_EVENT   *PLW_CLASS_EVENT; 
/********************************************************************************************************* 以哈希表散列函数为散列参数. *********************************************************************************************************/ #define __EVENT_Q_SIZE 8 /*Q HASH SIZE */
#define __EVENT_Q_EPRIO 32 /* 256 / 8 */
#define __EVENT_Q_SHIFT 5 /* 2 ^ 5 = 32 */

typedef union { 
         
    PLW_LIST_RING         WL_pringFifo;                                 /* 基于先入先出的等待队列 */
    PLW_LIST_RING         WL_pringPrio[__EVENT_Q_SIZE];                 /* 基于优先级的等待队列 */
} LW_UNION_WAITLIST;
typedef LW_UNION_WAITLIST *PLW_UNION_WAITLIST;

typedef struct { 
        
    LW_UNION_WAITLIST     WQ_wlQ;                                       /* 等待队列 */
    UINT16                WQ_usNum;                                     /* 等待队列中的线程个数 */
} LW_CLASS_WAITQUEUE;
typedef LW_CLASS_WAITQUEUE *PLW_CLASS_WAITQUEUE;

事件控制资源定义

一个是事件控制块缓冲,提供了分配事件控制块的来源;一个是事件对象资源管理,用于管理事件控制块缓存。

__KERNEL_EXT LW_CLASS_EVENT          _K_eventBuffer[LW_CFG_MAX_EVENTS]; /* 事件控制块缓冲区 */
__KERNEL_EXT LW_CLASS_OBJECT_RESRC   _K_resrcEvent;                     /* 事件对象资源管理 */

一些基本操作

/********************************************************************************************************* _EVENT_FIFO_Q_PTR *********************************************************************************************************/

#define _EVENT_FIFO_Q_PTR(iQ, ppringListPtr) \ do { \ ppringListPtr = &pevent->EVENT_wqWaitQ[iQ].WQ_wlQ.WL_pringFifo; \ } while (0)

/********************************************************************************************************* _EVENT_PRIORITY_Q_PTR *********************************************************************************************************/

#define _EVENT_PRIORITY_Q_PTR(iQ, ppringListPtr, ucPrioIndex) \ do { \ ppringListPtr = &pevent->EVENT_wqWaitQ[iQ].WQ_wlQ.WL_pringPrio[ucPrioIndex]; \ } while (0)

/********************************************************************************************************* _EVENT_DEL_Q_FIFO find the pointer which point a FIFO queue, a thread removed form it. *********************************************************************************************************/

#define _EVENT_DEL_Q_FIFO(iQ, ppringListPtr) \ do { \ ppringListPtr = &pevent->EVENT_wqWaitQ[iQ].WQ_wlQ.WL_pringFifo; \ } while (0)

/********************************************************************************************************* _EVENT_DEL_Q_PRIORITY find the pointer which point a priority queue, a thread removed form it. *********************************************************************************************************/

#define _EVENT_DEL_Q_PRIORITY(iQ, ppringListPtr) \ do { \ REGISTER INT i; \ ppringListPtr = &pevent->EVENT_wqWaitQ[iQ].WQ_wlQ.WL_pringPrio[0]; \ for (i = 0; i < __EVENT_Q_SIZE; i++) { \ if (*ppringListPtr) { \ break; \ } \ ppringListPtr++; \ } \ } while (0)

/********************************************************************************************************* _EVENT_INDEX_Q_PRIORITY *********************************************************************************************************/
#define _EVENT_INDEX_Q_PRIORITY(ucPriority, ucIndex) \ do { \ ucIndex = (UINT8)(ucPriority >> __EVENT_Q_SHIFT); \ } while (0)
/********************************************************************************************************* _EventWaitNum *********************************************************************************************************/
static LW_INLINE UINT16  _EventWaitNum (INT  iQ, PLW_CLASS_EVENT    pevent)
{ 
        
    return  (pevent->EVENT_wqWaitQ[iQ].WQ_usNum);
}
/********************************************************************************************************* _EventQGetTcbFifo (Make Oldest thread ready, So this is The Last Node In Ring) *********************************************************************************************************/
static LW_INLINE PLW_CLASS_TCB  _EventQGetTcbFifo (PLW_CLASS_EVENT    pevent, 
                                                   PLW_LIST_RING     *ppringList)
{ 
        
    REGISTER PLW_CLASS_TCB    ptcb;
    REGISTER PLW_LIST_RING    pringOldest;
    
    pringOldest = _list_ring_get_prev(*ppringList);
    
    ptcb = _LIST_ENTRY(pringOldest, LW_CLASS_TCB, TCB_ringEvent);
    
    return  (ptcb);
}
/********************************************************************************************************* _EventQGetTcbPriority (Make highest priority thread ready, So this is The Frist Node In Ring) *********************************************************************************************************/
static LW_INLINE PLW_CLASS_TCB  _EventQGetTcbPriority (PLW_CLASS_EVENT    pevent, 
                                                       PLW_LIST_RING     *ppringList)
{ 
        
    REGISTER PLW_CLASS_TCB    ptcb;

    ptcb = _LIST_ENTRY(*ppringList, LW_CLASS_TCB, TCB_ringEvent);
    
    return  (ptcb);
}

初始化

初始化函数中主要是把事件控制块缓冲区初始化中的各个块串成单链表,用于资源的分配和回收。同时对各个块的成员。

/********************************************************************************************************* ** 函数名称: _EventInit ** 功能描述: 初始化事件缓冲池 ** 输 入 : ** 输 出 : *********************************************************************************************************/
VOID  _EventInit (VOID)
{ 
        
    REGISTER ULONG                 ulI;
    REGISTER PLW_CLASS_EVENT       peventTemp1;
    REGISTER PLW_LIST_MONO         pmonoTemp1;

    REGISTER PLW_CLASS_EVENT    peventTemp2;
    REGISTER PLW_LIST_MONO      pmonoTemp2;
    
    _K_resrcEvent.RESRC_pmonoFreeHeader = &_K_eventBuffer[0].EVENT_monoResrcList;
                                                                            /* 设置资源表头 */
    peventTemp1 = &_K_eventBuffer[0];                                       /* 指向缓冲池首地址 */
    peventTemp2 = &_K_eventBuffer[1];                                       /* 指向缓冲池首地址 */
    
    for (ulI = 0; ulI < ((LW_CFG_MAX_EVENTS) - 1); ulI++) { 
        
        pmonoTemp1 = &peventTemp1->EVENT_monoResrcList;                     /* 获得资源表 */
        pmonoTemp2 = &peventTemp2->EVENT_monoResrcList;                     /* 获得资源表 */
        
        peventTemp1->EVENT_ucType  = LW_TYPE_EVENT_UNUSED;                  /* 事件类型 */
        peventTemp1->EVENT_usIndex = (UINT16)ulI;                           /* 事件缓冲区下标 */
   
        _LIST_MONO_LINK(pmonoTemp1, pmonoTemp2);                            /* 建立资源连接 */
        
        peventTemp1++;
        peventTemp2++;
    }
                                                                            /* 初始化最后一个节点 */
    pmonoTemp1 = &peventTemp1->EVENT_monoResrcList;                         /* 获得资源表 */
    
    peventTemp1->EVENT_ucType  = LW_TYPE_EVENT_UNUSED;                      /* 事件类型 */
    peventTemp1->EVENT_usIndex = (UINT16)ulI;                               /* 事件缓冲区下标 */

    _INIT_LIST_MONO_HEAD(pmonoTemp1);                                       /* 初始化最后节点 */
    
    _K_resrcEvent.RESRC_pmonoFreeTail = pmonoTemp1;
                                                                     /* LW_CFG_MAX_EVENTS == 1 */

    _K_resrcEvent.RESRC_uiUsed    = 0;
    _K_resrcEvent.RESRC_uiMaxUsed = 0;
}

分配和回收

/********************************************************************************************************* ** 函数名称: _Allocate_Event_Object ** 功能描述: 从空闲Event控件池中取出一个空闲Event ** 输 入 : ** 输 出 : 获得的Object地址,失败返回 NULL *********************************************************************************************************/
PLW_CLASS_EVENT  _Allocate_Event_Object (VOID)
{ 
        
    REGISTER PLW_LIST_MONO    pmonoFree;
    REGISTER PLW_CLASS_EVENT  peventFree;
    
    if (_LIST_MONO_IS_EMPTY(_K_resrcEvent.RESRC_pmonoFreeHeader)) { 
             /* 检查缓冲区是否为空 */
        return  (LW_NULL);
    }
    
    pmonoFree  = _list_mono_allocate_seq(&_K_resrcEvent.RESRC_pmonoFreeHeader, 
                                         &_K_resrcEvent.RESRC_pmonoFreeTail);
                                                                        /* 获得资源 */
    peventFree = _LIST_ENTRY(pmonoFree, LW_CLASS_EVENT, 
                             EVENT_monoResrcList);                      /* 获得资源表容器地址 */
    
    _K_resrcEvent.RESRC_uiUsed++;
    if (_K_resrcEvent.RESRC_uiUsed > _K_resrcEvent.RESRC_uiMaxUsed) { 
        
        _K_resrcEvent.RESRC_uiMaxUsed = _K_resrcEvent.RESRC_uiUsed;
    }
    
    return  (peventFree);
}
/********************************************************************************************************* ** 函数名称: _Free_Event_Object ** 功能描述: 将Event控制块交还缓冲池 ** 输 入 : ** 输 出 : *********************************************************************************************************/
VOID  _Free_Event_Object (PLW_CLASS_EVENT  pevent)
{ 
        
    REGISTER PLW_LIST_MONO    pmonoFree;
    
    pmonoFree = &pevent->EVENT_monoResrcList;
    
    _list_mono_free_seq(&_K_resrcEvent.RESRC_pmonoFreeHeader, 
                        &_K_resrcEvent.RESRC_pmonoFreeTail, 
                        pmonoFree);
                        
    _K_resrcEvent.RESRC_uiUsed--;
}

将线程从事件阻塞队列中添加或删除

当一个线程因获取不到事件资源时就会被阻塞,阻塞的线程也会因为资源可获取被唤醒,这就需要在事件对象上记录被阻塞的线程。一个事件可能同时会阻塞多个线程,而在唤醒时会按一定的顺序唤醒阻塞的线程,所以事件控制块通过双向链表来管理阻塞线程。对于读写信号量和消息队列会用到两条阻塞链表,所以事件控制块通统一定义了两个等待对象,每个等地啊对象有8+1个双向链表,不同类型事件按需使用。

SylixOS提供两种唤醒顺序策略,基于优先级唤醒和先来先唤醒:

  • FIFO策略 :先来先唤醒,阻塞时插入队首,唤醒时从队尾依次唤醒。
  • PRIORITY策略:高优先级先唤醒,阻塞时根据线程优先(数值越大优先级越低)级升序插入队列,唤醒时从头依次唤醒。为了提高阻塞时的插队实时性,SylixOS使用哈希链表来替代简单的双向链表。因为SylixOS最多有256个优先级,这里平均分为8组,即每32个优先级一组。操作时首先通过优先级除以32确定组号,再对组号对应的双链表进行升序插队,原理上耗时能降为单链表实现的1/8。
/********************************************************************************************************* ** 函数名称: _AddTCBToEventFifo ** 功能描述: 将一个线程加入 FIFO 事件等待队列 ** 输 入 : ptcb 任务控制块 ** pevent 事件控制块 ** ppringList 等待队列 ** 输 出 : NONE *********************************************************************************************************/
#if (LW_CFG_EVENT_EN > 0) && (LW_CFG_MAX_EVENTS > 0)

VOID  _AddTCBToEventFifo (PLW_CLASS_TCB    ptcb, 
                          PLW_CLASS_EVENT  pevent, 
                          PLW_LIST_RING   *ppringList)
{ 
        
    _List_Ring_Add_Ahead(&ptcb->TCB_ringEvent, ppringList);             /* 加入到 FIFO 队列头 */
    
    pevent->EVENT_wqWaitQ[ptcb->TCB_iPendQ].WQ_usNum++;                 /* 等待事件的个数++ */
}
/********************************************************************************************************* ** 函数名称: _DelTCBFromEventFifo ** 功能描述: 从 FIFO 事件等待队列中删除一个线程 ** 输 入 : ptcb 任务控制块 ** pevent 事件控制块 ** ppringList 等待队列 ** 输 出 : NONE *********************************************************************************************************/
VOID  _DelTCBFromEventFifo (PLW_CLASS_TCB      ptcb, 
                            PLW_CLASS_EVENT    pevent, 
                            PLW_LIST_RING     *ppringList)
{ 
        
    _List_Ring_Del(&ptcb->TCB_ringEvent, ppringList);
    
    pevent->EVENT_wqWaitQ[ptcb->TCB_iPendQ].WQ_usNum--;                 /* 等待事件的个数-- */
}
/********************************************************************************************************* ** 函数名称: _AddTCBToEventPriority ** 功能描述: 将一个线程加入 PRIORITY 事件等待队列 ** 输 入 : ptcb 任务控制块 ** pevent 事件控制块 ** ppringList 等待队列 ** 输 出 : NONE *********************************************************************************************************/
VOID  _AddTCBToEventPriority (PLW_CLASS_TCB    ptcb, 
                              PLW_CLASS_EVENT  pevent, 
                              PLW_LIST_RING   *ppringList)
{ 
        
             PLW_LIST_RING    pringList;
    REGISTER PLW_LIST_RING    pringListHeader;
    REGISTER PLW_CLASS_TCB    ptcbTemp;
    REGISTER UINT8            ucPriority;                               /* 优先级暂存变量 */
    
    ucPriority      = ptcb->TCB_ucPriority;                             /* 优先级 */
    pringListHeader = *ppringList;
    
    if (pringListHeader == LW_NULL) { 
                                           /* 没有等待任务 */
        _List_Ring_Add_Ahead(&ptcb->TCB_ringEvent, ppringList);         /* 直接添加 */
        
    } else { 
        
        ptcbTemp = _LIST_ENTRY(pringListHeader, LW_CLASS_TCB, TCB_ringEvent);
        if (LW_PRIO_IS_HIGH(ucPriority, ptcbTemp->TCB_ucPriority)) { 
        
            _List_Ring_Add_Ahead(&ptcb->TCB_ringEvent, ppringList);     /* 加入到队列头 */
        
        } else { 
        
            pringList = _list_ring_get_next(pringListHeader);
            while (pringList != pringListHeader) { 
        
                ptcbTemp = _LIST_ENTRY(pringList, LW_CLASS_TCB, TCB_ringEvent);
                if (LW_PRIO_IS_HIGH(ucPriority, ptcbTemp->TCB_ucPriority)) { 
        
                    break;
                }
                pringList = _list_ring_get_next(pringList);
            }
            _List_Ring_Add_Last(&ptcb->TCB_ringEvent, &pringList);
        }
    }
    
    pevent->EVENT_wqWaitQ[ptcb->TCB_iPendQ].WQ_usNum++;                 /* 等待事件的个数++ */
}
/********************************************************************************************************* ** 函数名称: _DelTCBFromEventPriority ** 功能描述: 从FIFO事件等待队列中删除一个线程 ** 输 入 : ptcb 任务控制块 ** pevent 事件控制块 ** ppringList 等待队列 ** 输 出 : NONE *********************************************************************************************************/
VOID  _DelTCBFromEventPriority (PLW_CLASS_TCB      ptcb, 
                                PLW_CLASS_EVENT    pevent, 
                                PLW_LIST_RING     *ppringList)
{ 
            
    _List_Ring_Del(&ptcb->TCB_ringEvent, ppringList);
    
    pevent->EVENT_wqWaitQ[ptcb->TCB_iPendQ].WQ_usNum--;                 /* 等待事件的个数-- */
}
  • 四个函数的输入参数都一样线程控制块,事件控制块,等待队列。其中这里的等待队列就来自于事件控制块的EVENT_wqWaitQ成员,具体是两个队列中的哪一个则是在调用前根据不同事件类型具体选择的。
  • 除了_AddTCBToEventPriority 函数外,其他三个都是队列首位的插入或删除操作,为O(1)算法。
  • WQ_usNum成员用于统计队列当前长度,而不需要通过遍历来获取。
  • _AddTCBToEventPriority 调用前已通过哈希算法得到具体要用哪个等待队列,这里只进行一个升序插入操作,为O(n)算法。

事件等待操作

如果一个线程申请事件时失败,就可能需要阻塞等待。首先需要让出CPU,及从就绪队列中擦删除当前线程,然后根据不同的等待策略插入对应的等待队列,如果需要超时唤醒还要插入延时唤醒队列。

/********************************************************************************************************* ** 函数名称: _EventWaitFifo ** 功能描述: 将一个线程加入 FIFO 事件等待队列,同时设置相关标志位 (进入内核且关中断状态下被调用) ** 输 入 : pevent 事件 ** ppringList 等待链表 ** 输 出 : NONE *********************************************************************************************************/
VOID  _EventWaitFifo (PLW_CLASS_EVENT  pevent, PLW_LIST_RING  *ppringList)
{ 
        
    REGISTER PLW_CLASS_PCB    ppcb;
             PLW_CLASS_TCB    ptcbCur;
    //获取当前线程控制块
    LW_TCB_GET_CUR(ptcbCur);                                            /* 当前任务控制块 */
    //设置等待事件指针
    ptcbCur->TCB_peventPtr = pevent;
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /* 从就绪队列中删除 */

    //加入事件等待队列
    _AddTCBToEventFifo(ptcbCur, pevent, ppringList);                    /* 加入等待队列 */
    //如果不是穷等待,则添加节点到延时等待唤醒链表
    if (ptcbCur->TCB_ulDelay) { 
        
        __ADD_TO_WAKEUP_LINE(ptcbCur);                                  /* 加入等待扫描链 */
    }

    ptcbCur->TCB_ucIsEventDelete = LW_EVENT_EXIST;                      /* 事件存在 */
}
/********************************************************************************************************* ** 函数名称: _EventWaitPriority ** 功能描述: 将一个线程加入优先级事件等待队列,同时设置相关标志位 (进入内核且关中断状态下被调用) ** 输 入 : pevent 事件 ** ppringList 等待链表 ** 输 出 : NONE *********************************************************************************************************/
VOID  _EventWaitPriority (PLW_CLASS_EVENT  pevent, PLW_LIST_RING  *ppringList)
{ 
        
    REGISTER PLW_CLASS_PCB    ppcb;
             PLW_CLASS_TCB    ptcbCur;
    //获取当前线程控制块
    LW_TCB_GET_CUR(ptcbCur);                                            /* 当前任务控制块 */
    //设置等待事件指针
    ptcbCur->TCB_peventPtr = pevent;
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /* 从就绪队列中删除 */

    //加入事件等待队列
    _AddTCBToEventPriority(ptcbCur, pevent, ppringList);                /* 加入等待队列 */
    //如果不是穷等待,则添加节点到延时等待唤醒链表
    if (ptcbCur->TCB_ulDelay) { 
        
        __ADD_TO_WAKEUP_LINE(ptcbCur);                                  /* 加入等待扫描链 */
    }
    
    ptcbCur->TCB_ucIsEventDelete = LW_EVENT_EXIST;                      /* 事件存在 */
}

事件就绪操作

将一个线程从 FIFO 事件等待队列中解锁并就绪, 同时设置相关标志位, 需要时进入就绪表.
将线程从等待队列和延时队列中删除。

/********************************************************************************************************* ** 函数名称: _EventReadyFifoLowLevel ** 功能描述: 将一个线程从 FIFO 事件等待队列中解锁并就绪, 同时设置相关标志位 ** 输 入 : pevent 事件 ** pvMsgBoxMessage 扩展消息 ** ppringList 等待链表 ** 输 出 : 激活的任务控制块 ** 全局变量: ** 调用模块: *********************************************************************************************************/
PLW_CLASS_TCB  _EventReadyFifoLowLevel (PLW_CLASS_EVENT  pevent, 
                                        PVOID            pvMsgBoxMessage, 
                                        PLW_LIST_RING   *ppringList)
{ 
        
    REGISTER PLW_CLASS_TCB    ptcb;
    //获取最旧项,即队尾项
    ptcb = _EventQGetTcbFifo(pevent, ppringList);                       /* 查找需要激活的线程 */
    
    _DelTCBFromEventFifo(ptcb, pevent, ppringList);
    
    ptcb->TCB_pvMsgBoxMessage = pvMsgBoxMessage;                        /* 传递二进制信号量简单消息 */
    
    if (ptcb->TCB_usStatus & LW_THREAD_STATUS_DELAY) { 
        
        __DEL_FROM_WAKEUP_LINE(ptcb);                                   /* 退出等待队列 */
        ptcb->TCB_ulDelay = 0ul;
    }
    
    return  (ptcb);
}
/********************************************************************************************************* ** 函数名称: _EventReadyPriorityLowLevel ** 功能描述: 将一个线程从优先级事件等待队列中解锁并就绪, 同时设置相关标志位 ** 输 入 : pevent 事件 ** pvMsgBoxMessage 扩展消息 ** ppringList 等待链表 ** 输 出 : 激活的任务控制块 ** 全局变量: ** 调用模块: *********************************************************************************************************/
PLW_CLASS_TCB  _EventReadyPriorityLowLevel (PLW_CLASS_EVENT  pevent, 
                                            PVOID            pvMsgBoxMessage, 
                                            PLW_LIST_RING   *ppringList)
{ 
        
    REGISTER PLW_CLASS_TCB    ptcb;
    //获取优先级最高项,即队首项
    ptcb = _EventQGetTcbPriority(pevent, ppringList);                   /* 查找需要激活的线程 */
    
    _DelTCBFromEventPriority(ptcb, pevent, ppringList);
    
    ptcb->TCB_pvMsgBoxMessage = pvMsgBoxMessage;                        /* 传递二进制信号量简单消息 */

    if (ptcb->TCB_usStatus & LW_THREAD_STATUS_DELAY) { 
        
        __DEL_FROM_WAKEUP_LINE(ptcb);                                   /* 退出等待队列 */
        ptcb->TCB_ulDelay = 0ul;
    }

    return  (ptcb);
}
/********************************************************************************************************* ** 函数名称: _EventReadyHighLevel ** 功能描述: 将一个线程从 FIFO 事件等待队列中解锁并就绪, 同时设置相关标志位, 需要时进入就绪表. ** 此函数在内核锁定状态被调用. ** 输 入 : ptcb 任务控制块 ** usWaitType 等待类型 ** 输 出 : NONE ** 全局变量: ** 调用模块: 此函数在开中断时被调用. *********************************************************************************************************/
VOID  _EventReadyHighLevel (PLW_CLASS_TCB    ptcb, UINT16   usWaitType)
{ 
        
             INTREG           iregInterLevel;
    REGISTER PLW_CLASS_PCB    ppcb;
    
    iregInterLevel = KN_INT_DISABLE();                                  /* 关闭中断 */
    
    ptcb->TCB_peventPtr = LW_NULL;
    
    if (ptcb->TCB_ucWaitTimeout) { 
        
        ptcb->TCB_ucWaitTimeout = LW_WAIT_TIME_CLEAR;                   /* 清除超时位 */
    
    } else { 
                                                                    /* 清除相应等待位 */
        ptcb->TCB_usStatus = (UINT16)(ptcb->TCB_usStatus & (~usWaitType));
        if (__LW_THREAD_IS_READY(ptcb)) { 
                                       /* 是否就绪 */
            ptcb->TCB_ucSchedActivate = LW_SCHED_ACT_INTERRUPT;         /* 中断激活方式 */
            ppcb = _GetPcb(ptcb);
            __ADD_TO_READY_RING(ptcb, ppcb);                            /* 加入到相对优先级就绪环 */
        }
    }
    
    KN_INT_ENABLE(iregInterLevel);                                      /* 开中断 */
}

事件解锁操作

/********************************************************************************************************* ** 函数名称: _EventUnQueue ** 功能描述: 将一个线程从事件等待队列中解锁 ** 输 入 : ptcb 任务控制块 ** 输 出 : 事件控制块 ** 全局变量: ** 调用模块: ** 注 意 : 如果是优先级等待队列, 则在等待过程中可能有优先级的改变, 所以不能靠当前优先级来判断队列的位置 *********************************************************************************************************/
PLW_CLASS_EVENT  _EventUnQueue (PLW_CLASS_TCB    ptcb)
{ 
        
    REGISTER PLW_CLASS_EVENT    pevent;
    REGISTER PLW_LIST_RING     *ppringList;
    
    pevent = ptcb->TCB_peventPtr;
    
    if (pevent->EVENT_ulOption & LW_OPTION_WAIT_PRIORITY) { 
                     /* 优先级队列 */
        ppringList = ptcb->TCB_ppringPriorityQueue;                     /* 确定等待队列位置 */
        _DelTCBFromEventPriority(ptcb, pevent, ppringList);             /* 从队列中移除 */
        
    } else { 
                                                                    /* FIFO 队列 */
        _EVENT_FIFO_Q_PTR(ptcb->TCB_iPendQ, ppringList);
        _DelTCBFromEventFifo(ptcb, pevent, ppringList);                 /* 从队列中移除 */
    }
    
    ptcb->TCB_peventPtr = LW_NULL;                                      /* 清除事件 */
    
    return  (pevent);
}

提升和恢复线程优先级

互斥信号量为了防止优先级翻转,会提升占用资源线程的优先级,待其运行完毕释放资源时还要恢复线程优先级。

/********************************************************************************************************* ** 函数名称: _EventPrioTryBoost ** 功能描述: 互斥信号量提升拥有任务优先级. ** 此函数在内核锁定状态被调用. ** 输 入 : pevent 事件 ** ptcbCur 当前任务控制块 ** 输 出 : NONE *********************************************************************************************************/
VOID  _EventPrioTryBoost (PLW_CLASS_EVENT  pevent, PLW_CLASS_TCB   ptcbCur)
{ 
        
    PLW_CLASS_TCB    ptcbOwner = (PLW_CLASS_TCB)pevent->EVENT_pvTcbOwn;
    
    if (ptcbOwner->TCB_iDeleteProcStatus) { 
                                     /* 任务已被删除或

相关文章