[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC] tools/ocaml/xb: Correct calculations of data/space the ring
On 28/10/15 16:18, Samuel Thibault wrote: > Andrew Cooper, le Wed 28 Oct 2015 16:05:36 +0000, a écrit : >> @@ -62,22 +62,32 @@ CAMLprim value ml_interface_read(value ml_interface, >> >> xen_mb(); >> >> - if ((prod - cons) > XENSTORE_RING_SIZE) >> + if (((prod - cons) > XENSTORE_RING_SIZE) || >> + ((cons - prod) < -XENSTORE_RING_SIZE)) > prod and cons are uint32_t, so the difference will still be unsigned. The RHS will also be promoted to unsigned, as int has insufficient range for the LHS. > IIRC the test is not bogus even when prod wraps around, (prod - cons) > will still correctly be the difference between both, modulo 2^32. (prod - cons) >= XENSTORE_RING_SIZE checks for the prod getting more than a ring's worth ahead of cons. (cons - prod) < -XENSTORE_RING_SIZE is supposed to check for cons getting ahead of prod (the naive (cons > prod) fails when the ring wraps), although I notice it still buggy in the case where cons == prod. > > Indeed, the read side also needs the same two-memcpy fix. > >> + /* Check for any pending data at all. */ >> + total_data = prod - cons; >> + if (total_data == 0) { > ... >> + else if (total_data > len) >> + /* Some data - make a partial read. */ >> + len = total_data; >> + >> + /* Check whether data crosses the end of the ring. */ >> + data = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); >> + if (len <= data) >> + /* Data within the remaining part of the ring. */ >> + memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), len); >> + else { >> + /* Data crosses the ring boundary. Read both halves. */ >> + memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), data); >> + memcpy(buffer + data, intf->req, len - data); >> + } >> + > That looks right and nice-looking to me. > >> xen_mb(); >> intf->req_cons += len; >> result = len; >> @@ -100,7 +110,7 @@ CAMLprim value ml_interface_write(value ml_interface, >> >> struct xenstore_domain_interface *intf = interface->addr; >> XENSTORE_RING_IDX cons, prod; >> - int can_write; >> + int total_space, space; >> uint32_t connection; >> >> cons = *(volatile uint32_t*)&intf->rsp_cons; >> @@ -111,17 +121,33 @@ CAMLprim value ml_interface_write(value ml_interface, >> caml_raise_constant(*caml_named_value("Xb.Reconnect")); >> >> xen_mb(); >> - if ( (prod - cons) >= XENSTORE_RING_SIZE ) { >> + >> + if (((prod - cons) > XENSTORE_RING_SIZE) || >> + ((cons - prod) < -XENSTORE_RING_SIZE)) > Ditto. > >> + /* Check for space to write the full message. */ >> + total_space = prod - cons; >> + if (total_space == 0) { > Shouldn't that be total_space == XENSTORE_RING_SIZE? Yes - I think it should. (I should probably kill my pending tests - they are not going to get very far...) ~Andrew > >> + /* No space at all - exit having done nothing. */ >> result = 0; >> goto exit; >> } >> + else if (total_space < len) >> + /* Some space - make a partial write. */ >> + len = total_space; >> + >> + /* Check for space until the ring wraps. */ >> + space = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); >> + if (len <= space ) >> + /* Message fits inside the remaining part of the ring. */ >> + memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len); >> + else { >> + /* Message wraps around the end of the ring. Write both halves. >> */ >> + memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, space); >> + memcpy(intf->rsp, buffer + space, len - space); >> + } > That looks right and nicer-looking than my attempt :) > > Samuel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |