diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-23 13:02:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-23 13:02:50 -0400 |
commit | e80eda94d3eaf1d12cfc97878eff77cd679dabc9 (patch) | |
tree | 38ab17e7b9839297708a6982d661c3725d181c3a /kernel | |
parent | d475f3f47a0427dfee483cecf9a7e9109e991423 (diff) |
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>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/posix-cpu-timers.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 7a51a5597c33..d30b304a3384 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -961,14 +961,16 @@ void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
961 | static void check_thread_timers(struct task_struct *tsk, | 961 | static void check_thread_timers(struct task_struct *tsk, |
962 | struct list_head *firing) | 962 | struct list_head *firing) |
963 | { | 963 | { |
964 | int maxfire; | ||
964 | struct list_head *timers = tsk->cpu_timers; | 965 | struct list_head *timers = tsk->cpu_timers; |
965 | 966 | ||
967 | maxfire = 20; | ||
966 | tsk->it_prof_expires = cputime_zero; | 968 | tsk->it_prof_expires = cputime_zero; |
967 | while (!list_empty(timers)) { | 969 | while (!list_empty(timers)) { |
968 | struct cpu_timer_list *t = list_entry(timers->next, | 970 | struct cpu_timer_list *t = list_entry(timers->next, |
969 | struct cpu_timer_list, | 971 | struct cpu_timer_list, |
970 | entry); | 972 | entry); |
971 | if (cputime_lt(prof_ticks(tsk), t->expires.cpu)) { | 973 | if (!--maxfire || cputime_lt(prof_ticks(tsk), t->expires.cpu)) { |
972 | tsk->it_prof_expires = t->expires.cpu; | 974 | tsk->it_prof_expires = t->expires.cpu; |
973 | break; | 975 | break; |
974 | } | 976 | } |
@@ -977,12 +979,13 @@ static void check_thread_timers(struct task_struct *tsk, | |||
977 | } | 979 | } |
978 | 980 | ||
979 | ++timers; | 981 | ++timers; |
982 | maxfire = 20; | ||
980 | tsk->it_virt_expires = cputime_zero; | 983 | tsk->it_virt_expires = cputime_zero; |
981 | while (!list_empty(timers)) { | 984 | while (!list_empty(timers)) { |
982 | struct cpu_timer_list *t = list_entry(timers->next, | 985 | struct cpu_timer_list *t = list_entry(timers->next, |
983 | struct cpu_timer_list, | 986 | struct cpu_timer_list, |
984 | entry); | 987 | entry); |
985 | if (cputime_lt(virt_ticks(tsk), t->expires.cpu)) { | 988 | if (!--maxfire || cputime_lt(virt_ticks(tsk), t->expires.cpu)) { |
986 | tsk->it_virt_expires = t->expires.cpu; | 989 | tsk->it_virt_expires = t->expires.cpu; |
987 | break; | 990 | break; |
988 | } | 991 | } |
@@ -991,12 +994,13 @@ static void check_thread_timers(struct task_struct *tsk, | |||
991 | } | 994 | } |
992 | 995 | ||
993 | ++timers; | 996 | ++timers; |
997 | maxfire = 20; | ||
994 | tsk->it_sched_expires = 0; | 998 | tsk->it_sched_expires = 0; |
995 | while (!list_empty(timers)) { | 999 | while (!list_empty(timers)) { |
996 | struct cpu_timer_list *t = list_entry(timers->next, | 1000 | struct cpu_timer_list *t = list_entry(timers->next, |
997 | struct cpu_timer_list, | 1001 | struct cpu_timer_list, |
998 | entry); | 1002 | entry); |
999 | if (tsk->sched_time < t->expires.sched) { | 1003 | if (!--maxfire || tsk->sched_time < t->expires.sched) { |
1000 | tsk->it_sched_expires = t->expires.sched; | 1004 | tsk->it_sched_expires = t->expires.sched; |
1001 | break; | 1005 | break; |
1002 | } | 1006 | } |
@@ -1013,6 +1017,7 @@ static void check_thread_timers(struct task_struct *tsk, | |||
1013 | static void check_process_timers(struct task_struct *tsk, | 1017 | static void check_process_timers(struct task_struct *tsk, |
1014 | struct list_head *firing) | 1018 | struct list_head *firing) |
1015 | { | 1019 | { |
1020 | int maxfire; | ||
1016 | struct signal_struct *const sig = tsk->signal; | 1021 | struct signal_struct *const sig = tsk->signal; |
1017 | cputime_t utime, stime, ptime, virt_expires, prof_expires; | 1022 | cputime_t utime, stime, ptime, virt_expires, prof_expires; |
1018 | unsigned long long sched_time, sched_expires; | 1023 | unsigned long long sched_time, sched_expires; |
@@ -1045,12 +1050,13 @@ static void check_process_timers(struct task_struct *tsk, | |||
1045 | } while (t != tsk); | 1050 | } while (t != tsk); |
1046 | ptime = cputime_add(utime, stime); | 1051 | ptime = cputime_add(utime, stime); |
1047 | 1052 | ||
1053 | maxfire = 20; | ||
1048 | prof_expires = cputime_zero; | 1054 | prof_expires = cputime_zero; |
1049 | while (!list_empty(timers)) { | 1055 | while (!list_empty(timers)) { |
1050 | struct cpu_timer_list *t = list_entry(timers->next, | 1056 | struct cpu_timer_list *t = list_entry(timers->next, |
1051 | struct cpu_timer_list, | 1057 | struct cpu_timer_list, |
1052 | entry); | 1058 | entry); |
1053 | if (cputime_lt(ptime, t->expires.cpu)) { | 1059 | if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) { |
1054 | prof_expires = t->expires.cpu; | 1060 | prof_expires = t->expires.cpu; |
1055 | break; | 1061 | break; |
1056 | } | 1062 | } |
@@ -1059,12 +1065,13 @@ static void check_process_timers(struct task_struct *tsk, | |||
1059 | } | 1065 | } |
1060 | 1066 | ||
1061 | ++timers; | 1067 | ++timers; |
1068 | maxfire = 20; | ||
1062 | virt_expires = cputime_zero; | 1069 | virt_expires = cputime_zero; |
1063 | while (!list_empty(timers)) { | 1070 | while (!list_empty(timers)) { |
1064 | struct cpu_timer_list *t = list_entry(timers->next, | 1071 | struct cpu_timer_list *t = list_entry(timers->next, |
1065 | struct cpu_timer_list, | 1072 | struct cpu_timer_list, |
1066 | entry); | 1073 | entry); |
1067 | if (cputime_lt(utime, t->expires.cpu)) { | 1074 | if (!--maxfire || cputime_lt(utime, t->expires.cpu)) { |
1068 | virt_expires = t->expires.cpu; | 1075 | virt_expires = t->expires.cpu; |
1069 | break; | 1076 | break; |
1070 | } | 1077 | } |
@@ -1073,12 +1080,13 @@ static void check_process_timers(struct task_struct *tsk, | |||
1073 | } | 1080 | } |
1074 | 1081 | ||
1075 | ++timers; | 1082 | ++timers; |
1083 | maxfire = 20; | ||
1076 | sched_expires = 0; | 1084 | sched_expires = 0; |
1077 | while (!list_empty(timers)) { | 1085 | while (!list_empty(timers)) { |
1078 | struct cpu_timer_list *t = list_entry(timers->next, | 1086 | struct cpu_timer_list *t = list_entry(timers->next, |
1079 | struct cpu_timer_list, | 1087 | struct cpu_timer_list, |
1080 | entry); | 1088 | entry); |
1081 | if (sched_time < t->expires.sched) { | 1089 | if (!--maxfire || sched_time < t->expires.sched) { |
1082 | sched_expires = t->expires.sched; | 1090 | sched_expires = t->expires.sched; |
1083 | break; | 1091 | break; |
1084 | } | 1092 | } |