Skip to content

Commit

Permalink
Posix timers: limit number of timers firing at once
Browse files Browse the repository at this point in the history
Bursty timers aren't good for anybody, very much including latency for
other programs when we trigger lots of timers in interrupt context.  So
set a random limit, after which we'll handle the rest on the next timer
tick.

Noted by Oleg Nesterov <oleg@tv-sign.ru>

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Linus Torvalds committed Oct 23, 2005
1 parent d475f3f commit e80eda9
Showing 1 changed file with 14 additions and 6 deletions.
20 changes: 14 additions & 6 deletions kernel/posix-cpu-timers.c
Original file line number Diff line number Diff line change
Expand Up @@ -961,14 +961,16 @@ void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
static void check_thread_timers(struct task_struct *tsk,
struct list_head *firing)
{
int maxfire;
struct list_head *timers = tsk->cpu_timers;

maxfire = 20;
tsk->it_prof_expires = cputime_zero;
while (!list_empty(timers)) {
struct cpu_timer_list *t = list_entry(timers->next,
struct cpu_timer_list,
entry);
if (cputime_lt(prof_ticks(tsk), t->expires.cpu)) {
if (!--maxfire || cputime_lt(prof_ticks(tsk), t->expires.cpu)) {
tsk->it_prof_expires = t->expires.cpu;
break;
}
Expand All @@ -977,12 +979,13 @@ static void check_thread_timers(struct task_struct *tsk,
}

++timers;
maxfire = 20;
tsk->it_virt_expires = cputime_zero;
while (!list_empty(timers)) {
struct cpu_timer_list *t = list_entry(timers->next,
struct cpu_timer_list,
entry);
if (cputime_lt(virt_ticks(tsk), t->expires.cpu)) {
if (!--maxfire || cputime_lt(virt_ticks(tsk), t->expires.cpu)) {
tsk->it_virt_expires = t->expires.cpu;
break;
}
Expand All @@ -991,12 +994,13 @@ static void check_thread_timers(struct task_struct *tsk,
}

++timers;
maxfire = 20;
tsk->it_sched_expires = 0;
while (!list_empty(timers)) {
struct cpu_timer_list *t = list_entry(timers->next,
struct cpu_timer_list,
entry);
if (tsk->sched_time < t->expires.sched) {
if (!--maxfire || tsk->sched_time < t->expires.sched) {
tsk->it_sched_expires = t->expires.sched;
break;
}
Expand All @@ -1013,6 +1017,7 @@ static void check_thread_timers(struct task_struct *tsk,
static void check_process_timers(struct task_struct *tsk,
struct list_head *firing)
{
int maxfire;
struct signal_struct *const sig = tsk->signal;
cputime_t utime, stime, ptime, virt_expires, prof_expires;
unsigned long long sched_time, sched_expires;
Expand Down Expand Up @@ -1045,12 +1050,13 @@ static void check_process_timers(struct task_struct *tsk,
} while (t != tsk);
ptime = cputime_add(utime, stime);

maxfire = 20;
prof_expires = cputime_zero;
while (!list_empty(timers)) {
struct cpu_timer_list *t = list_entry(timers->next,
struct cpu_timer_list,
entry);
if (cputime_lt(ptime, t->expires.cpu)) {
if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) {
prof_expires = t->expires.cpu;
break;
}
Expand All @@ -1059,12 +1065,13 @@ static void check_process_timers(struct task_struct *tsk,
}

++timers;
maxfire = 20;
virt_expires = cputime_zero;
while (!list_empty(timers)) {
struct cpu_timer_list *t = list_entry(timers->next,
struct cpu_timer_list,
entry);
if (cputime_lt(utime, t->expires.cpu)) {
if (!--maxfire || cputime_lt(utime, t->expires.cpu)) {
virt_expires = t->expires.cpu;
break;
}
Expand All @@ -1073,12 +1080,13 @@ static void check_process_timers(struct task_struct *tsk,
}

++timers;
maxfire = 20;
sched_expires = 0;
while (!list_empty(timers)) {
struct cpu_timer_list *t = list_entry(timers->next,
struct cpu_timer_list,
entry);
if (sched_time < t->expires.sched) {
if (!--maxfire || sched_time < t->expires.sched) {
sched_expires = t->expires.sched;
break;
}
Expand Down

0 comments on commit e80eda9

Please sign in to comment.