u64 sched_clock_cpu(int cpu) { u64 now, clock, this_clock, remote_clock; struct sched_clock_data *scd; if (sched_clock_stable) return sched_clock(); scd = cpu_sdc(cpu); /* * Normally this is not called in NMI context - but if it is, * trying to do any locking here is totally lethal. */ if (unlikely(in_nmi())) return scd->clock; if (unlikely(!sched_clock_running)) return 0ull; WARN_ON_ONCE(!irqs_disabled()); now = sched_clock(); if (cpu != raw_smp_processor_id()) { struct sched_clock_data *my_scd = this_scd(); lock_double_clock(scd, my_scd); this_clock = __update_sched_clock(my_scd, now); remote_clock = scd->clock; /* * Use the opportunity that we have both locks * taken to couple the two clocks: we take the * larger time as the latest time for both * runqueues. (this creates monotonic movement) */ if (likely((s64)(remote_clock - this_clock) < 0)) { clock = this_clock; scd->clock = clock; } else { /* * Should be rare, but possible: */ clock = remote_clock; my_scd->clock = remote_clock; } __raw_spin_unlock(&my_scd->lock); } else { __raw_spin_lock(&scd->lock); clock = __update_sched_clock(scd, now); } __raw_spin_unlock(&scd->lock); return clock; }
u64 sched_clock_cpu(int cpu) { struct sched_clock_data *scd = cpu_sdc(cpu); u64 now, clock; if (unlikely(!sched_clock_running)) return 0ull; WARN_ON_ONCE(!irqs_disabled()); now = sched_clock(); if (cpu != raw_smp_processor_id()) { /* * in order to update a remote cpu's clock based on our * unstable raw time rebase it against: * tick_raw (offset between raw counters) * tick_gotd (tick offset between cpus) */ struct sched_clock_data *my_scd = this_scd(); lock_double_clock(scd, my_scd); now -= my_scd->tick_raw; now += scd->tick_raw; now += my_scd->tick_gtod; now -= scd->tick_gtod; __raw_spin_unlock(&my_scd->lock); __update_sched_clock(scd, now, &clock); __raw_spin_unlock(&scd->lock); } else { __raw_spin_lock(&scd->lock); __update_sched_clock(scd, now, NULL); clock = scd->clock; __raw_spin_unlock(&scd->lock); } return clock; }