diff options
author | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-02-07 11:50:15 -0500 |
---|---|---|
committer | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-02-07 11:50:15 -0500 |
commit | 8a3cb25f615be35df14df9b224d90c464bb7afa4 (patch) | |
tree | 779c3d6113c9a2011844fea1f2b999421543358e /arch/i386 | |
parent | eb2ba33041b84cf15367288367494c6aec1da25a (diff) |
Modified apic.c to fix barrier-related issues with timer sync, now
use global timer (jiffies) to determine when sync occurs. Still broken
though, this is just a local checkpoint.
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/apic.c | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 268a32870c..13a08e8198 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -1198,13 +1198,20 @@ 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 0 | 1201 | #define STAGGER 1 |
1202 | #define WARM_UP_INTRS 10000 | 1202 | #define WAIT_TO_SYNC 30000 // 30s after boot (later: between syncs?) |
1203 | // later, define per-cpu variable and re-synch when intr_count % WARM_UP_INTRS == 0 | 1203 | #define QSYNC_TIME (INITIAL_JIFFIES+msecs_to_jiffies(WAIT_TO_SYNC)) |
1204 | static atomic_t quantum_sync_barrier = ATOMIC_INIT(0); // used to implement simple barrier | 1204 | // later: re-synch when intr_count % WARM_UP_INTRS == 0 |
1205 | static atomic_t quantum_sync_barrier = ATOMIC_INIT(0); | ||
1206 | // used to implement simple barrier | ||
1205 | static DEFINE_PER_CPU(int, synched) = 0; | 1207 | static DEFINE_PER_CPU(int, synched) = 0; |
1208 | static DEFINE_PER_CPU(int, intr_count) = 0; | ||
1206 | 1209 | ||
1207 | /* This function is called to align all quanta, and to stagger quanta if necessary. */ | 1210 | /* |
1211 | * This function is called to align all quanta, and to stagger quanta if | ||
1212 | * necessary. It relies on a barrier to synchronize all processors, so | ||
1213 | * that they all reset their APIC timers at the same time. | ||
1214 | */ | ||
1208 | void synchronize_quanta(void) | 1215 | void synchronize_quanta(void) |
1209 | { | 1216 | { |
1210 | int cpu = smp_processor_id(); | 1217 | int cpu = smp_processor_id(); |
@@ -1217,7 +1224,13 @@ void synchronize_quanta(void) | |||
1217 | */ | 1224 | */ |
1218 | disable_APIC_timer(); | 1225 | disable_APIC_timer(); |
1219 | atomic_inc(&quantum_sync_barrier); | 1226 | atomic_inc(&quantum_sync_barrier); |
1220 | while (atomic_read(&quantum_sync_barrier) < total_cpus); | 1227 | |
1228 | //debugging this... | ||
1229 | while (atomic_read(&quantum_sync_barrier) < total_cpus)//; | ||
1230 | { | ||
1231 | // printk("cpu %d, barrier = %d\n", cpu, atomic_read(&quantum_sync_barrier)); | ||
1232 | } | ||
1233 | |||
1221 | __setup_APIC_LVTT(calibration_result); | 1234 | __setup_APIC_LVTT(calibration_result); |
1222 | enable_APIC_timer(); | 1235 | enable_APIC_timer(); |
1223 | 1236 | ||
@@ -1258,13 +1271,29 @@ inline void smp_local_timer_interrupt(void) | |||
1258 | 1271 | ||
1259 | // JOHN: begin added code. | 1272 | // JOHN: begin added code. |
1260 | /* | 1273 | /* |
1261 | * Time to synchronize quanta, if it hasn't been done already. To avoid | 1274 | * Synchronize quanta, if it hasn't been done already. |
1262 | * placing a lot of code in an inline function, the actual sync code is | 1275 | * To keep the interrupt handler code as efficient as possible |
1263 | * placed in its own (non-inline) function - the majority of the time | 1276 | * in the common case, we check a flag and only check the |
1264 | * we won't even call it. | 1277 | * jiffy count (indicating the approximate system uptime after |
1278 | * which all processors should synch interrupts -- this jiffy count | ||
1279 | * needs to be high enough to ensure that all local APIC timers are | ||
1280 | * up and running) if the flag has not yet been set | ||
1281 | * (indicating that timers have not yet been synchronized). | ||
1282 | * An additional comparison is performed to see if the jiffy | ||
1283 | * count has exceeded QSYNC_TIME, at which point | ||
1284 | * the synchronization occurs, and the flag is set so we never enter | ||
1285 | * this code again (unless this is changed so that quanta are | ||
1286 | * periodically re-synchronized). | ||
1287 | * The synchronization code itself is placed in its own | ||
1288 | * (non-inline) function, to avoid issues with creating an inline | ||
1289 | * function that is too large. | ||
1265 | */ | 1290 | */ |
1266 | if (unlikely(!per_cpu(synched, cpu))) { | 1291 | if (unlikely(!per_cpu(synched, cpu))) { |
1267 | synchronize_quanta(); | 1292 | // per_cpu(intr_count, cpu)++; |
1293 | // if (unlikely(per_cpu(intr_count, cpu) > WARM_UP_INTRS)) { | ||
1294 | if (jiffies > QSYNC_TIME) { | ||
1295 | synchronize_quanta(); | ||
1296 | } | ||
1268 | } | 1297 | } |
1269 | // JOHN: end added code. | 1298 | // JOHN: end added code. |
1270 | 1299 | ||