23.11.28 최초 작성
24.01.23 struct timer_list 추가
Hz
만큼 증가함 (Armv8
: 기본 250Hz)jiffeis
자료형에 값이 저장되며 jiffeis_64
의 시작주소 ~ 4byte공간에 위치함ex)
// /source/sound/isa/wss/wss_lib.c
void snd_wss_mce_down(struct snd_wss *chip)
{
unsigned long flags;
unsigned long end_time;
int timeout;
int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
snd_wss_busy_wait(chip);
...
/* check condition up to 250 ms */
end_time = jiffies + msecs_to_jiffies(250);
while (snd_wss_in(chip, CS4231_TEST_INIT) &
CS4231_CALIB_IN_PROGRESS) {
if (time_after(jiffies, end_time)) {
snd_printk(KERN_ERR "mce_down - "
"auto calibration time out (2)\n");
return;
}
msleep(1);
}
...
}
msecs_to_jiffies
인자로 받은 값(msec)을 jiffies
단위 시간 정보로 변환해 줌// /source/include/linux/jiffies.h
static __always_inline unsigned long msecs_to_jiffies(const unsigned int m)
{
if (__builtin_constant_p(m)) {
if ((int)m < 0)
return MAX_JIFFY_OFFSET;
return _msecs_to_jiffies(m);
} else {
return __msecs_to_jiffies(m);
}
}
time_after(a,b)
: a > b 이면 true, 아니면 falsetime_before(a,b)
: a > b 이면 false, 아니면 truesched_clock()
: 해당 코드가 실행할 때의 시간정보 반환 (unsigned long long
)jiffies
)기준으로 특정 시간 이후 만료될 타이머struct timer_list
: 커널 타이머를 관리하는 구조체// include/linux/timer.h
struct timer_list {
struct hlist_node entry; //timer_bases전역변수에 타이머를 등록할때 사용
unsigned long expires; //만료시각 저장 (jiffies)
void (*function)(struct timer_list *); //동적 타이머 핸들러의 주소 저장
u32 flags;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
struct timer_bases
: 전체 동적 타이머를 관리// kernel/time/timer.c
static DEFINE_PER_CPU(struct timer_base, timer_bases[NR_BASES]);
static __latent_entropy void run_timer_softirq(struct softirq_action *h)
{
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
__run_timers(base);
if (IS_ENABLED(CONFIG_NO_HZ_COMMON))
__run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]));
}
struct timer_base
: struct timer_base {
raw_spinlock_t lock;
struct timer_list *running_timer; //현재 타이머 핸들러를 실행중인 동적 타이머 자료구조(만료됨)
#ifdef CONFIG_PREEMPT_RT
spinlock_t expiry_lock;
atomic_t timer_waiters;
#endif
unsigned long clk;
unsigned long next_expiry;
unsigned int cpu; //현재 타이머 벡터 cpu id
bool next_expiry_recalc; //다음에 만료될 시각 저장
bool is_idle;
bool timers_pending;
DECLARE_BITMAP(pending_map, WHEEL_SIZE); //타이머 휠 인덱스마다 1비트 업데이트
struct hlist_head vectors[WHEEL_SIZE]; //타이머 휠 리스트
} ____cacheline_aligned;
/source/include/linux/timer.h
timer_setup()
: 타이머 초기화struct timer_list
: 타이머의 정보를 저장하는 자료구조/source/kernel/time/timer.c
add_timer()
: 타이머 추가mod_timer()
: 타이머 설정run_timer_softirq()
: softirq
를 통해 타이머 스레드 활성화__run_timers()
: 타이머 작동__collect_expired_timers()
: 만료된 타이머 확인call_timer_fn()
: 만료된 타이머의 타이머 핸들러 호출