debuggers.hg

view tools/libxc/xc_suspend.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents f44438bc79ac
children 3ffdb094c2c0 f7605c6c9548
line source
1 /*
2 * This file is subject to the terms and conditions of the GNU General
3 * Public License. See the file "COPYING" in the main directory of
4 * this archive for more details.
5 */
7 #include "xc_private.h"
8 #include "xenguest.h"
10 #define SUSPEND_LOCK_FILE "/var/lib/xen/suspend_evtchn_lock.d"
11 static int lock_suspend_event(void)
12 {
13 int fd, rc;
14 mode_t mask;
15 char buf[128];
17 mask = umask(022);
18 fd = open(SUSPEND_LOCK_FILE, O_CREAT | O_EXCL | O_RDWR, 0666);
19 if (fd < 0)
20 {
21 ERROR("Can't create lock file for suspend event channel\n");
22 return -EINVAL;
23 }
24 umask(mask);
25 snprintf(buf, sizeof(buf), "%10ld", (long)getpid());
27 rc = write_exact(fd, buf, strlen(buf));
28 close(fd);
30 return rc;
31 }
33 static int unlock_suspend_event(void)
34 {
35 int fd, pid, n;
36 char buf[128];
38 fd = open(SUSPEND_LOCK_FILE, O_RDWR);
40 if (fd < 0)
41 return -EINVAL;
43 n = read(fd, buf, 127);
45 close(fd);
47 if (n > 0)
48 {
49 sscanf(buf, "%d", &pid);
50 /* We are the owner, so we can simply delete the file */
51 if (pid == getpid())
52 {
53 unlink(SUSPEND_LOCK_FILE);
54 return 0;
55 }
56 }
58 return -EPERM;
59 }
61 int xc_await_suspend(int xce, int suspend_evtchn)
62 {
63 int rc;
65 do {
66 rc = xc_evtchn_pending(xce);
67 if (rc < 0) {
68 ERROR("error polling suspend notification channel: %d", rc);
69 return -1;
70 }
71 } while (rc != suspend_evtchn);
73 /* harmless for one-off suspend */
74 if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
75 ERROR("failed to unmask suspend notification channel: %d", rc);
77 return 0;
78 }
80 int xc_suspend_evtchn_release(int xce, int suspend_evtchn)
81 {
82 if (suspend_evtchn >= 0)
83 xc_evtchn_unbind(xce, suspend_evtchn);
85 return unlock_suspend_event();
86 }
88 int xc_suspend_evtchn_init(int xc, int xce, int domid, int port)
89 {
90 int rc, suspend_evtchn = -1;
92 if (lock_suspend_event())
93 return -EINVAL;
95 suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
96 if (suspend_evtchn < 0) {
97 ERROR("failed to bind suspend event channel: %d", suspend_evtchn);
98 goto cleanup;
99 }
101 rc = xc_domain_subscribe_for_suspend(xc, domid, port);
102 if (rc < 0) {
103 ERROR("failed to subscribe to domain: %d", rc);
104 goto cleanup;
105 }
107 /* event channel is pending immediately after binding */
108 xc_await_suspend(xce, suspend_evtchn);
110 return suspend_evtchn;
112 cleanup:
113 if (suspend_evtchn != -1)
114 xc_suspend_evtchn_release(xce, suspend_evtchn);
116 return -1;
117 }