Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e80eda94 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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: default avatarLinus Torvalds <torvalds@osdl.org>
parent d475f3f4
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -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;
		}
@@ -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;
		}
@@ -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;
		}
@@ -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;
@@ -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;
		}
@@ -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;
		}
@@ -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;
		}