1분간 loop를 돌며 돌때마다 20ms씩 nanosleep를 주어 카운트를 세어 보았는데..

lee3390의 이미지

1분간 loop를 돌며 돌때마다 20ms씩 nanosleep를 주어 카운트를 세어 보았는데..

3000번을 돌아가 정상일텐데

실제로는 2500회 정도 뿐이 돌지를 않습니다.

레드헷 엔터프라이즈 4 update 4에

제온 2.8G 램 1기가인 IBM서버 장비인데.. 왜이렇게 오차가 심하나요?

오차를 줄일 수 있는 방법은 무엇이 있을가요?

    for( ; endTime > curTime ; ) {
        count++;
        if ( nanosleep(&sleepTime, NULL) < 0 ) {
            printf("%s\n",strerror(errno));
        }
        time(&curTime);
    }
bushi의 이미지

RTOS 가 아니거든요.

/dev/rtc 를 1024Hz 로 설정하시고 rtc periodic interrupt 를 이용하시면 오차는 확실히 줄어듭니다. 1024Hz 외에 다른 주파수로도 설정이 가능하긴 한데, 얼마 이상부턴 root 권한으로만 변경할 수 있습니다.
여러가지로 실험을 해봤는데 1024Hz 가 가장 오차가 적었습니다. 10ms 정도 해상도에서는요.

lee3390의 이미지

흠... nanosleep일 경우에 2500회 정도 루프를 도는데

select로 sleep를 걸 경우 2800회 정도 나오는군요..

select가 오차가 많이 적네요.. 휴...

bushi의 이미지

RTC periodic interrupt 사용은 그냥 저절로 되는게 아닙니다.

기본개념은..
ioctl(rtc_fp, RTC_PIE_ON);
으로 RTC_PI 를 활성화시키고,

read(rtc_fp, &tmp, sizeof(tmp);
으로 대기하면 1초에 1024번에 가깝게 깨어납니다.

누적오차를 줄이기 위한 트릭은 별도로 구현해야지요.

예전에 만든... pxa27x 의 OS timer 를 시뮬레이션하기 위한 코드 중의 일부입니다.

static void OSCR_proc(void *arg)
{
    timer_ctx_t *ctx = (timer_ctx_t*)arg;
    unsigned long tmp;
 
//  printf("OSCR thread started\n");
 
    while (read(ctx->rtc_fp, &tmp, sizeof(tmp)) >= 0) {
        ctx->OSCR++;
        if ((!ctx->in_interrupt) && (ctx->OSCR == ctx->OSMR)) {
            pthread_cond_signal(&tick_cond);
        }
    }
    if (!ctx->stop_all) perror("");
}
 
static void tick_proc(void *arg)
{
    timer_ctx_t *ctx = (timer_ctx_t *)arg;
    signed TEST_UNIT next_match;
 
//  printf("tick thread started\n");
 
    while (!ctx->stop_all) {
        ctx->in_interrupt = 0;
        pthread_cond_wait(&tick_cond, &tick_mutex);
        ctx->in_interrupt = 1;
        do {
            next_match = (ctx->OSMR += LIBK_LATCH);
            jiffies++;
            check_timer_task(ctx);
        } while ((signed TEST_UNIT)(next_match - ctx->OSCR) <= 8);
    }
}