# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 40b4860f554a91d537aeb021a038ffd4b335a221
# Parent d6e0eb8622cdd514a1f15e23dccac979cd611d18
Add memory barriers to console ring accesses. Similar to what
Rusty uses for xenbus messaging.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r d6e0eb8622cd -r 40b4860f554a
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Wed Oct 12
19:58:51 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Wed Oct 12
20:10:14 2005
@@ -34,14 +34,18 @@
{
int sent = 0;
struct xencons_interface *intf = xencons_interface();
+ XENCONS_RING_IDX cons, prod;
- while ((sent < len) &&
- (intf->out_prod - intf->out_cons) < sizeof(intf->out)) {
- intf->out[MASK_XENCONS_IDX(intf->out_prod, intf->out)] =
- data[sent];
- intf->out_prod++;
- sent++;
- }
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb();
+ BUG_ON((prod - cons) > sizeof(intf->out));
+
+ while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+ intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+ wmb();
+ intf->out_prod = prod;
/* Use evtchn: this is called early, before irq is set up. */
notify_remote_via_evtchn(xen_start_info->console_evtchn);
@@ -52,15 +56,22 @@
static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
{
struct xencons_interface *intf = xencons_interface();
+ XENCONS_RING_IDX cons, prod;
- while (intf->in_cons != intf->in_prod) {
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
+ BUG_ON((prod - cons) > sizeof(intf->in));
+
+ while (cons != prod) {
if (xencons_receiver != NULL)
xencons_receiver(
- intf->in + MASK_XENCONS_IDX(intf->in_cons,
- intf->in),
+ intf->in + MASK_XENCONS_IDX(cons++, intf->in),
1, regs);
- intf->in_cons++;
}
+
+ wmb();
+ intf->in_cons = cons;
return IRQ_HANDLED;
}
diff -r d6e0eb8622cd -r 40b4860f554a tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Wed Oct 12 19:58:51 2005
+++ b/tools/console/daemon/io.c Wed Oct 12 20:10:14 2005
@@ -79,44 +79,43 @@
static void buffer_append(struct domain *dom)
{
struct buffer *buffer = &dom->buffer;
- size_t size;
- XENCONS_RING_IDX oldcons;
- int notify = 0;
+ XENCONS_RING_IDX cons, prod, size;
struct xencons_interface *intf = dom->interface;
- while ((size = (intf->out_prod - intf->out_cons)) != 0) {
- notify = 1;
-
- if ((buffer->capacity - buffer->size) < size) {
- buffer->capacity += (size + 1024);
- buffer->data = realloc(buffer->data, buffer->capacity);
- if (buffer->data == NULL) {
- dolog(LOG_ERR, "Memory allocation failed");
- exit(ENOMEM);
- }
- }
-
- oldcons = intf->out_cons;
- while ((intf->out_cons - oldcons) < size) {
- buffer->data[buffer->size] = intf->out[
- MASK_XENCONS_IDX(intf->out_cons, intf->out)];
- buffer->size++;
- intf->out_cons++;
- }
-
- if (buffer->max_capacity &&
- buffer->size > buffer->max_capacity) {
- memmove(buffer->data + (buffer->size -
- buffer->max_capacity),
- buffer->data, buffer->max_capacity);
- buffer->data = realloc(buffer->data,
- buffer->max_capacity);
- buffer->capacity = buffer->max_capacity;
- }
- }
-
- if (notify)
- evtchn_notify(dom);
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb();
+
+ size = prod - cons;
+ if ((size == 0) || (size > sizeof(intf->out)))
+ return;
+
+ if ((buffer->capacity - buffer->size) < size) {
+ buffer->capacity += (size + 1024);
+ buffer->data = realloc(buffer->data, buffer->capacity);
+ if (buffer->data == NULL) {
+ dolog(LOG_ERR, "Memory allocation failed");
+ exit(ENOMEM);
+ }
+ }
+
+ while (cons != prod)
+ buffer->data[buffer->size++] = intf->out[
+ MASK_XENCONS_IDX(cons++, intf->out)];
+
+ mb();
+ intf->out_cons = cons;
+ evtchn_notify(dom);
+
+ if (buffer->max_capacity &&
+ buffer->size > buffer->max_capacity) {
+ memmove(buffer->data + (buffer->size -
+ buffer->max_capacity),
+ buffer->data, buffer->max_capacity);
+ buffer->data = realloc(buffer->data,
+ buffer->max_capacity);
+ buffer->capacity = buffer->max_capacity;
+ }
}
static bool buffer_empty(struct buffer *buffer)
@@ -419,10 +418,14 @@
char msg[80];
int i;
struct xencons_interface *intf = dom->interface;
- XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons;
-
- if (sizeof(intf->in) > filled)
- len = sizeof(intf->in) - filled;
+ XENCONS_RING_IDX cons, prod;
+
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
+
+ if (sizeof(intf->in) > (prod - cons))
+ len = sizeof(intf->in) - (prod - cons);
if (len > sizeof(msg))
len = sizeof(msg);
@@ -441,10 +444,11 @@
}
} else if (domain_is_valid(dom->domid)) {
for (i = 0; i < len; i++) {
- intf->in[MASK_XENCONS_IDX(intf->in_prod, intf->in)] =
+ intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
msg[i];
- intf->in_prod++;
- }
+ }
+ wmb();
+ intf->in_prod = prod;
evtchn_notify(dom);
} else {
close(dom->tty_fd);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|