int xb_read(void *data, unsigned len) { volatile struct xenstore_domain_interface *intf = xs_domain_interface(xb_addr); XENSTORE_RING_IDX cons, prod; extern int do_polled_io; while (len != 0) { unsigned int avail; const char *src; mutex_enter(&xb_wait_lock); while (intf->rsp_cons == intf->rsp_prod) { if (interrupts_unleashed && !do_polled_io) { if (cv_wait_sig(&xb_wait_cv, &xb_wait_lock) == 0) { mutex_exit(&xb_wait_lock); return (EINTR); } } else { /* polled mode needed for early probes */ (void) HYPERVISOR_yield(); } } mutex_exit(&xb_wait_lock); /* Read indexes, then verify. */ cons = intf->rsp_cons; prod = intf->rsp_prod; membar_enter(); if (!check_indexes(cons, prod)) return (EIO); src = get_input_chunk(cons, prod, (char *)intf->rsp, &avail); if (avail == 0) continue; if (avail > len) avail = len; /* We must read header before we read data. */ membar_consumer(); (void) memcpy(data, src, avail); data = (void *)((uintptr_t)data + avail); len -= avail; /* Other side must not see free space until we've copied out */ membar_enter(); intf->rsp_cons += avail; /* Implies mb(): they will see new header. */ ec_notify_via_evtchn(xen_info->store_evtchn); } return (0); }
int xb_read(void *data, unsigned len) { struct xenstore_domain_interface *intf = xenstore_domain_interface(); XENSTORE_RING_IDX cons, prod; int s = spltty(); while (len != 0) { unsigned int avail; const char *src; while (intf->rsp_cons == intf->rsp_prod) tsleep(&xenstore_interface, PRIBIO, "rdst", 0); /* Read indexes, then verify. */ cons = intf->rsp_cons; prod = intf->rsp_prod; xen_rmb(); if (!check_indexes(cons, prod)) { XENPRINTF(("xb_read EIO\n")); splx(s); return EIO; } src = get_input_chunk(cons, prod, intf->rsp, &avail); if (avail == 0) continue; if (avail > len) avail = len; /* We must read header before we read data. */ xen_rmb(); memcpy(data, src, avail); data = (char *)data + avail; len -= avail; /* Other side must not see free space until we've copied out */ xen_rmb(); intf->rsp_cons += avail; xen_rmb(); XENPRINTF(("Finished read of %i bytes (%i to go)\n", avail, len)); hypervisor_notify_via_evtchn(xen_start_info.store_evtchn); } splx(s); return 0; }
int xb_read(void *data, unsigned len) { struct xenstore_domain_interface *intf = xen_store_interface; XENSTORE_RING_IDX cons, prod; int rc; while (len != 0) { unsigned int avail; const char *src; rc = wait_event_interruptible( xb_waitq, intf->rsp_cons != intf->rsp_prod); if (rc < 0) return rc; /* Read indexes, then verify. */ cons = intf->rsp_cons; prod = intf->rsp_prod; mb(); if (!check_indexes(cons, prod)) { intf->rsp_cons = intf->rsp_prod = 0; return -EIO; } src = get_input_chunk(cons, prod, intf->rsp, &avail); if (avail == 0) continue; if (avail > len) avail = len; /* We must read header before we read data. */ rmb(); memcpy(data, src, avail); data += avail; len -= avail; /* Other side must not see free space until we've copied out */ mb(); intf->rsp_cons += avail; pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); /* Implies mb(): they will see new header. */ notify_remote_via_evtchn(xen_store_evtchn); } return 0; }
int xb_read(void *data, unsigned len) { struct xenstore_domain_interface *intf = xen_store_interface; XENSTORE_RING_IDX cons, prod; int rc; while (len != 0) { unsigned int avail; const char *src; rc = xb_wait_for_data_to_read(); if (rc < 0) return rc; /* Read indexes, then verify. */ cons = intf->rsp_cons; prod = intf->rsp_prod; if (!check_indexes(cons, prod)) { intf->rsp_cons = intf->rsp_prod = 0; return -EIO; } src = get_input_chunk(cons, prod, intf->rsp, &avail); if (avail == 0) continue; if (avail > len) avail = len; /* Must read data /after/ reading the producer index. */ virt_rmb(); memcpy(data, src, avail); data += avail; len -= avail; /* Other side must not see free space until we've copied out */ virt_mb(); intf->rsp_cons += avail; pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); /* Implies mb(): other side will see the updated consumer. */ notify_remote_via_evtchn(xen_store_evtchn); } return 0; }