1 /* Trigger a page-in in a separate thread-of-execution to avoid deadlock */
2 #include <pthread.h>
3 #include "xenpaging.h"
4 
5 struct page_in_args {
6     domid_t dom;
7     unsigned long *pagein_queue;
8     xc_interface *xch;
9 };
10 
11 static struct page_in_args page_in_args;
12 static unsigned long page_in_request;
13 static unsigned int page_in_possible;
14 
15 static pthread_t page_in_thread;
16 static pthread_cond_t page_in_cond = PTHREAD_COND_INITIALIZER;
17 static pthread_mutex_t page_in_mutex = PTHREAD_MUTEX_INITIALIZER;
18 
page_in(void * arg)19 static void *page_in(void *arg)
20 {
21     struct page_in_args *pia = arg;
22     void *page;
23     int i, num;
24     xen_pfn_t gfns[XENPAGING_PAGEIN_QUEUE_SIZE];
25 
26     while (1)
27     {
28         pthread_mutex_lock(&page_in_mutex);
29         while (!page_in_request)
30             pthread_cond_wait(&page_in_cond, &page_in_mutex);
31         num = 0;
32         for (i = 0; i < XENPAGING_PAGEIN_QUEUE_SIZE; i++)
33         {
34             if (!pia->pagein_queue[i])
35                continue;
36             gfns[num] = pia->pagein_queue[i];
37             pia->pagein_queue[i] = 0;
38             num++;
39         }
40         page_in_request = 0;
41         pthread_mutex_unlock(&page_in_mutex);
42 
43         /* Ignore errors */
44         page = xc_map_foreign_pages(pia->xch, pia->dom, PROT_READ, gfns, num);
45         if (page)
46             munmap(page, PAGE_SIZE * num);
47     }
48     page_in_possible = 0;
49     pthread_exit(NULL);
50 }
51 
page_in_trigger(void)52 void page_in_trigger(void)
53 {
54     if (!page_in_possible)
55         return;
56 
57     pthread_mutex_lock(&page_in_mutex);
58     page_in_request = 1;
59     pthread_mutex_unlock(&page_in_mutex);
60     pthread_cond_signal(&page_in_cond);
61 }
62 
create_page_in_thread(struct xenpaging * paging)63 void create_page_in_thread(struct xenpaging *paging)
64 {
65     page_in_args.dom = paging->vm_event.domain_id;
66     page_in_args.pagein_queue = paging->pagein_queue;
67     page_in_args.xch = paging->xc_handle;
68     if (pthread_create(&page_in_thread, NULL, page_in, &page_in_args) == 0)
69         page_in_possible = 1;
70 }
71 
72 /*
73  * Local variables:
74  * mode: C
75  * c-file-style: "BSD"
76  * c-basic-offset: 4
77  * indent-tabs-mode: nil
78  * End:
79  */
80