aboutsummaryrefslogtreecommitdiffstats
path: root/tools/console
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-10-12 21:10:14 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-10-12 21:10:14 +0100
commitdfc0b259c1b59b8b22e4a4b9fa2651deec42bc9d (patch)
treee9f582ba76d39f2f0547229078f2b07d229b1821 /tools/console
parent4e5630275d61645acaeb553b927723d187bd0627 (diff)
downloadxen-dfc0b259c1b59b8b22e4a4b9fa2651deec42bc9d.tar.gz
xen-dfc0b259c1b59b8b22e4a4b9fa2651deec42bc9d.tar.bz2
xen-dfc0b259c1b59b8b22e4a4b9fa2651deec42bc9d.zip
Add memory barriers to console ring accesses. Similar to what
Rusty uses for xenbus messaging. Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'tools/console')
-rw-r--r--tools/console/daemon/io.c76
1 files changed, 40 insertions, 36 deletions
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index fc772b7580..9039a96525 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -79,44 +79,43 @@ static void evtchn_notify(struct domain *dom)
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;
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb();
- 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++;
- }
+ size = prod - cons;
+ if ((size == 0) || (size > sizeof(intf->out)))
+ return;
- 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 ((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);
}
}
- if (notify)
- evtchn_notify(dom);
+ 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 @@ static void handle_tty_read(struct domain *dom)
char msg[80];
int i;
struct xencons_interface *intf = dom->interface;
- XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons;
+ XENCONS_RING_IDX cons, prod;
+
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
- if (sizeof(intf->in) > filled)
- len = sizeof(intf->in) - filled;
+ if (sizeof(intf->in) > (prod - cons))
+ len = sizeof(intf->in) - (prod - cons);
if (len > sizeof(msg))
len = sizeof(msg);
@@ -441,10 +444,11 @@ static void handle_tty_read(struct domain *dom)
}
} 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);