get_ftrace.sh-56521 [001] d.h1. 72.893553: irq_handler_entry: irq=11 name=arch_timer
get_ftrace.sh-56521 [001] d.h1. 72.893563: tick_do_update_jiffies64+0x4/0x150 <-tick_sched_do_timer+0xb0/0xb8
get_ftrace.sh-56521 [001] d.h1. 5972.893568: <stack trace>
=> tick_do_update_jiffies64+0x8/0x150 // 지피스 값이 업데이트된다
=> tick_sched_do_timer+0xb0/0xb8
=> tick_sched_timer+0x50/0xb8
=> __hrtimer_run_queues+0x114/0x350
=> hrtimer_interrupt+0xfc/0x258
=> arch_timer_handler_phys+0x38/0x48
=> handle_percpu_devid_irq+0xa8/0x240
=> generic_handle_domain_irq+0x34/0x50
=> gic_handle_irq+0xa0/0xd8
=> call_on_irq_stack+0x2c/0x54
=> do_interrupt_handler+0xe0/0xf8
=> el1_interrupt+0x38/0x70
=> el1h_64_irq_handler+0x18/0x28
=> el1h_64_irq+0x64/0x68
=> folio_add_lru+0xc4/0xf8
=> folio_add_lru_vma+0x30/0x48
=> lru_cache_add_inactive_or_unevictable+0x28/0x38
=> wp_page_copy+0x248/0x840
<idle>-0 [002] d.h1 316.919529: irq_handler_entry: irq=12 name=arch_timer
<idle>-0 [002] d.h2 316.919533: do_timer+0x4/0x38 // <-지피스 업데이트tick_do_update_jiffies64.part.17+0x80/0x120
<idle>-0 [002] d.h2 316.919536: <stack trace>
=> do_timer+0x8/0x38
=> tick_do_update_jiffies64.part.17+0x80/0x120
=> tick_sched_do_timer+0x84/0x88
=> tick_sched_timer+0x50/0xb8
=> __hrtimer_run_queues+0x11c/0x470
=> hrtimer_interrupt+0xfc/0x258
=> arch_timer_handler_phys+0x38/0x48
=> handle_percpu_devid_irq+0xa8/0x2a0
=> generic_handle_irq+0x38/0x50
=> __handle_domain_irq+0x9c/0x110
=> gic_handle_irq+0xb0/0xf0
=> el1_irq+0xc8/0x180
=> arch_cpu_idle+0x18/0x28
=> default_idle_call+0x58/0x1d4
=> do_idle+0x25c/0x270
=> cpu_startup_entry+0x30/0x70
=> secondary_start_kernel+0x170/0x180
https://elixir.bootlin.com/linux/v5.15/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; // 실행시간의 흐름을 관리하는 변수
...
/* check condition up to 250 ms */
end_time = jiffies + msecs_to_jiffies(250); // 지피스 : 엔드타임 시점, 50코드 시점과 지피스값이 다를 수 있다. 250 밀리초를 지피스 단위로 바꾸는 커널 api
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);
}
...
}
void kdt_driver_init(void)
{
unsigned long timeout = jiffies + 250;
...
while (SMC_GET_MMU_CMD(lp) & MC_BUSY) {
SMC_SET_INT_MASK(lp);
if (jiffies > timeout)
break;
}
void kdt_driver_init(void)
{
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
...
while (SMC_GET_MMU_CMD(lp) & MC_BUSY) {
SMC_SET_INT_MASK(lp);
if (jiffies > timeout) // 타임아웃보다 크면 벗어남
break;
}
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);
}
}
static int rtsx_pci_probe(struct pci_dev *pcidev,
const struct pci_device_id *id)
{
struct rtsx_pcr *pcr;
struct pcr_handle *handle;
...
schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200)); // 20미리초 이후의 워크를 딜레이해서 실행되도록 하는 아규먼트
...
}
static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
unsigned long irq_flags) // 프로브 : 부팅할때 디바이스 드라이버를 초기화할때 생성된다.
{
struct smc_local *lp = netdev_priv(dev);
int retval;
...
dev->watchdog_timeo = msecs_to_jiffies(watchdog); // 밀리초 단위의 정보
dev->netdev_ops = &smc_netdev_ops;
dev->ethtool_ops = &smc_ethtool_ops;
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)((b) - (a)) < 0))
#define time_before(a,b) time_after(b,a)
https://elixir.bootlin.com/linux/v5.15/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;
...
/* 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);
}
...
}
static void wq_watchdog_timer_fn(struct timer_list *unused)
{
unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
bool lockup_detected = false;
...
/* did we stall? */
if (time_after(now, ts + thresh)) {
lockup_detected = true;
pr_emerg("BUG: workqueue lockup - pool");
pr_cont_pool_info(pool);
pr_cont(" stuck for %us!\n",
jiffies_to_msecs(now - pool_ts) / 1000);
}
}
...
}
time_before() 함수의 사용 예시
https://elixir.bootlin.com/linux/v5.15.30/source/drivers/scsi/elx/libefc_sli/sli4.c
static bool
sli_wait_for_fw_ready(struct sli4 *sli4, u32 timeout_ms)
{
unsigned long end;
end = jiffies + msecs_to_jiffies(timeout_ms); // 밀리초 단위의 타임아웃 정보
do {
if (sli_fw_ready(sli4))
return true;
usleep_range(1000, 2000);
} while (time_before(jiffies, end)); // do while이 250밀리초 이상인 경우 빠져나옴 , 실행시간의 흐름을 체크하는 루틴
return false;
}
https://elixir.bootlin.com/linux/v5.15.30/source/sound/soc/mediatek/common/mtk-btcvsd.c
static int wait_for_bt_irq(struct mtk_btcvsd_snd *bt,
struct mtk_btcvsd_snd_stream *bt_stream)
{
unsigned long long t1, t2;
...
while (max_timeout_trial && !bt_stream->wait_flag) {
t1 = sched_clock(); // 시간 정보
if (bt_stream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = wait_event_interruptible_timeout(bt->tx_wait,
bt_stream->wait_flag,
nsecs_to_jiffies(timeout_limit));
...
}
t2 = sched_clock(); // 시간정보2
t2 = t2 - t1; /* in ns (10^9) */ // 시간정보를 뺀다
if (t2 > timeout_limit) { // 초과시 에러로그
dev_warn(bt->dev, "%s(), stream %d, timeout %llu, limit %llu, ret %d, flag %d\n",…
}