示例#1
0
/* Move the given node up through the heap to the appropriate position. */
static inline void
mm_move_up_large(mm_node **heap, idx_t window, idx_t idx, mm_node *node)
{
    mm_node *child;
    ai_t ai = node->ai;
    idx_t c_idx = mm_get_smallest_child(heap, window, idx, &child);

    while (ai > child->ai) {
        SWAP_NODES(heap, idx, node, c_idx, child);
        c_idx = mm_get_smallest_child(heap, window, idx, &child);
    }
}
示例#2
0
/* Move the given node down through the heap to the appropriate position. */
static inline void
mm_move_down_large(mm_node **heap, idx_t idx, mm_node *node, idx_t p_idx,
                   mm_node *parent)
{
    do {
        SWAP_NODES(heap, idx, node, p_idx, parent);
        if (idx == 0) {
            break;
        }
        p_idx = P_IDX(idx);
        parent = heap[p_idx];
    } while (node->ai < parent->ai);
}
示例#3
0
文件: KDTree.hpp 项目: rrti/kiran
	void MedianSplitSegment(std::vector<T>& segment, int sNodeNum, int eNodeNum, int newMedianIdx, int splitAxisIdx) {
		int sIdx = sNodeNum;
		int eIdx = eNodeNum;

		assert(sIdx >=                  0);
		assert(eIdx < int(segment.size()));

		#define SWAP_NODES(segment, idxA, idxB) { T n = segment[idxA]; segment[idxA] = segment[idxB]; segment[idxB] = n; }

		while (eIdx > sIdx) {
			const float v = segment[eIdx]->GetPos()[splitAxisIdx];

			// make sure (++i == sIdx) in the first iteration
			int i = sIdx - 1;
			int j = eIdx;

			for (;;) {
				// increase i until we find a farther node along splitAxisIdx
				// decrease j until we find a closer node along splitAxisIdx
				// swap the nodes at indices i and j unless they are in-order
				while (segment[++i]->GetPos()[splitAxisIdx] < v) {}
				while (segment[--j]->GetPos()[splitAxisIdx] > v && (j > sIdx)) {}

				if (i >= j) {
					break;
				}

				SWAP_NODES(segment, i, j);
			}

			SWAP_NODES(segment, i, eIdx);

			if (i >= newMedianIdx) { eIdx = i - 1; }
			if (i <  newMedianIdx) { sIdx = i + 1; }
		}

		#undef swap
	}
示例#4
0
/*
 * Copyright (c) 2013 Citrix Systems, Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

//
// balloon.c
//
// This module supports the Xen balloon functionality, that is, dynamic memory
// assignment and removal from a domain.
//
// Copyright (c) 2007, XenSource, Inc. - All rights reserved.
//
//--

#pragma warning (push, 3)

#include <ntddk.h>
#include <ntstrsafe.h>
#include "xsapi.h"
#include "scsiboot.h"

#include "hvm.h"
#include "hypercall.h"
#include "xenbus.h"
#include "xenutl.h"

#include <xen_types.h>
#include <memory.h>
#include <hvm_params.h>

#include "balloon.h"

#pragma warning (pop)

#define range_set_index_t PFN_NUMBER
#include "rangeset.c"

#define MIN(a, b)   ((a) < (b) ? (a) : (b))

#define TIME_US(_us)        ((_us) * 10)
#define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
#define TIME_S(_s)          (TIME_MS((_s) * 1000))
#define TIME_RELATIVE(_t)   (-(_t))

// Keep a made up MDL up our sleeve with room for the maximal number of
// PFN_NUMBERs.
//
// We also need an array of PFN_NUMBERs when communicating to Xen which pages
// are being returned or reclaimed, and that memory must be locked.  We could
// use the list as it exists in the page of pages and do the following every
// time we talk to Xen (for each page of pages)-
//
//  . Allocate an MDL
//  . Probe and Lock pages
//  . Virtual Lock
//  . Talk to Xen
//  . Virtual unlock
//  . Unlock pages
//  . Free MDL
//
// but that all seems like a lot of code, or in particular, a lot of guest
// OS calls.  Instead we'll reuse(/overload) the PFN array.
//
// Fortunately the native size of a Windows PFN is the same as the native
// (guest) size of a Xen PFN.

#define SHORT_MAX           (1 << 15)
#define MAX_PAGES_PER_MDL   ((SHORT_MAX - sizeof(MDL)) / sizeof(PFN_NUMBER))

#define BALLOON_PFN_ARRAY_SIZE  (MAX_PAGES_PER_MDL)

typedef struct _BALLOON
{
    ULONG               TopPage;

    // We aim for CurrentPages == TargetPages.
    ULONG               CurrentPages;
    ULONG               TargetPages;
    ULONG               MaxPages;

    // Various interesting statistics
    ULONG               AllocateFail;
    ULONG               PartialAllocate;
    ULONG               PartialPopulate;

    struct range_set    PfnsBalloonedOut;

    // Our pre-built MDL
    MDL                 Mdl;
    PFN_NUMBER          PfnArray[BALLOON_PFN_ARRAY_SIZE];

    KEVENT              WorkerDoneEvent;
    struct xm_thread    *WorkerThread;

    // Failure insertion and self-test flags
    BOOLEAN             FIST_inflation;
    BOOLEAN             FIST_deflation;

    // State flags
    BOOLEAN             Frozen;
    BOOLEAN             Initialized;
    BOOLEAN             Advertized;
    ULONG               AdvertizedSuspendCount;
    BOOLEAN             Active;
    ULONG               ActiveSuspendCount;

} BALLOON;

// There's only one balloon in a domain so make it global to make debugging
// easier.
static BALLOON Balloon;

static NTSTATUS
BalloonReadTargetPages(
    OUT ULONG   *TargetPages
    )
{
    ULONG64     Target;
    NTSTATUS    status;

    status = xenbus_read_int(XBT_NIL, "memory", "target", &Target);
    if (!NT_SUCCESS(status))
        goto fail1;

    *TargetPages = (ULONG)(Target / 4);
    return STATUS_SUCCESS;

fail1:
    TraceError(("%s: fail1 (%08x)\n", __FUNCTION__, status));

    return status;
}

static NTSTATUS
BalloonReadMaxPages(
    OUT ULONG   *MaxPages
    )
{
    ULONG64     StaticMax;
    NTSTATUS    status;

    status = xenbus_read_int(XBT_NIL, "memory", "static-max", &StaticMax);
    if (!NT_SUCCESS(status))
        goto fail1;

    *MaxPages = (ULONG)(StaticMax / 4);
    return STATUS_SUCCESS;
    
fail1:
    TraceError(("%s: fail1 (%08x)\n", __FUNCTION__, status));

    return status;
}

static ULONG
BalloonGetTopPage(
    VOID
    )
{
    PHYSICAL_MEMORY_RANGE   *Range;
    PHYSICAL_ADDRESS        TopAddress;
    ULONG                   Index;

    Range = MmGetPhysicalMemoryRanges();

    TopAddress.QuadPart = 0ull;
    for (Index = 0; Range[Index].BaseAddress.QuadPart != 0 || Range[Index].NumberOfBytes.QuadPart != 0; Index++) {
        PHYSICAL_ADDRESS EndAddress;
        CHAR Key[32];

        EndAddress.QuadPart = Range[Index].BaseAddress.QuadPart + Range[Index].NumberOfBytes.QuadPart;

        TraceInfo(("PHYSICAL MEMORY: RANGE[%u] %08x.%08x - %08x.%08x\n",
                   Index, Range[Index].BaseAddress.HighPart, Range[Index].BaseAddress.LowPart,
                   EndAddress.HighPart, EndAddress.LowPart));

        (VOID) Xmsnprintf(Key, sizeof (Key), "data/physical-memory/range%u", Index);

        (VOID) xenbus_printf(XBT_NIL, Key, "base", "%08x.%08x", 
                             Range[Index].BaseAddress.HighPart,
                             Range[Index].BaseAddress.LowPart);

        (VOID) xenbus_printf(XBT_NIL, Key, "end", "%08x.%08x",
                             EndAddress.HighPart,
                             EndAddress.LowPart);

        if (EndAddress.QuadPart > TopAddress.QuadPart)
            TopAddress.QuadPart = EndAddress.QuadPart;
    }

    TraceNotice(("PHYSICAL MEMORY: TOP = %08x.%08x\n", TopAddress.HighPart, TopAddress.LowPart));

    return (ULONG)(TopAddress.QuadPart >> PAGE_SHIFT);
}

typedef MDL *
(*PMM_ALLOCATE_PAGES_FOR_MDL_EX)(
    IN  LARGE_INTEGER,
    IN  LARGE_INTEGER,
    IN  LARGE_INTEGER,
    IN  SIZE_T,
    IN  MEMORY_CACHING_TYPE,
    IN  ULONG);

PMM_ALLOCATE_PAGES_FOR_MDL_EX   __MmAllocatePagesForMdlEx;
BOOLEAN                         AllocatorInitialized = FALSE;

static VOID
BalloonInitializeAllocator(
    VOID
    )
{
    UNICODE_STRING  Name;

    XM_ASSERT(__MmAllocatePagesForMdlEx == NULL);
    RtlInitUnicodeString(&Name, L"MmAllocatePagesForMdlEx");
    __MmAllocatePagesForMdlEx = (PMM_ALLOCATE_PAGES_FOR_MDL_EX)(ULONG_PTR)MmGetSystemRoutineAddress(&Name);

    AllocatorInitialized = TRUE;
}

// Look at index @Start in the heap, and push it down into its
// children so as to make it the root of a heap, assuming that both of
// its children are already heaps. */
static VOID
BalloonHeapPushDown(
    IN  PFN_NUMBER  *Heap,
    IN  ULONG       Start,
    IN  ULONG       Count
    )
{
    ULONG           LeftChild;
    ULONG           RightChild;

#define SWAP_NODES(_x, _y)              \
    do {                                \
        PFN_NUMBER  __val = Heap[(_y)]; \
                                        \
        Heap[(_y)] = Heap[(_x)];        \
        Heap[(_x)] = __val;             \
    } while (FALSE)

again:
    LeftChild = Start * 2 + 1;
    RightChild = Start * 2 + 2;

    if (RightChild < Count) {
        XM_ASSERT(Heap[LeftChild] != Heap[Start]);
        XM_ASSERT(Heap[RightChild] != Heap[Start]);
        XM_ASSERT(Heap[LeftChild] != Heap[RightChild]);

        if (Heap[LeftChild] < Heap[Start] &&
            Heap[RightChild] < Heap[Start])
            return;

        if (Heap[LeftChild] < Heap[Start] &&
            Heap[RightChild] > Heap[Start]) {
            SWAP_NODES(RightChild, Start);
            XM_ASSERT(Heap[RightChild] < Heap[Start]);
            Start = RightChild;
            goto again;
        }

        if (Heap[RightChild] < Heap[Start] &&
            Heap[LeftChild] > Heap[Start]) {
            SWAP_NODES(LeftChild, Start);
            XM_ASSERT(Heap[LeftChild] < Heap[Start]);
            Start = LeftChild;
            goto again;
        }

        // (Heap[LeftChild] > Heap[Start] &&
        //  Heap[RightChild] > Heap[Start])
        if (Heap[LeftChild] > Heap[RightChild]) {
            SWAP_NODES(LeftChild, Start);
            XM_ASSERT(Heap[LeftChild] < Heap[Start]);
            Start = LeftChild;
        } else {
            SWAP_NODES(RightChild, Start);
            XM_ASSERT(Heap[RightChild] < Heap[Start]);
            Start = RightChild;
        }

        goto again;
    }

    if (LeftChild < Count) {    // Only one child
        XM_ASSERT(Heap[LeftChild] != Heap[Start]);
        if (Heap[LeftChild] < Heap[Start])
            return;

        SWAP_NODES(LeftChild, Start);
        XM_ASSERT(Heap[LeftChild] < Heap[Start]);
        Start = LeftChild;
        goto again;
    }

#undef SWAP_NODES
}