From b258298c70249e60ea7c65c60bd5ee1250609921 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 20 Dec 2013 01:31:32 +0100 Subject: [PATCH] kernel: Protect cpu_ent::active_time with sequential lock atomic_{get, set}64() are problematic on architectures without 64 bit compare and swap. Also, using sequential lock instead of atomic access ensures that any reads from cpu_ent::active_time won't require any writes to shared memory. --- headers/private/kernel/cpu.h | 1 + src/system/kernel/cpu.cpp | 10 +++++++++- src/system/kernel/scheduler/scheduler_cpu.cpp | 5 ++++- src/system/kernel/smp.cpp | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index 17b056afdb..dad23c6c56 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -56,6 +56,7 @@ typedef struct cpu_ent { timer quantum_timer; // keeping track of CPU activity + seqlock active_time_lock; bigtime_t active_time; bigtime_t irq_time; bigtime_t interrupt_time; diff --git a/src/system/kernel/cpu.cpp b/src/system/kernel/cpu.cpp index a0ffcaf7f4..c984f353d1 100644 --- a/src/system/kernel/cpu.cpp +++ b/src/system/kernel/cpu.cpp @@ -159,7 +159,15 @@ cpu_get_active_time(int32 cpu) if (cpu < 0 || cpu > smp_get_num_cpus()) return 0; - return atomic_get64(&gCPU[cpu].active_time); + bigtime_t activeTime; + uint32 count; + + do { + count = acquire_read_seqlock(&gCPU[cpu].active_time_lock); + activeTime = gCPU[cpu].active_time; + } while (!release_read_seqlock(&gCPU[cpu].active_time_lock, count)); + + return activeTime; } diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index 3c8203ac12..57544ae83e 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -180,7 +180,10 @@ CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData) = (oldThread->kernel_time - cpuEntry->last_kernel_time) + (oldThread->user_time - cpuEntry->last_user_time); - atomic_add64(&cpuEntry->active_time, active); + WriteSequentialLocker locker(cpuEntry->active_time_lock); + cpuEntry->active_time += active; + locker.Unlock(); + oldThreadData->UpdateActivity(active); } diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index 780912abc8..3631234771 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -701,6 +701,7 @@ acquire_read_seqlock(seqlock* lock) { bool release_read_seqlock(seqlock* lock, uint32 count) { + arch_cpu_memory_read_barrier(); uint32 current = atomic_get((int32*)&lock->count); if (count % 2 == 1 || current != count) {