Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/malloc.c

    r5b46ec8 r3e6a98c5  
    6767/** Heap shrink granularity
    6868 *
    69  * Try not to pump and stress the heap too much
     69 * Try not to pump and stress the heap to much
    7070 * by shrinking and enlarging it too often.
    71  * A heap area won't shrink if the released
     71 * A heap area won't shrunk if it the released
    7272 * free block is smaller than this constant.
    7373 *
     
    200200        do { \
    201201                if (!(expr)) {\
    202                         heap_unlock(); \
     202                        futex_up(&malloc_futex); \
    203203                        assert_abort(#expr, __FILE__, __LINE__); \
    204204                } \
     
    210210
    211211#endif /* NDEBUG */
    212 
    213 
    214 #ifdef FUTEX_UPGRADABLE
    215 /** True if the heap may be accessed from multiple threads. */
    216 static bool multithreaded = false;
    217 
    218 /** Makes accesses to the heap thread safe. */
    219 void malloc_enable_multithreaded(void)
    220 {
    221         multithreaded = true;
    222 }
    223 
    224 /** Serializes access to the heap from multiple threads. */
    225 static inline void heap_lock(void)
    226 {
    227         if (multithreaded) {
    228                 futex_down(&malloc_futex);
    229         } else {
    230                 /*
    231                  * Malloc never switches fibrils while the heap is locked.
    232                  * Similarly, it never creates new threads from within the
    233                  * locked region. Therefore, if there are no other threads
    234                  * except this one, the whole operation will complete without
    235                  * any interruptions.
    236                  */
    237         }
    238 }
    239 
    240 /** Serializes access to the heap from multiple threads. */
    241 static inline void heap_unlock(void)
    242 {
    243         if (multithreaded) {
    244                 futex_up(&malloc_futex);
    245         } else {
    246                 /*
    247                  * Malloc never switches fibrils while the heap is locked.
    248                  * Similarly, it never creates new threads from within the
    249                  * locked region. Therefore, if there are no other threads
    250                  * except this one, the whole operation will complete without
    251                  * any interruptions.
    252                  */
    253         }
    254 }
    255 
    256 #else
    257 
    258 /** Makes accesses to the heap thread safe. */
    259 void malloc_enable_multithreaded(void)
    260 {
    261         /* No-op. Already using thread-safe heap locking operations. */
    262 }
    263 
    264 /** Serializes access to the heap from multiple threads. */
    265 static inline void heap_lock(void)
    266 {
    267         futex_down(&malloc_futex);
    268 }
    269 
    270 /** Serializes access to the heap from multiple threads. */
    271 static inline void heap_unlock(void)
    272 {
    273         futex_up(&malloc_futex);
    274 }
    275 #endif
    276 
    277212
    278213/** Initialize a heap block
     
    354289        size_t asize = ALIGN_UP(size, PAGE_SIZE);
    355290        void *astart = as_area_create(AS_AREA_ANY, asize,
    356             AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE, AS_AREA_UNPAGED);
     291            AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE);
    357292        if (astart == AS_MAP_FAILED)
    358293                return false;
     
    850785void *malloc(const size_t size)
    851786{
    852         heap_lock();
     787        futex_down(&malloc_futex);
    853788        void *block = malloc_internal(size, BASE_ALIGN);
    854         heap_unlock();
    855 
     789        futex_up(&malloc_futex);
     790       
    856791        return block;
    857792}
     
    872807        size_t palign =
    873808            1 << (fnzb(max(sizeof(void *), align) - 1) + 1);
    874 
    875         heap_lock();
     809       
     810        futex_down(&malloc_futex);
    876811        void *block = malloc_internal(size, palign);
    877         heap_unlock();
    878 
     812        futex_up(&malloc_futex);
     813       
    879814        return block;
    880815}
     
    893828                return malloc(size);
    894829       
    895         heap_lock();
     830        futex_down(&malloc_futex);
    896831       
    897832        /* Calculate the position of the header. */
     
    928863                ptr = ((void *) head) + sizeof(heap_block_head_t);
    929864        } else {
     865                /*
     866                 * Look at the next block. If it is free and the size is
     867                 * sufficient then merge the two. Otherwise just allocate
     868                 * a new block, copy the original data into it and
     869                 * free the original block.
     870                 */
    930871                heap_block_head_t *next_head =
    931872                    (heap_block_head_t *) (((void *) head) + head->size);
    932                 bool have_next = ((void *) next_head < area->end);
    933 
    934                 if (((void *) head) + real_size > area->end) {
    935                         /*
    936                          * The current area is too small to hold the resized
    937                          * block. Make sure there are no used blocks standing
    938                          * in our way and try to grow the area using real_size
    939                          * as a safe upper bound.
    940                          */
    941 
    942                         bool have_next_next;
    943 
    944                         if (have_next) {
    945                                 have_next_next = (((void *) next_head) +
    946                                     next_head->size < area->end);
    947                         }
    948                         if (!have_next || (next_head->free && !have_next_next)) {
    949                                 /*
    950                                  * There is no next block in this area or
    951                                  * it is a free block and there is no used
    952                                  * block following it. There can't be any
    953                                  * free block following it either as
    954                                  * two free blocks would be merged.
    955                                  */
    956                                 (void) area_grow(area, real_size);
    957                         }
    958                 }
    959                
    960                 /*
    961                  * Look at the next block. If it is free and the size is
    962                  * sufficient then merge the two. Otherwise just allocate a new
    963                  * block, copy the original data into it and free the original
    964                  * block.
    965                  */
    966 
    967                 if (have_next && (head->size + next_head->size >= real_size) &&
    968                     next_head->free) {
     873               
     874                if (((void *) next_head < area->end) &&
     875                    (head->size + next_head->size >= real_size) &&
     876                    (next_head->free)) {
    969877                        block_check(next_head);
    970                         block_init(head, head->size + next_head->size, false,
    971                             area);
     878                        block_init(head, head->size + next_head->size, false, area);
    972879                        split_mark(head, real_size);
    973880                       
    974881                        ptr = ((void *) head) + sizeof(heap_block_head_t);
    975882                        next_fit = NULL;
    976                 } else {
     883                } else
    977884                        reloc = true;
    978                 }
    979         }
    980        
    981         heap_unlock();
     885        }
     886       
     887        futex_up(&malloc_futex);
    982888       
    983889        if (reloc) {
     
    1002908                return;
    1003909       
    1004         heap_lock();
     910        futex_down(&malloc_futex);
    1005911       
    1006912        /* Calculate the position of the header. */
     
    1047953        heap_shrink(area);
    1048954       
    1049         heap_unlock();
     955        futex_up(&malloc_futex);
    1050956}
    1051957
    1052958void *heap_check(void)
    1053959{
    1054         heap_lock();
     960        futex_down(&malloc_futex);
    1055961       
    1056962        if (first_heap_area == NULL) {
    1057                 heap_unlock();
     963                futex_up(&malloc_futex);
    1058964                return (void *) -1;
    1059965        }
     
    1069975                    (((uintptr_t) area->start % PAGE_SIZE) != 0) ||
    1070976                    (((uintptr_t) area->end % PAGE_SIZE) != 0)) {
    1071                         heap_unlock();
     977                        futex_up(&malloc_futex);
    1072978                        return (void *) area;
    1073979                }
     
    1080986                        /* Check heap block consistency */
    1081987                        if (head->magic != HEAP_BLOCK_HEAD_MAGIC) {
    1082                                 heap_unlock();
     988                                futex_up(&malloc_futex);
    1083989                                return (void *) head;
    1084990                        }
     
    1088994                        if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) ||
    1089995                            (head->size != foot->size)) {
    1090                                 heap_unlock();
     996                                futex_up(&malloc_futex);
    1091997                                return (void *) foot;
    1092998                        }
     
    10941000        }
    10951001       
    1096         heap_unlock();
     1002        futex_up(&malloc_futex);
    10971003       
    10981004        return NULL;
Note: See TracChangeset for help on using the changeset viewer.