188 lines
5.7 KiB
Diff
188 lines
5.7 KiB
Diff
|
changeset: 23596:c49e22648d0e
|
||
|
user: Olaf Hering <olaf@aepfle.de>
|
||
|
date: Fri Jun 10 10:47:28 2011 +0200
|
||
|
files: tools/xenpaging/Makefile tools/xenpaging/pagein.c tools/xenpaging/xenpaging.c tools/xenpaging/xenpaging.h
|
||
|
description:
|
||
|
xenpaging: implement stopping of pager by sending SIGTERM/SIGINT
|
||
|
|
||
|
Write all paged-out pages back into the guest if the pager is
|
||
|
interrupted by ctrl-c or if it receives SIGTERM.
|
||
|
|
||
|
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||
|
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||
|
|
||
|
|
||
|
---
|
||
|
tools/xenpaging/Makefile | 1
|
||
|
tools/xenpaging/pagein.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
|
||
|
tools/xenpaging/xenpaging.c | 35 ++++++++++++++++++++--
|
||
|
tools/xenpaging/xenpaging.h | 3 +
|
||
|
4 files changed, 104 insertions(+), 3 deletions(-)
|
||
|
|
||
|
Index: xen-4.1.2-testing/tools/xenpaging/Makefile
|
||
|
===================================================================
|
||
|
--- xen-4.1.2-testing.orig/tools/xenpaging/Makefile
|
||
|
+++ xen-4.1.2-testing/tools/xenpaging/Makefile
|
||
|
@@ -10,6 +10,7 @@ POLICY = default
|
||
|
|
||
|
SRC :=
|
||
|
SRCS += file_ops.c xenpaging.c policy_$(POLICY).c
|
||
|
+SRCS += pagein.c
|
||
|
|
||
|
CFLAGS += -Werror
|
||
|
CFLAGS += -Wno-unused
|
||
|
Index: xen-4.1.2-testing/tools/xenpaging/pagein.c
|
||
|
===================================================================
|
||
|
--- /dev/null
|
||
|
+++ xen-4.1.2-testing/tools/xenpaging/pagein.c
|
||
|
@@ -0,0 +1,68 @@
|
||
|
+/* Trigger a page-in in a separate thread-of-execution to avoid deadlock */
|
||
|
+#include <pthread.h>
|
||
|
+#include "xc_private.h"
|
||
|
+
|
||
|
+struct page_in_args {
|
||
|
+ domid_t dom;
|
||
|
+ xc_interface *xch;
|
||
|
+};
|
||
|
+
|
||
|
+static struct page_in_args page_in_args;
|
||
|
+static unsigned long page_in_gfn;
|
||
|
+static unsigned int page_in_possible;
|
||
|
+
|
||
|
+static pthread_t page_in_thread;
|
||
|
+static pthread_cond_t page_in_cond = PTHREAD_COND_INITIALIZER;
|
||
|
+static pthread_mutex_t page_in_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||
|
+
|
||
|
+static void *page_in(void *arg)
|
||
|
+{
|
||
|
+ struct page_in_args *pia = arg;
|
||
|
+ void *page;
|
||
|
+ xen_pfn_t gfn;
|
||
|
+
|
||
|
+ while (1)
|
||
|
+ {
|
||
|
+ pthread_mutex_lock(&page_in_mutex);
|
||
|
+ while (!page_in_gfn)
|
||
|
+ pthread_cond_wait(&page_in_cond, &page_in_mutex);
|
||
|
+ gfn = page_in_gfn;
|
||
|
+ page_in_gfn = 0;
|
||
|
+ pthread_mutex_unlock(&page_in_mutex);
|
||
|
+
|
||
|
+ /* Ignore errors */
|
||
|
+ page = xc_map_foreign_pages(pia->xch, pia->dom, PROT_READ, &gfn, 1);
|
||
|
+ if (page)
|
||
|
+ munmap(page, PAGE_SIZE);
|
||
|
+ }
|
||
|
+ page_in_possible = 0;
|
||
|
+ pthread_exit(NULL);
|
||
|
+}
|
||
|
+
|
||
|
+void page_in_trigger(unsigned long gfn)
|
||
|
+{
|
||
|
+ if (!page_in_possible)
|
||
|
+ return;
|
||
|
+
|
||
|
+ pthread_mutex_lock(&page_in_mutex);
|
||
|
+ page_in_gfn = gfn;
|
||
|
+ pthread_mutex_unlock(&page_in_mutex);
|
||
|
+ pthread_cond_signal(&page_in_cond);
|
||
|
+}
|
||
|
+
|
||
|
+void create_page_in_thread(domid_t domain_id, xc_interface *xch)
|
||
|
+{
|
||
|
+ page_in_args.dom = domain_id;
|
||
|
+ page_in_args.xch = xch;
|
||
|
+ if (pthread_create(&page_in_thread, NULL, page_in, &page_in_args) == 0)
|
||
|
+ page_in_possible = 1;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Local variables:
|
||
|
+ * mode: C
|
||
|
+ * c-set-style: "BSD"
|
||
|
+ * c-basic-offset: 4
|
||
|
+ * indent-tabs-mode: nil
|
||
|
+ * End:
|
||
|
+ */
|
||
|
Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c
|
||
|
===================================================================
|
||
|
--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c
|
||
|
+++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c
|
||
|
@@ -650,6 +650,9 @@ int main(int argc, char *argv[])
|
||
|
sigaction(SIGINT, &act, NULL);
|
||
|
sigaction(SIGALRM, &act, NULL);
|
||
|
|
||
|
+ /* listen for page-in events to stop pager */
|
||
|
+ create_page_in_thread(paging->mem_event.domain_id, xch);
|
||
|
+
|
||
|
/* Evict pages */
|
||
|
for ( i = 0; i < paging->num_pages; i++ )
|
||
|
{
|
||
|
@@ -665,7 +668,7 @@ int main(int argc, char *argv[])
|
||
|
DPRINTF("%d pages evicted. Done.\n", i);
|
||
|
|
||
|
/* Swap pages in and out */
|
||
|
- while ( !interrupted )
|
||
|
+ while ( 1 )
|
||
|
{
|
||
|
/* Wait for Xen to signal that a page needs paged in */
|
||
|
rc = xenpaging_wait_for_event_or_timeout(paging);
|
||
|
@@ -728,8 +731,12 @@ int main(int argc, char *argv[])
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
- /* Evict a new page to replace the one we just paged in */
|
||
|
- evict_victim(paging, &victims[i], fd, i);
|
||
|
+ /* Evict a new page to replace the one we just paged in,
|
||
|
+ * or clear this pagefile slot on exit */
|
||
|
+ if ( interrupted )
|
||
|
+ victims[i].gfn = INVALID_MFN;
|
||
|
+ else
|
||
|
+ evict_victim(paging, &victims[i], fd, i);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
@@ -756,6 +763,28 @@ int main(int argc, char *argv[])
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
+
|
||
|
+ /* Write all pages back into the guest */
|
||
|
+ if ( interrupted == SIGTERM || interrupted == SIGINT )
|
||
|
+ {
|
||
|
+ for ( i = 0; i < paging->domain_info->max_pages; i++ )
|
||
|
+ {
|
||
|
+ if ( test_bit(i, paging->bitmap) )
|
||
|
+ {
|
||
|
+ page_in_trigger(i);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ /* If no more pages to process, exit loop */
|
||
|
+ if ( i == paging->domain_info->max_pages )
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Exit on any other signal */
|
||
|
+ if ( interrupted )
|
||
|
+ break;
|
||
|
+ }
|
||
|
}
|
||
|
DPRINTF("xenpaging got signal %d\n", interrupted);
|
||
|
|
||
|
Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.h
|
||
|
===================================================================
|
||
|
--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.h
|
||
|
+++ xen-4.1.2-testing/tools/xenpaging/xenpaging.h
|
||
|
@@ -53,6 +53,9 @@ typedef struct xenpaging_victim {
|
||
|
} xenpaging_victim_t;
|
||
|
|
||
|
|
||
|
+extern void create_page_in_thread(domid_t domain_id, xc_interface *xch);
|
||
|
+extern void page_in_trigger(unsigned long gfn);
|
||
|
+
|
||
|
#endif // __XEN_PAGING_H__
|
||
|
|
||
|
|