bug-hurd
[Top][All Lists]
Advanced

[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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]