On 04/24/2014 02:16 AM, Frederic Weisbecker wrote: >> + again: >> + active = ACCESS_ONCE(ts->idle_active); >> + smp_rmb(); >> + count = ACCESS_ONCE(ts->idle_sleeptime); >> + if (active == 1) { >> + ktime_t delta, start; >> + >> + smp_rmb(); >> + start = ACCESS_ONCE(ts->idle_entrytime); >> + if (start.tv64 == 0) { >> + /* >> + * Other CPU is updating the count. >> + * We don't know whether fetched count is valid. >> + */ >> + goto again; >> + } >> + delta = ktime_sub(now, start); >> + count = ktime_add(count, delta); > > There is still a possibility that you race with an updater here. > Lets take these initial values, all of which belong to ts(CPU 1): > > // idle_sleeptime == 0 > // idle_entrytime == 0 > // ktime_get() == 100 > // idle_active = 1 > > CPU 0 CPU 1 > > count = idle_sleeptime // = 0 > tick_nohz_stop_idle(); > tick_nohz_start_idle(); > /* now idle_sleeptime == > 100 > and idle_entrytime == > 100 > ktime_get() is still > 100 > and idle_active is > still 1 > as it has toggled two > times */ > delta = now - idle_entrytime; // 100 - 100 > count += delta // == 0 > > Then you get the spurious 0 result. > > So memory barriers probably aren't enough here. seqcount would solve the > issue as it maintains > update seq tokens.
I think you are right. I'll use your approach (seqcount) in the next version. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/