aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorJohn M. Calandrino <jmc@jupiter-cs.cs.unc.edu>2007-02-09 14:32:01 -0500
committerJohn M. Calandrino <jmc@jupiter-cs.cs.unc.edu>2007-02-09 14:32:01 -0500
commit372757f9ec10a83c6663955ae5bf7c5c18e204e7 (patch)
treea7d9396b96e99903c6ac3301b20a649e778fb32c /arch/i386
parent9da64b82a7b271b695ee3d392fe2e7738c6d75ee (diff)
Added support for periodic resynchronization of aligned quanta.
Support added with some small modifications. Staggered quanta are still synchronized only once, it might not be necessary to re-stagger quanta at all. This seems to be running okay but is not guaranteed to be bug-free, and still needs to be checked for alignment accuracy.
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/kernel/apic.c69
1 files changed, 38 insertions, 31 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 7ffc2fb9a3..1df9229e20 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -1198,24 +1198,29 @@ EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
1198#undef APIC_DIVISOR 1198#undef APIC_DIVISOR
1199 1199
1200/* JOHN: Begin added code, starting with quantum sync function. */ 1200/* JOHN: Begin added code, starting with quantum sync function. */
1201#define STAGGER 1 1201#define STAGGER 0
1202#define WAIT_TO_SYNC 30000 /* 30s after boot (later: between syncs?) */ 1202#define WAIT_TO_SYNC 30000 /* time between syncs and before 1st sync */
1203#define QSYNC_TIME (INITIAL_JIFFIES+msecs_to_jiffies(WAIT_TO_SYNC)) 1203static atomic_t qsync_time = ATOMIC_INIT(INITIAL_JIFFIES);
1204 /* later: change from define to variable, update? */
1205static atomic_t quantum_sync_barrier = ATOMIC_INIT(0); 1204static atomic_t quantum_sync_barrier = ATOMIC_INIT(0);
1206 /* used to implement simple barrier */ 1205static atomic_t barrier_use_count = ATOMIC_INIT(1);
1207static DEFINE_PER_CPU(int, synched) = 0; 1206static atomic_t sync_done = ATOMIC_INIT(0);
1208 1207
1209/* 1208/*
1210 * This function is called to align all quanta, and to stagger quanta if 1209 * This function is called to align all quanta, and to stagger quanta if
1211 * necessary. It relies on a barrier to synchronize all processors, so 1210 * necessary. It relies on a barrier to synchronize all processors, so
1212 * that they all reset their APIC timers at the same time. 1211 * that they all reset their APIC timers at the same time. If quanta
1212 * should be staggered, the appropriate stagger delay is then added at
1213 * each processor. Staggered quanta are synchronized only once (it is
1214 * only important that quanta remain relatively misaligned, not that they
1215 * remain equally spaced forever). Aligned quanta, however, are
1216 * periodically realigned, which in most cases should not result
1217 * in substantial timing issues after the first alignment.
1213 */ 1218 */
1214void synchronize_quanta(void) 1219void synchronize_quanta(void)
1215{ 1220{
1216 int cpu = smp_processor_id(); 1221 int cpu = smp_processor_id();
1217 int total_cpus = num_online_cpus(); 1222 int total_cpus = num_online_cpus();
1218 int stagger_interval = jiffies_to_usecs(1)/total_cpus; 1223 int stagger_interval = jiffies_to_usecs(1) / total_cpus;
1219 1224
1220 /* 1225 /*
1221 * Disable APIC timer, wait for all other processors to reach barrier, 1226 * Disable APIC timer, wait for all other processors to reach barrier,
@@ -1223,7 +1228,8 @@ void synchronize_quanta(void)
1223 */ 1228 */
1224 disable_APIC_timer(); 1229 disable_APIC_timer();
1225 atomic_inc(&quantum_sync_barrier); 1230 atomic_inc(&quantum_sync_barrier);
1226 while (atomic_read(&quantum_sync_barrier) < total_cpus) 1231 while (atomic_read(&quantum_sync_barrier) <
1232 atomic_read(&barrier_use_count) * total_cpus)
1227 { 1233 {
1228 /* Delay, otherwise atomic_inc's cannot occur. */ 1234 /* Delay, otherwise atomic_inc's cannot occur. */
1229 udelay(1); 1235 udelay(1);
@@ -1231,17 +1237,26 @@ void synchronize_quanta(void)
1231 __setup_APIC_LVTT(calibration_result); 1237 __setup_APIC_LVTT(calibration_result);
1232 enable_APIC_timer(); 1238 enable_APIC_timer();
1233 1239
1234 /* Add necessary stagger for this CPU, if required. */ 1240 /*
1241 * Add necessary stagger for this CPU, if required. Do _not_
1242 * update qsync_time. Otherwise, we update the qsync_time
1243 * and increment the barrier count, which allows the barrier to
1244 * be "reused" (at least, until overflow occurs in roughly X*2^29
1245 * seconds, or roughly X*17 years -- for a 30 second wait interval,
1246 * this means 510 years until overflow, which seems safe).
1247 */
1235 if (STAGGER) { 1248 if (STAGGER) {
1236 int stagger_us = cpu*stagger_interval; 1249 int stagger_us = cpu * stagger_interval;
1237 disable_APIC_timer(); 1250 disable_APIC_timer();
1238 udelay(stagger_us); 1251 udelay(stagger_us);
1239 __setup_APIC_LVTT(calibration_result); 1252 __setup_APIC_LVTT(calibration_result);
1240 enable_APIC_timer(); 1253 enable_APIC_timer();
1254 atomic_inc(&sync_done);
1255 } else if (cpu == 0) {
1256 /* The first CPU updates qsync_time and "resets" barrier */
1257 atomic_add(msecs_to_jiffies(WAIT_TO_SYNC), &qsync_time);
1258 atomic_inc(&barrier_use_count);
1241 } 1259 }
1242
1243 /* Set "synched" flag so this code is not executed again. */
1244 per_cpu(synched, cpu) = 1;
1245} 1260}
1246/* JOHN: end added code. */ 1261/* JOHN: end added code. */
1247 1262
@@ -1257,10 +1272,6 @@ void synchronize_quanta(void)
1257 1272
1258inline void smp_local_timer_interrupt(void) 1273inline void smp_local_timer_interrupt(void)
1259{ 1274{
1260 /* JOHN: begin added code. */
1261 int cpu = smp_processor_id();
1262 /* JOHN: end added code. */
1263
1264 profile_tick(CPU_PROFILING); 1275 profile_tick(CPU_PROFILING);
1265#ifdef CONFIG_SMP 1276#ifdef CONFIG_SMP
1266 update_process_times(user_mode_vm(get_irq_regs())); 1277 update_process_times(user_mode_vm(get_irq_regs()));
@@ -1268,23 +1279,19 @@ inline void smp_local_timer_interrupt(void)
1268 1279
1269 /* JOHN: begin added code. 1280 /* JOHN: begin added code.
1270 * 1281 *
1271 * Synchronize quanta, if it hasn't been done already. 1282 * Synchronize quanta if we have reached qsync_time plus wait
1272 * To keep the interrupt handler code as efficient as possible 1283 * interval. For staggered quanta, this only happens once,
1273 * in the common case, we check a flag and only check the 1284 * i.e., sync_done is only set in the staggered case. For aligned
1274 * jiffy count if the flag is not set. When the jiffy count is 1285 * quanta, this value is updated so that realignments
1275 * high enough to ensure that all local APIC timers are 1286 * occur periodically.
1276 * up and running, as indicated by reaching QSYNC_TIME,
1277 * the synchronization occurs, and the flag is set so we never enter
1278 * this code again (unless this is changed so that quanta are
1279 * periodically re-synchronized?).
1280 * The synchronization code itself is placed in its own 1287 * The synchronization code itself is placed in its own
1281 * (non-inline) function, to avoid issues with creating an inline 1288 * (non-inline) function, to avoid issues with creating an inline
1282 * function that is too large. 1289 * function that is too large.
1283 */ 1290 */
1284 if (unlikely(!per_cpu(synched, cpu))) { 1291 if (unlikely(!atomic_read(&sync_done) &&
1285 if (jiffies > QSYNC_TIME) { 1292 jiffies > atomic_read(&qsync_time) +
1286 synchronize_quanta(); 1293 msecs_to_jiffies(WAIT_TO_SYNC))) {
1287 } 1294 synchronize_quanta();
1288 } 1295 }
1289 /* JOHN: end added code. */ 1296 /* JOHN: end added code. */
1290 1297