[PATCH kvm-unit-tests 08/18] alloc: implement free

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

 



Track block size in lib/alloc.c and not in alloc_ops.  alloc_ops->free
gets the size from the malloc implementation.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 arm/Makefile.common     |  1 +
 lib/alloc.c             | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/alloc.h             | 33 ++++++-------------------
 lib/alloc_phys.c        | 23 +++++++++--------
 powerpc/Makefile.common |  1 +
 5 files changed, 86 insertions(+), 38 deletions(-)
 create mode 100644 lib/alloc.c

diff --git a/arm/Makefile.common b/arm/Makefile.common
index 6979a24..e09c3e2 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -35,6 +35,7 @@ include $(SRCDIR)/scripts/asm-offsets.mak
 
 cflatobjs += lib/util.o
 cflatobjs += lib/alloc_phys.o
+cflatobjs += lib/alloc.o
 cflatobjs += lib/devicetree.o
 cflatobjs += lib/pci.o
 cflatobjs += lib/pci-host-generic.o
diff --git a/lib/alloc.c b/lib/alloc.c
new file mode 100644
index 0000000..61cb292
--- /dev/null
+++ b/lib/alloc.c
@@ -0,0 +1,66 @@
+#include "alloc.h"
+
+void *malloc(size_t size)
+{
+	return memalign(sizeof(long), size);
+}
+
+void *calloc(size_t nmemb, size_t size)
+{
+	void *ptr = malloc(nmemb * size);
+	if (ptr)
+		memset(ptr, 0, nmemb * size);
+	return ptr;
+}
+
+#define METADATA_EXTRA	(2 * sizeof(uintptr_t))
+#define OFS_SLACK	(-2 * sizeof(uintptr_t))
+#define OFS_SIZE	(-sizeof(uintptr_t))
+
+static inline void *block_begin(void *mem)
+{
+	uintptr_t slack = *(uintptr_t *)(mem + OFS_SLACK);
+	return mem - slack;
+}
+
+static inline uintptr_t block_size(void *mem)
+{
+	return *(uintptr_t *)(mem + OFS_SIZE);
+}
+
+void free(void *ptr)
+{
+	if (!alloc_ops->free)
+		return;
+
+	void *base = block_begin(ptr);
+	uintptr_t sz = block_size(ptr);
+
+	alloc_ops->free(base, sz);
+}
+
+void *memalign(size_t alignment, size_t size)
+{
+	void *p;
+	uintptr_t blkalign;
+	uintptr_t mem;
+
+	assert(alloc_ops && alloc_ops->memalign);
+	if (alignment <= sizeof(uintptr_t))
+		alignment = sizeof(uintptr_t);
+	else
+		size += alignment - 1;
+
+	blkalign = MAX(alignment, alloc_ops->align_min);
+	size = ALIGN(size + METADATA_EXTRA, alloc_ops->align_min);
+	p = alloc_ops->memalign(blkalign, size);
+
+	/* Leave room for metadata before aligning the result.  */
+	mem = (uintptr_t)p + METADATA_EXTRA;
+	mem = ALIGN(mem, alignment);
+
+	/* Write the metadata */
+	*(uintptr_t *)(mem + OFS_SLACK) = mem - (uintptr_t)p;
+	*(uintptr_t *)(mem + OFS_SIZE) = size;
+	return (void *)mem;
+}
diff --git a/lib/alloc.h b/lib/alloc.h
index 24f85b4..f560c4a 100644
--- a/lib/alloc.h
+++ b/lib/alloc.h
@@ -24,36 +24,17 @@
 
 struct alloc_ops {
 	void *(*memalign)(size_t alignment, size_t size);
+	void (*free)(void *ptr, size_t size);
+	size_t align_min;
 };
 
 extern struct alloc_ops *alloc_ops;
 
-/*
- * Our malloc implementation is currently so simple that it can just
- * be inlined. :)
- */
-static inline void *malloc(size_t size)
-{
-	assert(alloc_ops && alloc_ops->memalign);
-	return alloc_ops->memalign(sizeof(long), size);
-}
-
-static inline void *calloc(size_t nmemb, size_t size)
-{
-	void *ptr = malloc(nmemb * size);
-	if (ptr)
-		memset(ptr, 0, nmemb * size);
-	return ptr;
-}
+void *malloc(size_t size);
+void *calloc(size_t nmemb, size_t size);
+void free(void *ptr);
+void *memalign(size_t alignment, size_t size);
 
-static inline void free(void *ptr)
-{
-}
-
-static inline void *memalign(size_t alignment, size_t size)
-{
-	assert(alloc_ops && alloc_ops->memalign);
-	return alloc_ops->memalign(alignment, size);
-}
+extern struct alloc_ops *alloc_ops;
 
 #endif /* _ALLOC_H_ */
diff --git a/lib/alloc_phys.c b/lib/alloc_phys.c
index 6befb5c..d09395d 100644
--- a/lib/alloc_phys.c
+++ b/lib/alloc_phys.c
@@ -23,7 +23,15 @@ static struct phys_alloc_region regions[PHYS_ALLOC_NR_REGIONS];
 static int nr_regions;
 
 static struct spinlock lock;
-static phys_addr_t base, top, align_min;
+static phys_addr_t base, top;
+
+static void *early_memalign(size_t alignment, size_t size);
+static struct alloc_ops early_alloc_ops = {
+	.memalign = early_memalign,
+	.align_min = DEFAULT_MINIMUM_ALIGNMENT
+};
+
+struct alloc_ops *alloc_ops = &early_alloc_ops;
 
 void phys_alloc_show(void)
 {
@@ -31,7 +39,7 @@ void phys_alloc_show(void)
 
 	spin_lock(&lock);
 	printf("phys_alloc minimum alignment: %#" PRIx64 "\n",
-		(u64)align_min);
+		(u64)early_alloc_ops.align_min);
 	for (i = 0; i < nr_regions; ++i)
 		printf("%016" PRIx64 "-%016" PRIx64 " [%s]\n",
 			(u64)regions[i].base,
@@ -47,7 +55,6 @@ void phys_alloc_init(phys_addr_t base_addr, phys_addr_t size)
 	spin_lock(&lock);
 	base = base_addr;
 	top = base + size;
-	align_min = DEFAULT_MINIMUM_ALIGNMENT;
 	nr_regions = 0;
 	spin_unlock(&lock);
 }
@@ -56,7 +63,7 @@ void phys_alloc_set_minimum_alignment(phys_addr_t align)
 {
 	assert(align && !(align & (align - 1)));
 	spin_lock(&lock);
-	align_min = align;
+	early_alloc_ops.align_min = align;
 	spin_unlock(&lock);
 }
 
@@ -74,8 +81,6 @@ static phys_addr_t phys_alloc_aligned_safe(phys_addr_t size,
 	if (safe && sizeof(long) == 4)
 		top_safe = MIN(top_safe, 1ULL << 32);
 
-	align = MAX(align, align_min);
-
 	addr = ALIGN(base, align);
 	size += addr - base;
 
@@ -125,9 +130,3 @@ static void *early_memalign(size_t alignment, size_t size)
 
 	return phys_to_virt(addr);
 }
-
-static struct alloc_ops early_alloc_ops = {
-	.memalign = early_memalign,
-};
-
-struct alloc_ops *alloc_ops = &early_alloc_ops;
diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
index 126590a..21dea40 100644
--- a/powerpc/Makefile.common
+++ b/powerpc/Makefile.common
@@ -31,6 +31,7 @@ include $(SRCDIR)/scripts/asm-offsets.mak
 
 cflatobjs += lib/util.o
 cflatobjs += lib/alloc_phys.o
+cflatobjs += lib/alloc.o
 cflatobjs += lib/devicetree.o
 cflatobjs += lib/powerpc/io.o
 cflatobjs += lib/powerpc/hcall.o
-- 
2.14.2






[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux