/* Global entry points */
int page_descrs_init (void)
{
    page_descr_t *main_descr, *page_descr, *pool_head, *cache_head;
    int i;

    /* Allocate first descriptor page */
    malloc_base = page_get(1);
    if (malloc_base == NULL) {
        set_errno(ENOMEM);
        MEMOPS_PRINTF("%s: cannot get main descriptor\n", __func__);
        return -1;
    }
    /* Init free slots in this page */
    free_slots_init(malloc_base, sizeof(page_descr_t), PAGE_SIZE);
    /* Init main descriptor */
    page_descr = malloc_base;
    main_descr = main_descr_get();
    main_descr->addr = page_descr;
    main_descr->nb = 0;
    main_descr->next = page_descr;
    main_descr->prev = page_descr;
    page_descr->nb = 1;
    page_descr->addr = page_descr + 2;
    page_descr->next = main_descr;
    page_descr->prev = main_descr;
    /* Init pool lists heads */
    for (i = 0; i <= POOL_MAX; i++) {
        pool_head = page_descr_get();
        if (pool_head == NULL) {
            page_put(malloc_base, 1);
            malloc_base = NULL;
            MEMOPS_PRINTF("%s: cannot get pool descriptor %d\n", __func__, i);
            return -1;
        }
        pool_head->prev = pool_head;
        pool_head->next = pool_head;
        pool_head->addr = NULL;
    }
    /* Init page caches lists heads */
    for (i = 0; i < CACHE_MAX; i++) {
        cache_head = page_descr_get();
        if (cache_head == NULL) {
            page_put(malloc_base, 1);
            malloc_base = NULL;
            MEMOPS_PRINTF("%s: cannot get page cache descriptor %d\n",
                          __func__, i);
            return -1;
        }
        cache_head->prev = cache_head;
        cache_head->next = cache_head;
    }

    return 0;
}
/* Big area management (size > PAGE_SIZE / 2) */
static void *big_malloc (int nb_pages)
{
    page_descr_t *main_descr, *pool_head, *pool_descr;

    main_descr = main_descr_get();
    pool_head = pool_head_get(POOL_MAX);
    pool_descr = page_descr_get();
    if (pool_descr == NULL) {
        MEMOPS_PRINTF("%s: cannot get pool descr\n", __func__);
        return NULL;
    }
    pool_descr->addr = page_get(nb_pages);
    if (pool_descr->addr == NULL) {
        page_descr_put(pool_descr);
        MEMOPS_PRINTF("%s: cannot get page\n", __func__);
        return NULL;
    }
    if (page_cache_add_page(pool_descr, POOL_MAX) < 0) {
        page_put(pool_descr->addr, nb_pages);
        page_descr_put(pool_descr);
        MEMOPS_PRINTF("%s: cannot get add page to cache\n", __func__);
        return NULL;
    }
    pool_descr->prev = pool_head->prev;
    pool_descr->next = pool_head;
    pool_descr->nb = nb_pages;
    pool_head->prev->next = pool_descr;
    pool_head->prev = pool_descr;

    return pool_descr->addr;
}
/* Allocation by pool (size <= PAGE_SIZE / 2) */
static void pool_descr_free (page_descr_t *cache_descr,
                             page_descr_t *pool_descr)
{
    page_put(PAGE(pool_descr->addr), 1);
    page_cache_remove_descr(cache_descr);
    pool_descr->next->prev = pool_descr->prev;
    pool_descr->prev->next = pool_descr->next;
    page_descr_put(pool_descr);
}
static void *pool_malloc (int pool_idx)
{
    page_descr_t *main_descr, *pool_head, *pool_descr;
    free_slot_t *first_free, *next_free;

    main_descr = main_descr_get();
    pool_head = pool_head_get(pool_idx);
    pool_descr = pool_head->addr;
    if (pool_descr == NULL || pool_descr->addr == NULL) {
        pool_descr = descr_find_free(pool_head, NULL);
        if (pool_descr == NULL) {
            pool_descr = page_descr_get();
            if (pool_descr == NULL) {
                MEMOPS_PRINTF("%s: cannot get pool descr\n", __func__);
                return NULL;
            }
            pool_descr->addr = page_get(1);
            if (pool_descr->addr == NULL) {
                MEMOPS_PRINTF("%s: cannot allocate new page\n", __func__);
                page_descr_put(pool_descr);
                return NULL;
            }
            if (page_cache_add_page(pool_descr, pool_idx) < 0) {
                MEMOPS_PRINTF("%s: cannot add new page to cache\n", __func__);
                page_put(pool_descr->addr, 1);
                page_descr_put(pool_descr);
                return NULL;
            }
            free_slots_init(pool_descr->addr,
                            1 << (MIN_ELEM_BITS + pool_idx), PAGE_SIZE);
            pool_descr->nb = 0;
            pool_descr->prev = pool_head->prev;
            pool_descr->next = pool_head;
            pool_head->prev->next = pool_descr;
            pool_head->prev = pool_descr;
            pool_head->nb++;
        }
        pool_head->addr = pool_descr;
    }
    first_free = pool_descr->addr;
    next_free = first_free->next;
    //    memset(first_free, 0, 1 << (MIN_ELEM_BITS + pool_idx));
    pool_descr->addr = next_free;
    if (pool_descr->nb == 0)
        pool_head->nb--;
    pool_descr->nb++;

    return first_free;
}
Exemple #5
0
void __free_pages(struct page *pages, unsigned long n, struct page_zone *zone)
{
	unsigned long flags;
	struct page *p;

	spin_lock_irq(&zone->lock, &flags);

	for (p = pages; p < pages + n; p++) {
		page_put(p);
	}

	zone->num_free += n;

	spin_unlock_irq(&zone->lock, flags);
}
static void big_free (page_descr_t *cache_descr)
{
    page_descr_t *pool_descr;

    pool_descr = page_cache_page_descr(cache_descr);
    if (pool_descr->addr != NULL && pool_descr->nb != 0) {
        page_put(pool_descr->addr, pool_descr->nb);
        pool_descr->next->prev = pool_descr->prev;
        pool_descr->prev->next = pool_descr->next;
        page_descr_put(pool_descr);
        page_cache_remove_descr(cache_descr);
    } else {
        MEMOPS_PRINTF("%s: ERROR %p %d\n",
                      __func__, pool_descr->addr, (int)pool_descr->nb);
    }
}
/* Page descriptors management */
static void page_descr_free (page_descr_t *head_descr)
{
    head_descr->next->prev = head_descr->prev;
    head_descr->prev->next = head_descr->next;
    page_put(head_descr, 1);
}