Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 3292623 in mainline


Ignore:
Timestamp:
2010-04-17T01:16:55Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
e1da7ec
Parents:
596d65c
Message:

thread-safe heap allocator

Location:
uspace/lib/c/generic
Files:
2 edited

Legend:

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

    r596d65c r3292623  
    6262void __main(void *pcb_ptr)
    6363{
    64         int retval;
    65 
     64        /* Initialize user task run-time environment */
    6665        __heap_init();
    6766        __async_init();
     
    7574        char **argv;
    7675       
     76        /* Get command line arguments and initialize
     77           standard input and output */
    7778        if (__pcb == NULL) {
    7879                argc = 0;
     
    8687        }
    8788       
    88         retval = main(argc, argv);
    89 
    90         __stdio_done();
    91         (void) task_retval(retval);
     89        /* Run main() and set task return value
     90           according the result */
     91        (void) task_retval(main(argc, argv));
    9292}
    9393
    9494void __exit(void)
    9595{
     96        __stdio_done();
    9697        fibril_teardown(__tcb_get()->fibril_data);
    9798        _exit(0);
  • uspace/lib/c/generic/malloc.c

    r596d65c r3292623  
    4343#include <bitops.h>
    4444#include <mem.h>
     45#include <futex.h>
    4546#include <adt/gcdlcm.h>
    4647
     
    7576#define NET_SIZE(size)  ((size) - STRUCT_OVERHEAD)
    7677
    77 
    7878/** Header of a heap block
    7979 *
     
    104104extern char _heap;
    105105
     106/** Futex for thread-safe heap manipulation */
     107static futex_t malloc_futex = FUTEX_INITIALIZER;
     108
    106109/** Address of heap start */
    107110static void *heap_start = 0;
     
    119122 *
    120123 * Fills in the structures related to a heap block.
     124 * Should be called only inside the critical section.
    121125 *
    122126 * @param addr Address of the block.
     
    144148 * Verifies that the structures related to a heap block still contain
    145149 * the magic constants. This helps detect heap corruption early on.
     150 * Should be called only inside the critical section.
    146151 *
    147152 * @param addr Address of the block.
     
    161166}
    162167
     168/** Increase the heap area size
     169 *
     170 * Should be called only inside the critical section.
     171 *
     172 * @param size Number of bytes to grow the heap by.
     173 *
     174 */
    163175static bool grow_heap(size_t size)
    164176{
     
    189201}
    190202
     203/** Decrease the heap area
     204 *
     205 * Should be called only inside the critical section.
     206 *
     207 * @param size Number of bytes to shrink the heap by.
     208 *
     209 */
    191210static void shrink_heap(void)
    192211{
     
    196215/** Initialize the heap allocator
    197216 *
    198  * Finds how much physical memory we have and creates
     217 * Find how much physical memory we have and create
    199218 * the heap management structures that mark the whole
    200219 * physical memory as a single free block.
     
    203222void __heap_init(void)
    204223{
     224        futex_down(&malloc_futex);
     225       
    205226        if (as_area_create((void *) &_heap, PAGE_SIZE,
    206227            AS_AREA_WRITE | AS_AREA_READ)) {
     
    213234                block_init(heap_start, heap_end - heap_start, true);
    214235        }
    215 }
    216 
     236       
     237        futex_up(&malloc_futex);
     238}
     239
     240/** Get maximum heap address
     241 *
     242 */
    217243uintptr_t get_max_heap_addr(void)
    218244{
     245        futex_down(&malloc_futex);
     246       
    219247        if (max_heap_size == (size_t) -1)
    220248                max_heap_size =
    221249                    max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
    222250       
    223         return ((uintptr_t) heap_start + max_heap_size);
    224 }
    225 
     251        uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
     252       
     253        futex_up(&malloc_futex);
     254       
     255        return max_heap_addr;
     256}
     257
     258/** Split heap block and mark it as used.
     259 *
     260 * Should be called only inside the critical section.
     261 *
     262 * @param cur  Heap block to split.
     263 * @param size Number of bytes to split and mark from the beginning
     264 *             of the block.
     265 *
     266 */
    226267static void split_mark(heap_block_head_t *cur, const size_t size)
    227268{
     
    243284
    244285/** Allocate a memory block
     286 *
     287 * Should be called only inside the critical section.
    245288 *
    246289 * @param size  The size of the block to allocate.
     
    356399}
    357400
     401/** Allocate memory by number of elements
     402 *
     403 * @param nmemb Number of members to allocate.
     404 * @param size  Size of one member in bytes.
     405 *
     406 * @return Allocated memory or NULL.
     407 *
     408 */
    358409void *calloc(const size_t nmemb, const size_t size)
    359410{
     
    361412        if (block == NULL)
    362413                return NULL;
    363 
     414       
    364415        memset(block, 0, nmemb * size);
    365416        return block;
    366417}
    367418
     419/** Allocate memory
     420 *
     421 * @param size Number of bytes to allocate.
     422 *
     423 * @return Allocated memory or NULL.
     424 *
     425 */
    368426void *malloc(const size_t size)
    369427{
    370         return malloc_internal(size, BASE_ALIGN);
    371 }
    372 
     428        futex_down(&malloc_futex);
     429        void *block = malloc_internal(size, BASE_ALIGN);
     430        futex_up(&malloc_futex);
     431       
     432        return block;
     433}
     434
     435/** Allocate memory with specified alignment
     436 *
     437 * @param align Alignment in byes.
     438 * @param size  Number of bytes to allocate.
     439 *
     440 * @return Allocated memory or NULL.
     441 *
     442 */
    373443void *memalign(const size_t align, const size_t size)
    374444{
     
    379449            1 << (fnzb(max(sizeof(void *), align) - 1) + 1);
    380450       
    381         return malloc_internal(size, palign);
    382 }
    383 
     451        futex_down(&malloc_futex);
     452        void *block = malloc_internal(size, palign);
     453        futex_up(&malloc_futex);
     454       
     455        return block;
     456}
     457
     458/** Reallocate memory block
     459 *
     460 * @param addr Already allocated memory or NULL.
     461 * @param size New size of the memory block.
     462 *
     463 * @return Reallocated memory or NULL.
     464 *
     465 */
    384466void *realloc(const void *addr, const size_t size)
    385467{
    386468        if (addr == NULL)
    387469                return malloc(size);
     470       
     471        futex_down(&malloc_futex);
    388472       
    389473        /* Calculate the position of the header. */
     
    398482       
    399483        void *ptr = NULL;
     484        bool reloc = false;
    400485        size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
    401486        size_t orig_size = head->size;
     
    415500        } else {
    416501                /* Look at the next block. If it is free and the size is
    417                    sufficient then merge the two. */
     502                   sufficient then merge the two. Otherwise just allocate
     503                   a new block, copy the original data into it and
     504                   free the original block. */
    418505                heap_block_head_t *next_head =
    419506                    (heap_block_head_t *) (((void *) head) + head->size);
     
    427514                       
    428515                        ptr = ((void *) head) + sizeof(heap_block_head_t);
    429                 } else {
    430                         ptr = malloc(size);
    431                         if (ptr != NULL) {
    432                                 memcpy(ptr, addr, NET_SIZE(orig_size));
    433                                 free(addr);
    434                         }
     516                } else
     517                        reloc = true;
     518        }
     519       
     520        futex_up(&malloc_futex);
     521       
     522        if (reloc) {
     523                ptr = malloc(size);
     524                if (ptr != NULL) {
     525                        memcpy(ptr, addr, NET_SIZE(orig_size));
     526                        free(addr);
    435527                }
    436528        }
     
    442534 *
    443535 * @param addr The address of the block.
     536 *
    444537 */
    445538void free(const void *addr)
    446539{
     540        futex_down(&malloc_futex);
     541       
    447542        /* Calculate the position of the header. */
    448543        heap_block_head_t *head
     
    483578       
    484579        shrink_heap();
     580       
     581        futex_up(&malloc_futex);
    485582}
    486583
Note: See TracChangeset for help on using the changeset viewer.