|
[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
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.
IIRC the test is not bogus even when prod wraps around, (prod - cons)
will still correctly be the difference between both, modulo 2^32.
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?
> + /* 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 |