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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user