概念
为防止某些关键过程操作线程被删除或重启,SylixOS提供线程安全模式相关接口。线程进入安全模式后, 任何对本线程的删除或重启操作都会推迟到线程退出安全模式时进行。
接口
/*********************************************************************************************************
** 函数名称: API_ThreadSafe
** 功能描述: 线程进入安全模式(不得在中断中调用)
** 输 入 :
** 输 出 :
*********************************************************************************************************/
ULONG API_ThreadSafe (VOID)
/*********************************************************************************************************
** 函数名称: API_ThreadUnsafe
** 功能描述: 线程退出安全模式 (不得在中断中调用)
** 输 入 : 无
** 输 出 :
*********************************************************************************************************/
ULONG API_ThreadUnsafe (VOID)
/*********************************************************************************************************
** 函数名称: API_ThreadIsSafe
** 功能描述: 检测目标线程是否处于安全模式.
** 输 入 : ulId 线程句柄
** 输 出 : LW_TRUE 线程处于安全模式,LW_FALSE错误或非安全模式
*********************************************************************************************************/
BOOL API_ThreadIsSafe (LW_OBJECT_HANDLE ulId)
示例
/*********************************************************************************************************
** 函数名称: _TyWrite
** 功能描述: 向终端写入数据
** 输 入 :
** ptyDev TY 设备
** pcBuffer, 需要写入终端的数据
** stNBytes 需要写入的数据大小
** 输 出 : 实际写入的字节数, 小于 1 表示错误
** 全局变量:
** 调用模块:
** 注 意 : 当任务在获取写同步信号量后获取互斥信号量前被删除, 则 tty 会丢失写同步, 所以这里提前进入安全
模式.
*********************************************************************************************************/
ssize_t _TyWrite (TY_DEV_ID ptyDev,
PCHAR pcBuffer,
size_t stNBytes)
{
INTREG iregInterLevel;
REGISTER INT iBytesput;
REGISTER ssize_t sstNbStart = stNBytes;
REGISTER ULONG ulError;
if (pcBuffer == LW_NULL) {
_ErrorHandle(EINVAL);
return (PX_ERROR);
}
if (stNBytes == 0) {
return (0);
}
LW_THREAD_SAFE(); /* 任务提前进入安全状态 */
while (stNBytes > 0) {
ulError = API_SemaphoreBPend(ptyDev->TYDEV_hWrtSyncSemB, ptyDev->TYDEV_ulWTimeout);
if (ulError) {
LW_THREAD_UNSAFE();
_ErrorHandle(ERROR_IO_DEVICE_TIMEOUT); /* 超时 */
return (sstNbStart - stNBytes);
}
TYDEV_LOCK(ptyDev, LW_THREAD_UNSAFE(); return (PX_ERROR)); /* 等待设备使用权 */
if (ptyDev->TYDEV_iAbortFlag & OPT_WABORT) { /* is abort? */
ptyDev->TYDEV_iAbortFlag &= ~OPT_WABORT; /* 清除 abort */
TYDEV_UNLOCK(ptyDev); /* 释放设备使用权 */
LW_THREAD_UNSAFE();
_ErrorHandle(ERROR_IO_ABORT); /* abort */
return (sstNbStart - stNBytes);
}
if (ptyDev->TYDEV_tydevwrstat.TYDEVWRSTAT_bCanceled) { /* 检查是否被禁止输出了 */
ptyDev->TYDEV_tydevwrstat.TYDEVWRSTAT_bCanceled = LW_FALSE; /* 清除 canceled */
TYDEV_UNLOCK(ptyDev); /* 释放设备使用权 */
LW_THREAD_UNSAFE();
_ErrorHandle(ERROR_IO_CANCELLED);
return (sstNbStart - stNBytes);
}
LW_SPIN_LOCK_QUICK(&ptyDev->TYDEV_slLock, &iregInterLevel); /* 锁定 spinlock 并关闭中断 */
iBytesput = rngBufPut(ptyDev->TYDEV_vxringidWrBuf,
pcBuffer,
(INT)stNBytes); /* 将数据写入缓冲区 */
LW_SPIN_UNLOCK_QUICK(&ptyDev->TYDEV_slLock, iregInterLevel); /* 解锁 spinlock 打开中断 */
_TyTxStartup(ptyDev); /* 启动设备发送 */
stNBytes -= (size_t)iBytesput; /* 剩余需要发送的数据 */
pcBuffer += iBytesput; /* 新的缓冲区起始地址 */
LW_SPIN_LOCK_QUICK(&ptyDev->TYDEV_slLock, &iregInterLevel); /* 锁定 spinlock 并关闭中断 */
if (rngFreeBytes(ptyDev->TYDEV_vxringidWrBuf) > 0) {
LW_SPIN_UNLOCK_QUICK(&ptyDev->TYDEV_slLock, iregInterLevel);/* 解锁 spinlock 打开中断 */
API_SemaphoreBPost(ptyDev->TYDEV_hWrtSyncSemB); /* 缓冲区还有空间 */
} else {
LW_SPIN_UNLOCK_QUICK(&ptyDev->TYDEV_slLock, iregInterLevel);/* 解锁 spinlock 打开中断 */
}
TYDEV_UNLOCK(ptyDev); /* 释放设备使用权 */
}
LW_THREAD_UNSAFE(); /* 退出安全模式 */
return (sstNbStart);
}