From 2100fa1099b086411270a2876dde0532ea2806fa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 Apr 2013 02:09:36 +0200 Subject: bus: calculate iovec for messages only when we need it --- src/libsystemd-bus/bus-message.c | 68 ++++++++++++++-------------------------- src/libsystemd-bus/bus-message.h | 3 +- src/libsystemd-bus/bus-socket.c | 37 +++++++++++++++++++++- src/libsystemd-bus/sd-bus.c | 4 +-- 4 files changed, 64 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 4d4f3b5260..fb4718085b 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -302,7 +302,6 @@ int bus_message_from_malloc( m->n_iovec = 1; m->iovec[0].iov_base = buffer; m->iovec[0].iov_len = length; - m->size = length; r = message_parse_fields(m); if (r < 0) @@ -2794,42 +2793,6 @@ static int message_parse_fields(sd_bus_message *m) { return 0; } -static void setup_iovec(sd_bus_message *m) { - assert(m); - assert(m->sealed); - - m->n_iovec = 0; - m->size = 0; - - m->iovec[m->n_iovec].iov_base = m->header; - m->iovec[m->n_iovec].iov_len = sizeof(*m->header); - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - - if (m->fields) { - m->iovec[m->n_iovec].iov_base = m->fields; - m->iovec[m->n_iovec].iov_len = m->header->fields_size; - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - - if (m->header->fields_size % 8 != 0) { - static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 }; - - m->iovec[m->n_iovec].iov_base = (void*) padding; - m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8; - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - } - } - - if (m->body) { - m->iovec[m->n_iovec].iov_base = m->body; - m->iovec[m->n_iovec].iov_len = m->header->body_size; - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - } -} - int bus_message_seal(sd_bus_message *m, uint64_t serial) { int r; @@ -2857,8 +2820,6 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) { m->header->serial = serial; m->sealed = true; - setup_iovec(m); - return 0; } @@ -3074,22 +3035,31 @@ int bus_message_dump(sd_bus_message *m) { int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { size_t total; - unsigned i; void *p, *e; assert(m); assert(buffer); assert(sz); - for (i = 0, total = 0; i < m->n_iovec; i++) - total += m->iovec[i].iov_len; + total = bus_message_size(m); p = malloc(total); if (!p) return -ENOMEM; - for (i = 0, e = p; i < m->n_iovec; i++) - e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len); + e = mempcpy(p, m->header, sizeof(*m->header)); + + if (m->fields) { + e = mempcpy(e, m->fields, m->header->fields_size); + + if (m->header->fields_size % 8 != 0) + e = mempset(e, 0, 8 - (m->header->fields_size % 8)); + } + + if (m->body) + e = mempcpy(e, m->body, m->header->body_size); + + assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p)); *buffer = p; *sz = total; @@ -3162,3 +3132,13 @@ const char* bus_message_get_arg(sd_bus_message *m, unsigned i) { return t; } + +size_t bus_message_size(sd_bus_message *m) { + assert(m); + assert(m->sealed); + + return + sizeof(*m->header) + + ALIGN8(m->header->fields_size) + + m->header->body_size; +} diff --git a/src/libsystemd-bus/bus-message.h b/src/libsystemd-bus/bus-message.h index cc1e10d843..126ced0083 100644 --- a/src/libsystemd-bus/bus-message.h +++ b/src/libsystemd-bus/bus-message.h @@ -92,7 +92,6 @@ struct sd_bus_message { struct iovec iovec[4]; unsigned n_iovec; - size_t size; char *peeked_signature; }; @@ -146,3 +145,5 @@ int bus_message_from_malloc( const char* bus_message_get_arg(sd_bus_message *m, unsigned i); int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap); + +size_t bus_message_size(sd_bus_message *m); diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c index 1a0d9266f2..5e285c9e52 100644 --- a/src/libsystemd-bus/bus-socket.c +++ b/src/libsystemd-bus/bus-socket.c @@ -58,6 +58,39 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) { } } +static void append_iovec(sd_bus_message *m, const void *p, size_t sz) { + assert(m); + assert(p); + assert(sz > 0); + + m->iovec[m->n_iovec].iov_base = (void*) p; + m->iovec[m->n_iovec].iov_len = sz; + m->n_iovec++; +} + +static void bus_message_setup_iovec(sd_bus_message *m) { + assert(m); + assert(m->sealed); + + if (m->n_iovec > 0) + return; + + append_iovec(m, m->header, sizeof(*m->header)); + + if (m->fields) { + append_iovec(m, m->fields, m->header->fields_size); + + if (m->header->fields_size % 8 != 0) { + static const uint8_t padding[7] = {}; + + append_iovec(m, padding, 8 - (m->header->fields_size % 8)); + } + } + + if (m->body) + append_iovec(m, m->body, m->header->body_size); +} + bool bus_socket_auth_needs_write(sd_bus *b) { unsigned i; @@ -729,9 +762,11 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { assert(idx); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); - if (*idx >= m->size) + if (*idx >= bus_message_size(m)) return 0; + bus_message_setup_iovec(m); + n = m->n_iovec * sizeof(struct iovec); iov = alloca(n); memcpy(iov, m->iovec, n); diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 2f084c26b3..89172e6369 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -965,7 +965,7 @@ static int dispatch_wqueue(sd_bus *bus) { } else if (r == 0) /* Didn't do anything this time */ return ret; - else if (bus->windex >= bus->wqueue[0]->size) { + else if (bus->windex >= bus_message_size(bus->wqueue[0])) { /* Fully written. Let's drop the entry from * the queue. * @@ -1066,7 +1066,7 @@ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) { if (r < 0) { sd_bus_close(bus); return r; - } else if (idx < m->size) { + } else if (idx < bus_message_size(m)) { /* Wasn't fully written. So let's remember how * much was written. Note that the first entry * of the wqueue array is always allocated so -- cgit v1.2.3-54-g00ecf