diff -Naur -x '*.o' -x '*.ko' -x '*.order' -x '*.builtin' -x '*.cmd' -x '*.mod.c' linux-yocto-3.19.2_untouched/mm/slob.c linux-yocto-3.19.2/mm/slob.c --- linux-yocto-3.19.2_untouched/mm/slob.c 2018-05-04 15:15:00.445347537 -0700 +++ linux-yocto-3.19.2/mm/slob.c 2018-06-06 17:07:53.244403545 -0700 @@ -68,6 +68,9 @@ #include #include +#include +#include + #include #include @@ -101,6 +104,8 @@ static LIST_HEAD(free_slob_medium); static LIST_HEAD(free_slob_large); +size_t num_pages = 0; + /* * slob_page_free: true for pages on free_slob_pages list. */ @@ -211,55 +216,117 @@ free_pages((unsigned long)b, order); } -/* - * Allocate a slob block within a given slob_page sp. - */ static void *slob_page_alloc(struct page *sp, size_t size, int align) { - slob_t *prev, *cur, *aligned = NULL; - int delta = 0, units = SLOB_UNITS(size); + slob_t *prev, *cur, *aligned = NULL, *best = NULL, *best_prev = NULL; + int delta = 0; + int units = SLOB_UNITS(size); + slobidx_t avail; + /* Find best fit block on page that can fit what needs to be allocated */ for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { - slobidx_t avail = slob_units(cur); + avail = slob_units(cur); + /* Use aligned blocks if requested */ if (align) { aligned = (slob_t *)ALIGN((unsigned long)cur, align); delta = aligned - cur; } - if (avail >= units + delta) { /* room enough? */ - slob_t *next; + + /* If the current block is the best option seen yet, store it */ + if(avail >= units + delta && (!best || avail < slob_units(best))) { + best = cur; + best_prev = prev; + } + + /* If this is the last block, exit loop */ + if (slob_last(cur)) { + break; + } + + } + + /* Allocate the best block found above, if found */ + if (best != NULL){ + slob_t *next; - if (delta) { /* need to fragment head to align? */ - next = slob_next(cur); - set_slob(aligned, avail - delta, next); - set_slob(cur, delta, aligned); - prev = cur; - cur = aligned; - avail = slob_units(cur); - } + /* Align if necessary */ + if (align) { + aligned = (slob_t *)ALIGN((unsigned long)best, align); + delta = aligned - best; + } + + /* Get the amount of space available */ + avail = slob_units(best); - next = slob_next(cur); - if (avail == units) { /* exact fit? unlink. */ - if (prev) - set_slob(prev, slob_units(prev), next); - else - sp->freelist = next; - } else { /* fragment */ - if (prev) - set_slob(prev, slob_units(prev), cur + units); - else - sp->freelist = cur + units; - set_slob(cur + units, avail - units, next); + + if (delta) { /* need to fragment head to align? */ + next = slob_next(best); + set_slob(aligned, (avail - delta), next); + set_slob(best, delta, aligned); + best_prev = best; + best = aligned; + avail = slob_units(best); + } + + next = slob_next(best); + + /* exact fit? unlink. */ + if (avail == units) { + if (best_prev) + set_slob(best_prev, slob_units(best_prev), next); + else + sp->freelist = next; + } else { /* fragment */ + if (best_prev){ + set_slob(best_prev, slob_units(best_prev), best + units); } + else{ + sp->freelist = best + units; + } + set_slob(best + units, avail - units, next); + } + + sp->units -= units; + if (!sp->units) + clear_slob_page_free(sp); + return best; + } + + return NULL; +} + + +static int find_closest_block_size_in_page(struct page *sp, size_t size, int align) +{ + slob_t *prev, *cur, *aligned = NULL, *best = NULL; + int delta = 0, units = SLOB_UNITS(size); - sp->units -= units; - if (!sp->units) - clear_slob_page_free(sp); - return cur; + for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { + slobidx_t avail = slob_units(cur); + + /* Align if necessary */ + if (align) { + aligned = (slob_t *)ALIGN((unsigned long)cur, align); + delta = aligned - cur; } - if (slob_last(cur)) - return NULL; + + /* Keep track of the better block if we've found one */ + if(avail >= units + delta && (!best || avail < slob_units(best))){ + best = cur; + } + + /* If we're at the end, return the best block, or -1 if not found*/ + if (slob_last(cur)) { + if(best){ + return slob_units(best); + }else{ + return -1; + } + } + } + return -1; } /* @@ -267,11 +334,12 @@ */ 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; + struct page *sp = NULL, *best_pg = NULL; + struct list_head *slob_list = NULL; slob_t *b = NULL; unsigned long flags; + slobidx_t best_fit = 0; + slobidx_t cur_fit; if (size < SLOB_BREAK1) slob_list = &free_slob_small; @@ -281,53 +349,67 @@ slob_list = &free_slob_large; spin_lock_irqsave(&slob_lock, flags); - /* Iterate through each partially free page, try to find room */ + + /* Iterate through each page for find a spot if possible */ list_for_each_entry(sp, slob_list, lru) { #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; + /* + * 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 - /* Enough room on this page? */ - if (sp->units < SLOB_UNITS(size)) - continue; - - /* Attempt to alloc */ - prev = sp->lru.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; + /* Enough room on this page? */ + if (sp->units < SLOB_UNITS(size)) + continue; + + /* Find out if there's space for this in the current page */ + cur_fit = find_closest_block_size_in_page(sp, size, align); + + /* If not, continue*/ + if(cur_fit == -1){ + continue; + } + + /* Stop if we've found something that perfectly matches */ + if (cur_fit == SLOB_UNITS(size)) { + best_pg = sp; + break; + } + + /* Store the current best fit block, if it's better than previous */ + if (best_fit > cur_fit || best_pg == NULL) { + best_pg = sp; + best_fit = cur_fit; + } + } + + /* Attempt to allocate */ + if(best_pg != NULL){ + b = slob_page_alloc(best_pg, size, align); } + spin_unlock_irqrestore(&slob_lock, flags); - /* Not enough space: must allocate a new page */ + /* Make a new page if we never found a spot */ if (!b) { - b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); - if (!b) - return NULL; - sp = virt_to_page(b); - __SetPageSlab(sp); - - spin_lock_irqsave(&slob_lock, flags); - sp->units = SLOB_UNITS(PAGE_SIZE); - sp->freelist = b; - INIT_LIST_HEAD(&sp->lru); - 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); + b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); + if (!b) + return NULL; + sp = virt_to_page(b); + __SetPageSlab(sp); + + spin_lock_irqsave(&slob_lock, flags); + sp->units = SLOB_UNITS(PAGE_SIZE); + sp->freelist = b; + INIT_LIST_HEAD(&sp->lru); + 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); + num_pages++; } if (unlikely((gfp & __GFP_ZERO) && b)) memset(b, 0, size); @@ -362,6 +444,7 @@ __ClearPageSlab(sp); page_mapcount_reset(sp); slob_free_pages(b, 0); + num_pages--; return; } @@ -640,3 +723,31 @@ { slab_state = FULL; } + +asmlinkage long sys_slob_free(void) { + struct list_head *temp; + struct page *sp; + unsigned long free_units = 0; + + temp = &free_slob_small; + list_for_each_entry(sp, temp, lru) { + free_units += sp->units; + } + temp = &free_slob_medium; + list_for_each_entry(sp, temp, lru) { + free_units += sp->units; + } + temp = &free_slob_large; + list_for_each_entry(sp, temp, lru) { + free_units += sp->units; + } + + return free_units; +} + +asmlinkage long sys_slob_used(void) { + long slob_total_used; + + slob_total_used = SLOB_UNITS(PAGE_SIZE) * num_pages; + return slob_total_used; +} \ No newline at end of file diff -Naur -x '*.o' -x '*.ko' -x '*.order' -x '*.builtin' -x '*.cmd' -x '*.mod.c' linux-yocto-3.19.2_untouched/include/linux/syscalls.h linux-yocto-3.19.2/include/linux/syscalls.h --- linux-yocto-3.19.2_untouched/include/linux/syscalls.h 2018-05-04 15:14:59.075324834 -0700 +++ linux-yocto-3.19.2/include/linux/syscalls.h 2018-06-06 16:32:02.518020727 -0700 @@ -882,4 +882,6 @@ const char __user *const __user *argv, const char __user *const __user *envp, int flags); +asmlinkage long sys_slob_free(void); +asmlinkage long sys_slob_used(void); #endif diff -Naur -x '*.o' -x '*.ko' -x '*.order' -x '*.builtin' -x '*.cmd' -x '*.mod.c' linux-yocto-3.19.2_untouched/arch/x86/syscalls/syscall_32.tbl linux-yocto-3.19.2/arch/x86/syscalls/syscall_32.tbl --- linux-yocto-3.19.2_untouched/arch/x86/syscalls/syscall_32.tbl 2018-05-04 15:14:40.077010007 -0700 +++ linux-yocto-3.19.2/arch/x86/syscalls/syscall_32.tbl 2018-06-06 16:31:26.578421117 -0700 @@ -365,3 +365,6 @@ 356 i386 memfd_create sys_memfd_create 357 i386 bpf sys_bpf 358 i386 execveat sys_execveat stub32_execveat + +400 i386 slob_free sys_slob_free +401 i386 slob_used sys_slob_used \ No newline at end of file --- linux-yocto-3.19.2_untouched/.config 2018-05-04 15:15:03.830403632 -0700 +++ linux-yocto-3.19.2/.config 2018-06-05 17:11:02.799939154 -0700 @@ -146,7 +146,6 @@ CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_MEMCG_SWAP_ENABLED=y -CONFIG_MEMCG_KMEM=y # CONFIG_CGROUP_PERF is not set CONFIG_CGROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y @@ -211,12 +210,10 @@ CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SLUB is not set +CONFIG_SLOB=y # CONFIG_SYSTEM_TRUSTED_KEYRING is not set CONFIG_PROFILING=y CONFIG_TRACEPOINTS=y @@ -251,7 +248,6 @@ CONFIG_HAVE_PERF_USER_STACK_DUMP=y CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y -CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y CONFIG_HAVE_CMPXCHG_LOCAL=y CONFIG_HAVE_CMPXCHG_DOUBLE=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y @@ -275,7 +271,6 @@ # CONFIG_GCOV_KERNEL is not set CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 CONFIG_MODULES=y @@ -3787,8 +3782,6 @@ # CONFIG_PAGE_EXTENSION is not set # CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_DEBUG_OBJECTS is not set -# CONFIG_SLUB_DEBUG_ON is not set -# CONFIG_SLUB_STATS is not set CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_STACK_USAGE is not set