On 21/03/2016 16:36, Alex Bennée wrote:
> > 341 /* The icount_warp_timer is rescheduled soon after
> > vm_clock_warp_start
> > 342 * changes from -1 to another value, so the race here is okay.
> > 343 */
> > 344 if (atomic_read(&vm_clock_warp_start) == -1) {
> > 345 return;
> > 346 }
> > 347
> Odd, the comments say that vm_clock_warp start is protected by the
> seqlock, and in fact every other access to it is a plain access.
Yes, the comment says why this is safe.
The change from -1 to positive is here:
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
vm_clock_warp_start = clock;
}
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
timer_mod_anticipate(icount_warp_timer, clock + deadline);
If we get a race we must be like this:
icount_warp_rt qemu_start_warp_timer
-------------- ---------------------
read -1
write to vm_clock_warp_start
unlock
timer_mod_anticipate (*)
As soon as you reach (*) the timer is rescheduled and will read a value
other than -1.
> It seems to me the code should probably just be:
>
> seqlock_write_lock(&timers_state.vm_clock_seqlock);
> if (vm_clock_warp_start !== -1 && runstate_is_running()) {
> .. do stuff ..
> }
> vm_clock_warp_start = -1;
> seqlock_write_unlock(&timers_state.vm_clock_seqlock);
>
> if (we_did_stuff && qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) {
> qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
> }
Yes, you can make it like that, or even better wrap the read with a
seqlock_read_begin/seqlock_read_retry loop. The condition will often be
false and it's pointless to lock/unlock the mutex for that.
Paolo