/********************************************************************************************************* ** 函数名称: pthread_cond_timedwait ** 功能描述: 等待一个条件变量广播信号(带有超时). ** 输 入 : pcond 条件变量控制块 ** pmutex 互斥信号量 ** abs_timeout 超时时间 (注意: 这里是绝对时间, 即一个确定的历史时间例如: 2009.12.31 15:36:04) 笔者觉得这个不是很爽, 应该再加一个函数可以等待相对时间. ** 输 出 : ERROR CODE ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API int pthread_cond_timedwait (pthread_cond_t *pcond, pthread_mutex_t *pmutex, const struct timespec *abs_timeout) { ULONG ulTimeout; ULONG ulError; struct timespec tvNow; struct timespec tvWait = {0, 0}; if ((pcond == LW_NULL) || (pmutex == LW_NULL)) { errno = EINVAL; return (EINVAL); } if ((abs_timeout == LW_NULL) || (abs_timeout->tv_nsec < 0) || (abs_timeout->tv_nsec >= __TIMEVAL_NSEC_MAX)) { errno = EINVAL; return (EINVAL); } __pthread_cond_init_invisible(pcond); __pthread_mutex_init_invisible(pmutex); lib_clock_gettime(CLOCK_REALTIME, &tvNow); /* 获得当前系统时间 */ if (__timespecLeftTime(&tvNow, abs_timeout)) { tvWait = *abs_timeout; __timespecSub(&tvWait, &tvNow); /* 计算与当前等待的时间间隔 */ } /* * 注意: 当 tvWait 超过ulong tick范围时, 将自然产生溢出, 导致超时时间不准确. */ ulTimeout = __timespecToTick(&tvWait); /* 变换为 tick */ ulError = API_ThreadCondWait(pcond, pmutex->PMUTEX_ulMutex, ulTimeout); if (ulError == ERROR_THREAD_WAIT_TIMEOUT) { errno = ETIMEDOUT; return (ETIMEDOUT); } else if (ulError) { errno = EINVAL; return (EINVAL); } else { return (ERROR_NONE); } }
LW_API int pthread_cond_reltimedwait_np (pthread_cond_t *pcond, pthread_mutex_t *pmutex, const struct timespec *rel_timeout) { ULONG ulTimeout; ULONG ulError; if ((pcond == LW_NULL) || (pmutex == LW_NULL)) { errno = EINVAL; return (EINVAL); } if ((rel_timeout == LW_NULL) || (rel_timeout->tv_nsec < 0) || (rel_timeout->tv_nsec >= __TIMEVAL_NSEC_MAX)) { errno = EINVAL; return (EINVAL); } __pthread_cond_init_invisible(pcond); __pthread_mutex_init_invisible(pmutex); /* * 注意: 当 rel_timeout 超过ulong tick范围时, 将自然产生溢出, 导致超时时间不准确. */ ulTimeout = __timespecToTick(rel_timeout); /* 变换为 tick */ ulError = API_ThreadCondWait(pcond, pmutex->PMUTEX_ulMutex, ulTimeout); if (ulError == ERROR_THREAD_WAIT_TIMEOUT) { errno = ETIMEDOUT; return (ETIMEDOUT); } else if (ulError) { errno = EINVAL; return (EINVAL); } else { return (ERROR_NONE); } }
/********************************************************************************************************* ** 函数名称: nanosleep ** 功能描述: 使调用此函数的线程睡眠一个指定的时间, 睡眠过程中可能被信号唤醒. (POSIX) ** 输 入 : rqtp 睡眠的时间 ** rmtp 保存剩余时间的结构. ** 输 出 : ERROR_NONE or PX_ERROR error == EINTR 表示被信号激活. ** 全局变量: ** 调用模块: API 函数 (不得在中断中调用) *********************************************************************************************************/ LW_API INT nanosleep (const struct timespec *rqtp, struct timespec *rmtp) { INTREG iregInterLevel; PLW_CLASS_TCB ptcbCur; REGISTER PLW_CLASS_PCB ppcb; REGISTER ULONG ulKernelTime; REGISTER INT iRetVal; INT iSchedRet; REGISTER ULONG ulError; ULONG ulTick; struct timespec tvStart; struct timespec tvTemp; if ((!rqtp) || (rqtp->tv_nsec < 0) || (rqtp->tv_nsec >= __TIMEVAL_NSEC_MAX)) { /* 时间格式错误 */ _ErrorHandle(EINVAL); return (PX_ERROR); } ulTick = __timespecToTick((struct timespec *)rqtp); if (!ulTick) { /* 不到一个 tick */ __timePassSpec(rqtp); /* 平静度过 */ if (rmtp) { rmtp->tv_sec = 0; /* 不存在时间差别 */ rmtp->tv_nsec = 0; } return (ERROR_NONE); } __timeGetHighResolution(&tvStart); /* 记录开始的时间 */ __THREAD_CANCEL_POINT(); /* 测试取消点 */ LW_TCB_GET_CUR_SAFE(ptcbCur); /* 当前任务控制块 */ MONITOR_EVT_LONG2(MONITOR_EVENT_ID_THREAD, MONITOR_EVENT_THREAD_SLEEP, ptcbCur->TCB_ulId, ulTick, LW_NULL); __wait_again: iregInterLevel = __KERNEL_ENTER_IRQ(); /* 进入内核 */ ppcb = _GetPcb(ptcbCur); __DEL_FROM_READY_RING(ptcbCur, ppcb); /* 从就绪表中删除 */ ptcbCur->TCB_ulDelay = ulTick; __ADD_TO_WAKEUP_LINE(ptcbCur); /* 加入等待扫描链 */ __KERNEL_TIME_GET_NO_SPINLOCK(ulKernelTime, ULONG); /* 记录系统时间 */ iSchedRet = __KERNEL_EXIT_IRQ(iregInterLevel); /* 调度器解锁 */ if (iSchedRet == LW_SIGNAL_EINTR) { iRetVal = PX_ERROR; /* 被信号激活 */ ulError = EINTR; } else { if (iSchedRet == LW_SIGNAL_RESTART) { /* 信号要求重启等待 */ ulTick = _sigTimeoutRecalc(ulKernelTime, ulTick); /* 重新计算等待时间 */ if (ulTick != 0ul) { goto __wait_again; /* 重新等待剩余的 tick */ } } iRetVal = ERROR_NONE; /* 自然唤醒 */ ulError = ERROR_NONE; } if (ulError == ERROR_NONE) { /* tick 已经延迟结束 */ __timeGetHighResolution(&tvTemp); __timespecSub(&tvTemp, &tvStart); /* 计算已经延迟的时间 */ if (__timespecLeftTime(&tvTemp, rqtp)) { /* 还有剩余时间需要延迟 */ struct timespec tvNeed = *rqtp; __timespecSub(&tvNeed, &tvTemp); __timePassSpec(&tvNeed); /* 平静度过 */ } if (rmtp) { rmtp->tv_sec = 0; /* 不存在时间差别 */ rmtp->tv_nsec = 0; } } else { /* 信号唤醒 */ if (rmtp) { *rmtp = *rqtp; __timeGetHighResolution(&tvTemp); __timespecSub(&tvTemp, &tvStart); /* 计算已经延迟的时间 */ if (__timespecLeftTime(&tvTemp, rmtp)) { /* 没有延迟够 */ __timespecSub(rmtp, &tvTemp); /* 计算没有延迟够的时间 */ } } } _ErrorHandle(ulError); /* 设置 errno 值 */ return (iRetVal); }
/********************************************************************************************************* ** 函数名称: sigtimedwait ** 功能描述: 等待 sigset 内信号的到来,以串行的方式从信号队列中取出信号进行处理, 信号将不再被执行. ** 输 入 : psigset 指定的信号集 ** psiginfo 获取的信号信息 ** ptv 超时时间 (NULL 表示一直等待) ** 输 出 : ERROR ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API INT sigtimedwait (const sigset_t *psigset, struct siginfo *psiginfo, const struct timespec *ptv) { INTREG iregInterLevel; PLW_CLASS_TCB ptcbCur; REGISTER PLW_CLASS_PCB ppcb; INT iSigNo; PLW_CLASS_SIGCONTEXT psigctx; struct siginfo siginfo; LW_CLASS_SIGWAIT sigwt; ULONG ulTimeout; if (!psigset) { _ErrorHandle(EINVAL); return (PX_ERROR); } if (ptv == LW_NULL) { /* 永久等待 */ ulTimeout = LW_OPTION_WAIT_INFINITE; } else { ulTimeout = __timespecToTick(ptv); } __THREAD_CANCEL_POINT(); /* 测试取消点 */ LW_TCB_GET_CUR_SAFE(ptcbCur); /* 当前任务控制块 */ MONITOR_EVT_D2(MONITOR_EVENT_ID_SIGNAL, MONITOR_EVENT_SIGNAL_SIGWAIT, ptcbCur->TCB_ulId, *psigset, LW_NULL); __KERNEL_ENTER(); /* 进入内核 */ psigctx = _signalGetCtx(ptcbCur); iSigNo = _sigPendGet(psigctx, psigset, &siginfo); /* 检查当前是否有等待的信号 */ if (__issig(iSigNo)) { __KERNEL_EXIT(); /* 退出内核 */ if (psiginfo) { *psiginfo = siginfo; } return (siginfo.si_signo); } if (ulTimeout == LW_OPTION_NOT_WAIT) { /* 不进行等待 */ __KERNEL_EXIT(); /* 退出内核 */ _ErrorHandle(EAGAIN); return (PX_ERROR); } iregInterLevel = KN_INT_DISABLE(); /* 关闭中断 */ ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_SIGNAL; /* 等待信号 */ ptcbCur->TCB_ucWaitTimeout = LW_WAIT_TIME_CLEAR; /* 清空等待时间 */ ppcb = _GetPcb(ptcbCur); __DEL_FROM_READY_RING(ptcbCur, ppcb); /* 从就绪表中删除 */ if (ulTimeout != LW_OPTION_WAIT_INFINITE) { ptcbCur->TCB_ulDelay = ulTimeout; /* 设置超时时间 */ __ADD_TO_WAKEUP_LINE(ptcbCur); /* 加入等待扫描链 */ } else { ptcbCur->TCB_ulDelay = 0ul; } KN_INT_ENABLE(iregInterLevel); /* 打开中断 */ sigwt.SIGWT_sigset = *psigset; psigctx->SIGCTX_sigwait = &sigwt; /* 保存等待信息 */ if (__KERNEL_EXIT()) { /* 是否其他信号激活 */ psigctx->SIGCTX_sigwait = LW_NULL; _ErrorHandle(EINTR); /* SA_RESTART 也退出 */ return (PX_ERROR); } __KERNEL_ENTER(); /* 进入内核 */ if (ptcbCur->TCB_ucWaitTimeout == LW_WAIT_TIME_OUT) { /* 等待超时 */ __KERNEL_EXIT(); /* 退出内核 */ _ErrorHandle(EAGAIN); return (PX_ERROR); } __KERNEL_EXIT(); /* 退出内核 */ psigctx->SIGCTX_sigwait = LW_NULL; if (psiginfo) { *psiginfo = sigwt.SIGWT_siginfo; } return (sigwt.SIGWT_siginfo.si_signo); }
/********************************************************************************************************* ** 函数名称: pthread_rwlock_wrlock ** 功能描述: 等待一个读写锁可写 (带有超时的阻塞). ** 输 入 : prwlock 句柄 ** abs_timeout 绝对超时时间 ** 输 出 : ERROR CODE ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API int pthread_rwlock_timedwrlock (pthread_rwlock_t *prwlock, const struct timespec *abs_timeout) { ULONG ulTimeout; ULONG ulOrgKernelTime; ULONG ulError = ERROR_NONE; struct timespec tvNow; struct timespec tvWait = {0, 0}; if (prwlock == LW_NULL) { errno = EINVAL; return (EINVAL); } if ((abs_timeout == LW_NULL) || (abs_timeout->tv_nsec < 0) || (abs_timeout->tv_nsec >= __TIMEVAL_NSEC_MAX)) { errno = EINVAL; return (EINVAL); } __pthread_rwlock_init_invisible(prwlock); lib_clock_gettime(CLOCK_REALTIME, &tvNow); /* 获得当前系统时间 */ if (__timespecLeftTime(&tvNow, abs_timeout)) { tvWait = *abs_timeout; __timespecSub(&tvWait, &tvNow); /* 计算与当前等待的时间间隔 */ } /* * 注意: 当 tvWait 超过ulong tick范围时, 将自然产生溢出, 导致超时时间不准确. */ ulTimeout = __timespecToTick(&tvWait); /* 变换为 tick */ __PX_RWLOCK_LOCK(prwlock); /* 锁定读写锁 */ prwlock->PRWLOCK_uiWPendCounter++; /* 等待写的数量++ */ do { __KERNEL_TIME_GET(ulOrgKernelTime, ULONG); /* 记录系统时间 */ if (prwlock->PRWLOCK_uiOpCounter == 0) { /* * 没有正在操作的线程 */ prwlock->PRWLOCK_uiOpCounter++; /* 正在操作的线程++ */ prwlock->PRWLOCK_uiWPendCounter--; /* 退出等待状态 */ prwlock->PRWLOCK_uiStatus = __PX_RWLOCK_STATUS_WRITING; /* 转换为写模式 */ break; } else { /* * 如果有等待写入的线程或者存在正在读取的线程. */ __PX_RWLOCK_UNLOCK(prwlock); /* 解锁读写锁 */ ulError = API_SemaphoreCPend(prwlock->PRWLOCK_ulWSemaphore, ulTimeout); /* 等待读写锁状态变换 */ __PX_RWLOCK_LOCK(prwlock); /* 锁定读写锁 */ if (ulError) { break; /* 直接跳出 */ } } ulTimeout = _sigTimeoutRecalc(ulOrgKernelTime, ulTimeout); /* 重新计算等待时间 */ } while (1); if (ulError == ERROR_NONE) { prwlock->PRWLOCK_ulOwner = API_ThreadIdSelf(); /* 读写锁拥有者 */ } __PX_RWLOCK_UNLOCK(prwlock); /* 解锁读写锁 */ if (ulError == ERROR_THREAD_WAIT_TIMEOUT) { ulError = ETIMEDOUT; errno = ETIMEDOUT; } return ((INT)ulError); }
/********************************************************************************************************* ** 函数名称: pthread_rwlock_timedrdlock ** 功能描述: 等待一个读写锁可读 (带有超时的阻塞). ** 输 入 : prwlock 句柄 ** abs_timeout 绝对超时时间 ** 输 出 : ERROR CODE ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API int pthread_rwlock_timedrdlock (pthread_rwlock_t *prwlock, const struct timespec *abs_timeout) { ULONG ulTimeout; ULONG ulOrgKernelTime; ULONG ulError = ERROR_NONE; struct timespec tvNow; struct timespec tvWait = {0, 0}; if (prwlock == LW_NULL) { errno = EINVAL; return (EINVAL); } if ((abs_timeout == LW_NULL) || (abs_timeout->tv_nsec < 0) || (abs_timeout->tv_nsec >= __TIMEVAL_NSEC_MAX)) { errno = EINVAL; return (EINVAL); } __pthread_rwlock_init_invisible(prwlock); lib_clock_gettime(CLOCK_REALTIME, &tvNow); /* 获得当前系统时间 */ if (__timespecLeftTime(&tvNow, abs_timeout)) { tvWait = *abs_timeout; __timespecSub(&tvWait, &tvNow); /* 计算与当前等待的时间间隔 */ } /* * 注意: 当 tvWait 超过ulong tick范围时, 将自然产生溢出, 导致超时时间不准确. */ ulTimeout = __timespecToTick(&tvWait); /* 变换为 tick */ __PX_RWLOCK_LOCK(prwlock); /* 锁定读写锁 */ prwlock->PRWLOCK_uiRPendCounter++; /* 等待读的数量++ */ do { __KERNEL_TIME_GET(ulOrgKernelTime, ULONG); /* 记录系统时间 */ if ((prwlock->PRWLOCK_uiStatus == __PX_RWLOCK_STATUS_READING) && (prwlock->PRWLOCK_uiWPendCounter == 0)) { /* * 如果写入器未持有读锁, 并且没有任何写入器基于改锁阻塞. 则调用线程立即获取读锁. */ prwlock->PRWLOCK_uiOpCounter++; /* 正在操作数量++ */ prwlock->PRWLOCK_uiRPendCounter--; /* 退出等待模式 */ break; /* 直接跳出 */ } else { /* * 如果写入器正在操作或者, 或者有多个写入器正在等待该锁, 将阻塞. */ __PX_RWLOCK_UNLOCK(prwlock); /* 解锁读写锁 */ ulError = API_SemaphoreCPend(prwlock->PRWLOCK_ulRSemaphore, ulTimeout); /* 等待读写锁状态变换 */ __PX_RWLOCK_LOCK(prwlock); /* 锁定读写锁 */ if (ulError) { break; /* 直接跳出 */ } } ulTimeout = _sigTimeoutRecalc(ulOrgKernelTime, ulTimeout); /* 重新计算等待时间 */ } while (1); __PX_RWLOCK_UNLOCK(prwlock); /* 解锁读写锁 */ if (ulError == ERROR_THREAD_WAIT_TIMEOUT) { ulError = ETIMEDOUT; errno = ETIMEDOUT; } return ((INT)ulError); }
/********************************************************************************************************* ** 函数名称: aio_suspend ** 功能描述: 等待指定的一个或多个异步 I/O 请求操作完成 ** 输 入 : list aio 请求控制块数组 (如果其中有 NULL, 程序将忽略) ** nent 数组元素个数 ** timeout 超时时间 ** 输 出 : ERROR or OK ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API int aio_suspend (const struct aiocb * const list[], int nent, const struct timespec *timeout) { AIO_WAIT_CHAIN *paiowc; struct aiowait *paiowait; ULONG ulTimeout; BOOL bNeedWait = LW_FALSE; int iWait = 0; /* paiowait 下标 */ int iCnt; /* list 下标 */ int iRet = ERROR_NONE; #ifdef __SYLIXOS_KERNEL if (__PROC_GET_PID_CUR() != 0) { /* 需要使用外部库提供的 aio */ errno = ENOSYS; return (PX_ERROR); } #endif /* __SYLIXOS_KERNEL */ __THREAD_CANCEL_POINT(); /* 测试取消点 */ if ((nent <= 0) || (list == LW_NULL)) { errno = EINVAL; return (PX_ERROR); } if (timeout == LW_NULL) { /* 永久等待 */ ulTimeout = LW_OPTION_WAIT_INFINITE; } else { ulTimeout = __timespecToTick(timeout); } paiowc = __aioCreateWaitChain(nent, LW_TRUE); /* 创建等待队列 */ if (paiowc == LW_NULL) { errno = ENOMEM; /* should be EAGAIN ? */ return (PX_ERROR); } paiowait = paiowc->aiowc_paiowait; API_SemaphoreMPend(_G_aioqueue.aioq_mutex, LW_OPTION_WAIT_INFINITE); for (iCnt = 0; iCnt < nent; iCnt++) { if (list[iCnt]) { if (list[iCnt]->aio_req.aioreq_error == EINPROGRESS) { /* 必须为正在处理状态 */ paiowait[iWait].aiowt_pcond = &paiowc->aiowc_cond; paiowait[iWait].aiowt_pcnt = LW_NULL; paiowait[iWait].aiowt_psigevent = LW_NULL; paiowait[iWait].aiowt_paiowc = LW_NULL; /* 不需要代理线程释放 */ iRet = __aioAttachWait(list[iCnt], &paiowait[iWait]); if (iRet != ERROR_NONE) { errno = EINVAL; break; } _List_Line_Add_Tail(&paiowait[iWait].aiowt_line, &paiowc->aiowc_pline); /* 加入 wait 链表 */ iWait++; bNeedWait = LW_TRUE; /* 有 wait 链表节点连接, */ } else { break; } } } if (iRet != ERROR_NONE) { /* __aioAttachWait 失败 */ __aioDeleteWaitChain(paiowc); API_SemaphoreMPost(_G_aioqueue.aioq_mutex); errno = EINVAL; return (PX_ERROR); } if ((iCnt == nent) && bNeedWait) { /* 是否需要等待 */ API_ThreadCleanupPush(__aioWaitCleanup, paiowc); iRet = (INT)API_ThreadCondWait(&paiowc->aiowc_cond, _G_aioqueue.aioq_mutex, ulTimeout); API_ThreadCleanupPop(LW_FALSE); /* 这里已经锁定 _G_aioqueue */ /* 不能运行 __aioWaitCleanup */ __aioDeleteWaitChain(paiowc); if (iRet != ERROR_NONE) { API_SemaphoreMPost(_G_aioqueue.aioq_mutex); errno = EAGAIN; return (PX_ERROR); } } else { /* 不需要等待 */ __aioDeleteWaitChain(paiowc); } API_SemaphoreMPost(_G_aioqueue.aioq_mutex); return (iRet); }