|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] Global virq for low memory situations
>>> On 23.02.12 at 20:59, Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx> wrote:
> @@ -300,6 +301,87 @@ static unsigned long init_node_heap(int
> return needed;
> }
>
> +/* Default to 64 MiB */
> +#define DEFAULT_LOW_MEM_VIRQ_MIB 64
> +#define MAX_LOW_MEM_VIRQ_MIB 1024
> +
> +static unsigned long long __read_mostly opt_low_mem_virq =
> + (DEFAULT_LOW_MEM_VIRQ_MIB << 20);
> +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 setup_low_mem_virq(void)
__init
> +{
> + unsigned int order;
> + unsigned long long 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, (unsigned long long)
> + (total_avail_pages << PAGE_SHIFT));
The cast needs to be on total_avail_pages, not the result of the
shift. Also, unsigned long long is the wrong type (paddr_t was
invented for this very purpose).
Further, the initial threshold should clearly be *below* the currently
available amount (e.g. at half of it).
> +
> + /* Then, cap to some predefined maximum */
> + threshold = min(threshold, (unsigned long long)
> + (MAX_LOW_MEM_VIRQ_MIB << 20));
Same here wrt the cast.
> +
> + /* 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 ( (1 << order) > low_mem_virq_th )
> + order--;
> +
> + /* Set bounds, ready to go */
> + low_mem_virq_th = low_mem_virq_orig = 1 << order;
1UL << ...
> + low_mem_virq_th_order = order;
> +
> + printk("Current low memory virq threshold set at 0x%lx pages.\n",
"Initial ..."
> + 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 = 1 << (low_mem_virq_th_order + 1);
1UL << ...
> + if ( low_mem_virq_th_order > 0 )
> + low_mem_virq_th_order--;
> + low_mem_virq_th = 1 << low_mem_virq_th_order;
Same here.
> + 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 = 1 << low_mem_virq_th_order;
And here.
> + if ( low_mem_virq_th == low_mem_virq_orig )
> + low_mem_virq_high = -1UL;
> + else
> + low_mem_virq_high = 1 << (low_mem_virq_th_order + 2);
And here.
> + }
> +}
> +
> /* Allocate 2^@order contiguous pages. */
> static struct page_info *alloc_heap_pages(
> unsigned int zone_lo, unsigned int zone_hi,
> @@ -420,6 +502,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 +1106,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 dd69d9b1aee9 -r da02cb8485de 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) Dangerously low on heap memory
> */
Either the default threshold ought to be *much* lower (say 64k), or
the "dangerously" here is completely misleading.
>
> /* Architecture-specific VIRQ definitions. */
> #define VIRQ_ARCH_0 16
Given that this new vIRQ ought to be handled in user space, do you
have an implementation ready to contribute as well?
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |