xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Andres Lagar-Cavilla <andres@lagarcavilla.org>
To: xen-devel@lists.xensource.com
Cc: ian.campbell@citrix.com, andres@gridcentric.ca, tim@xen.org,
	JBeulich@suse.com, ian.jackson@citrix.com, adin@gridcentric.ca
Subject: [PATCH 1 of 2] Global virq for low memory situations
Date: Tue, 28 Feb 2012 16:56:16 -0500	[thread overview]
Message-ID: <c44e9fe0ecca69b516d8.1330466176@xdev.gridcentric.ca> (raw)
In-Reply-To: <patchbomb.1330466175@xdev.gridcentric.ca>

 xen/common/page_alloc.c  |  92 ++++++++++++++++++++++++++++++++++++++++++++++++
 xen/include/public/xen.h |   1 +
 2 files changed, 93 insertions(+), 0 deletions(-)


When a low memory threshold on the Xen heap is reached, we fire a global dom0
virq. If someone's listening, they can free up some more memory. The low
threshold is configurable via the command line token 'low_mem_virq_limit", and
defaults to 64MiB.

We define a new virq VIRQ_ENOMEM. Potential listeners include squeezed,
xenballoond, or anything else that can be fired through xencommons.

We error-check the low mem virq against initial available heap (after dom0
allocation), to avoid firing immediately.

Virq issuing is controlled by a hysteresis algorithm: when memory dips below a
threshold, the virq is issued and the next virq will fire when memory shrinks
another order of magnitude. The virq will not fire again in the current "band"
until memory grows over the next higher order of magnitude.

Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla.org>

diff -r 0696aa1de7c2 -r c44e9fe0ecca xen/common/page_alloc.c
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -35,6 +35,7 @@
 #include <xen/perfc.h>
 #include <xen/numa.h>
 #include <xen/nodemask.h>
+#include <xen/event.h>
 #include <xen/tmem.h>
 #include <xen/tmem_xen.h>
 #include <public/sysctl.h>
@@ -300,6 +301,91 @@ static unsigned long init_node_heap(int 
     return needed;
 }
 
+/* Default to 64 MiB */
+#define DEFAULT_LOW_MEM_VIRQ    (((paddr_t) 64)   << 20)
+#define MAX_LOW_MEM_VIRQ        (((paddr_t) 1024) << 20)
+
+static paddr_t __read_mostly opt_low_mem_virq = DEFAULT_LOW_MEM_VIRQ;
+size_param("low_mem_virq_limit", opt_low_mem_virq);
+
+/* Thresholds to control hysteresis. In pages */
+/* When memory grows above this threshold, reset hysteresis.
+ * -1 initially to not reset until at least one virq issued. */
+static unsigned long low_mem_virq_high      = -1UL;
+/* Threshold at which we issue virq */
+static unsigned long low_mem_virq_th        = 0;
+/* Original threshold after all checks completed */
+static unsigned long low_mem_virq_orig      = 0;
+/* Order for current threshold */
+static unsigned int  low_mem_virq_th_order  = 0;
+
+/* Perform bootstrapping checks and set bounds */
+static void __init setup_low_mem_virq(void)
+{
+    unsigned int order;
+    paddr_t threshold;
+
+    /* Dom0 has already been allocated by now. So check we won't 
+     * be complaining immediately with whatever's left of the heap. */
+    threshold = min(opt_low_mem_virq, 
+                    ((paddr_t) total_avail_pages) << PAGE_SHIFT);
+
+    /* Then, cap to some predefined maximum */
+    threshold = min(threshold, MAX_LOW_MEM_VIRQ);
+
+    /* If the user specified no knob, and we are at the current available 
+     * level, halve the threshold. */
+    if ( (opt_low_mem_virq == DEFAULT_LOW_MEM_VIRQ)
+            && (threshold == (((paddr_t) total_avail_pages) << PAGE_SHIFT)) )
+        threshold >>= 1;
+
+    /* Threshold bytes -> pages */
+    low_mem_virq_th = threshold >> PAGE_SHIFT;
+
+    /* Next, round the threshold down to the next order */
+    order = get_order_from_pages(low_mem_virq_th);
+    if ( (1UL << order) > low_mem_virq_th ) 
+        order--;
+
+    /* Set bounds, ready to go */
+    low_mem_virq_th = low_mem_virq_orig = 1UL << order;
+    low_mem_virq_th_order = order;
+
+    printk("Initial low memory virq threshold set at 0x%lx pages.\n",
+            low_mem_virq_th);
+}
+
+static void check_low_mem_virq(void)
+{
+    if ( total_avail_pages <= low_mem_virq_th )
+    {
+        send_global_virq(VIRQ_ENOMEM);
+
+        /* Update thresholds. Next warning will be when we drop below
+         * next order. However, we wait until we grow beyond one
+         * order above us to complain again at the current order */
+        low_mem_virq_high   = 1UL << (low_mem_virq_th_order + 1);
+        if ( low_mem_virq_th_order > 0 )
+            low_mem_virq_th_order--;
+        low_mem_virq_th     = 1UL << low_mem_virq_th_order;
+        return;
+    }
+
+    if ( total_avail_pages >= low_mem_virq_high )
+    {
+        /* Reset hysteresis. Bring threshold up one order.
+         * If we are back where originally set, set high
+         * threshold to -1 to avoid further growth of 
+         * virq threshold. */
+        low_mem_virq_th_order++;
+        low_mem_virq_th = 1UL << low_mem_virq_th_order;
+        if ( low_mem_virq_th == low_mem_virq_orig )
+            low_mem_virq_high = -1UL;
+        else
+            low_mem_virq_high = 1UL << (low_mem_virq_th_order + 2);
+    }
+}
+
 /* Allocate 2^@order contiguous pages. */
 static struct page_info *alloc_heap_pages(
     unsigned int zone_lo, unsigned int zone_hi,
@@ -420,6 +506,8 @@ static struct page_info *alloc_heap_page
     total_avail_pages -= request;
     ASSERT(total_avail_pages >= 0);
 
+    check_low_mem_virq();
+
     if ( d != NULL )
         d->last_alloc_node = node;
 
@@ -1022,6 +1110,10 @@ void __init scrub_heap_pages(void)
     }
 
     printk("done.\n");
+
+    /* Now that the heap is initialized, run checks and set bounds
+     * for the low mem virq algorithm. */
+    setup_low_mem_virq();
 }
 
 
diff -r 0696aa1de7c2 -r c44e9fe0ecca xen/include/public/xen.h
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -157,6 +157,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define VIRQ_PCPU_STATE 9  /* G. (DOM0) PCPU state changed                   */
 #define VIRQ_MEM_EVENT  10 /* G. (DOM0) A memory event has occured           */
 #define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient                     */
+#define VIRQ_ENOMEM     12 /* G. (DOM0) Low on heap memory       */
 
 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16

  reply	other threads:[~2012-02-28 21:56 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-28 21:56 [PATCH 0 of 2] Virq for low memory condition, V3 Andres Lagar-Cavilla
2012-02-28 21:56 ` Andres Lagar-Cavilla [this message]
2012-02-28 23:50   ` [PATCH 1 of 2] Global virq for low memory situations Dan Magenheimer
2012-02-29  4:17     ` Andres Lagar-Cavilla
2012-02-29  8:54     ` Jan Beulich
2012-02-29  8:53   ` Jan Beulich
2012-02-28 21:56 ` [PATCH 2 of 2] Lowmemd: Simple demo code to show use of VIRQ_ENOMEM Andres Lagar-Cavilla
2012-02-29  8:57   ` Jan Beulich
  -- strict thread matches above, loose matches on Subject: below --
2012-03-01  2:25 [PATCH 0 of 2] Virq for low memory condition, V4 Andres Lagar-Cavilla
2012-03-01  2:25 ` [PATCH 1 of 2] Global virq for low memory situations Andres Lagar-Cavilla
2012-03-01 19:19   ` Dan Magenheimer
2012-03-01 19:26     ` Andres Lagar-Cavilla
2012-03-01 21:08       ` Dan Magenheimer
2012-03-06 20:03 [PATCH 0 of 2] Virq for low memory conditions, V5 Andres Lagar-Cavilla
2012-03-06 20:03 ` [PATCH 1 of 2] Global virq for low memory situations Andres Lagar-Cavilla

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c44e9fe0ecca69b516d8.1330466176@xdev.gridcentric.ca \
    --to=andres@lagarcavilla.org \
    --cc=JBeulich@suse.com \
    --cc=adin@gridcentric.ca \
    --cc=andres@gridcentric.ca \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@citrix.com \
    --cc=tim@xen.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).