瀏覽代碼

memalign(): refactoring

Ioannis Koutras 12 年之前
父節點
當前提交
5878ca5a32
共有 6 個文件被更改,包括 167 次插入96 次删除
  1. 5 0
      include/dmmlib/freelist/freelist.h
  2. 7 0
      src/CMakeLists.txt
  3. 1 1
      src/freelist/malloc.c
  4. 115 0
      src/freelist/memalign.c
  5. 23 94
      src/memalign.c
  6. 16 1
      src/release_memory.c

+ 5 - 0
include/dmmlib/freelist/freelist.h

@@ -61,4 +61,9 @@ void freelist_free(freelist_rb_t *raw_block, void *ptr);
 
 void * freelist_realloc(freelist_rb_t *raw_block, void *ptr, size_t size);
 
+#ifdef WITH_MEMALIGN
+void * freelist_memalign(freelist_rb_t *raw_block, size_t alignment,
+        size_t size);
+#endif /* WITH_MEMALIGN */
+
 #endif /* FREELIST_H */

+ 7 - 0
src/CMakeLists.txt

@@ -213,6 +213,13 @@ if(WITH_MEMALIGN)
     ${dmmlib_SRCS}
     memalign.c
   )
+
+  if(RAW_BLOCKS_TYPE STREQUAL "freelist")
+    set(dmmlib_SRCS
+      ${dmmlib_SRCS}
+      freelist/memalign.c
+      )
+  endif(RAW_BLOCKS_TYPE STREQUAL "freelist")
 endif(WITH_MEMALIGN)
 
 if(PARSE_ENV)

+ 1 - 1
src/freelist/malloc.c

@@ -57,7 +57,7 @@ size_t req_padding(size_t size) {
 
     align = size % 4;
     if(align != 0) {
-        size += 4 - align;
+        size += (4 - align);
     }
 
     return size;

+ 115 - 0
src/freelist/memalign.c

@@ -0,0 +1,115 @@
+/*
+ *   Copyright Institute of Communication and Computer Systems (ICCS)
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+/**
+ * @file   freelist/memalign.c
+ * @author Ioannis Koutras
+ * @date   February 2013
+ * @brief  memalign() implementation for freelist-organised raw blocks
+ */
+
+#include "dmmlib/freelist/freelist.h"
+
+#include <inttypes.h>
+
+#include "memcpy.h"
+
+#include "dmmlib/config.h"
+#include "freelist/block_header_funcs.h"
+
+void * freelist_memalign(freelist_rb_t *raw_block, size_t alignment,
+        size_t size) {
+    void *return_ptr;
+
+    return_ptr = freelist_malloc(raw_block, size + alignment - 1);
+
+    if(return_ptr != NULL) {
+
+check_alignment:
+
+        if(((uintptr_t) return_ptr) % alignment == 0) {
+            /* Memory address is already aligned, no need for
+             * modifications */
+            return return_ptr;
+        }
+
+        size_t padding = (- (size_t) return_ptr) & (alignment - 1);
+
+        block_header_t *block_header = get_header(return_ptr);
+
+        /* Check if the currently selected memory block is the first
+         * allocated in the raw block. If it is, then there is no previous
+         * block in the data layout, so we cannot increase its size as this
+         * would conclude to wasted space. Instead of this, we try to
+         * allocate another block which is guaranteed not to be the first
+         * memory block at this point. If we find one, then we free the
+         * first allocated block and repeat the process of alignment.
+         * Otherwise, we go to the next raw block. */
+
+        size_t previous_size_availability =
+            get_previous_size_availability(block_header);
+
+        if(previous_size_availability == 1) {
+            void *old_ptr = return_ptr;
+
+            return_ptr = freelist_malloc(raw_block, size + alignment - 1);
+
+            freelist_free(raw_block, old_ptr);
+
+            if(return_ptr != NULL) {
+                goto check_alignment;
+            }
+        } else {
+            size_t previous_size = previous_size_availability >> 1;
+            size_t previous_availability = previous_size_availability & 1;
+            block_header_t *previous_block = (block_header_t *)
+                ((uintptr_t) block_header - previous_size);
+
+            block_header_t *next_block = get_dlnext(raw_block,
+                    block_header);
+
+            previous_size += padding;
+            previous_block->size = (previous_size << 1) |
+                previous_availability;
+
+            block_header->previous_size = (previous_size << 1) |
+                previous_availability;
+
+#ifdef REQUEST_SIZE_INFO
+            block_header->requested_size = size;
+#endif /* REQUEST_SIZE_INFO */
+
+            size_t new_size = get_size(block_header) - padding;
+
+            block_header->size = (new_size << 1) | 1;
+
+            if(next_block != NULL) {
+                next_block->previous_size = block_header->size;
+            } else { /* The aligned memory block is the border pointer */
+                raw_block->border_ptr = (block_header_t *)
+                    ((uintptr_t) block_header + padding);
+            }
+
+            memcpy((void *) ((uintptr_t) block_header + padding),
+                    (void *) block_header, HEADER_SIZE);
+
+            return_ptr = (void *)((uintptr_t) return_ptr + padding);
+        }
+    }
+
+    return return_ptr;
+}

+ 23 - 94
src/memalign.c

@@ -40,7 +40,6 @@
 #include "trace.h"
 
 #include "default_rb.h"
-#include "freelist/block_header_funcs.h"
 
 #ifdef BITMAP_RB_ONLY
 #error Current memory-aligned allocation implementation supports only \
@@ -70,93 +69,16 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) {
         LOCK_RAW_BLOCK(raw_block);
         encapsulated_rb = (freelist_rb_t *) 
             ((uintptr_t) raw_block + sizeof(raw_block_header_t));
-        *memptr = dmmlib_malloc(encapsulated_rb, size + alignment - 1);
+        *memptr = freelist_memalign(encapsulated_rb, alignment, size);
         UNLOCK_RAW_BLOCK(raw_block);
-
-CheckAlignment:
-
-        if(*memptr != NULL) {
-
-            /* Check that a valid pointer has been returned */
-            assert(((uintptr_t) raw_block < (uintptr_t) *memptr) &&
-                    ((uintptr_t) *memptr < (uintptr_t) raw_block +
-                     raw_block->size));
-
-            if(((uintptr_t) *memptr) % alignment == 0) {
-                /* Memory address is already aligned, no need for
-                 * modifications */
-                break;
-            }
-
-            size_t padding = (- (size_t) *memptr) & (alignment - 1);
-
-            block_header_t *block_header = get_header(*memptr);
-
-            /* Check if the currently selected memory block is the first
-             * allocated in the raw block. If it is, then there is no previous
-             * block in the data layout, so we cannot increase its size as this
-             * would conclude to wasted space. Instead of this, we try to
-             * allocate another block which is guaranteed not to be the first
-             * memory block at this point. If we find one, then we free the
-             * first allocated block and repeat the process of alignment.
-             * Otherwise, we go to the next raw block. */
-
-            size_t previous_size_availability =
-                get_previous_size_availability(block_header);
-
-            if(previous_size_availability == 1) {
-                void *old_ptr = *memptr;
-
-                *memptr = dmmlib_malloc(encapsulated_rb, size + alignment - 1);
-
-                dmmlib_free(encapsulated_rb, old_ptr);
-
-                if(*memptr != NULL) {
-                    goto CheckAlignment;
-                } else {
-                    /* Abandon current raw block */
-                }
-            } else {
-                size_t previous_size = previous_size_availability >> 1;
-                size_t previous_availability = previous_size_availability & 1;
-                block_header_t *previous_block = (block_header_t *)
-                    ((uintptr_t) block_header - previous_size);
-
-                block_header_t *next_block = get_dlnext(encapsulated_rb,
-                        block_header);
-
-                previous_size += padding;
-                previous_block->size = (previous_size << 1) |
-                    previous_availability;
-
-                block_header->previous_size = (previous_size << 1) |
-                    previous_availability;
-
-                size_t new_size = get_size(block_header) - padding;
-
-                block_header->size = (new_size << 1) | 1;
-
-                if(next_block != NULL) {
-                    next_block->previous_size = block_header->size;
-                } else { /* The aligned memory block is the border pointer */
-                    encapsulated_rb->border_ptr = (block_header_t *)
-                        ((uintptr_t) block_header + padding);
-                }
-
-                memcpy((void *) ((uintptr_t) block_header + padding),
-                        (void *) block_header, HEADER_SIZE);
-
-                *memptr = (void *)((uintptr_t) *memptr + padding);
-
-                break;
-            }
-        }
     }
 
     if(*memptr == NULL) {
 
-        if( 2 * size > SYS_ALLOC_SIZE - sizeof(raw_block_header_t) -
-                sizeof(freelist_rb_t)) { /* A big block has to be created */
+        if( 2 * (size + alignment - 1)  > SYS_ALLOC_SIZE -
+                    sizeof(raw_block_header_t) - sizeof(freelist_rb_t)) {
+
+            /* A big block has to be created */
 
             *memptr = (void *)create_raw_block(size + alignment - 1 +
                     sizeof(raw_block_header_t), BIGBLOCK);
@@ -165,9 +87,11 @@ CheckAlignment:
                 *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);
 
+                    /* 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
@@ -175,12 +99,20 @@ CheckAlignment:
                                 sizeof(raw_block_header_t)
                            );
 
-                    munmap((void *)((uintptr_t) *memptr
-                                - sizeof(raw_block_header_t)
-                                - padding),
-                            (size_t) padding);
-
+                    /* 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));
+                    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
@@ -190,7 +122,8 @@ CheckAlignment:
                 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 *) *memptr));
+                UNLOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) *memptr -
+                                sizeof(raw_block_header_t))));
                 UNLOCK_GLOBAL();
 #endif /* WITH_DEBUG */
 
@@ -206,12 +139,8 @@ CheckAlignment:
 
                 encapsulated_rb = (DEFAULT_RB_T *)
                     ((uintptr_t) raw_block + sizeof(raw_block_header_t));
-                *memptr = dmmlib_malloc(encapsulated_rb, size + alignment - 1);
+                *memptr = freelist_memalign(encapsulated_rb, alignment, size);
                 UNLOCK_RAW_BLOCK(raw_block);
-
-                if(*memptr != NULL) {
-                    goto CheckAlignment;
-                }
             }
         }
     }

+ 16 - 1
src/release_memory.c

@@ -27,6 +27,21 @@
 
 #include <sys/mman.h>
 
+#include <unistd.h>
+#include <inttypes.h>
+#include <assert.h>
+
 void release_memory(raw_block_header_t *raw_block) {
-    munmap((void *)raw_block, raw_block->size);
+    int error_code;
+
+    size_t pagesize = (size_t) sysconf(_SC_PAGESIZE);
+    size_t padding = (uintptr_t) raw_block % pagesize;
+
+    if(padding != 0) {
+        error_code = munmap((void *) ((uintptr_t) raw_block - padding),
+                    raw_block->size + padding);
+    } else {
+        error_code = munmap((void *)raw_block, raw_block->size);
+    }
+    assert(error_code == 0);
 }