/* 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; }
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); }