Skip to content

Commit

Permalink
117th
Browse files Browse the repository at this point in the history
  • Loading branch information
iamroot12a committed Jul 15, 2017
1 parent 10f6b97 commit b946e2e
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 0 deletions.
5 changes: 5 additions & 0 deletions fs/proc/loadavg.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@

static int loadavg_proc_show(struct seq_file *m, void *v)
{

/* IAMROOT-12:
* -------------
* 글로벌 로드 출력
*/
unsigned long avnrun[3];

get_avenrun(avnrun, FIXED_1/200, 0);
Expand Down
11 changes: 11 additions & 0 deletions include/linux/timekeeper_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
* The struct is separate from struct timekeeper as it is also used
* for a fast NMI safe accessor to clock monotonic.
*/

/* IAMROOT-12:
* -------------
* cycle_last: timekeeping을 위해 읽은 클럭소스의 마지막 값
*/
struct tk_read_base {
struct clocksource *clock;
cycle_t (*read)(struct clocksource *cs);
Expand Down Expand Up @@ -75,6 +80,12 @@ struct tk_read_base {
* wall_to_monotonic is no longer the boot time, getboottime must be
* used instead.
*/

/* IAMROOT-12:
* -------------
* cycle_interval
* 1 jiffes에 해당하는 cycle 수
*/
struct timekeeper {
struct tk_read_base tkr;
u64 xtime_sec;
Expand Down
61 changes: 61 additions & 0 deletions kernel/sched/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
*/

/* Variables and functions for calc_load */

/* IAMROOT-12:
* -------------
* avenload[]를 산출할 때 사용하는 로드를 정한다.
* calc_load() 함수에서 사용한다.
*/
atomic_long_t calc_load_tasks;

/* IAMROOT-12:
Expand Down Expand Up @@ -85,6 +91,15 @@ long calc_load_fold_active(struct rq *this_rq)
{
long nr_active, delta = 0;

/* IAMROOT-12:
* -------------
* 로드 계산에 적용되지 않은 변동된 active 태스크 수를 산출한다.
*
* nohz idle시 nr_running=0
* nohz full시 nr_running=1
*
* nr_uninterruptible은 로드 계산을 위한 active 태스크 수에 포함시킨다.
*/
nr_active = this_rq->nr_running;
nr_active += (long) this_rq->nr_uninterruptible;

Expand All @@ -102,6 +117,15 @@ long calc_load_fold_active(struct rq *this_rq)
static unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{

/* IAMROOT-12:
* -------------
* old * k + new * (1 - k)
* -> load * exp + active * (2048 - exp)
*
* 예: load(old)=4096, active(new)=2048, exp(k)=1884 (1min)
* -> 3932
*/
load *= exp;
load += active * (FIXED_1 - exp);
load += 1UL << (FSHIFT - 1);
Expand Down Expand Up @@ -198,6 +222,11 @@ void calc_load_enter_idle(void)
* We're going into NOHZ mode, if there's any pending delta, fold it
* into the pending idle delta.
*/

/* IAMROOT-12:
* -------------
* nohz idle 진입 시 로드 계산에 사용할 변동된 active 태스크 수를 알아온다.
*/
delta = calc_load_fold_active(this_rq);
if (delta) {
int idx = calc_load_write_idx();
Expand Down Expand Up @@ -326,6 +355,13 @@ static void calc_global_nohz(void)
{
long delta, active, n;

/* IAMROOT-12:
* -------------
* nohz로 인해 5초 이상 더 소모된 경우 이 루틴에 진입한다.
*
* n = nohz로 인해 계산 못한 횟 수
* (calc_global_load()에서 한 번 계산한 것 제외)
*/
if (!time_before(jiffies, calc_load_update + 10)) {
/*
* Catch-up, fold however many we are behind still
Expand Down Expand Up @@ -378,13 +414,38 @@ void calc_global_load(unsigned long ticks)
/*
* Fold the 'old' idle-delta to include all NO_HZ cpus.
*/

/* IAMROOT-12:
* -------------
* calc_load_idle[]을 읽어온다. (동기화 방법을 사용하여 idx=0/1을 구분)
* 읽어온 delta(로드 값에 사용할 변동된 active 태스크 수) 값을
* calc_load_tasks에 추가한다.
*
* idle로 누적되는 값을 읽어오되 10tick 구간을 제외한 값을 읽어온다.
* 추후 10tick에 대한 구간은 차후에 읽어오게 하였다.
*
* nohz idle 진입 시의 active 태스크 수를 cpu 로드에 반영하여 사용한다.
*/
delta = calc_load_fold_idle();
if (delta)
atomic_long_add(delta, &calc_load_tasks);

/* IAMROOT-12:
* -------------
* load의 정확도로 11비트를 사용한 2048을 사용한다. (즉 1.0 = 2048)
*/
active = atomic_long_read(&calc_load_tasks);
active = active > 0 ? active * FIXED_1 : 0;


/* IAMROOT-12:
* -------------
* 1분, 5분, 15분에 대한 글로벌 로드 값을 산출한다.
*
* EXP_1=1884 (0.9200)
* EXP_5=2014 (0.9835)
* EXP_15=2037 (0.9945)
*/
avenrun[0] = calc_load(avenrun[0], EXP_1, active);
avenrun[1] = calc_load(avenrun[1], EXP_5, active);
avenrun[2] = calc_load(avenrun[2], EXP_15, active);
Expand Down
10 changes: 10 additions & 0 deletions kernel/time/hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,10 @@ static void retrigger_next_event(void *arg)
if (!hrtimer_hres_active())
return;

/* IAMROOT-12:
* -------------
* timekeeping의 realtime이 변경된 경우 hrtimer의 리트리거 작업을 해야 한다.
*/
raw_spin_lock(&base->lock);
hrtimer_update_base(base);
hrtimer_force_reprogram(base, 0);
Expand Down Expand Up @@ -900,6 +904,12 @@ static inline void retrigger_next_event(void *arg) { }
*/
void clock_was_set(void)
{

/* IAMROOT-12:
* -------------
* timekeeping의 realtime이 바뀌었으므로 cpu마다 동작하는 hrtimer들도
* 거기에 따른 리트리거 작업을 한다.
*/
#ifdef CONFIG_HIGH_RES_TIMERS
/* Retrigger the CPU local events everywhere */
on_each_cpu(retrigger_next_event, NULL, 1);
Expand Down
53 changes: 53 additions & 0 deletions kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -1717,10 +1717,20 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
u64 raw_nsecs;

/* If the offset is smaller then a shifted interval, do nothing */

/* IAMROOT-12:
* -------------
* 해당 shift 단위에서 처리할 수 없는 작은 offset이기 때문에 빠져나간다.
*/
if (offset < interval)
return offset;

/* Accumulate one shifted interval */

/* IAMROOT-12:
* -------------
* 마지막 처리 시각을 cycle_interval의 로그2 승수 단위로 기록한다.
*/
offset -= interval;
tk->tkr.cycle_last += interval;

Expand Down Expand Up @@ -1761,17 +1771,32 @@ void update_wall_time(void)
raw_spin_lock_irqsave(&timekeeper_lock, flags);

/* Make sure we're fully resumed: */

/* IAMROOT-12:
* -------------
* suspend 시도 중에는 timekeeping 갱신이되지 않도록 한다.
*/
if (unlikely(timekeeping_suspended))
goto out;

#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
offset = real_tk->cycle_interval;
#else

/* IAMROOT-12:
* -------------
* (now - last & mask)
*/
offset = clocksource_delta(tk->tkr.read(tk->tkr.clock),
tk->tkr.cycle_last, tk->tkr.mask);
#endif

/* Check if there's really nothing to do */

/* IAMROOT-12:
* -------------
* cycle_interval(1 jiffies에 해당하는 cycle) 보다 작은 offset 값은 무시한다.
*/
if (offset < real_tk->cycle_interval)
goto out;

Expand All @@ -1783,9 +1808,22 @@ void update_wall_time(void)
* chunk in one go, and then try to consume the next smaller
* doubled multiple.
*/

/* IAMROOT-12:
* -------------
* ntpd가 큰 시간 간격을 바꾸면 문제가 발생하므로 cycle_interval 단위로
* 시간을 바꿔야하는데 nohz 시스템으로 인해 큰 offset가 발생하여
* 이를 한 꺼번에 바꾸는데 인터럽트 레이튼시가 커지는 문제가 발생한다.
* 따라서 로그2 단위로 처리를 하도록 하였다.
*/
shift = ilog2(offset) - ilog2(tk->cycle_interval);
shift = max(0, shift);
/* Bound shift to one less than what overflows tick_length */

/* IAMROOT-12:
* -------------
* ntp가 인식할 수 없는 단위로 시간을 바꾸지 않게 제한한다.
*/
maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
shift = min(shift, maxshift);
while (offset >= tk->cycle_interval) {
Expand Down Expand Up @@ -1821,13 +1859,23 @@ void update_wall_time(void)
* memcpy under the tk_core.seq against one before we start
* updating.
*/

/* IAMROOT-12:
* -------------
* real_tk <- tk 복사
*/
memcpy(real_tk, tk, sizeof(*tk));
timekeeping_update(real_tk, clock_set);
write_seqcount_end(&tk_core.seq);
out:
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
if (clock_set)
/* Have to call _delayed version, since in irq context*/

/* IAMROOT-12:
* -------------
* bottom-half인 워크큐를 사용하여 realtime이 설정되었음을 알린다.
*/
clock_was_set_delayed();
}

Expand Down Expand Up @@ -1907,6 +1955,11 @@ struct timespec64 get_monotonic_coarse64(void)
void do_timer(unsigned long ticks)
{
jiffies_64 += ticks;

/* IAMROOT-12:
* -------------
* 글로벌 로드 산출
*/
calc_global_load(ticks);
}

Expand Down

0 comments on commit b946e2e

Please sign in to comment.