2011. 10. 17. 21:08
현재시각(wall time) OS이야기2011. 10. 17. 21:08
현재시각 wall time은 kernel/timer.c에서 다음과 같이 정의되어있다.
struct timespec xtime;
timespec 자료구조는 <linux/time.h> 에서 다음과 같이 정의되어있다.
struct timespec{
time_t tv_sec;
long tv_nsec;
}
xtime.tv_sec값에는 1970.1.1 이후부터 지금까지의 시간이 초 단위로 저장된다. 이날짜를 에포크라고 부른다. 대부분의 유닉스시스템에서의 현재 시각은 바로 이 에포크를 기준으로 한 상대적인 날짜를 의미한다. xtime.v_nsec 값은 마지막 초 이후에 경과된 나노초값을 나타낸다.
xtime 변수를 사용하렴녀 xtime_lock 락을 얻어야 하는데, 이것은 일반적인 스핀락이 아닌 seq락으로 구현되어있다.
- xtime을 갱신하려면 write_seqlock()을 사용한다.
write_seqlock(&xtime_lock);
/* xtime을 실행한다 */
write_sequnlock(&xtime_lock)
xtime을 읽기 위해서는 다음과 같이 read_seqbegin()과 read_seqretry() 함수를 사용한다.
do_gettimeofday 함수
do
{
struct timespec xtime;
timespec 자료구조는 <linux/time.h> 에서 다음과 같이 정의되어있다.
struct timespec{
time_t tv_sec;
long tv_nsec;
}
xtime.tv_sec값에는 1970.1.1 이후부터 지금까지의 시간이 초 단위로 저장된다. 이날짜를 에포크라고 부른다. 대부분의 유닉스시스템에서의 현재 시각은 바로 이 에포크를 기준으로 한 상대적인 날짜를 의미한다. xtime.v_nsec 값은 마지막 초 이후에 경과된 나노초값을 나타낸다.
xtime 변수를 사용하렴녀 xtime_lock 락을 얻어야 하는데, 이것은 일반적인 스핀락이 아닌 seq락으로 구현되어있다.
- xtime을 갱신하려면 write_seqlock()을 사용한다.
write_seqlock(&xtime_lock);
/* xtime을 실행한다 */
write_sequnlock(&xtime_lock)
xtime을 읽기 위해서는 다음과 같이 read_seqbegin()과 read_seqretry() 함수를 사용한다.
do_gettimeofday 함수
do
{
unsigned long lost;
seq = read_seqbegin(&xtime_lock);
usec = timer->get_offset();
lost = jiffies - wall_jiffies;
if(lost)
usec += lost * (1000000 / HZ);
sec = xtime.tv_sec;
usec += (xtime.tv_nsec / 1000);
seq = read_seqbegin(&xtime_lock);
usec = timer->get_offset();
lost = jiffies - wall_jiffies;
if(lost)
usec += lost * (1000000 / HZ);
sec = xtime.tv_sec;
usec += (xtime.tv_nsec / 1000);
}while(read_seqretry(&xtime_lock, seq));
이 루프는 라이터가 없는 상태에서 리더가 데이터를 읽을 때까지 반복한다. 만약 루프가 진행되는 동안 타이머 인터럽트가 발생하여 xtime이 갱신된다면, 리턴되는 시퀀스 번호가 유효하지 않게 되므로 루프는 계속 반복된다.
유저공간에서 현재시각을 알아내기 위한 인터페이스는 gettimeofday()이며, 이는 sys_gettimeofday()로 구현되어 있다.
asmlinkage long sys_gettimeofday(struct timeval *tv, struct timezone *tz)
{
이 루프는 라이터가 없는 상태에서 리더가 데이터를 읽을 때까지 반복한다. 만약 루프가 진행되는 동안 타이머 인터럽트가 발생하여 xtime이 갱신된다면, 리턴되는 시퀀스 번호가 유효하지 않게 되므로 루프는 계속 반복된다.
유저공간에서 현재시각을 알아내기 위한 인터페이스는 gettimeofday()이며, 이는 sys_gettimeofday()로 구현되어 있다.
asmlinkage long sys_gettimeofday(struct timeval *tv, struct timezone *tz)
{
if(likely(tv))
{
struct timeval ktv;
do_gettimeofday(&ktv);
if(copy_to_user(tv, &ktv, sizeof(ktv))
return -EFAULT;
}
if(unlikely(tz))
{
{
struct timeval ktv;
do_gettimeofday(&ktv);
if(copy_to_user(tv, &ktv, sizeof(ktv))
return -EFAULT;
}
if(unlikely(tz))
{
if(copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
return -EFAULT;
}
return 0;
return 0;
}
이 함수에서 tv에 NULL아닌 값이 주어질 경우에는 아키텍쳐 종속적인 do_gettimeofday()를 호출하는데, 이 함수는 앞서 설명한 xtime 읽기 루프를 실행한다. 이와 유사하에 만약 tz에 NULL아닌 값이 주어진다면 유저에게 시스템 타임 존을 리턴한다.
만약 현재 시각을 복사하거나 시간존을 유저에게 리턴하는 과정에서 오류가 있는 경우 이 함수는 -EFAULT를 리턴한다. 그렇지 안핟면 성공을 의미하는 0을 리턴한다.
이 함수에서 tv에 NULL아닌 값이 주어질 경우에는 아키텍쳐 종속적인 do_gettimeofday()를 호출하는데, 이 함수는 앞서 설명한 xtime 읽기 루프를 실행한다. 이와 유사하에 만약 tz에 NULL아닌 값이 주어진다면 유저에게 시스템 타임 존을 리턴한다.
만약 현재 시각을 복사하거나 시간존을 유저에게 리턴하는 과정에서 오류가 있는 경우 이 함수는 -EFAULT를 리턴한다. 그렇지 안핟면 성공을 의미하는 0을 리턴한다.
'OS이야기' 카테고리의 다른 글
실행지연 (0) | 2011.10.17 |
---|---|
타이머 (0) | 2011.10.17 |
jiffies wraparound (0) | 2011.10.17 |
지피 - jiffy (0) | 2011.10.17 |
어떤 Bottom Half를 사용해야 하는가? (0) | 2011.10.16 |