/* * slob_alloc: entry point into the slob allocator. */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { struct slob_page *sp = NULL; struct slob_page *sp_t; struct list_head *slob_list; slob_t *b = NULL; unsigned long flags; if (size < SLOB_BREAK1) slob_list = &free_slob_small; else if (size < SLOB_BREAK2) slob_list = &free_slob_medium; else slob_list = &free_slob_large; spin_lock_irqsave(&slob_lock, flags); /* Iterate through each partially free page, try to find room */ list_for_each_entry(sp_t, slob_list, list) { #ifdef CONFIG_NUMA /* * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ if (node != -1 && page_to_nid(&sp_t->page) != node) continue; #endif /* Enough room on this page? */ if (sp_t->units < SLOB_UNITS(size)) /* Not enough room */ continue; if (sp == NULL) sp = sp_t; if (sp_t->units < sp->units) /* Get the smallest slob_page that * is large enough for our needs */ sp = sp_t; } /* Attempt to alloc */ if(sp != NULL) { b = slob_page_alloc(sp, size, align); } spin_unlock_irqrestore(&slob_lock, flags); /* Not enough space: must allocate a new page */ if (!b) { b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; sp = slob_page(b); set_slob_page(sp); /* We allocatted a new page, increment the count */ slob_page_count++; spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); sp->free = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); b = slob_page_alloc(sp, size, align); BUG_ON(!b); spin_unlock_irqrestore(&slob_lock, flags); } if (unlikely((gfp & __GFP_ZERO) && b)) memset(b, 0, size); return b; }
static void slob_free(void *block, int size) { struct page *sp; slob_t *prev, *next, *b = (slob_t *)block; slobidx_t units; unsigned long flags; struct list_head *slob_list; if (unlikely(ZERO_OR_NULL_PTR(block))) return; BUG_ON(!size); sp = slob_page(block); units = SLOB_UNITS(size); spin_lock_irqsave(&slob_lock, flags); if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) { if (slob_page_free(sp)) clear_slob_page_free(sp); spin_unlock_irqrestore(&slob_lock, flags); clear_slob_page(sp); free_slob_page(sp); slob_free_pages(b, 0); return; } if (!slob_page_free(sp)) { sp->units = units; sp->freelist = b; set_slob(b, units, (void *)((unsigned long)(b + SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK)); if (size < SLOB_BREAK1) slob_list = &free_slob_small; else if (size < SLOB_BREAK2) slob_list = &free_slob_medium; else slob_list = &free_slob_large; set_slob_page_free(sp, slob_list); goto out; } sp->units += units; if (b < (slob_t *)sp->freelist) { if (b + units == sp->freelist) { units += slob_units(sp->freelist); sp->freelist = slob_next(sp->freelist); } set_slob(b, units, sp->freelist); sp->freelist = b; } else { prev = sp->freelist; next = slob_next(prev); while (b > next) { prev = next; next = slob_next(prev); } if (!slob_last(prev) && b + units == next) { units += slob_units(next); set_slob(b, units, slob_next(next)); } else set_slob(b, units, next); if (prev + slob_units(prev) == b) { units = slob_units(b) + slob_units(prev); set_slob(prev, units, slob_next(b)); } else set_slob(prev, slob_units(prev), b); } out: spin_unlock_irqrestore(&slob_lock, flags); }
/* * slob_alloc: entry point into the slob allocator. */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { struct slob_page *sp; struct list_head *slob_list; slob_t *b = NULL; unsigned long flags; int i; unsigned long int count_free; #ifdef BESTFIT_PAGE slobidx_t min,prev_min; struct slob_page *curr; int flag_if; int check; #else struct list_head *prev; #endif /*arxikopoioyme ta total_alloc kai ta total_free*/ if(flag_mem==0){ total_alloc = 0; total_free = 0; flag_mem = 1; } if (size < SLOB_BREAK1) slob_list = &free_slob_small; else if (size < SLOB_BREAK2) slob_list = &free_slob_medium; else slob_list = &free_slob_large; spin_lock_irqsave(&slob_lock, flags); /* Iterate through each partially free page, try to find room */ counter_print++; #ifdef BESTFIT_PAGE flag_if = 0; curr = NULL; min = 0; prev_min = SLOB_UNITS(size); /*diatexoume th lista mexri na broyme thn kalyterh selida*/ list_for_each_entry(sp, slob_list, list) { #ifdef CONFIG_NUMA /* * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ if (node != -1 && page_to_nid(&sp->page) != node) continue; #endif /* Enough room on this page? */ if (sp->units < prev_min){ continue; } if(flag_if==0){ check = check_block(sp,size,align); if(check){ min = sp->units; curr = sp; flag_if = 1; } } else{ if(sp->units <= min){ check = check_block(sp,size,align); if(check){ min = sp->units; curr = sp; } } } } //kaloyme thn slob_page_alloc if(curr!=NULL){ b = slob_page_alloc(curr, size, align); } else{ b = NULL; } #else list_for_each_entry(sp, slob_list, list) { #ifdef CONFIG_NUMA /* * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ if (node != -1 && page_to_nid(&sp->page) != node) continue; #endif /* Enough room on this page? */ if (sp->units < SLOB_UNITS(size)) continue; /* Attempt to alloc */ prev = sp->list.prev; b = slob_page_alloc(sp, size, align); if (!b) continue; /* Improve fragment distribution and reduce our average * search time by starting our next search here. (see * Knuth vol 1, sec 2.5, pg 449) */ if (prev != slob_list->prev && slob_list->next != prev->next) list_move_tail(slob_list, prev->next); break; } #endif spin_unlock_irqrestore(&slob_lock, flags); /* Not enough space: must allocate a new page */ if (!b) { b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; sp = slob_page(b); set_slob_page(sp); spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); sp->free = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); b = slob_page_alloc(sp, size, align); BUG_ON(!b); spin_unlock_irqrestore(&slob_lock, flags); } if (unlikely((gfp & __GFP_ZERO) && b)) memset(b, 0, size); /*diatrexoyme kai tis treis listes megethon gia na metrhsoyme ta synolika free olwn twn selidwn*/ count_free = 0; for(i=0;i<3;i++){ if (i==0){ slob_list = &free_slob_small; } else if (i==1){ slob_list = &free_slob_medium; } else{ slob_list = &free_slob_large; } list_for_each_entry(sp, slob_list, list) { count_free = count_free + sp->units; } }
static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { struct page *sp; struct list_head *prev; struct list_head *slob_list; slob_t *b = NULL; unsigned long flags; if (size < SLOB_BREAK1) slob_list = &free_slob_small; else if (size < SLOB_BREAK2) slob_list = &free_slob_medium; else slob_list = &free_slob_large; spin_lock_irqsave(&slob_lock, flags); list_for_each_entry(sp, slob_list, list) { #ifdef CONFIG_NUMA /* * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ if (node != NUMA_NO_NODE && page_to_nid(sp) != node) continue; #endif if (sp->units < SLOB_UNITS(size)) continue; prev = sp->list.prev; b = slob_page_alloc(sp, size, align); if (!b) continue; if (prev != slob_list->prev && slob_list->next != prev->next) list_move_tail(slob_list, prev->next); break; } spin_unlock_irqrestore(&slob_lock, flags); if (!b) { b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; sp = slob_page(b); set_slob_page(sp); spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); sp->freelist = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); b = slob_page_alloc(sp, size, align); BUG_ON(!b); spin_unlock_irqrestore(&slob_lock, flags); } if (unlikely((gfp & __GFP_ZERO) && b)) memset(b, 0, size); return b; }