unix: implement getitimer(2) and setitimer(2) on Linux
Wrap the low-level system calls with a more idiomatic Go API and a set of
constants to indicate which timer should be queried or modified.
man 2 getitimer indicates that these system calls are obsolete as of
POSIX.1-2008, but the code I am working on has not been ported to the modern
timer_gettime(2) and timer_settime(2) APIs as of yet.
Change-Id: I91482e141047846cadf47aa2417b8770955986bf
Reviewed-on: https://go-review.googlesource.com/c/sys/+/384054
Run-TryBot: Matt Layher <mdlayher@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dominik Honnef <dominik@honnef.co>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Matt Layher <mdlayher@gmail.com>
diff --git a/unix/linux/types.go b/unix/linux/types.go
index 71499f6..e93be95 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -459,6 +459,8 @@
type ItimerSpec C.struct_itimerspec
+type Itimerval C.struct_itimerval
+
const (
TIME_OK = C.TIME_OK
TIME_INS = C.TIME_INS
diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh
index a47b035..e92ddea 100755
--- a/unix/mkerrors.sh
+++ b/unix/mkerrors.sh
@@ -597,6 +597,7 @@
$2 ~ /^DEVLINK_/ ||
$2 ~ /^ETHTOOL_/ ||
$2 ~ /^LWTUNNEL_IP/ ||
+ $2 ~ /^ITIMER_/ ||
$2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ ||
$2 ~/^PPPIOC/ ||
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index e52e8b9..f5915e2 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -14,6 +14,7 @@
import (
"encoding/binary"
"syscall"
+ "time"
"unsafe"
)
@@ -2314,6 +2315,52 @@
//sys shmdt(addr uintptr) (err error)
//sys shmget(key int, size int, flag int) (id int, err error)
+//sys getitimer(which int, currValue *Itimerval) (err error)
+//sys setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error)
+
+// MakeItimerval creates an Itimerval from interval and value durations.
+func MakeItimerval(interval, value time.Duration) Itimerval {
+ return Itimerval{
+ Interval: NsecToTimeval(interval.Nanoseconds()),
+ Value: NsecToTimeval(value.Nanoseconds()),
+ }
+}
+
+// A value which may be passed to the which parameter for Getitimer and
+// Setitimer.
+type ItimerWhich int
+
+// Possible which values for Getitimer and Setitimer.
+const (
+ ItimerReal ItimerWhich = ITIMER_REAL
+ ItimerVirtual ItimerWhich = ITIMER_VIRTUAL
+ ItimerProf ItimerWhich = ITIMER_PROF
+)
+
+// Getitimer wraps getitimer(2) to return the current value of the timer
+// specified by which.
+func Getitimer(which ItimerWhich) (Itimerval, error) {
+ var it Itimerval
+ if err := getitimer(int(which), &it); err != nil {
+ return Itimerval{}, err
+ }
+
+ return it, nil
+}
+
+// Setitimer wraps setitimer(2) to arm or disarm the timer specified by which.
+// It returns the previous value of the timer.
+//
+// If the Itimerval argument is the zero value, the timer will be disarmed.
+func Setitimer(which ItimerWhich, it Itimerval) (Itimerval, error) {
+ var prev Itimerval
+ if err := setitimer(int(which), &it, &prev); err != nil {
+ return Itimerval{}, err
+ }
+
+ return prev, nil
+}
+
/*
* Unimplemented
*/
@@ -2333,7 +2380,6 @@
// GetMempolicy
// GetRobustList
// GetThreadArea
-// Getitimer
// Getpmsg
// IoCancel
// IoDestroy
diff --git a/unix/zerrors_linux.go b/unix/zerrors_linux.go
index 6bce658..664db64 100644
--- a/unix/zerrors_linux.go
+++ b/unix/zerrors_linux.go
@@ -1268,6 +1268,9 @@
IP_XFRM_POLICY = 0x11
ISOFS_SUPER_MAGIC = 0x9660
ISTRIP = 0x20
+ ITIMER_PROF = 0x2
+ ITIMER_REAL = 0x0
+ ITIMER_VIRTUAL = 0x1
IUTF8 = 0x4000
IXANY = 0x800
JFFS2_SUPER_MAGIC = 0x72b6
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index 93edda4..30fa405 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -2032,3 +2032,23 @@
}
return
}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getitimer(which int, currValue *Itimerval) (err error) {
+ _, _, e1 := Syscall(SYS_GETITIMER, uintptr(which), uintptr(unsafe.Pointer(currValue)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error) {
+ _, _, e1 := Syscall(SYS_SETITIMER, uintptr(which), uintptr(unsafe.Pointer(newValue)), uintptr(unsafe.Pointer(oldValue)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go
index 66788f1..824cadb 100644
--- a/unix/ztypes_linux.go
+++ b/unix/ztypes_linux.go
@@ -24,6 +24,11 @@
Value Timespec
}
+type Itimerval struct {
+ Interval Timeval
+ Value Timeval
+}
+
const (
TIME_OK = 0x0
TIME_INS = 0x1