diff options
author | Vicent Marti <tanoku@gmail.com> | 2014-01-23 16:27:52 -0500 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-01-23 14:05:05 -0800 |
commit | a201c20b41a2f0725977bcb89a2a66135d776ba2 (patch) | |
tree | b92f2959254e3ef18c496a644012abbe9a431096 | |
parent | c3d8da571f11b0146e60591c040da399d411c3f2 (diff) | |
download | git-a201c20b41a2f0725977bcb89a2a66135d776ba2.tar.gz |
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 <tanoku@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | ewah/ewah_io.c | 33 |
1 files changed, 24 insertions, 9 deletions
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); } |