Procházet zdrojové kódy

malloc() and memalign(): check for size before parsing through raw blocks

Ioannis Koutras před 12 roky
rodič
revize
f2dea9fed9
2 změnil soubory, kde provedl 126 přidání a 138 odebrání
  1. 56 62
      src/malloc.c
  2. 70 76
      src/memalign.c

+ 56 - 62
src/malloc.c

@@ -38,21 +38,45 @@
 #include "statistics.h"
 
 void * malloc(size_t size) {
+    size_t sys_alloc_size;
     raw_block_header_t *raw_block, *new_raw_block;
     DEFAULT_RB_T *encapsulated_rb;
     void *ptr;
 
-    ptr = NULL;
-
     if(size == 0) {
         return (void *) 0xD34D;
     }
-    
-    /* Try to find a raw block available for allocation */
 
-    SLIST_FOREACH(raw_block, &systemallocator.rb_head, pointers) {
+#ifdef WITH_KNOBS
+    sys_alloc_size = (size_t) systemallocator.dmm_knobs.sys_alloc_size;
+#else /* WITH_KNOBS */
+    sys_alloc_size = SYS_ALLOC_SIZE;
+#endif /* WITH_KNOBS */
+
+    /* Check if the size is appropriate for the use of a freelist-organized or
+     * bitmap-organized raw block. */
+
+#ifdef BITMAP_RB_ONLY
+    /* FIXME currently the raw block size and resolution are fixed */
+    size_t bm_vector_size = BMAP_EL_SIZE * (sys_alloc_size + BMAP_EL_SIZE -
+            sizeof(raw_block_header_t) - sizeof(bitmap_rb_t)) /
+        (BMAP_EL_SIZE + BMAP_EL_SIZE_BITS * BITMAP_RESOLUTION);
+
+    if(2 * size < sys_alloc_size - sizeof(raw_block_header_t) -
+            sizeof(bitmap_rb_t) - bm_vector_size) {
+#endif /* BITMAP_RB_ONLY */
+
+#ifdef FL_RB_ONLY
+    if(2 * size < sys_alloc_size - sizeof(raw_block_header_t) -
+            sizeof(freelist_rb_t)) {
+#endif /* FL_RB_ONLY */
+
+        ptr = NULL;
+
+        /* Try to find a raw block available for allocation */
+        SLIST_FOREACH(raw_block, &systemallocator.rb_head, pointers) {
 #ifdef TRYLOCK_ON_MALLOC
-        if(TRYLOCK_RAW_BLOCK(raw_block) == 0) {
+            if(TRYLOCK_RAW_BLOCK(raw_block) == 0) {
 #else /* TRYLOCK_ON_MALLOC */
             LOCK_RAW_BLOCK(raw_block);
 #endif /* TRYLOCK_ON_MALLOC */
@@ -69,64 +93,13 @@ void * malloc(size_t size) {
                 break;
             }
 #ifdef TRYLOCK_ON_MALLOC
-        }
-#endif /* TRYLOCK_ON_MALLOC */
-    }
-
-    if(ptr == NULL) {
-        /* No suitable memory block has been found, a new raw block shall be
-         * created. */
-
-        size_t sys_alloc_size;
-
-#ifdef WITH_KNOBS
-        sys_alloc_size = (size_t) systemallocator.dmm_knobs.sys_alloc_size;
-#else /* WITH_KNOBS */
-        sys_alloc_size = SYS_ALLOC_SIZE;
-#endif /* WITH_KNOBS */
-
-#ifdef BITMAP_RB_ONLY
-        /* Check if the request would fit in a new bitmap raw block
-         * FIXME currently the raw block size and resolution are fixed
-         */
-
-        size_t bm_vector_size = BMAP_EL_SIZE *
-            (sys_alloc_size + BMAP_EL_SIZE -
-                sizeof(raw_block_header_t) - sizeof(bitmap_rb_t)) /
-            (BMAP_EL_SIZE + BMAP_EL_SIZE_BITS * BITMAP_RESOLUTION);
-
-        if(2 * size > sys_alloc_size - sizeof(raw_block_header_t) -
-                sizeof(bitmap_rb_t) - bm_vector_size) {
-#endif /* BITMAP_RB_ONLY */
-
-#ifdef FL_RB_ONLY
-        if( 2 * size > sys_alloc_size - sizeof(raw_block_header_t) -
-                sizeof(freelist_rb_t)) {
-#endif /* FL_RB_ONLY */
-
-            /* The memory request size is too large to serve it inside a raw
-             * block which contains multiple memory blocks, a big raw block
-             * shall be used. */
-
-            ptr = create_raw_block(size + sizeof(raw_block_header_t),
-                        BIGBLOCK);
-            if(ptr != NULL) {
-
-#ifdef WITH_DEBUG
-                LOCK_GLOBAL();
-                LOCK_RAW_BLOCK(((raw_block_header_t *)ptr));
-                SLIST_INSERT_HEAD(&systemallocator.bb_head,
-                        (raw_block_header_t *) ptr, pointers);
-                UNLOCK_RAW_BLOCK(((raw_block_header_t *)ptr));
-                UNLOCK_GLOBAL();
-#endif /* WITH_DEBUG */
-
-                ptr = (void *)((uintptr_t) ptr + sizeof(raw_block_header_t));
             }
+#endif /* TRYLOCK_ON_MALLOC */
+        }
 
-        } else {
-            /* Try to create a new raw block and allocate a memory block from
-             * there */
+        if(ptr == NULL) {
+            /* No raw block was found, try to create a new one and allocate a
+             * memory block from there. */
 
             new_raw_block = create_raw_block(sys_alloc_size, DEFAULT_RB_TYPE);
             if(new_raw_block != NULL) {
@@ -142,6 +115,27 @@ void * malloc(size_t size) {
                 UNLOCK_RAW_BLOCK(new_raw_block);
             }
         }
+    } else {
+        /* The memory request size is too large to serve it inside a
+         * freelist-organized or bitmap-organized raw block, so a big raw block
+         * shall be used. */
+
+        ptr = create_raw_block(size + sizeof(raw_block_header_t), BIGBLOCK);
+
+        if(ptr != NULL) {
+
+#ifdef WITH_DEBUG
+            /* Add the big block to a list of used big blocks */
+            LOCK_GLOBAL();
+            LOCK_RAW_BLOCK(((raw_block_header_t *)ptr));
+            SLIST_INSERT_HEAD(&systemallocator.bb_head,
+                    (raw_block_header_t *) ptr, pointers);
+            UNLOCK_RAW_BLOCK(((raw_block_header_t *)ptr));
+            UNLOCK_GLOBAL();
+#endif /* WITH_DEBUG */
+
+            ptr = (void *)((uintptr_t) ptr + sizeof(raw_block_header_t));
+        }
     }
 
     MEM_TRACE("dmmlib - m %p %zu\n", ptr, size);

+ 70 - 76
src/memalign.c

@@ -53,17 +53,24 @@ void *memalign(size_t alignment, size_t size) {
     void *memptr;
     DEFAULT_RB_T *encapsulated_rb;
     raw_block_header_t *raw_block;
+    size_t extra_size;
 
     /* Verify that alignment is a power of two */
     assert((alignment && !(alignment & (alignment - 1))) != 0);
 
     memptr = NULL;
 
-    /* Search the available freelist-organized raw blocks for a block whose size
-     * is size + alignment - 1 */
-    SLIST_FOREACH(raw_block, &systemallocator.rb_head, pointers) {
+    /* extra_size denotes the worst-case scenario. Because memcpy() is used, at
+     * least HEADER_SIZE is needed for no memory overlap. */
+    extra_size = sizeof(raw_block_header_t) + alignment - 1;
+
+    if(2 * (size + extra_size) < SYS_ALLOC_SIZE - sizeof(raw_block_header_t) -
+            sizeof(freelist_rb_t)) {
+
+        /* Search the available freelist-organized raw blocks */
+        SLIST_FOREACH(raw_block, &systemallocator.rb_head, pointers) {
 #ifdef TRYLOCK_ON_MALLOC
-        if(TRYLOCK_RAW_BLOCK(raw_block) == 0) {
+            if(TRYLOCK_RAW_BLOCK(raw_block) == 0) {
 #else /* TRYLOCK_ON_MALLOC */
             LOCK_RAW_BLOCK(raw_block);
 #endif /* TRYLOCK_ON_MALLOC */
@@ -76,80 +83,11 @@ void *memalign(size_t alignment, size_t size) {
                 break;
             }
 #ifdef TRYLOCK_ON_MALLOC
-        }
+            }
 #endif /* TRYLOCK_ON_MALLOC */
-    }
-
-    if(memptr == NULL) {
-
-        if( 2 * (size + alignment - 1)  > SYS_ALLOC_SIZE -
-                    sizeof(raw_block_header_t) - sizeof(freelist_rb_t)) {
-
-            /* A big block has to be created */
-
-            /* extra_size denotes the worst-case scenario. Because memcpy() is
-             * used, at least HEADER_SIZE is needed for no memory overlap. */
-            size_t extra_size = sizeof(raw_block_header_t) + alignment - 1;
-
-            memptr = (void *)create_raw_block(size + extra_size +
-                    sizeof(raw_block_header_t), BIGBLOCK);
-
-            if(memptr != NULL) {
-
-                memptr = (void *)((uintptr_t) memptr +
-                        sizeof(raw_block_header_t));
-
-                /* Check if alignment is needed */
-                if(((uintptr_t) memptr) % alignment != 0) {
-                    size_t padding = (- (size_t) memptr) & (alignment - 1);
-                    while(padding < sizeof(raw_block_header_t)) {
-                        padding += alignment;
-                    }
-
-                    /* Sometimes a deadlock is observed unless the old mutex is
-                     * destroyed.
-                     */
-                    DESTROY_RAW_BLOCK_LOCK(((raw_block_header_t *) memptr));
-
-                    /* Copy the raw block's header to the new location */
-                    memcpy((void *)((uintptr_t) memptr
-                                - sizeof(raw_block_header_t) + padding),
-                                (void *)((uintptr_t) memptr
-                                - sizeof(raw_block_header_t)),
-                                sizeof(raw_block_header_t)
-                           );
-
-                    /* Update *memptr */
-                    memptr = (void *)((uintptr_t) memptr + padding);
-
-                    /* Update big block's size and requested size */
-                    raw_block_header_t *aligned_header =
-                        (raw_block_header_t *)((uintptr_t) memptr -
-                                sizeof(raw_block_header_t));
-                    INIT_RAW_BLOCK_LOCK(aligned_header);
-                    LOCK_RAW_BLOCK(aligned_header);
-                    aligned_header->size -= padding;
-#ifdef REQUEST_SIZE_INFO
-                    aligned_header->requested_size = size;
-#endif /* REQUEST_SIZE_INFO */
-                    UNLOCK_RAW_BLOCK(aligned_header);
-
-                }
-
-#ifdef WITH_DEBUG
-                LOCK_GLOBAL();
-                LOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) memptr -
-                                sizeof(raw_block_header_t))));
-                SLIST_INSERT_HEAD(&systemallocator.bb_head,
-                        (raw_block_header_t *) ((uintptr_t) memptr -
-                            sizeof(raw_block_header_t)), pointers);
-                UNLOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) memptr -
-                                sizeof(raw_block_header_t))));
-                UNLOCK_GLOBAL();
-#endif /* WITH_DEBUG */
+        }
 
-            }
-        } else { /* Create a new raw block and use it */
+        if(memptr == NULL) { /* no block was found, try to create a new one */
             raw_block = create_raw_block((size_t) SYS_ALLOC_SIZE,
                     DEFAULT_RB_TYPE);
             if(raw_block != NULL) {
@@ -164,6 +102,62 @@ void *memalign(size_t alignment, size_t size) {
                 UNLOCK_RAW_BLOCK(raw_block);
             }
         }
+    } else { /* A big block has to be created */
+
+        memptr = (void *)create_raw_block(size + extra_size +
+                sizeof(raw_block_header_t), BIGBLOCK);
+
+        if(memptr != NULL) {
+
+            memptr = (void *)((uintptr_t) memptr + sizeof(raw_block_header_t));
+
+            /* Check if alignment is needed */
+            if(((uintptr_t) memptr) % alignment != 0) {
+                size_t padding = (- (size_t) memptr) & (alignment - 1);
+                while(padding < sizeof(raw_block_header_t)) {
+                    padding += alignment;
+                }
+
+                /* Sometimes a deadlock is observed unless the old mutex is
+                 * destroyed. */
+                DESTROY_RAW_BLOCK_LOCK(((raw_block_header_t *) memptr));
+
+                /* Copy the raw block's header to the new location */
+                memcpy((void *)((uintptr_t) memptr -
+                            sizeof(raw_block_header_t) + padding),
+                        (void *)((uintptr_t) memptr -
+                            sizeof(raw_block_header_t)),
+                        sizeof(raw_block_header_t)
+                      );
+
+                /* Update *memptr */
+                memptr = (void *)((uintptr_t) memptr + padding);
+
+                /* Update big block's size and requested size */
+                raw_block_header_t *aligned_header =
+                    (raw_block_header_t *)((uintptr_t) memptr -
+                            sizeof(raw_block_header_t));
+                INIT_RAW_BLOCK_LOCK(aligned_header);
+                LOCK_RAW_BLOCK(aligned_header);
+                aligned_header->size -= padding;
+#ifdef REQUEST_SIZE_INFO
+                aligned_header->requested_size = size;
+#endif /* REQUEST_SIZE_INFO */
+                UNLOCK_RAW_BLOCK(aligned_header);
+            }
+
+#ifdef WITH_DEBUG
+            LOCK_GLOBAL();
+            LOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) memptr -
+                            sizeof(raw_block_header_t))));
+            SLIST_INSERT_HEAD(&systemallocator.bb_head,
+                    (raw_block_header_t *) ((uintptr_t) memptr -
+                        sizeof(raw_block_header_t)), pointers);
+            UNLOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) memptr -
+                            sizeof(raw_block_header_t))));
+            UNLOCK_GLOBAL();
+#endif /* WITH_DEBUG */
+        }
     }
 
     if(memptr != NULL) {