Esempio n. 1
0
/*********************************************************************************************************
** 函数名称: 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);
    }
}
Esempio n. 2
0
/*********************************************************************************************************
** 函数名称: 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);
    }
}
Esempio n. 3
0
/*********************************************************************************************************
** 函数名称: __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);                                                 /*  错误返回                    */
}
Esempio n. 4
0
/*********************************************************************************************************
** 函数名称: 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);
}
Esempio n. 5
0
/*********************************************************************************************************
** 函数名称: 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);
}