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;
|
timer quantum_timer;
|
||||||
|
|
||||||
// keeping track of CPU activity
|
// keeping track of CPU activity
|
||||||
|
seqlock active_time_lock;
|
||||||
bigtime_t active_time;
|
bigtime_t active_time;
|
||||||
bigtime_t irq_time;
|
bigtime_t irq_time;
|
||||||
bigtime_t interrupt_time;
|
bigtime_t interrupt_time;
|
||||||
|
|||||||
@@ -159,7 +159,15 @@ cpu_get_active_time(int32 cpu)
|
|||||||
if (cpu < 0 || cpu > smp_get_num_cpus())
|
if (cpu < 0 || cpu > smp_get_num_cpus())
|
||||||
return 0;
|
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->kernel_time - cpuEntry->last_kernel_time)
|
||||||
+ (oldThread->user_time - cpuEntry->last_user_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);
|
oldThreadData->UpdateActivity(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -701,6 +701,7 @@ acquire_read_seqlock(seqlock* lock) {
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
release_read_seqlock(seqlock* lock, uint32 count) {
|
release_read_seqlock(seqlock* lock, uint32 count) {
|
||||||
|
arch_cpu_memory_read_barrier();
|
||||||
uint32 current = atomic_get((int32*)&lock->count);
|
uint32 current = atomic_get((int32*)&lock->count);
|
||||||
|
|
||||||
if (count % 2 == 1 || current != count) {
|
if (count % 2 == 1 || current != count) {
|
||||||
|
|||||||
Reference in New Issue
Block a user