From a201c20b41a2f0725977bcb89a2a66135d776ba2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 23 Jan 2014 16:27:52 -0500 Subject: ewah: support platforms that require aligned reads The caller may hand us an unaligned buffer (e.g., because it is an mmap of a file with many ewah bitmaps). On some platforms (like SPARC) this can cause a bus error. We can fix it with a combination of get_be32 and moving the data into an aligned buffer (which we would do anyway, but we can move it before fixing the endianness). Signed-off-by: Vicent Marti Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- ewah/ewah_io.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'ewah') diff --git a/ewah/ewah_io.c b/ewah/ewah_io.c index aed0da6866..4a7fae6b8c 100644 --- a/ewah/ewah_io.c +++ b/ewah/ewah_io.c @@ -112,23 +112,38 @@ int ewah_serialize(struct ewah_bitmap *self, int fd) int ewah_read_mmap(struct ewah_bitmap *self, void *map, size_t len) { - uint32_t *read32 = map; - eword_t *read64; - size_t i; + uint8_t *ptr = map; + + self->bit_size = get_be32(ptr); + ptr += sizeof(uint32_t); + + self->buffer_size = self->alloc_size = get_be32(ptr); + ptr += sizeof(uint32_t); - self->bit_size = ntohl(*read32++); - self->buffer_size = self->alloc_size = ntohl(*read32++); self->buffer = ewah_realloc(self->buffer, self->alloc_size * sizeof(eword_t)); if (!self->buffer) return -1; - for (i = 0, read64 = (void *)read32; i < self->buffer_size; ++i) - self->buffer[i] = ntohll(*read64++); + /* + * Copy the raw data for the bitmap as a whole chunk; + * if we're in a little-endian platform, we'll perform + * the endianness conversion in a separate pass to ensure + * we're loading 8-byte aligned words. + */ + memcpy(self->buffer, ptr, self->buffer_size * sizeof(uint64_t)); + ptr += self->buffer_size * sizeof(uint64_t); + +#if __BYTE_ORDER != __BIG_ENDIAN + { + size_t i; + for (i = 0; i < self->buffer_size; ++i) + self->buffer[i] = ntohll(self->buffer[i]); + } +#endif - read32 = (void *)read64; - self->rlw = self->buffer + ntohl(*read32++); + self->rlw = self->buffer + get_be32(ptr); return (3 * 4) + (self->buffer_size * 8); } -- cgit v1.2.3