[RFC PATCH v3 02/10] slab: add SLIB (Library memory allocator) for arch/lib

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



add SLIB allocator for arch/lib (CONFIG_LIB) to wrap kmalloc and co.
This will bring user's own allocator of libos: malloc(3) etc.

Signed-off-by: Hajime Tazaki <tazaki@xxxxxxxxxxxxxx>
---
 include/linux/slab.h     |   6 +-
 include/linux/slib_def.h |  21 +++++
 init/Kconfig             |   8 ++
 mm/Makefile              |   1 +
 mm/slab.h                |   4 +
 mm/slib.c                | 205 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 244 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/slib_def.h
 create mode 100644 mm/slib.c

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 9a139b6..b167daa 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -192,7 +192,7 @@ size_t ksize(const void *);
 #endif
 #endif
 
-#ifdef CONFIG_SLOB
+#if defined(CONFIG_SLOB) || defined(CONFIG_SLIB)
 /*
  * SLOB passes all requests larger than one page to the page allocator.
  * No kmalloc array is necessary since objects of different sizes can
@@ -350,6 +350,9 @@ kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
 }
 #endif
 
+#ifdef CONFIG_SLIB
+#include <linux/slib_def.h>
+#else
 static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 {
 	unsigned int order = get_order(size);
@@ -428,6 +431,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 	}
 	return __kmalloc(size, flags);
 }
+#endif /* CONFIG_SLIB */
 
 /*
  * Determine size used for the nth kmalloc cache.
diff --git a/include/linux/slib_def.h b/include/linux/slib_def.h
new file mode 100644
index 0000000..d9fe7d5
--- /dev/null
+++ b/include/linux/slib_def.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_SLLB_DEF_H
+#define _LINUX_SLLB_DEF_H
+
+
+struct kmem_cache {
+	unsigned int object_size;
+	const char *name;
+	size_t size;
+	size_t align;
+	unsigned long flags;
+	void (*ctor)(void *);
+};
+
+void *__kmalloc(size_t size, gfp_t flags);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+static __always_inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc(size, flags);
+}
+
+#endif /* _LINUX_SLLB_DEF_H */
diff --git a/init/Kconfig b/init/Kconfig
index 9afb971..8bdee98 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1695,6 +1695,14 @@ config SLOB
 	   allocator. SLOB is generally more space efficient but
 	   does not perform as well on large systems.
 
+config SLIB
+	bool "SLIB (Library Allocator)"
+	depends on LIB
+	help
+	   SLIB replaces the slab allocator with a registered allocator
+	   function via lib_init() used by libos (CONFIG_LIB). It usually
+	   used malloc(3) or any allocators.
+
 endchoice
 
 config SLUB_CPU_PARTIAL
diff --git a/mm/Makefile b/mm/Makefile
index 4bf586e..8c66951 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
 obj-$(CONFIG_SLOB) += slob.o
+obj-$(CONFIG_SLIB) += slib.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_KSM) += ksm.o
 obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
diff --git a/mm/slab.h b/mm/slab.h
index 1cf40054..89c2319 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -37,6 +37,10 @@ struct kmem_cache {
 #include <linux/slub_def.h>
 #endif
 
+#ifdef CONFIG_SLIB
+#include <linux/slib_def.h>
+#endif
+
 #include <linux/memcontrol.h>
 
 /*
diff --git a/mm/slib.c b/mm/slib.c
new file mode 100644
index 0000000..37596862
--- /dev/null
+++ b/mm/slib.c
@@ -0,0 +1,205 @@
+/*
+ * Library Slab Allocator (SLIB)
+ *
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@xxxxxxxxx>
+ *         Hajime Tazaki <tazaki@xxxxxxxxxxxxxx>
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/page-flags.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/slib_def.h>
+
+/* glues */
+struct kmem_cache *files_cachep;
+
+void kfree(const void *p)
+{
+	unsigned long start;
+
+	if (p == 0)
+		return;
+	start = (unsigned long)p;
+	start -= sizeof(size_t);
+	lib_free((void *)start);
+}
+size_t ksize(const void *p)
+{
+	size_t *psize = (size_t *)p;
+
+	psize--;
+	return *psize;
+}
+void *__kmalloc(size_t size, gfp_t flags)
+{
+	void *p = lib_malloc(size + sizeof(size));
+	unsigned long start;
+
+	if (!p)
+		return NULL;
+
+	if (p != 0 && (flags & __GFP_ZERO))
+		lib_memset(p, 0, size + sizeof(size));
+	lib_memcpy(p, &size, sizeof(size));
+	start = (unsigned long)p;
+	return (void *)(start + sizeof(size));
+}
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
+{
+	return kmalloc(size, flags);
+}
+
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+
+	if (!new_size) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ret = __kmalloc(new_size, flags);
+	if (ret && p != ret)
+		kfree(p);
+
+	return ret;
+}
+
+struct kmem_cache *
+kmem_cache_create(const char *name, size_t size, size_t align,
+		  unsigned long flags, void (*ctor)(void *))
+{
+	struct kmem_cache *cache = kmalloc(sizeof(struct kmem_cache), flags);
+
+	if (!cache)
+		return NULL;
+	cache->name = name;
+	cache->size = size;
+	cache->align = align;
+	cache->flags = flags;
+	cache->ctor = ctor;
+	return cache;
+}
+void kmem_cache_destroy(struct kmem_cache *cache)
+{
+	kfree(cache);
+}
+int kmem_cache_shrink(struct kmem_cache *cache)
+{
+	return 1;
+}
+const char *kmem_cache_name(struct kmem_cache *cache)
+{
+	return cache->name;
+}
+void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+	void *p = kmalloc(cache->size, flags);
+
+	if (p == 0)
+		return NULL;
+	if (cache->ctor)
+		(cache->ctor)(p);
+	return p;
+
+}
+void kmem_cache_free(struct kmem_cache *cache, void *p)
+{
+	kfree(p);
+}
+
+struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+		       struct zonelist *zonelist, nodemask_t *nodemask)
+{
+	void *p;
+	struct page *page;
+	unsigned long pointer;
+
+	/* typically, called from networking code by alloc_page or */
+	/* directly with an order = 0. */
+	if (order)
+		return NULL;
+	p = lib_malloc(sizeof(struct page) + (1 << PAGE_SHIFT));
+	page = (struct page *)p;
+
+	atomic_set(&page->_count, 1);
+	page->flags = 0;
+	pointer = (unsigned long)page;
+	pointer += sizeof(struct page);
+	page->virtual = (void *)pointer;
+	return page;
+}
+void __free_pages(struct page *page, unsigned int order)
+{
+	/* typically, called from networking code by __free_page */
+	lib_assert(order == 0);
+	lib_free(page);
+}
+
+void put_page(struct page *page)
+{
+	if (atomic_dec_and_test(&page->_count))
+		lib_free(page);
+}
+unsigned long get_zeroed_page(gfp_t gfp_mask)
+{
+	return __get_free_pages(gfp_mask | __GFP_ZERO, 0);
+}
+
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+	return alloc_pages(gfp_mask, get_order(size));
+}
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+{
+	int size = (1 << order) * PAGE_SIZE;
+	void *p = kmalloc(size, gfp_mask);
+
+	return (unsigned long)p;
+}
+void free_pages(unsigned long addr, unsigned int order)
+{
+	if (addr != 0)
+		kfree((void *)addr);
+}
+
+void *vmalloc(unsigned long size)
+{
+	return lib_malloc(size);
+}
+void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return kmalloc(size, gfp_mask);
+}
+void vfree(const void *addr)
+{
+	lib_free((void *)addr);
+}
+void *vmalloc_node(unsigned long size, int node)
+{
+	return lib_malloc(size);
+}
+void vmalloc_sync_all(void)
+{
+}
+void *__alloc_percpu(size_t size, size_t align)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+void free_percpu(void __percpu *ptr)
+{
+	kfree(ptr);
+}
+void *__alloc_bootmem_nopanic(unsigned long size,
+			      unsigned long align,
+			      unsigned long goal)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
-- 
2.1.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]