Beispiel #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);
    }
}
Beispiel #2
0
/*********************************************************************************************************
** 函数名称: __timePassSpec
** 功能描述: 平静等待指定的短时间
** 输 入  : ptv       短时间
** 全局变量: NONE
** 调用模块: 
*********************************************************************************************************/
static VOID  __timePassSpec (const struct timespec  *ptv)
{
#if LW_CFG_TIME_HIGH_RESOLUTION_EN > 0
    struct timespec  tvEnd, tvNow;
    
    __timeGetHighResolution(&tvEnd);
    __timespecAdd(&tvEnd, ptv);
    do {
        __timeGetHighResolution(&tvNow);
    } while (__timespecLeftTime(&tvNow, &tvEnd));
#else
    bspDelayNs((ULONG)lNsec);                                           /*  使用 BSP 断延迟函数         */
#endif                                                                  /*  LW_CFG_TIME_HIGH_RESOLUT... */
}
Beispiel #3
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);
    }
}
Beispiel #4
0
/*********************************************************************************************************
** 函数名称: 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);
}
/*********************************************************************************************************
** 函数名称: 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);
}