summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--mk/Makefile.deb1
-rw-r--r--mk/Makefile.rpm1
-rw-r--r--mk/Makefile.tgz1
-rw-r--r--system/system.go76
-rw-r--r--xe-daemon/xe-daemon.go8
6 files changed, 88 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index f4e3984..b4e455e 100644
--- a/Makefile
+++ b/Makefile
@@ -30,6 +30,7 @@ endif
XE_DAEMON_SOURCES :=
XE_DAEMON_SOURCES += ./xe-daemon/xe-daemon.go
XE_DAEMON_SOURCES += ./syslog/syslog.go
+XE_DAEMON_SOURCES += ./system/system.go
XE_DAEMON_SOURCES += ./guestmetric/guestmetric.go
XE_DAEMON_SOURCES += ./guestmetric/guestmetric_linux.go
XE_DAEMON_SOURCES += ./xenstoreclient/xenstore.go
diff --git a/mk/Makefile.deb b/mk/Makefile.deb
index e22a207..496f332 100644
--- a/mk/Makefile.deb
+++ b/mk/Makefile.deb
@@ -38,6 +38,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities)
XE_DAEMON_GO_SOURCES :=
XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one
XE_DAEMON_GO_SOURCES += ./syslog/syslog.go
+XE_DAEMON_GO_SOURCES += ./system/system.go
XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go
XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go
XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go
diff --git a/mk/Makefile.rpm b/mk/Makefile.rpm
index d7bd7d5..de1fde2 100644
--- a/mk/Makefile.rpm
+++ b/mk/Makefile.rpm
@@ -35,6 +35,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities)
XE_DAEMON_GO_SOURCES :=
XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one
XE_DAEMON_GO_SOURCES += ./syslog/syslog.go
+XE_DAEMON_GO_SOURCES += ./system/system.go
XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go
XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go
XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go
diff --git a/mk/Makefile.tgz b/mk/Makefile.tgz
index 86c6995..7b19f26 100644
--- a/mk/Makefile.tgz
+++ b/mk/Makefile.tgz
@@ -38,6 +38,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities)
XE_DAEMON_GO_SOURCES :=
XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one
XE_DAEMON_GO_SOURCES += ./syslog/syslog.go
+XE_DAEMON_GO_SOURCES += ./system/system.go
XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go
XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go
XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go
diff --git a/system/system.go b/system/system.go
new file mode 100644
index 0000000..b21d000
--- /dev/null
+++ b/system/system.go
@@ -0,0 +1,76 @@
+package sys
+
+import (
+ "math"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+const (
+ CLOCK_REALTIME = 0
+ TFD_CLOEXEC = 02000000
+ TFD_TIMER_ABSTIME = 1
+ TFD_TIMER_CANCEL_ON_SET = 2
+)
+
+type ITimerSpec struct {
+ Interval syscall.Timespec
+ Value syscall.Timespec
+}
+
+// System call wrapper for timerfd_create, generated with mksyscall.pl
+func timerfdCreate(clockid int, flags int) (fd int, err error) {
+ r0, _, e1 := syscall.Syscall(syscall.SYS_TIMERFD_CREATE,
+ uintptr(clockid), uintptr(flags), 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// System call wrapper for timerfd_settime, generated with mksyscall.pl
+func timerfdSettime(fd int, flags int, new_value *ITimerSpec,
+ old_value *ITimerSpec) (err error) {
+ _, _, e1 := syscall.Syscall6(syscall.SYS_TIMERFD_SETTIME, uintptr(fd),
+ uintptr(flags),
+ uintptr(unsafe.Pointer(new_value)),
+ uintptr(unsafe.Pointer(old_value)), 0, 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+/*
+ * Send a notification on @c when the system has just been resumed after
+ * sleep. This is implemented by watching for a change in real time compared
+ * with monotonic time. This may cause a spurious notification if the time
+ * is changed by a user or NTP jump.
+ */
+func NotifyResumed(c chan int) {
+ ts := ITimerSpec{Interval: syscall.Timespec{math.MaxInt32, 0},
+ Value: syscall.Timespec{0, 0}}
+ buf := make([]byte, 8)
+ for {
+ fd, err := timerfdCreate(CLOCK_REALTIME, TFD_CLOEXEC)
+ if err != nil {
+ return
+ }
+
+ err = timerfdSettime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &ts, nil)
+ if err != nil {
+ return
+ }
+
+ _, err = syscall.Read(fd, buf)
+ if err == syscall.ECANCELED {
+ // Wait a bit for the system to settle down after resuming
+ time.Sleep(time.Duration(1) * time.Second)
+ c <- 1
+ }
+
+ syscall.Close(fd)
+ }
+}
diff --git a/xe-daemon/xe-daemon.go b/xe-daemon/xe-daemon.go
index 839e454..17c4bfd 100644
--- a/xe-daemon/xe-daemon.go
+++ b/xe-daemon/xe-daemon.go
@@ -3,6 +3,7 @@ package main
import (
guestmetric "../guestmetric"
syslog "../syslog"
+ system "../system"
xenstoreclient "../xenstoreclient"
"flag"
"fmt"
@@ -52,6 +53,9 @@ func main() {
exitChannel := make(chan os.Signal, 1)
signal.Notify(exitChannel, syscall.SIGTERM, syscall.SIGINT)
+ resumedChannel := make(chan int)
+ go system.NotifyResumed(resumedChannel)
+
xs, err := xenstoreclient.NewCachedXenstore(0)
if err != nil {
message := fmt.Sprintf("NewCachedXenstore error: %v\n", err)
@@ -135,6 +139,10 @@ func main() {
}
return
+ case <-resumedChannel:
+ logger.Printf("Trigger refresh after system resume\n")
+ continue
+
case <-time.After(time.Duration(*sleepInterval) * time.Second):
continue
}