cpu_purr_data is a per-cpu array used to account for stolen time on
partitioned systems. It used to be the case that cpus accessed each
others' cpu_purr_data, so each entry was protected by a spinlock.
However, the code was reworked ("Simplify stolen time calculation")
with the result that each cpu accesses its own cpu_purr_data and not
those of other cpus. This means we can get rid of the spinlock as
long as we're careful to disable interrupts when accessing
cpu_purr_data in process context.
Signed-off-by: Nathan Lynch <ntl@pobox.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
int initialized; /* thread is running */
u64 tb; /* last TB value read */
u64 purr; /* last PURR value read */
int initialized; /* thread is running */
u64 tb; /* last TB value read */
u64 purr; /* last PURR value read */
+/*
+ * Each entry in the cpu_purr_data array is manipulated only by its
+ * "owner" cpu -- usually in the timer interrupt but also occasionally
+ * in process context for cpu online. As long as cpus do not touch
+ * each others' cpu_purr_data, disabling local interrupts is
+ * sufficient to serialize accesses.
+ */
static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
static void snapshot_tb_and_purr(void *data)
{
static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
static void snapshot_tb_and_purr(void *data)
{
struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
p->tb = mftb();
p->purr = mfspr(SPRN_PURR);
wmb();
p->initialized = 1;
p->tb = mftb();
p->purr = mfspr(SPRN_PURR);
wmb();
p->initialized = 1;
+ local_irq_restore(flags);
*/
void snapshot_timebases(void)
{
*/
void snapshot_timebases(void)
{
if (!cpu_has_feature(CPU_FTR_PURR))
return;
if (!cpu_has_feature(CPU_FTR_PURR))
return;
- for_each_possible_cpu(cpu)
- spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
}
on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
}
+/*
+ * Must be called with interrupts disabled.
+ */
void calculate_steal_time(void)
{
u64 tb, purr;
void calculate_steal_time(void)
{
u64 tb, purr;
pme = &per_cpu(cpu_purr_data, smp_processor_id());
if (!pme->initialized)
return; /* this can happen in early boot */
pme = &per_cpu(cpu_purr_data, smp_processor_id());
if (!pme->initialized)
return; /* this can happen in early boot */
tb = mftb();
purr = mfspr(SPRN_PURR);
stolen = (tb - pme->tb) - (purr - pme->purr);
tb = mftb();
purr = mfspr(SPRN_PURR);
stolen = (tb - pme->tb) - (purr - pme->purr);
account_steal_time(current, stolen);
pme->tb = tb;
pme->purr = purr;
account_steal_time(current, stolen);
pme->tb = tb;
pme->purr = purr;
- spin_unlock(&pme->lock);
if (!cpu_has_feature(CPU_FTR_PURR))
return;
if (!cpu_has_feature(CPU_FTR_PURR))
return;
pme = &per_cpu(cpu_purr_data, smp_processor_id());
pme = &per_cpu(cpu_purr_data, smp_processor_id());
- spin_lock_irqsave(&pme->lock, flags);
pme->tb = mftb();
pme->purr = mfspr(SPRN_PURR);
pme->initialized = 1;
pme->tb = mftb();
pme->purr = mfspr(SPRN_PURR);
pme->initialized = 1;
- spin_unlock_irqrestore(&pme->lock, flags);
+ local_irq_restore(flags);
}
#endif /* CONFIG_PPC_SPLPAR */
}
#endif /* CONFIG_PPC_SPLPAR */