diff --git a/tools/ocaml/libs/xb/xs_ring_stubs.c b/tools/ocaml/libs/xb/xs_ring_stubs.c index fd561a2..5c771d6 100644 --- a/tools/ocaml/libs/xb/xs_ring_stubs.c +++ b/tools/ocaml/libs/xb/xs_ring_stubs.c @@ -99,12 +99,12 @@ CAMLprim value ml_interface_write(value ml_interface, int result; struct xenstore_domain_interface *intf = interface->addr; - XENSTORE_RING_IDX cons, prod; + XENSTORE_RING_IDX cons, old_prod, prod; int can_write; uint32_t connection; cons = *(volatile uint32_t*)&intf->rsp_cons; - prod = *(volatile uint32_t*)&intf->rsp_prod; + old_prod = prod = *(volatile uint32_t*)&intf->rsp_prod; connection = *(volatile uint32_t*)&intf->connection; if (connection != XENSTORE_CONNECTED) @@ -116,15 +116,30 @@ CAMLprim value ml_interface_write(value ml_interface, goto exit; } if (MASK_XENSTORE_IDX(prod) >= MASK_XENSTORE_IDX(cons)) + { can_write = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); - else + if (can_write < len) + { + /* Not enough room at end of ring. Copy what we can first. */ + memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, can_write); + prod += can_write; + len -= can_write; + buffer += can_write; + + /* We are now back at beginning of ring. */ + can_write = MASK_XENSTORE_IDX(cons) - MASK_XENSTORE_IDX(prod); + } + } + else can_write = MASK_XENSTORE_IDX(cons) - MASK_XENSTORE_IDX(prod); if (can_write < len) + /* Real short write: not enough room. */ len = can_write; memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len); + prod += len; xen_mb(); - intf->rsp_prod += len; - result = len; + intf->rsp_prod = prod; + result = prod - old_prod; exit: ml_result = Val_int(result); CAMLreturn(ml_result);