/********************************************************************************************************* ** 函数名称: API_TimeSleepUntil ** 功能描述: 线程睡眠直到一个指定的时间 (与当前时钟差值不得超过 ULONG_MAX 个 tick) ** 输 入 : clockid 时钟类型 CLOCK_REALTIME or CLOCK_MONOTONIC ** tv 指定的时间 ** bSigRet 是否允许信号唤醒 ** 输 出 : ERROR_NONE or EINTR ** 全局变量: ** 调用模块: API 函数 (不得在中断中调用) *********************************************************************************************************/ LW_API ULONG API_TimeSleepUntil (clockid_t clockid, const struct timespec *tv, BOOL bSigRet) { struct timespec tvNow; struct timespec tvTemp; if ((clockid != CLOCK_REALTIME) && (clockid != CLOCK_REALTIME)) { _ErrorHandle(EINVAL); return (EINVAL); } lib_clock_gettime(clockid, &tvNow); if (!__timespecLeftTime(&tvNow, tv)) { return (ERROR_NONE); } tvTemp = *tv; __timespecSub(&tvTemp, &tvNow); if (nanosleep(&tvTemp, LW_NULL)) { return (API_GetLastError()); } else { return (ERROR_NONE); } }
/********************************************************************************************************* ** 函数名称: 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); } }
/********************************************************************************************************* ** 函数名称: __ataWait ** 功能描述: 等待ATA设备准备好 ** 输 入 : patactrler ATA控制器结构指针 ** iRequest 等待状态 ** 输 出 : ERROR ** 全局变量: ** 调用模块: *********************************************************************************************************/ INT __ataWait (__PATA_CTRL patactrler, INT iRequest) { __PATA_CTRL patactrl = LW_NULL; struct timespec tvOld; struct timespec tvNow; volatile INT i; if (!patactrler) { _DebugHandle(__ERRORMESSAGE_LEVEL, "parameter error.\r\n"); _ErrorHandle(EINVAL); return (PX_ERROR); } patactrl = patactrler; lib_clock_gettime(CLOCK_MONOTONIC, &tvOld); switch (iRequest) { case __ATA_STAT_READY: for (i = 0; i < __ATA_TIMEOUT_LOOP; i++) { if ((__ATA_CTRL_INBYTE(patactrl, __ATA_ASTATUS(patactrl)) & __ATA_STAT_BUSY) == 0) { /* 等待设备不忙 */ break; } lib_clock_gettime(CLOCK_MONOTONIC, &tvNow); if ((tvNow.tv_sec - tvOld.tv_sec) >= __ATA_TIMEOUT_SEC) { /* 超时退出 */ break; } } for (i = 0; i < __ATA_TIMEOUT_LOOP; i++) { if (__ATA_CTRL_INBYTE(patactrl, __ATA_ASTATUS(patactrl)) & __ATA_STAT_READY) { /* 设备准备好 */ return (0); } lib_clock_gettime(CLOCK_MONOTONIC, &tvNow); if ((tvNow.tv_sec - tvOld.tv_sec) >= __ATA_TIMEOUT_SEC) { /* 超时退出 */ break; } } break; case __ATA_STAT_BUSY: for (i = 0; i < __ATA_TIMEOUT_LOOP; i++) { if ((__ATA_CTRL_INBYTE(patactrl, __ATA_ASTATUS(patactrl)) & __ATA_STAT_BUSY) == 0) { /* 等待设备不忙 */ return (ERROR_NONE); } lib_clock_gettime(CLOCK_MONOTONIC, &tvNow); if ((tvNow.tv_sec - tvOld.tv_sec) >= __ATA_TIMEOUT_SEC) { /* 超时退出 */ break; } } break; case __ATA_STAT_DRQ: for (i = 0; i < __ATA_TIMEOUT_LOOP; i++) { if (__ATA_CTRL_INBYTE(patactrl, __ATA_ASTATUS(patactrl)) & __ATA_STAT_DRQ) { /* 设备准备好传输数据 */ return (ERROR_NONE); } lib_clock_gettime(CLOCK_MONOTONIC, &tvNow); if ((tvNow.tv_sec - tvOld.tv_sec) >= __ATA_TIMEOUT_SEC) { /* 超时退出 */ break; } } break; case __ATA_STAT_SEEKCMPLT: for (i = 0; i < __ATA_TIMEOUT_LOOP; i++) { if (__ATA_CTRL_INBYTE(patactrl, __ATA_ASTATUS(patactrl)) & __ATA_STAT_SEEKCMPLT) { /* 设备就绪 */ return (ERROR_NONE); } lib_clock_gettime(CLOCK_MONOTONIC, &tvNow); if ((tvNow.tv_sec - tvOld.tv_sec) >= __ATA_TIMEOUT_SEC) { /* 超时退出 */ break; } } break; case __ATA_STAT_IDLE: for (i = 0; i < __ATA_TIMEOUT_LOOP; i++) { if ((__ATA_CTRL_INBYTE(patactrl, __ATA_ASTATUS(patactrl)) & \ (__ATA_STAT_BUSY | __ATA_STAT_DRQ)) == 0) { /* 设备空闲 */ return (ERROR_NONE); } lib_clock_gettime(CLOCK_MONOTONIC, &tvNow); if ((tvNow.tv_sec - tvOld.tv_sec) >= __ATA_TIMEOUT_SEC) { /* 超时退出 */ break; } } break; default: break; } return (PX_ERROR); /* 错误返回 */ }
/********************************************************************************************************* ** 函数名称: 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); }