[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] gnumach: kern: kalloc optimization for constant size requests
From: |
Maksym Planeta |
Subject: |
[PATCH] gnumach: kern: kalloc optimization for constant size requests |
Date: |
Tue, 29 Mar 2011 09:26:39 +0300 |
If request's object size is know at compile time than zone where it will
be placed can be determined at this time.
There was added a wrapper which determines, whether size is constant or
variable. It works similarly to linux's kmalloc in linux/slab_def.h
To some of variables which don't change their value after initialization
where added const specifier.
Signed-off-by: Maksym Planeta <mcsim.planeta@gmail.com>
---
kern/kalloc.c | 80 +----------------------------------------
kern/kalloc.h | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++-
kern/zone_sizes.h | 17 +++++++++
3 files changed, 120 insertions(+), 80 deletions(-)
create mode 100644 kern/zone_sizes.h
diff --git a/kern/kalloc.c b/kern/kalloc.c
index 4460d59..db794b8 100644
--- a/kern/kalloc.c
+++ b/kern/kalloc.c
@@ -39,66 +39,10 @@
#include <mach/vm_param.h>
#include <kern/debug.h>
-#include <kern/zalloc.h>
#include <kern/kalloc.h>
-#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_map.h>
-
-
-vm_map_t kalloc_map;
-vm_size_t kalloc_map_size = 8 * 1024 * 1024;
-vm_size_t kalloc_max;
-
-/*
- * All allocations of size less than kalloc_max are rounded to the
- * next highest power of 2. This allocator is built on top of
- * the zone allocator. A zone is created for each potential size
- * that we are willing to get in small blocks.
- *
- * We assume that kalloc_max is not greater than 64K;
- * thus 16 is a safe array size for k_zone and k_zone_name.
- */
-
-int first_k_zone = -1;
-struct zone *k_zone[16];
-static char *k_zone_name[16] = {
- "kalloc.1", "kalloc.2",
- "kalloc.4", "kalloc.8",
- "kalloc.16", "kalloc.32",
- "kalloc.64", "kalloc.128",
- "kalloc.256", "kalloc.512",
- "kalloc.1024", "kalloc.2048",
- "kalloc.4096", "kalloc.8192",
- "kalloc.16384", "kalloc.32768"
-};
-
-/*
- * Max number of elements per zone. zinit rounds things up correctly
- * Doing things this way permits each zone to have a different maximum size
- * based on need, rather than just guessing; it also
- * means its patchable in case you're wrong!
- */
-unsigned long k_zone_max[16] = {
- 1024, /* 1 Byte */
- 1024, /* 2 Byte */
- 1024, /* 4 Byte */
- 1024, /* 8 Byte */
- 1024, /* 16 Byte */
- 4096, /* 32 Byte */
- 4096, /* 64 Byte */
- 4096, /* 128 Byte */
- 4096, /* 256 Byte */
- 1024, /* 512 Byte */
- 1024, /* 1024 Byte */
- 1024, /* 2048 Byte */
- 1024, /* 4096 Byte */
- 4096, /* 8192 Byte */
- 64, /* 16384 Byte */
- 64, /* 32768 Byte */
-};
-
/*
* Initialize the memory allocator. This should be called only
* once on a system wide basis (i.e. first processor to get here
@@ -107,10 +51,6 @@ unsigned long k_zone_max[16] = {
* This initializes all of the zones.
*/
-#ifndef NDEBUG
-static int kalloc_init_called;
-#endif
-
void kalloc_init()
{
vm_offset_t min, max;
@@ -121,18 +61,6 @@ void kalloc_init()
kalloc_map = kmem_suballoc(kernel_map, &min, &max,
kalloc_map_size, FALSE);
-
- /*
- * Ensure that zones up to size 8192 bytes exist.
- * This is desirable because messages are allocated
- * with kalloc, and messages up through size 8192 are common.
- */
-
- if (PAGE_SIZE < 16*1024)
- kalloc_max = 16*1024;
- else
- kalloc_max = PAGE_SIZE;
-
/*
* Allocate a zone for each size we are going to handle.
* We specify non-paged memory.
@@ -142,9 +70,7 @@ void kalloc_init()
k_zone[i] = 0;
continue;
}
- if (size == MINSIZE) {
- first_k_zone = i;
- }
+
k_zone[i] = zinit(size, 0, k_zone_max[i] * size, size,
size >= PAGE_SIZE ? ZONE_COLLECTABLE : 0,
k_zone_name[i]);
@@ -155,7 +81,7 @@ void kalloc_init()
#endif
}
-vm_offset_t kalloc(size)
+vm_offset_t __kalloc(size)
vm_size_t size;
{
register int zindex;
@@ -164,8 +90,6 @@ vm_offset_t kalloc(size)
/* compute the size of the block that we will actually allocate */
- assert (kalloc_init_called);
-
allocsize = size;
if (size < kalloc_max) {
allocsize = MINSIZE;
diff --git a/kern/kalloc.h b/kern/kalloc.h
index a80f6db..3a6d7b2 100644
--- a/kern/kalloc.h
+++ b/kern/kalloc.h
@@ -28,13 +28,112 @@
#define _KERN_KALLOC_H_
#include <mach/machine/vm_types.h>
+#include <kern/zalloc.h>
+#include <vm/vm_kern.h>
#define MINSIZE 16
-extern vm_offset_t kalloc (vm_size_t size);
+vm_map_t kalloc_map;
+const vm_size_t kalloc_map_size = 8 * 1024 * 1024;
+
+/*
+ * Ensure that zones up to size 8192 bytes exist.
+ * This is desirable because messages are allocated
+ * with kalloc, and messages up through size 8192 are common.
+ */
+const vm_size_t kalloc_max = PAGE_SIZE < 32 * 1024 ? 32 * 1024 : PAGE_SIZE;
+
+/*
+ * All allocations of size less than kalloc_max are rounded to the
+ * next highest power of 2. This allocator is built on top of
+ * the zone allocator. A zone is created for each potential size
+ * that we are willing to get in small blocks.
+ *
+ * We assume that kalloc_max is not greater than 64K;
+ * thus 16 is a safe array size for k_zone and k_zone_name.
+ */
+
+#define ZONE(val, pow) \
+ MINSIZE == val ? pow :
+const int first_k_zone =
+#include "zone_sizes.h"
+ -1;
+#undef ZONE
+
+struct zone *k_zone[16];
+
+#define ZONE(val, pow)\
+ "kalloc."#val ,
+static char *k_zone_name[16] = {
+#include "zone_sizes.h"
+};
+#undef ZONE
+
+/*
+ * Max number of elements per zone. zinit rounds things up correctly
+ * Doing things this way permits each zone to have a different maximum size
+ * based on need, rather than just guessing; it also
+ * means its patchable in case you're wrong!
+ */
+const unsigned long k_zone_max[16] = {
+ 1024, /* 1 Byte */
+ 1024, /* 2 Byte */
+ 1024, /* 4 Byte */
+ 1024, /* 8 Byte */
+ 1024, /* 16 Byte */
+ 4096, /* 32 Byte */
+ 4096, /* 64 Byte */
+ 4096, /* 128 Byte */
+ 4096, /* 256 Byte */
+ 1024, /* 512 Byte */
+ 1024, /* 1024 Byte */
+ 1024, /* 2048 Byte */
+ 1024, /* 4096 Byte */
+ 4096, /* 8192 Byte */
+ 64, /* 16384 Byte */
+ 64, /* 32768 Byte */
+};
+
+#ifndef NDEBUG
+static int kalloc_init_called;
+#endif
+
+extern vm_offset_t __kalloc (vm_size_t size);
extern vm_offset_t kget (vm_size_t size);
extern void kfree (vm_offset_t data, vm_size_t size);
-
extern void kalloc_init (void);
+inline vm_offset_t kalloc(size)
+ vm_size_t size;
+{
+ assert (kalloc_init_called);
+
+ if (__builtin_constant_p(size)) {
+ int zindex = 0;
+ vm_offset_t addr;
+
+ /*
+ * If our size is small enough, check the queue for
that size
+ * and allocate.
+ */
+ if (size < kalloc_max) {
+#define ZONE(val, index)
\
+ if ((size <= val)&&(index >= first_k_zone))
\
+ goto found;
\
+ else
\
+ zindex++;
+#include "zone_sizes.h"
+#undef CACHE
+ found:
+ addr = zalloc(k_zone[zindex]);
+ } else {
+ if (kmem_alloc_wired(kalloc_map, &addr, size)
+ != KERN_SUCCESS)
+ addr = 0;
+ }
+ return(addr);
+ }
+ return __kalloc(size);
+}
+
#endif /* _KERN_KALLOC_H_ */
diff --git a/kern/zone_sizes.h b/kern/zone_sizes.h
new file mode 100644
index 0000000..029b3bd
--- /dev/null
+++ b/kern/zone_sizes.h
@@ -0,0 +1,17 @@
+ZONE(1, 0);
+ZONE(2, 1);
+ZONE(4, 2);
+ZONE(8, 3);
+ZONE(16, 4);
+ZONE(32, 5);
+ZONE(64, 6);
+ZONE(128, 8);
+ZONE(256, 9);
+ZONE(512, 10);
+ZONE(1024, 11);
+ZONE(2048, 12);
+ZONE(4096, 13);
+ZONE(8192, 14);
+ZONE(16384, 15);
+ZONE(32768, 16);
+
--
1.7.2.3
- [PATCH] gnumach: kern: kalloc optimization for constant size requests,
Maksym Planeta <=