From 3681064d51587c1db0324b3d5c23c2ddbcff6e8f Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Tue, 8 Feb 2022 09:24:17 -0500 Subject: [PATCH] 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 TryBot-Result: Gopher Robot Reviewed-by: Dominik Honnef Reviewed-by: Ian Lance Taylor Trust: Matt Layher --- unix/linux/types.go | 2 ++ unix/mkerrors.sh | 1 + unix/syscall_linux.go | 48 +++++++++++++++++++++++++++++++++++++++++- unix/zerrors_linux.go | 3 +++ unix/zsyscall_linux.go | 20 ++++++++++++++++++ unix/ztypes_linux.go | 5 +++++ 6 files changed, 78 insertions(+), 1 deletion(-) diff --git a/unix/linux/types.go b/unix/linux/types.go index 71499f6e..e93be95d 100644 --- a/unix/linux/types.go +++ b/unix/linux/types.go @@ -459,6 +459,8 @@ type Timex C.struct_timex 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 a47b035f..e92ddea0 100755 --- a/unix/mkerrors.sh +++ b/unix/mkerrors.sh @@ -597,6 +597,7 @@ ccflags="$@" $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 e52e8b9e..f5915e23 100644 --- a/unix/syscall_linux.go +++ b/unix/syscall_linux.go @@ -14,6 +14,7 @@ package unix import ( "encoding/binary" "syscall" + "time" "unsafe" ) @@ -2314,6 +2315,52 @@ type RemoteIovec struct { //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 @@ type RemoteIovec struct { // GetMempolicy // GetRobustList // GetThreadArea -// Getitimer // Getpmsg // IoCancel // IoDestroy diff --git a/unix/zerrors_linux.go b/unix/zerrors_linux.go index 6bce6580..664db640 100644 --- a/unix/zerrors_linux.go +++ b/unix/zerrors_linux.go @@ -1268,6 +1268,9 @@ const ( 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 93edda4c..30fa4055 100644 --- a/unix/zsyscall_linux.go +++ b/unix/zsyscall_linux.go @@ -2032,3 +2032,23 @@ func shmget(key int, size int, flag int) (id int, err error) { } 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 66788f15..824cadb4 100644 --- a/unix/ztypes_linux.go +++ b/unix/ztypes_linux.go @@ -24,6 +24,11 @@ type ItimerSpec struct { Value Timespec } +type Itimerval struct { + Interval Timeval + Value Timeval +} + const ( TIME_OK = 0x0 TIME_INS = 0x1