All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] xmalloc: make close-to-PAGE_SIZE allocations more efficient
@ 2013-02-18 12:45 Jan Beulich
  2013-02-18 13:26 ` Keir Fraser
  0 siblings, 1 reply; 2+ messages in thread
From: Jan Beulich @ 2013-02-18 12:45 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 7350 bytes --]

Rather than bumping their sizes to slightly above (a multiple of)
PAGE_SIZE (in order to store tracking information), thus requiring
a non-order-0 allocation even when no more than a page is being
requested, return the result of alloc_xenheap_pages() directly, and use
the struct page_info field underlying PFN_ORDER() to store the actual
size (needed for freeing the memory).

This leverages the fact that sub-allocation of memory obtained from the
page allocator can only ever result in non-page-aligned memory chunks
(with the exception of zero size allocations with sufficiently high
alignment being requested, which is why zero-size allocations now get
special cased).

Use the new property to simplify allocation of the trap info array for
PV guests on x86.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -369,13 +369,6 @@ int switch_compat(struct domain *d)
     return -ENOMEM;
 }
 
-static inline bool_t standalone_trap_ctxt(struct vcpu *v)
-{
-    BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) > PAGE_SIZE);
-    return NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) + sizeof(*v)
-           > PAGE_SIZE;
-}
-
 int vcpu_initialise(struct vcpu *v)
 {
     struct domain *d = v->domain;
@@ -427,19 +420,15 @@ int vcpu_initialise(struct vcpu *v)
 
     if ( !is_idle_domain(d) )
     {
-        if ( standalone_trap_ctxt(v) )
+        BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) >
+                     PAGE_SIZE);
+        v->arch.pv_vcpu.trap_ctxt = xzalloc_array(struct trap_info,
+                                                  NR_VECTORS);
+        if ( !v->arch.pv_vcpu.trap_ctxt )
         {
-            v->arch.pv_vcpu.trap_ctxt = alloc_xenheap_page();
-            if ( !v->arch.pv_vcpu.trap_ctxt )
-            {
-                rc = -ENOMEM;
-                goto done;
-            }
-            clear_page(v->arch.pv_vcpu.trap_ctxt);
+            rc = -ENOMEM;
+            goto done;
         }
-        else
-            v->arch.pv_vcpu.trap_ctxt = (void *)v + PAGE_SIZE -
-                NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt);
 
         /* PV guests by default have a 100Hz ticker. */
         v->periodic_period = MILLISECS(10);
@@ -467,8 +456,8 @@ int vcpu_initialise(struct vcpu *v)
     {
         vcpu_destroy_fpu(v);
 
-        if ( !is_hvm_domain(d) && standalone_trap_ctxt(v) )
-            free_xenheap_page(v->arch.pv_vcpu.trap_ctxt);
+        if ( !is_hvm_domain(d) )
+            xfree(v->arch.pv_vcpu.trap_ctxt);
     }
 
     return rc;
@@ -483,8 +472,8 @@ void vcpu_destroy(struct vcpu *v)
 
     if ( is_hvm_vcpu(v) )
         hvm_vcpu_destroy(v);
-    else if ( standalone_trap_ctxt(v) )
-        free_xenheap_page(v->arch.pv_vcpu.trap_ctxt);
+    else
+        xfree(v->arch.pv_vcpu.trap_ctxt);
 }
 
 int arch_domain_create(struct domain *d, unsigned int domcr_flags)
--- a/xen/common/xmalloc_tlsf.c
+++ b/xen/common/xmalloc_tlsf.c
@@ -26,6 +26,7 @@
 #include <xen/config.h>
 #include <xen/irq.h>
 #include <xen/mm.h>
+#include <xen/pfn.h>
 #include <asm/time.h>
 
 #define MAX_POOL_NAME_LEN       16
@@ -524,25 +525,30 @@ static void xmalloc_pool_put(void *p)
     free_xenheap_page(p);
 }
 
-static void *xmalloc_whole_pages(unsigned long size)
+static void *xmalloc_whole_pages(unsigned long size, unsigned long align)
 {
-    struct bhdr *b;
-    unsigned int i, pageorder = get_order_from_bytes(size + BHDR_OVERHEAD);
-    char *p;
+    unsigned int i, order = get_order_from_bytes(size);
+    void *res, *p;
+
+    if ( align > size )
+        get_order_from_bytes(align);
 
-    b = alloc_xenheap_pages(pageorder, 0);
-    if ( b == NULL )
+    res = alloc_xenheap_pages(order, 0);
+    if ( res == NULL )
         return NULL;
 
-    b->size = PAGE_ALIGN(size + BHDR_OVERHEAD);
-    for ( p = (char *)b + b->size, i = 0; i < pageorder; ++i )
+    for ( p = res + PAGE_ALIGN(size), i = 0; i < order; ++i )
         if ( (unsigned long)p & (PAGE_SIZE << i) )
         {
             free_xenheap_pages(p, i);
             p += PAGE_SIZE << i;
         }
 
-    return (void *)b->ptr.buffer;
+    PFN_ORDER(virt_to_page(res)) = PFN_UP(size);
+    /* Check that there was no truncation: */
+    ASSERT(PFN_ORDER(virt_to_page(res)) == PFN_UP(size));
+
+    return res;
 }
 
 static void tlsf_init(void)
@@ -559,6 +565,11 @@ static void tlsf_init(void)
  * xmalloc()
  */
 
+#ifndef ZERO_BLOCK_PTR
+/* Return value for zero-size allocation, distinguished from NULL. */
+#define ZERO_BLOCK_PTR ((void *)-1L)
+#endif
+
 void *_xmalloc(unsigned long size, unsigned long align)
 {
     void *p = NULL;
@@ -566,6 +577,9 @@ void *_xmalloc(unsigned long size, unsig
 
     ASSERT(!in_irq());
 
+    if ( !size )
+        return ZERO_BLOCK_PTR;
+
     ASSERT((align & (align - 1)) == 0);
     if ( align < MEM_ALIGN )
         align = MEM_ALIGN;
@@ -577,7 +591,7 @@ void *_xmalloc(unsigned long size, unsig
     if ( size < PAGE_SIZE )
         p = xmem_pool_alloc(size, xenpool);
     if ( p == NULL )
-        p = xmalloc_whole_pages(size);
+        return xmalloc_whole_pages(size - align + MEM_ALIGN, align);
 
     /* Add alignment padding. */
     if ( (pad = -(long)p & (align - 1)) != 0 )
@@ -604,11 +618,28 @@ void xfree(void *p)
 {
     struct bhdr *b;
 
-    if ( p == NULL )
+    if ( p == NULL || p == ZERO_BLOCK_PTR )
         return;
 
     ASSERT(!in_irq());
 
+    if ( !((unsigned long)p & (PAGE_SIZE - 1)) )
+    {
+        unsigned long size = PFN_ORDER(virt_to_page(p));
+        unsigned int i, order = get_order_from_pages(size);
+
+        BUG_ON((unsigned long)p & ((PAGE_SIZE << order) - 1));
+        for ( i = 0; ; ++i )
+        {
+            if ( !(size & (1 << i)) )
+                continue;
+            size -= 1 << i;
+            free_xenheap_pages(p + (size << PAGE_SHIFT), i);
+            if ( i + 1 >= order )
+                return;
+        }
+    }
+
     /* Strip alignment padding. */
     b = (struct bhdr *)((char *) p - BHDR_OVERHEAD);
     if ( b->size & 1 )
@@ -618,21 +649,5 @@ void xfree(void *p)
         ASSERT(!(b->size & 1));
     }
 
-    if ( b->size >= PAGE_SIZE )
-    {
-        unsigned int i, order = get_order_from_bytes(b->size);
-
-        BUG_ON((unsigned long)b & ((PAGE_SIZE << order) - 1));
-        for ( i = 0; ; ++i )
-        {
-            if ( !(b->size & (PAGE_SIZE << i)) )
-                continue;
-            b->size -= PAGE_SIZE << i;
-            free_xenheap_pages((void *)b + b->size, i);
-            if ( i + 1 >= order )
-                break;
-        }
-    }
-    else
-        xmem_pool_free(p, xenpool);
+    xmem_pool_free(p, xenpool);
 }
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -91,6 +91,9 @@
 /* Primary stack is restricted to 8kB by guard pages. */
 #define PRIMARY_STACK_SIZE 8192
 
+/* Return value for zero-size _xmalloc(), distinguished from NULL. */
+#define ZERO_BLOCK_PTR ((void *)0xBAD0BAD0BAD0BAD0UL)
+
 #ifndef __ASSEMBLY__
 extern unsigned long trampoline_phys;
 #define bootsym_phys(sym)                                 \



[-- Attachment #2: xmalloc-exact-pages.patch --]
[-- Type: text/plain, Size: 7409 bytes --]

xmalloc: make close-to-PAGE_SIZE allocations more efficient

Rather than bumping their sizes to slightly above (a multiple of)
PAGE_SIZE (in order to store tracking information), thus requiring
a non-order-0 allocation even when no more than a page is being
requested, return the result of alloc_xenheap_pages() directly, and use
the struct page_info field underlying PFN_ORDER() to store the actual
size (needed for freeing the memory).

This leverages the fact that sub-allocation of memory obtained from the
page allocator can only ever result in non-page-aligned memory chunks
(with the exception of zero size allocations with sufficiently high
alignment being requested, which is why zero-size allocations now get
special cased).

Use the new property to simplify allocation of the trap info array for
PV guests on x86.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -369,13 +369,6 @@ int switch_compat(struct domain *d)
     return -ENOMEM;
 }
 
-static inline bool_t standalone_trap_ctxt(struct vcpu *v)
-{
-    BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) > PAGE_SIZE);
-    return NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) + sizeof(*v)
-           > PAGE_SIZE;
-}
-
 int vcpu_initialise(struct vcpu *v)
 {
     struct domain *d = v->domain;
@@ -427,19 +420,15 @@ int vcpu_initialise(struct vcpu *v)
 
     if ( !is_idle_domain(d) )
     {
-        if ( standalone_trap_ctxt(v) )
+        BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) >
+                     PAGE_SIZE);
+        v->arch.pv_vcpu.trap_ctxt = xzalloc_array(struct trap_info,
+                                                  NR_VECTORS);
+        if ( !v->arch.pv_vcpu.trap_ctxt )
         {
-            v->arch.pv_vcpu.trap_ctxt = alloc_xenheap_page();
-            if ( !v->arch.pv_vcpu.trap_ctxt )
-            {
-                rc = -ENOMEM;
-                goto done;
-            }
-            clear_page(v->arch.pv_vcpu.trap_ctxt);
+            rc = -ENOMEM;
+            goto done;
         }
-        else
-            v->arch.pv_vcpu.trap_ctxt = (void *)v + PAGE_SIZE -
-                NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt);
 
         /* PV guests by default have a 100Hz ticker. */
         v->periodic_period = MILLISECS(10);
@@ -467,8 +456,8 @@ int vcpu_initialise(struct vcpu *v)
     {
         vcpu_destroy_fpu(v);
 
-        if ( !is_hvm_domain(d) && standalone_trap_ctxt(v) )
-            free_xenheap_page(v->arch.pv_vcpu.trap_ctxt);
+        if ( !is_hvm_domain(d) )
+            xfree(v->arch.pv_vcpu.trap_ctxt);
     }
 
     return rc;
@@ -483,8 +472,8 @@ void vcpu_destroy(struct vcpu *v)
 
     if ( is_hvm_vcpu(v) )
         hvm_vcpu_destroy(v);
-    else if ( standalone_trap_ctxt(v) )
-        free_xenheap_page(v->arch.pv_vcpu.trap_ctxt);
+    else
+        xfree(v->arch.pv_vcpu.trap_ctxt);
 }
 
 int arch_domain_create(struct domain *d, unsigned int domcr_flags)
--- a/xen/common/xmalloc_tlsf.c
+++ b/xen/common/xmalloc_tlsf.c
@@ -26,6 +26,7 @@
 #include <xen/config.h>
 #include <xen/irq.h>
 #include <xen/mm.h>
+#include <xen/pfn.h>
 #include <asm/time.h>
 
 #define MAX_POOL_NAME_LEN       16
@@ -524,25 +525,30 @@ static void xmalloc_pool_put(void *p)
     free_xenheap_page(p);
 }
 
-static void *xmalloc_whole_pages(unsigned long size)
+static void *xmalloc_whole_pages(unsigned long size, unsigned long align)
 {
-    struct bhdr *b;
-    unsigned int i, pageorder = get_order_from_bytes(size + BHDR_OVERHEAD);
-    char *p;
+    unsigned int i, order = get_order_from_bytes(size);
+    void *res, *p;
+
+    if ( align > size )
+        get_order_from_bytes(align);
 
-    b = alloc_xenheap_pages(pageorder, 0);
-    if ( b == NULL )
+    res = alloc_xenheap_pages(order, 0);
+    if ( res == NULL )
         return NULL;
 
-    b->size = PAGE_ALIGN(size + BHDR_OVERHEAD);
-    for ( p = (char *)b + b->size, i = 0; i < pageorder; ++i )
+    for ( p = res + PAGE_ALIGN(size), i = 0; i < order; ++i )
         if ( (unsigned long)p & (PAGE_SIZE << i) )
         {
             free_xenheap_pages(p, i);
             p += PAGE_SIZE << i;
         }
 
-    return (void *)b->ptr.buffer;
+    PFN_ORDER(virt_to_page(res)) = PFN_UP(size);
+    /* Check that there was no truncation: */
+    ASSERT(PFN_ORDER(virt_to_page(res)) == PFN_UP(size));
+
+    return res;
 }
 
 static void tlsf_init(void)
@@ -559,6 +565,11 @@ static void tlsf_init(void)
  * xmalloc()
  */
 
+#ifndef ZERO_BLOCK_PTR
+/* Return value for zero-size allocation, distinguished from NULL. */
+#define ZERO_BLOCK_PTR ((void *)-1L)
+#endif
+
 void *_xmalloc(unsigned long size, unsigned long align)
 {
     void *p = NULL;
@@ -566,6 +577,9 @@ void *_xmalloc(unsigned long size, unsig
 
     ASSERT(!in_irq());
 
+    if ( !size )
+        return ZERO_BLOCK_PTR;
+
     ASSERT((align & (align - 1)) == 0);
     if ( align < MEM_ALIGN )
         align = MEM_ALIGN;
@@ -577,7 +591,7 @@ void *_xmalloc(unsigned long size, unsig
     if ( size < PAGE_SIZE )
         p = xmem_pool_alloc(size, xenpool);
     if ( p == NULL )
-        p = xmalloc_whole_pages(size);
+        return xmalloc_whole_pages(size - align + MEM_ALIGN, align);
 
     /* Add alignment padding. */
     if ( (pad = -(long)p & (align - 1)) != 0 )
@@ -604,11 +618,28 @@ void xfree(void *p)
 {
     struct bhdr *b;
 
-    if ( p == NULL )
+    if ( p == NULL || p == ZERO_BLOCK_PTR )
         return;
 
     ASSERT(!in_irq());
 
+    if ( !((unsigned long)p & (PAGE_SIZE - 1)) )
+    {
+        unsigned long size = PFN_ORDER(virt_to_page(p));
+        unsigned int i, order = get_order_from_pages(size);
+
+        BUG_ON((unsigned long)p & ((PAGE_SIZE << order) - 1));
+        for ( i = 0; ; ++i )
+        {
+            if ( !(size & (1 << i)) )
+                continue;
+            size -= 1 << i;
+            free_xenheap_pages(p + (size << PAGE_SHIFT), i);
+            if ( i + 1 >= order )
+                return;
+        }
+    }
+
     /* Strip alignment padding. */
     b = (struct bhdr *)((char *) p - BHDR_OVERHEAD);
     if ( b->size & 1 )
@@ -618,21 +649,5 @@ void xfree(void *p)
         ASSERT(!(b->size & 1));
     }
 
-    if ( b->size >= PAGE_SIZE )
-    {
-        unsigned int i, order = get_order_from_bytes(b->size);
-
-        BUG_ON((unsigned long)b & ((PAGE_SIZE << order) - 1));
-        for ( i = 0; ; ++i )
-        {
-            if ( !(b->size & (PAGE_SIZE << i)) )
-                continue;
-            b->size -= PAGE_SIZE << i;
-            free_xenheap_pages((void *)b + b->size, i);
-            if ( i + 1 >= order )
-                break;
-        }
-    }
-    else
-        xmem_pool_free(p, xenpool);
+    xmem_pool_free(p, xenpool);
 }
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -91,6 +91,9 @@
 /* Primary stack is restricted to 8kB by guard pages. */
 #define PRIMARY_STACK_SIZE 8192
 
+/* Return value for zero-size _xmalloc(), distinguished from NULL. */
+#define ZERO_BLOCK_PTR ((void *)0xBAD0BAD0BAD0BAD0UL)
+
 #ifndef __ASSEMBLY__
 extern unsigned long trampoline_phys;
 #define bootsym_phys(sym)                                 \

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] xmalloc: make close-to-PAGE_SIZE allocations more efficient
  2013-02-18 12:45 [PATCH] xmalloc: make close-to-PAGE_SIZE allocations more efficient Jan Beulich
@ 2013-02-18 13:26 ` Keir Fraser
  0 siblings, 0 replies; 2+ messages in thread
From: Keir Fraser @ 2013-02-18 13:26 UTC (permalink / raw)
  To: Jan Beulich, xen-devel

On 18/02/2013 12:45, "Jan Beulich" <JBeulich@suse.com> wrote:

> Rather than bumping their sizes to slightly above (a multiple of)
> PAGE_SIZE (in order to store tracking information), thus requiring
> a non-order-0 allocation even when no more than a page is being
> requested, return the result of alloc_xenheap_pages() directly, and use
> the struct page_info field underlying PFN_ORDER() to store the actual
> size (needed for freeing the memory).
> 
> This leverages the fact that sub-allocation of memory obtained from the
> page allocator can only ever result in non-page-aligned memory chunks
> (with the exception of zero size allocations with sufficiently high
> alignment being requested, which is why zero-size allocations now get
> special cased).
> 
> Use the new property to simplify allocation of the trap info array for
> PV guests on x86.
> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Acked-by: Keir Fraser <keir@xen.org>

> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -369,13 +369,6 @@ int switch_compat(struct domain *d)
>      return -ENOMEM;
>  }
>  
> -static inline bool_t standalone_trap_ctxt(struct vcpu *v)
> -{
> -    BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) >
> PAGE_SIZE);
> -    return NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) + sizeof(*v)
> -           > PAGE_SIZE;
> -}
> -
>  int vcpu_initialise(struct vcpu *v)
>  {
>      struct domain *d = v->domain;
> @@ -427,19 +420,15 @@ int vcpu_initialise(struct vcpu *v)
>  
>      if ( !is_idle_domain(d) )
>      {
> -        if ( standalone_trap_ctxt(v) )
> +        BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) >
> +                     PAGE_SIZE);
> +        v->arch.pv_vcpu.trap_ctxt = xzalloc_array(struct trap_info,
> +                                                  NR_VECTORS);
> +        if ( !v->arch.pv_vcpu.trap_ctxt )
>          {
> -            v->arch.pv_vcpu.trap_ctxt = alloc_xenheap_page();
> -            if ( !v->arch.pv_vcpu.trap_ctxt )
> -            {
> -                rc = -ENOMEM;
> -                goto done;
> -            }
> -            clear_page(v->arch.pv_vcpu.trap_ctxt);
> +            rc = -ENOMEM;
> +            goto done;
>          }
> -        else
> -            v->arch.pv_vcpu.trap_ctxt = (void *)v + PAGE_SIZE -
> -                NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt);
>  
>          /* PV guests by default have a 100Hz ticker. */
>          v->periodic_period = MILLISECS(10);
> @@ -467,8 +456,8 @@ int vcpu_initialise(struct vcpu *v)
>      {
>          vcpu_destroy_fpu(v);
>  
> -        if ( !is_hvm_domain(d) && standalone_trap_ctxt(v) )
> -            free_xenheap_page(v->arch.pv_vcpu.trap_ctxt);
> +        if ( !is_hvm_domain(d) )
> +            xfree(v->arch.pv_vcpu.trap_ctxt);
>      }
>  
>      return rc;
> @@ -483,8 +472,8 @@ void vcpu_destroy(struct vcpu *v)
>  
>      if ( is_hvm_vcpu(v) )
>          hvm_vcpu_destroy(v);
> -    else if ( standalone_trap_ctxt(v) )
> -        free_xenheap_page(v->arch.pv_vcpu.trap_ctxt);
> +    else
> +        xfree(v->arch.pv_vcpu.trap_ctxt);
>  }
>  
>  int arch_domain_create(struct domain *d, unsigned int domcr_flags)
> --- a/xen/common/xmalloc_tlsf.c
> +++ b/xen/common/xmalloc_tlsf.c
> @@ -26,6 +26,7 @@
>  #include <xen/config.h>
>  #include <xen/irq.h>
>  #include <xen/mm.h>
> +#include <xen/pfn.h>
>  #include <asm/time.h>
>  
>  #define MAX_POOL_NAME_LEN       16
> @@ -524,25 +525,30 @@ static void xmalloc_pool_put(void *p)
>      free_xenheap_page(p);
>  }
>  
> -static void *xmalloc_whole_pages(unsigned long size)
> +static void *xmalloc_whole_pages(unsigned long size, unsigned long align)
>  {
> -    struct bhdr *b;
> -    unsigned int i, pageorder = get_order_from_bytes(size + BHDR_OVERHEAD);
> -    char *p;
> +    unsigned int i, order = get_order_from_bytes(size);
> +    void *res, *p;
> +
> +    if ( align > size )
> +        get_order_from_bytes(align);
>  
> -    b = alloc_xenheap_pages(pageorder, 0);
> -    if ( b == NULL )
> +    res = alloc_xenheap_pages(order, 0);
> +    if ( res == NULL )
>          return NULL;
>  
> -    b->size = PAGE_ALIGN(size + BHDR_OVERHEAD);
> -    for ( p = (char *)b + b->size, i = 0; i < pageorder; ++i )
> +    for ( p = res + PAGE_ALIGN(size), i = 0; i < order; ++i )
>          if ( (unsigned long)p & (PAGE_SIZE << i) )
>          {
>              free_xenheap_pages(p, i);
>              p += PAGE_SIZE << i;
>          }
>  
> -    return (void *)b->ptr.buffer;
> +    PFN_ORDER(virt_to_page(res)) = PFN_UP(size);
> +    /* Check that there was no truncation: */
> +    ASSERT(PFN_ORDER(virt_to_page(res)) == PFN_UP(size));
> +
> +    return res;
>  }
>  
>  static void tlsf_init(void)
> @@ -559,6 +565,11 @@ static void tlsf_init(void)
>   * xmalloc()
>   */
>  
> +#ifndef ZERO_BLOCK_PTR
> +/* Return value for zero-size allocation, distinguished from NULL. */
> +#define ZERO_BLOCK_PTR ((void *)-1L)
> +#endif
> +
>  void *_xmalloc(unsigned long size, unsigned long align)
>  {
>      void *p = NULL;
> @@ -566,6 +577,9 @@ void *_xmalloc(unsigned long size, unsig
>  
>      ASSERT(!in_irq());
>  
> +    if ( !size )
> +        return ZERO_BLOCK_PTR;
> +
>      ASSERT((align & (align - 1)) == 0);
>      if ( align < MEM_ALIGN )
>          align = MEM_ALIGN;
> @@ -577,7 +591,7 @@ void *_xmalloc(unsigned long size, unsig
>      if ( size < PAGE_SIZE )
>          p = xmem_pool_alloc(size, xenpool);
>      if ( p == NULL )
> -        p = xmalloc_whole_pages(size);
> +        return xmalloc_whole_pages(size - align + MEM_ALIGN, align);
>  
>      /* Add alignment padding. */
>      if ( (pad = -(long)p & (align - 1)) != 0 )
> @@ -604,11 +618,28 @@ void xfree(void *p)
>  {
>      struct bhdr *b;
>  
> -    if ( p == NULL )
> +    if ( p == NULL || p == ZERO_BLOCK_PTR )
>          return;
>  
>      ASSERT(!in_irq());
>  
> +    if ( !((unsigned long)p & (PAGE_SIZE - 1)) )
> +    {
> +        unsigned long size = PFN_ORDER(virt_to_page(p));
> +        unsigned int i, order = get_order_from_pages(size);
> +
> +        BUG_ON((unsigned long)p & ((PAGE_SIZE << order) - 1));
> +        for ( i = 0; ; ++i )
> +        {
> +            if ( !(size & (1 << i)) )
> +                continue;
> +            size -= 1 << i;
> +            free_xenheap_pages(p + (size << PAGE_SHIFT), i);
> +            if ( i + 1 >= order )
> +                return;
> +        }
> +    }
> +
>      /* Strip alignment padding. */
>      b = (struct bhdr *)((char *) p - BHDR_OVERHEAD);
>      if ( b->size & 1 )
> @@ -618,21 +649,5 @@ void xfree(void *p)
>          ASSERT(!(b->size & 1));
>      }
>  
> -    if ( b->size >= PAGE_SIZE )
> -    {
> -        unsigned int i, order = get_order_from_bytes(b->size);
> -
> -        BUG_ON((unsigned long)b & ((PAGE_SIZE << order) - 1));
> -        for ( i = 0; ; ++i )
> -        {
> -            if ( !(b->size & (PAGE_SIZE << i)) )
> -                continue;
> -            b->size -= PAGE_SIZE << i;
> -            free_xenheap_pages((void *)b + b->size, i);
> -            if ( i + 1 >= order )
> -                break;
> -        }
> -    }
> -    else
> -        xmem_pool_free(p, xenpool);
> +    xmem_pool_free(p, xenpool);
>  }
> --- a/xen/include/asm-x86/config.h
> +++ b/xen/include/asm-x86/config.h
> @@ -91,6 +91,9 @@
>  /* Primary stack is restricted to 8kB by guard pages. */
>  #define PRIMARY_STACK_SIZE 8192
>  
> +/* Return value for zero-size _xmalloc(), distinguished from NULL. */
> +#define ZERO_BLOCK_PTR ((void *)0xBAD0BAD0BAD0BAD0UL)
> +
>  #ifndef __ASSEMBLY__
>  extern unsigned long trampoline_phys;
>  #define bootsym_phys(sym)                                 \
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-02-18 13:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-18 12:45 [PATCH] xmalloc: make close-to-PAGE_SIZE allocations more efficient Jan Beulich
2013-02-18 13:26 ` Keir Fraser

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.