概述 取消一个线程要确保该线程能够释放其所持有的锁、分配的内存,使整个系统保持一致性。线程取消的途径有两种:异步取消和延时取消。
异步取消:被取消线程收到取消信号后,立即死亡。该线程缩持有的资源可能得不到释放,这是一种非安全的线程取消方式。
延时取消:系统默认取消方式,是一种比较安全的线程取消机制,被取消线程取消时,只是设置取消点(ptcbDel->TCB_bCancelRequest)为true,被取消线程继续运行,等到安全位置后进行取消操作。
取消点: 在使用延迟取消机制时,一个线程在可以被取消的地方定义取消点,当收到取消请求时,被取消的线程执行到取消点时退出,或者在一个取消点调用被阻塞时退出。
关键结构体 程序清单2.1 TCB结构体部分节选
typedef struct __lw_tcb {
...
LW_LIST_LINE TCB_lineManage; /* 内核管理用线表 */
LW_LIST_RING TCB_ringReady; /* 相同优先级就绪环 */
LW_CLASS_WAKEUP_NODE TCB_wunDelay; /* 等待节点 */
#define TCB_ulDelay TCB_wunDelay.WUN_ulCounter
...
#if (LW_CFG_EVENT_EN > 0) && (LW_CFG_MAX_EVENTS > 0)
LW_LIST_RING TCB_ringEvent; /* 事件等待队列表 */
PLW_CLASS_EVENT TCB_peventPtr; /* 等待事件指针 */
PLW_LIST_RING TCB_ppringPriorityQueue; / 在 PRIORITY 队列位置 */
/* 由于删除线程时需要解等待链,*/
/* 这时需要确定队列位置 */
#endif
#if LW_CFG_COROUTINE_EN > 0
LW_CLASS_COROUTINE TCB_crcbOrigent; /* 协程起源点 */
PLW_LIST_RING TCB_pringCoroutineHeader; /* 协程首地址 */
#endif /* LW_CFG_COROUTINE_EN > 0 */
...
volatile ULONG TCB_ulCPUId; /* 如果正在运行, 表示运行 CPU */
volatile BOOL TCB_bIsCand; /* 是否在候选运行表中 */
#if LW_CFG_SMP_EN > 0
struct __lw_tcb TCB_ptcbWaitStatus; / 等待状态修改的目标线程 */
PLW_LIST_LINE TCB_plineStatusReqHeader; /* 等待修改本线程状态 */
LW_LIST_LINE TCB_lineStatusPend; /* 等待目标线程状态修改 */
#endif /* LW_CFG_SMP_EN */
...
PLW_EVENTSETNODE TCB_pesnPtr; /* 指向该线程等待 */
...
#if LW_CFG_THREAD_CANCEL_EN > 0
BOOL TCB_bCancelRequest; /* 取消请求 */
INT TCB_iCancelState; /* 取消状态 */
INT TCB_iCancelType; /* 取消类型 */
#endif /* LW_CFG_THREAD_CANCEL_EN */
...
#if LW_CFG_THREAD_DEL_EN > 0
struct __lw_tcb TCB_ptcbDeleteMe; / 要将本线程删除的 TCB */
struct __lw_tcb TCB_ptcbDeleteWait; / 等待对方删除的 TCB */
#endif /* LW_CFG_THREAD_DEL_EN > 0 */
UINT8 TCB_ucStackAutoAllocFlag; /* 堆栈是否有系统在堆中开辟 */
PVOID TCB_pvVProcessContext; /* 进程上下文 */
...
} LW_CLASS_TCB;
程序清单2.2 等待队列
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; /* 等待队列 */
UIN×××6 WQ_usNum; /* 等待队列中的线程个数 */
} LW_CLASS_WAITQUEUE;
typedef LW_CLASS_WAITQUEUE *PLW_CLASS_WAITQUEUE;
程序清单2.3 事件集
typedef struct { /* 事件集 */
LW_LIST_MONO EVENTSET_monoResrcList; /* 空闲资源表 */
UINT8 EVENTSET_ucType; /* 类型 */
PLW_LIST_LINE EVENTSET_plineWaitList; /* 指向第一个等待线程 */
ULONG EVENTSET_ulEventSets; /* 32 bit 事件位 */
ULONG EVENTSET_ulOption; /* 事件集选项 */
UIN×××6 EVENTSET_usIndex; /* 数组中的索引 */
CHAR EVENTSET_cEventSetName[LW_CFG_OBJECT_NAME_SIZE];
/* 事件标志组名 */
} LW_CLASS_EVENTSET;
typedef LW_CLASS_EVENTSET *PLW_CLASS_EVENTSET;
typedef struct { /* 事件集节点 */
LW_LIST_LINE EVENTSETNODE_lineManage; /* 事件标志组管理表 */
PVOID EVENTSETNODE_ptcbMe; /* 指向等待任务的TCB */
PVOID EVENTSETNODE_pesEventSet; /* 指向标志组 */
ULONG EVENTSETNODE_ulEventSets; /* 标志组开始等待 */
UINT8 EVENTSETNODE_ucWaitType; /* 等待类型 */
} LW_CLASS_EVENTSETNODE;
typedef LW_CLASS_EVENTSETNODE *PLW_CLASS_EVENTSETNODE;
typedef PLW_CLASS_EVENTSETNODE PLW_EVENTSETNODE;
流程 API_ThreadCancel函数流程:
图3.1 API_ThreadCancel函数
API_ThreadTestCancel函数流程:
图3.2 API_ThreadTestCancel函数
pthread_delete函数流程:
图3.3 pthread_delete函数
__threadDelete函数流程:
图3.4 __threadDelete函数