diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2011-03-03 06:06:28 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-03-10 14:47:58 -0500 |
commit | 24b51c2f2de019a4596415e7bb1e92711127d0e0 (patch) | |
tree | 4cfef59033541c67f7e96bffcfadef135f85f666 /drivers/xen | |
parent | ada6814c878c4d95fc8ca1402e49effbf3cc319a (diff) |
xen: events: Make round-robin scan fairer by snapshotting each l2 word once only
(except for starting l2 word, which we scan in two parts).
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
[ijc: forward ported from linux-2.6.18-xen.hg 990:427276ac595d]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/events.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index c49cb6d6b838..0c3f17ba3956 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -1045,7 +1045,9 @@ static DEFINE_PER_CPU(unsigned int, current_bit_idx); | |||
1045 | */ | 1045 | */ |
1046 | static void __xen_evtchn_do_upcall(void) | 1046 | static void __xen_evtchn_do_upcall(void) |
1047 | { | 1047 | { |
1048 | int start_word_idx, start_bit_idx; | ||
1048 | int word_idx, bit_idx; | 1049 | int word_idx, bit_idx; |
1050 | int i; | ||
1049 | int cpu = get_cpu(); | 1051 | int cpu = get_cpu(); |
1050 | struct shared_info *s = HYPERVISOR_shared_info; | 1052 | struct shared_info *s = HYPERVISOR_shared_info; |
1051 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); | 1053 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); |
@@ -1065,10 +1067,12 @@ static void __xen_evtchn_do_upcall(void) | |||
1065 | #endif | 1067 | #endif |
1066 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); | 1068 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); |
1067 | 1069 | ||
1068 | word_idx = __this_cpu_read(current_word_idx); | 1070 | start_word_idx = __this_cpu_read(current_word_idx); |
1069 | bit_idx = __this_cpu_read(current_bit_idx); | 1071 | start_bit_idx = __this_cpu_read(current_bit_idx); |
1072 | |||
1073 | word_idx = start_word_idx; | ||
1070 | 1074 | ||
1071 | while (pending_words != 0) { | 1075 | for (i = 0; pending_words != 0; i++) { |
1072 | unsigned long pending_bits; | 1076 | unsigned long pending_bits; |
1073 | unsigned long words; | 1077 | unsigned long words; |
1074 | 1078 | ||
@@ -1084,13 +1088,23 @@ static void __xen_evtchn_do_upcall(void) | |||
1084 | } | 1088 | } |
1085 | word_idx = __ffs(words); | 1089 | word_idx = __ffs(words); |
1086 | 1090 | ||
1091 | pending_bits = active_evtchns(cpu, s, word_idx); | ||
1092 | bit_idx = 0; /* usually scan entire word from start */ | ||
1093 | if (word_idx == start_word_idx) { | ||
1094 | /* We scan the starting word in two parts */ | ||
1095 | if (i == 0) | ||
1096 | /* 1st time: start in the middle */ | ||
1097 | bit_idx = start_bit_idx; | ||
1098 | else | ||
1099 | /* 2nd time: mask bits done already */ | ||
1100 | bit_idx &= (1UL << start_bit_idx) - 1; | ||
1101 | } | ||
1102 | |||
1087 | do { | 1103 | do { |
1088 | unsigned long bits; | 1104 | unsigned long bits; |
1089 | int port, irq; | 1105 | int port, irq; |
1090 | struct irq_desc *desc; | 1106 | struct irq_desc *desc; |
1091 | 1107 | ||
1092 | pending_bits = active_evtchns(cpu, s, word_idx); | ||
1093 | |||
1094 | bits = MASK_LSBS(pending_bits, bit_idx); | 1108 | bits = MASK_LSBS(pending_bits, bit_idx); |
1095 | 1109 | ||
1096 | /* If we masked out all events, move on. */ | 1110 | /* If we masked out all events, move on. */ |
@@ -1121,10 +1135,8 @@ static void __xen_evtchn_do_upcall(void) | |||
1121 | __this_cpu_write(current_bit_idx, bit_idx); | 1135 | __this_cpu_write(current_bit_idx, bit_idx); |
1122 | } while (bit_idx != 0); | 1136 | } while (bit_idx != 0); |
1123 | 1137 | ||
1124 | pending_bits = active_evtchns(cpu, s, word_idx); | 1138 | /* Scan start_l1i twice; all others once. */ |
1125 | 1139 | if ((word_idx != start_word_idx) || (i != 0)) | |
1126 | /* If we handled all ports, clear the selector bit. */ | ||
1127 | if (pending_bits == 0) | ||
1128 | pending_words &= ~(1UL << word_idx); | 1140 | pending_words &= ~(1UL << word_idx); |
1129 | 1141 | ||
1130 | word_idx = (word_idx + 1) % BITS_PER_LONG; | 1142 | word_idx = (word_idx + 1) % BITS_PER_LONG; |