[커널 18차] 70주차
2022.09.24 22:14
hrtimer 진행
git : https://github.com/iamroot18/5.10/commit/893cf3736b05a7bcf8f63b333e422b47f4976dd8
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index df0121d127d6..575be407c243 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -123,6 +123,14 @@ enum hrtimer_restart {
*/
struct hrtimer {
struct timerqueue_node node;
+
+/*
+ * IAMROOT, 2022.09.24:
+ *
+ * - slack --|---------------|---
+ * ^ ^
+ * _softexpires node.expires
+ */
ktime_t _softexpires;
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index ef6f6a293bca..1bc714c90095 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -326,6 +326,23 @@ SEQCOUNT_LOCKNAME(ww_mutex, struct ww_mutex, true, &s->lock->base, ww_mu
*
* Return: count to be passed to read_seqcount_retry()
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - papago
+ * __read_seqcount_begin() - 장벽 없이 seqcount_t 읽기 섹션을 시작합니다.
+ *
+ * @s: seqcount_t 또는 seqcount_LOCKNAME_t 변형에 대한 포인터입니다.
+ *
+ * __read_seqcount_begin은 read_seqcount_begin과 비슷하지만 smp_rmb() 장벽이
+ * 없습니다. 호출자는 이 중요한 섹션에서 보호할 변수를 실제로 로드하기 전에
+ * smp_rmb() 또는 이에 상응하는 순서가 제공되었는지 확인해야 합니다.
+ *
+ * 중요한 코드에서만 신중하게 사용하고 장벽이 제공되는 방식을 설명합니다.
+ *
+ * return: read_seqcount_retry()에 전달할 카운트.
+ *
+ * - raw_write_seqcount_barrier()과 같이 본다.
+ */
#define __read_seqcount_begin(s) \
({ \
unsigned __seq; \
@@ -622,6 +639,24 @@ static inline void do_write_seqcount_end(seqcount_t *s)
* WRITE_ONCE(X, false);
* }
*/
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - papago
+ * 이것은 일반적인 일관성 보증 대신 주문 보증을 제공하는 데 사용할 수 있습니다.
+ * 두 개의 연속적인 wmb()를 접을 수 있기 때문에 하나의 wmb가 더 저렴합니다.
+ *
+ * 장벽을 둘러싼 쓰기는 원자성으로 선언되어야 합니다(예: WRITE_ONCE를 통해):
+ * a) 컴파일러 최적화를 피하면서 쓰기를 원자적으로 다른 스레드에서 볼 수 있도록
+ * 합니다. b) 어떤 쓰기가 독자의 임계 영역에 전파될 것인지 문서화합니다.
+ * 이는 독자가 진행 중인 쓰기를 인식할 수 있도록 장벽 전후의 쓰기가 모두
+ * seq-writer 임계 섹션에 포함되지 않기 때문에 필요합니다.
+ *
+ * - 빈번한 갱신상황에 다른 core들이 빠르게 인지해야될때
+ * - __read_seqcount_begin(), __read_seqcount_retry()와 같이 본다.
+ *
+ * - write를 한시점에서 모든 core가 sequence를 읽을때 갱신된것을 보장해야 될때.
+ */
#define raw_write_seqcount_barrier(s) \
do_raw_write_seqcount_barrier(seqprop_ptr(s))
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 1019b15947ab..ba19d7aaa26a 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -262,6 +262,10 @@ struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base,
* to the current CPU or leave it on the previously assigned CPU if
* the timer callback is currently running.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - cpu상황에 따라 timer를 다른 cpu의 clock base로 옮긴다.
+ */
static inline struct hrtimer_clock_base *
switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
int pinned)
@@ -564,6 +568,10 @@ __next_base(struct hrtimer_cpu_base *cpu_base, unsigned int *active)
return &cpu_base->clock_base[idx];
}
+/*
+ * IAMROOT, 2022.09.24:
+ * - cpu_base의 active mask의 clock base를 iterate한다.
+ */
#define for_each_active_base(base, cpu_base, active) \
while ((base = __next_base((cpu_base), &(active))))
@@ -776,6 +784,11 @@ static ktime_t hrtimer_update_next_event(struct hrtimer_cpu_base *cpu_base)
return expires_next;
}
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - hard irq offset 을 갱신한다음에 soft irq에도 적용한다.
+ */
static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
{
ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
@@ -805,6 +818,10 @@ static inline int __hrtimer_hres_active(struct hrtimer_cpu_base *cpu_base)
cpu_base->hres_active : 0;
}
+/*
+ * IAMROOT, 2022.09.24:
+ * - this_cpu의 hrtime 동작여부 확인.
+ */
static inline int hrtimer_hres_active(void)
{
return __hrtimer_hres_active(this_cpu_ptr(&hrtimer_bases));
@@ -899,6 +916,10 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
* High resolution timer enabled ?
*/
static bool hrtimer_hres_enabled __read_mostly = true;
+/*
+ * IAMROOT, 2022.09.24:
+ * - hr timer가 동작하는 최소 실행 시간.
+ */
unsigned int hrtimer_resolution __read_mostly = LOW_RES_NSEC;
EXPORT_SYMBOL_GPL(hrtimer_resolution);
@@ -1277,6 +1298,34 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
* Note: This only updates the timer expiry value and does not requeue
* the timer.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - ex) orun = 0 (old time ----------> new time)
+ *
+ * 1. 만료시각이 now보다 뒤에 이미 설정되있다.
+ * vNow vExpire
+ * |-------|
+ *
+ * 2. timer가 enqueued 상태.
+ *
+ * - ex) orun = 1
+ * 1. delta가 interval보다 짧은상태.
+ * <---delta --->
+ * vExpire vNow
+ * |-------------*---|-----------------|
+ * <-interval-------->
+ * ^NewExpire
+ *
+ * - ex) orun = 2
+ *
+ * 1. delta가 interval보다 나중일때
+ * <---delta --------------->
+ * vExpire vNow
+ * |-----------------|-------*---------|
+ * <-interval--------> ^NewExpire
+ *
+ * - next expire 시간을 interval 단위로 갱신한다.
+ */
u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
{
u64 orun = 1;
@@ -1284,20 +1333,67 @@ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
delta = ktime_sub(now, hrtimer_get_expires(timer));
+/*
+ * IAMROOT, 2022.09.24:
+ * - expire시간이 아직 안지낫으면 return.
+ * over_run이 없어서 return 0.
+ */
if (delta < 0)
return 0;
+/*
+ * IAMROOT, 2022.09.24:
+ * - 이미 실행 대기중.
+ */
if (WARN_ON(timer->state & HRTIMER_STATE_ENQUEUED))
return 0;
+/*
+ * IAMROOT, 2022.09.24:
+ * - @internal이 hardware 지원시간보다 낮을경우 보정한다.
+ */
if (interval < hrtimer_resolution)
interval = hrtimer_resolution;
+/*
+ * IAMROOT, 2022.09.24:
+ * - 실행되야될 timer가 internal보다 지낫다면.
+ */
if (unlikely(delta >= interval)) {
s64 incr = ktime_to_ns(interval);
+/*
+ * IAMROOT, 2022.09.24:
+ * - interval 개수 = delta / interval.
+ */
orun = ktime_divns(delta, incr);
+
+/*
+ * IAMROOT, 2022.09.24:
+ * -
+ * 1
+ * <----------- delta -------------------->
+ * vExpire vNow
+ * |-------|-------|-------|-------|-------|
+ * <-incr->
+ * orun = delta / incr = 5
+ *
+ * 2.
+ * <----------- delta -------->
+ * vExpire vNow
+ * |-------|-------|-------|-------|----
+ * <-incr-> <------->
+ * <-incr->
+ * orun = delta / incr = 3.
+ * now보다 전시간이므로 orun을 하나 더 추가.
+ * orun = 3 + 1 = 4
+ *
+ */
hrtimer_add_expires_ns(timer, incr * orun);
+/*
+ * IAMROOT, 2022.09.24:
+ * - 예외처리.
+ */
if (hrtimer_get_expires_tv64(timer) > now)
return orun;
/*
@@ -1501,6 +1597,10 @@ static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
return tim;
}
+/*
+ * IAMROOT, 2022.09.24:
+ * - softirq만 갱신해준다. next timer가 있다면 reprogram
+ */
static void
hrtimer_update_softirq_timer(struct hrtimer_cpu_base *cpu_base, bool reprogram)
{
@@ -2081,6 +2181,11 @@ EXPORT_SYMBOL_GPL(hrtimer_init);
*
* It is important for this function to not return a false negative.
*/
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - @timer가 queue에 있거나 running중인지 확인한다.
+ */
bool hrtimer_active(const struct hrtimer *timer)
{
struct hrtimer_clock_base *base;
@@ -2090,6 +2195,12 @@ bool hrtimer_active(const struct hrtimer *timer)
base = READ_ONCE(timer->base);
seq = raw_read_seqcount_begin(&base->seq);
+/*
+ * IAMROOT, 2022.09.24:
+ * - 탈출조건
+ * 1. timer가 queue에 있다.
+ * 2. running중인 timer가 timer다.
+ */
if (timer->state != HRTIMER_STATE_INACTIVE ||
base->running == timer)
return true;
@@ -2097,6 +2208,10 @@ bool hrtimer_active(const struct hrtimer *timer)
} while (read_seqcount_retry(&base->seq, seq) ||
base != READ_ONCE(timer->base));
+/*
+ * IAMROOT, 2022.09.24:
+ * - timer->state == HRTIMER_STATE_INACTIVE && base->running != timer
+ */
return false;
}
EXPORT_SYMBOL_GPL(hrtimer_active);
@@ -2119,6 +2234,31 @@ EXPORT_SYMBOL_GPL(hrtimer_active);
* __run_hrtimer() invocations.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - papago
+ * __run_hrtimer()의 write_seqcount_barrier()는 사물을 3개의 개별 섹션으로
+ * 나눕니다.
+ *
+ * - queued: the timer is queued
+ * - callback: the timer is being ran
+ * - post: the timer is inactive or (re)queued
+ *
+ * read side측에서 우리는 같은 섹션에서 실행 중인 timer->state 및 cpu_base->state를
+ * 관찰했는지 확인하고, 보는 동안 변경된 사항이 있으면 재시도합니다.
+ * 여기에는 sequence number만으로는 충분하지 않기 때문에 timer->base 변경이
+ * 포함됩니다.
+ *
+ * 그렇지 않으면 read side측이 여러 연속 __run_hrtimer()호출로 번지는 경우
+ * 여전히 false negative를 관찰할수 있기 때문에 sequence number가 필요 합니다.
+ *
+ * - timer를 실행시킨다.
+ * timer를 queue에서 빼와(remove, state = HRTIMER_STATE_INACTIVE)
+ * base->running에 갱신하고, 실행이 끝나면 base->running을 NULL로 다시 갱신한다.
+ * - read side(hrtimer_active()) 측에서 동기화를 위해 barrier seqcount를 사용한다.
+ * (__run_timers()가 많이 호출되는 상황에서, read side가 true가 되야되는
+ * 상황임에도 false가 호출되는 상황이 있을수 있기 때문에)
+ */
static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
struct hrtimer_clock_base *base,
struct hrtimer *timer, ktime_t *now,
@@ -2131,8 +2271,22 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
lockdep_assert_held(&cpu_base->lock);
debug_deactivate(timer);
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - 1.
+ * base->running == NULL
+ * timer->state == HRTIMER_STATE_ENQUEUED
+ */
base->running = timer;
+/*
+ * IAMROOT, 2022.09.24:
+ * - 2.
+ * base->running == timer
+ * timer->state == HRTIMER_STATE_ENQUEUED
+ */
+
/*
* Separate the ->running assignment from the ->state assignment.
*
@@ -2140,8 +2294,27 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
* hrtimer_active() cannot observe base->running == NULL &&
* timer->state == INACTIVE.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - papago
+ * Separate the ->running assignment from the ->state assignment.
+ *
+ * 일반 쓰기 장벽과 마찬가지로 이것은 hrtimer_active()의 읽기 측이
+ * base->running == NULL && timer->state == INACTIVE를 관찰할 수 없도록 합니다.
+ *
+ * - 3. seq홀수 -> smp_wmb -> seq짝수
+ * base->running == timer
+ * timer->state == HRTIMER_STATE_ENQUEUED
+ */
raw_write_seqcount_barrier(&base->seq);
+/*
+ * IAMROOT, 2022.09.24:
+ * - @timer를 실행할 예정이다. 등록되있는 대기열에서 뺀다음에 실행을 준비한다.
+ * - 4.
+ * base->running == timer
+ * timer->state == HRTIMER_STATE_INACTIVE
+ */
__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0);
fn = timer->function;
@@ -2150,6 +2323,13 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
* timer is restarted with a period then it becomes an absolute
* timer. If its not restarted it does not matter.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - papago
+ * TIME_LOW_RES 경우에 대해 '상대적' 플래그를 지웁니다. 타이머가 마침표와 함께
+ * 다시 시작되면 절대 타이머가 됩니다. 다시 시작하지 않으면 문제가 되지
+ * 않습니다.
+ */
if (IS_ENABLED(CONFIG_TIME_LOW_RES))
timer->is_rel = false;
@@ -2162,6 +2342,10 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
trace_hrtimer_expire_entry(timer, now);
expires_in_hardirq = lockdep_hrtimer_enter(timer);
+/*
+ * IAMROOT, 2022.09.24:
+ * - 실행
+ */
restart = fn(timer);
lockdep_hrtimer_exit(expires_in_hardirq);
@@ -2177,6 +2361,11 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
* hrtimer_start_range_ns() can have popped in and enqueued the timer
* for us already.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - @timer가 restart를 해야되는데, 그사이에 다시 queue에 안들어 가있다면
+ * queue에 넣는다.
+ */
if (restart != HRTIMER_NORESTART &&
!(timer->state & HRTIMER_STATE_ENQUEUED))
enqueue_hrtimer(timer, base, HRTIMER_MODE_ABS);
@@ -2188,12 +2377,22 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
* hrtimer_active() cannot observe base->running.timer == NULL &&
* timer->state == INACTIVE.
*/
+
raw_write_seqcount_barrier(&base->seq);
WARN_ON_ONCE(base->running != timer);
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - running이 완료 됬다.
+ */
base->running = NULL;
}
+/*
+ * IAMROOT, 2022.09.24:
+ * - clock base를 iterate하며 slack range에따라 timer를 실행한다.
+ */
static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
unsigned long flags, unsigned int active_mask)
{
@@ -2206,6 +2405,23 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
basenow = ktime_add(now, base->offset);
+/*
+ * IAMROOT, 2022.09.24:
+ * - 가장 빨리 wakeup되야 되는 timer를 가져온다.
+ *
+ *
+ * - ex) timer1, timer2, timer3이 다음과 같은상황
+ * (_softexpires --------------- node.expire)
+ *
+ * vinterrup
+ * timer1 ----------------
+ * timer2 ----------------------
+ * timer3 ---------
+ *
+ * next_expire는 node.expire가 제일빠른 timer1로 선택되고, timer1이 실행될때
+ * timer2, timer3도 같이 실행된다.
+ * (node.expire 순서대로 실행. timer1->timer3->timer2)
+ */
while ((node = timerqueue_getnext(&base->active))) {
struct hrtimer *timer;
@@ -2223,6 +2439,19 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
* are right-of a not yet expired timer, because that
* timer will have to trigger a wakeup anyway.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - papago
+ * softexpire를 사용하는 즉각적인 목표는 소프트 만료 후 가장 빠른 인터럽트에서
+ * 타이머를 실행하지 않고 깨우기를 최소화하는 것입니다.
+ * 이를 통해 겹치는 간격에 대한 찌르는 쿼리에 응답할 수 있는 우선 순위 검색
+ * 트리를 사용하지 않고 대신 이미 가지고 있는 간단한 BST를 사용할 수 있습니다.
+ * 아직 만료되지 않은 타이머의 오른쪽에 있는 타이머를 지연시켜 추가 깨우기를
+ * 추가하지 않습니다. 해당 타이머는 어쨌든 깨우기를 트리거해야 하기 때문입니다.
+ *
+ * - 현재시각이 _softexpires에 도래하지 않았다면, 즉 제일 빠른 timer의 slack
+ * 범위이내로 들어오지 않았다면 그냥 종료.
+ */
if (basenow < hrtimer_get_softexpires_tv64(timer))
break;
@@ -2235,7 +2464,8 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
/*
* IAMROOT, 2022.09.17:
- * - TODO
+ * - this_cpu의 expire된 softirq용 hrtimer를 clock base를 순회하며
+ * _softexpires를 지난 timer들을 전부 실행한다.
*/
static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h)
{
@@ -2243,9 +2473,17 @@ static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h)
unsigned long flags;
ktime_t now;
+/*
+ * IAMROOT, 2022.09.24:
+ * - cpu_base->softirq_expiry_lock, cpu_base->lock 을 lock 건다.
+ */
hrtimer_cpu_base_lock_expiry(cpu_base);
raw_spin_lock_irqsave(&cpu_base->lock, flags);
+/*
+ * IAMROOT, 2022.09.24:
+ * - clock base들의 offset 갱신.
+ */
now = hrtimer_update_base(cpu_base);
__hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_SOFT);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index b348749a9fc6..a55105afa33c 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -45,6 +45,10 @@ DEFINE_RAW_SPINLOCK(timekeeper_lock);
* The most important data for readout fits into a single 64 byte
* cache line.
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - 현새 시각을 관리하기 위한 구조체.
+ */
static struct {
seqcount_raw_spinlock_t seq;
struct timekeeper timekeeper;
@@ -186,6 +190,10 @@ static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
* a read of the fast-timekeeper tkrs (which is protected by its own locking
* and update logic).
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - read 함수를 통해 clocksource의 clock을 알아 온다.
+ */
static inline u64 tk_clock_read(const struct tk_read_base *tkr)
{
struct clocksource *clock = READ_ONCE(tkr->clock);
@@ -279,6 +287,11 @@ static inline u64 timekeeping_get_delta(const struct tk_read_base *tkr)
static inline void timekeeping_check_update(struct timekeeper *tk, u64 offset)
{
}
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - clock delta = now(tk_clock_read) - old(tkr->cycle_last)
+ */
static inline u64 timekeeping_get_delta(const struct tk_read_base *tkr)
{
u64 cycle_now, delta;
@@ -368,7 +381,10 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
}
/* Timekeeper helper functions. */
-
+/*
+ * IAMROOT, 2022.09.24:
+ * - clock을 ns로 변환한다.
+ */
static inline u64 timekeeping_delta_to_ns(const struct tk_read_base *tkr, u64 delta)
{
u64 nsec;
@@ -379,6 +395,12 @@ static inline u64 timekeeping_delta_to_ns(const struct tk_read_base *tkr, u64 de
return nsec;
}
+/*
+ * IAMROOT, 2022.09.24:
+ * - tkr에 저장된 시간을오부터 지나간 시간(ns)를 알아온다.
+ * - delta = now(clock을 callback에서 읽음) - old(tkr에 있는값)
+ * delta를 ns로 변환하여 return.
+ */
static inline u64 timekeeping_get_ns(const struct tk_read_base *tkr)
{
u64 delta;
@@ -2285,6 +2307,11 @@ void do_timer(unsigned long ticks)
*
* Called from hrtimer_interrupt() or retrigger_next_event()
*/
+/*
+ * IAMROOT, 2022.09.24:
+ * - timekeeper로 인자값들을 update해준다.
+ * mono는 항상 offset이 0이기 때문에 할필요가 없다.
+ */
ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, ktime_t *offs_real,
ktime_t *offs_boot, ktime_t *offs_tai)
{
@@ -2293,13 +2320,25 @@ ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, ktime_t *offs_real,
ktime_t base;
u64 nsecs;
+/*
+ * IAMROOT, 2022.09.24:
+ * - seqlock으로 인자값들을 tk 값으로 갱신한다.
+ */
do {
seq = read_seqcount_begin(&tk_core.seq);
+/*
+ * IAMROOT, 2022.09.24:
+ * - base + delta nsec로 now의 완전한 시각을 구한다.
+ */
base = tk->tkr_mono.base;
nsecs = timekeeping_get_ns(&tk->tkr_mono);
base = ktime_add_ns(base, nsecs);
+/*
+ * IAMROOT, 2022.09.24:
+ * - sequence가 바뀌엇을대만 갱신을 한다. 즉 interrupt 발생 시간을 저장한다.
+ */
if (*cwsseq != tk->clock_was_set_seq) {
*cwsseq = tk->clock_was_set_seq;
*offs_real = tk->offs_real;
@@ -2308,6 +2347,11 @@ ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, ktime_t *offs_real,
}
/* Handle leapsecond insertion adjustments */
+/*
+ * IAMROOT, 2022.09.24:
+ * - tk가 발생한 interrupt 시간보다 한참 지나서 이 루틴에 들어왔다면
+ * real time은 overflow된 1초를 빼준다.
+ */
if (unlikely(base >= tk->next_leap_ktime))
*offs_real = ktime_sub(tk->offs_real, ktime_set(1, 0));
diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h
index 4ca2787d1642..415e310c5003 100644
--- a/kernel/time/timekeeping_internal.h
+++ b/kernel/time/timekeeping_internal.h
@@ -27,6 +27,11 @@ static inline u64 clocksource_delta(u64 now, u64 last, u64 mask)
return ret & ~(mask >> 1) ? 0 : ret;
}
#else
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - cycle delta
+ */
static inline u64 clocksource_delta(u64 now, u64 last, u64 mask)
{
return (now - last) & mask;
diff --git a/lib/timerqueue.c b/lib/timerqueue.c
index 8034bfda310a..5161254f20ac 100644
--- a/lib/timerqueue.c
+++ b/lib/timerqueue.c
@@ -17,6 +17,11 @@
#define __node_2_tq(_n) \
rb_entry((_n), struct timerqueue_node, node)
+
+/*
+ * IAMROOT, 2022.09.24:
+ * - expires를 기준으로 정렬한다.
+ */
static inline bool __timerqueue_less(struct rb_node *a, const struct rb_node *b)
{
return __node_2_tq(a)->expires < __node_2_tq(b)->expires;
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 631 |
247 | 커널 스터디 공개 노트 링크 [1] | 박동하 | 2016.05.20 | 233169 |
246 | [커널 17차] 41주차 | ㅇㅇㅇ | 2021.06.13 | 36552 |
245 | [커널 17차] 56주차 | ㅇㅇㅇ | 2021.10.03 | 27531 |
244 | [커널 18차] 1주차 | V4bel | 2021.05.29 | 3600 |
243 | [커널 17차 6조] 2주차 | 김정근 | 2020.08.31 | 2175 |
242 | [커널 17차 2조] 4주차 | wellbeing | 2020.09.12 | 1518 |
241 | 커널 스터디 13차 D조 스터디 로그 링크입니다. | 목태양 | 2016.05.15 | 1226 |
240 | 해킹&보안 1차 A팀 스터디로그 링크 | 수비니겨 | 2016.05.19 | 1186 |
239 | [커널 16차 B조] 1주차 [1] | kdy0252 | 2019.05.25 | 1084 |
238 | [커널 17차 A조] 20주차 | 주영 | 2021.01.11 | 1019 |
237 | [커널 20차] 24주차 | 이민찬 | 2023.10.22 | 838 |
236 | [커널 17차 2조] 5주차 | wellbeing | 2020.09.19 | 739 |
235 | [커널 17차 8조] 1주차 [3] | JSYoo5B | 2020.08.22 | 718 |
234 | [커널 19차] 0주차 - 오리엔테이션 | 리턴 | 2022.05.07 | 602 |
233 | [커널 17차] 26주차 | 주영 | 2021.03.01 | 541 |
232 | [커널 19차] 37 주차 | Min | 2023.02.04 | 479 |
231 | [커널 19차] 1주차 | 리턴 | 2022.05.16 | 460 |
230 | [커널 17차] 32주차 | ㅇㅇㅇ | 2021.04.11 | 445 |
229 | [커널 17차 A조] 12주차 | 주영 | 2020.11.16 | 410 |
.