mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Posix timers: limit number of timers firing at once
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>
This commit is contained in:
parent
d475f3f47a
commit
e80eda94d3
@ -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,
|
static void check_thread_timers(struct task_struct *tsk,
|
||||||
struct list_head *firing)
|
struct list_head *firing)
|
||||||
{
|
{
|
||||||
|
int maxfire;
|
||||||
struct list_head *timers = tsk->cpu_timers;
|
struct list_head *timers = tsk->cpu_timers;
|
||||||
|
|
||||||
|
maxfire = 20;
|
||||||
tsk->it_prof_expires = cputime_zero;
|
tsk->it_prof_expires = cputime_zero;
|
||||||
while (!list_empty(timers)) {
|
while (!list_empty(timers)) {
|
||||||
struct cpu_timer_list *t = list_entry(timers->next,
|
struct cpu_timer_list *t = list_entry(timers->next,
|
||||||
struct cpu_timer_list,
|
struct cpu_timer_list,
|
||||||
entry);
|
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;
|
tsk->it_prof_expires = t->expires.cpu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -977,12 +979,13 @@ static void check_thread_timers(struct task_struct *tsk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
++timers;
|
++timers;
|
||||||
|
maxfire = 20;
|
||||||
tsk->it_virt_expires = cputime_zero;
|
tsk->it_virt_expires = cputime_zero;
|
||||||
while (!list_empty(timers)) {
|
while (!list_empty(timers)) {
|
||||||
struct cpu_timer_list *t = list_entry(timers->next,
|
struct cpu_timer_list *t = list_entry(timers->next,
|
||||||
struct cpu_timer_list,
|
struct cpu_timer_list,
|
||||||
entry);
|
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;
|
tsk->it_virt_expires = t->expires.cpu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -991,12 +994,13 @@ static void check_thread_timers(struct task_struct *tsk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
++timers;
|
++timers;
|
||||||
|
maxfire = 20;
|
||||||
tsk->it_sched_expires = 0;
|
tsk->it_sched_expires = 0;
|
||||||
while (!list_empty(timers)) {
|
while (!list_empty(timers)) {
|
||||||
struct cpu_timer_list *t = list_entry(timers->next,
|
struct cpu_timer_list *t = list_entry(timers->next,
|
||||||
struct cpu_timer_list,
|
struct cpu_timer_list,
|
||||||
entry);
|
entry);
|
||||||
if (tsk->sched_time < t->expires.sched) {
|
if (!--maxfire || tsk->sched_time < t->expires.sched) {
|
||||||
tsk->it_sched_expires = t->expires.sched;
|
tsk->it_sched_expires = t->expires.sched;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1013,6 +1017,7 @@ static void check_thread_timers(struct task_struct *tsk,
|
|||||||
static void check_process_timers(struct task_struct *tsk,
|
static void check_process_timers(struct task_struct *tsk,
|
||||||
struct list_head *firing)
|
struct list_head *firing)
|
||||||
{
|
{
|
||||||
|
int maxfire;
|
||||||
struct signal_struct *const sig = tsk->signal;
|
struct signal_struct *const sig = tsk->signal;
|
||||||
cputime_t utime, stime, ptime, virt_expires, prof_expires;
|
cputime_t utime, stime, ptime, virt_expires, prof_expires;
|
||||||
unsigned long long sched_time, sched_expires;
|
unsigned long long sched_time, sched_expires;
|
||||||
@ -1045,12 +1050,13 @@ static void check_process_timers(struct task_struct *tsk,
|
|||||||
} while (t != tsk);
|
} while (t != tsk);
|
||||||
ptime = cputime_add(utime, stime);
|
ptime = cputime_add(utime, stime);
|
||||||
|
|
||||||
|
maxfire = 20;
|
||||||
prof_expires = cputime_zero;
|
prof_expires = cputime_zero;
|
||||||
while (!list_empty(timers)) {
|
while (!list_empty(timers)) {
|
||||||
struct cpu_timer_list *t = list_entry(timers->next,
|
struct cpu_timer_list *t = list_entry(timers->next,
|
||||||
struct cpu_timer_list,
|
struct cpu_timer_list,
|
||||||
entry);
|
entry);
|
||||||
if (cputime_lt(ptime, t->expires.cpu)) {
|
if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) {
|
||||||
prof_expires = t->expires.cpu;
|
prof_expires = t->expires.cpu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1059,12 +1065,13 @@ static void check_process_timers(struct task_struct *tsk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
++timers;
|
++timers;
|
||||||
|
maxfire = 20;
|
||||||
virt_expires = cputime_zero;
|
virt_expires = cputime_zero;
|
||||||
while (!list_empty(timers)) {
|
while (!list_empty(timers)) {
|
||||||
struct cpu_timer_list *t = list_entry(timers->next,
|
struct cpu_timer_list *t = list_entry(timers->next,
|
||||||
struct cpu_timer_list,
|
struct cpu_timer_list,
|
||||||
entry);
|
entry);
|
||||||
if (cputime_lt(utime, t->expires.cpu)) {
|
if (!--maxfire || cputime_lt(utime, t->expires.cpu)) {
|
||||||
virt_expires = t->expires.cpu;
|
virt_expires = t->expires.cpu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1073,12 +1080,13 @@ static void check_process_timers(struct task_struct *tsk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
++timers;
|
++timers;
|
||||||
|
maxfire = 20;
|
||||||
sched_expires = 0;
|
sched_expires = 0;
|
||||||
while (!list_empty(timers)) {
|
while (!list_empty(timers)) {
|
||||||
struct cpu_timer_list *t = list_entry(timers->next,
|
struct cpu_timer_list *t = list_entry(timers->next,
|
||||||
struct cpu_timer_list,
|
struct cpu_timer_list,
|
||||||
entry);
|
entry);
|
||||||
if (sched_time < t->expires.sched) {
|
if (!--maxfire || sched_time < t->expires.sched) {
|
||||||
sched_expires = t->expires.sched;
|
sched_expires = t->expires.sched;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user