|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] mce: Fix race condition in mctelem_xchg_head
On Thu, 2014-01-16 at 13:56 +0000, Jan Beulich wrote:
> >>> On 16.01.14 at 14:26, Frediano Ziglio <frediano.ziglio@xxxxxxxxxx> wrote:
> > The function that exchange the head is racy.
> > The cmpxchg and the compare are not atomic.
> > Assume two thread one (T1) inserting on committed list and another
> > trying to comsume it (T2).
> > T1 start inserting the element (A), set prev pointer (commit list use
> > mcte_prev) then is stop after the cmpxchg succeeded.
> > T2 get the list and change elements (A) and update the commit list
> > head.
> > T1 resume, read pointer to prev again and compare with result from
> > cmpxchg which succeeded but in the meantime prev changed in memory.
> > Not T1 assume the element was not inserted on the list and try to
> > insert again. Now A however is in another state and should not be
> > modified by T1.
> > To solve the race use temporary variable for prev pointer.
> > Note that compiler should not optimize the memory fetch as cmpxhg
> > do a full barrier.
>
> This last sentence is pretty pointless, since there's an explicit
> wmb() between setting old and doing the cmpxchg. (Question is
> whether that wmb() actually is necessary; without a comment I
> can't easily see what it is supposed to fence - surely it's not the
> write to *oldp. And that's regardless of it being redundant with
> the barrier embedded with cmpxchgptr().)
>
> But overall, while I think your analysis is correct, the description
> could do with some cleanup, also spelling-wise.
>
Yes, sorry, I'm not native English. Suggestion accepted.
The race is here
if (cmpxchgptr(headp, *old, new) == *old)
You do the cmpxchg (which is atomic), then you read old pointer (*old)
then you compare cmpxchg result with the content of the pointer.
Yes, wmb is quite useless, cmpxchg should be enough.
> > static void mctelem_xchg_head(struct mctelem_ent **headp,
> > - struct mctelem_ent **old,
> > + struct mctelem_ent **oldp,
> > struct mctelem_ent *new)
> > {
> > + struct mctelem_ent *old;
> > +
> > for (;;) {
> > - *old = *headp;
> > + *oldp = old = *headp;
> > wmb();
> > - if (cmpxchgptr(headp, *old, new) == *old)
> > + if (cmpxchgptr(headp, old, new) == old)
> > break;
> > }
> > }
>
> Now that you use a temporary, it would make sense (and make
> the code easier to read) if you set *oldp to old just once, after
> the loop.
>
> Jan
>
No, this will create another race. After cmpxchg you must assume that
the list element can be own by somebody else.
Frediano
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |