Make smalloc redzone pointer properly aligned
authorJens Axboe <jens.axboe@oracle.com>
Tue, 7 Jul 2009 15:43:11 +0000 (17:43 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 7 Jul 2009 15:43:11 +0000 (17:43 +0200)
It would SIGBUS on archs that require proper alignment, and work
suboptimally on others. Real fix is pending, making sure that
we always return naturally aligned pointers. But this at least
makes it work on sparc64.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
smalloc.c

index e82ef1d..e0bc498 100644 (file)
--- a/smalloc.c
+++ b/smalloc.c
@@ -268,9 +268,20 @@ void scleanup(void)
 }
 
 #ifdef SMALLOC_REDZONE
+static void *postred_ptr(struct block_hdr *hdr)
+{
+       const int int_mask = sizeof(unsigned int) - 1;
+       unsigned long ptr;
+
+       ptr = (unsigned long) hdr + hdr->size - sizeof(unsigned int);
+       ptr = (ptr + int_mask) & ~int_mask;
+
+       return (void *) ptr;
+}
+
 static void fill_redzone(struct block_hdr *hdr)
 {
-       unsigned int *postred = (void *) hdr + hdr->size - sizeof(unsigned int);
+       unsigned int *postred = postred_ptr(hdr);
 
        hdr->prered = SMALLOC_PRE_RED;
        *postred = SMALLOC_POST_RED;
@@ -278,7 +289,7 @@ static void fill_redzone(struct block_hdr *hdr)
 
 static void sfree_check_redzone(struct block_hdr *hdr)
 {
-       unsigned int *postred = (void *) hdr + hdr->size - sizeof(unsigned int);
+       unsigned int *postred = postred_ptr(hdr);
 
        if (hdr->prered != SMALLOC_PRE_RED) {
                fprintf(stderr, "smalloc pre redzone destroyed!\n");
@@ -414,8 +425,12 @@ static void *smalloc_pool(struct pool *pool, unsigned int size)
        unsigned int alloc_size = size + sizeof(struct block_hdr);
        void *ptr;
 
+       /*
+        * Use twice the size for good luck, we may need to adjust
+        * alignment.
+        */
 #ifdef SMALLOC_REDZONE
-       alloc_size += sizeof(unsigned int);
+       alloc_size += 2 * sizeof(unsigned int);
 #endif
 
        ptr = __smalloc_pool(pool, alloc_size);