271 lines
6.9 KiB
Go
271 lines
6.9 KiB
Go
// Copyright 2018 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package linux
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
// ClockTick is the length of time represented by a single clock tick, as
|
|
// used by times(2) and /proc/[pid]/stat.
|
|
ClockTick = time.Second / CLOCKS_PER_SEC
|
|
|
|
// CLOCKS_PER_SEC is the number of ClockTicks per second.
|
|
//
|
|
// Linux defines this to be 100 on most architectures, irrespective of
|
|
// CONFIG_HZ. Userspace obtains the value through sysconf(_SC_CLK_TCK),
|
|
// which uses the AT_CLKTCK entry in the auxiliary vector if one is
|
|
// provided, and assumes 100 otherwise (glibc:
|
|
// sysdeps/posix/sysconf.c:__sysconf() =>
|
|
// sysdeps/unix/sysv/linux/getclktck.c, elf/dl-support.c:_dl_aux_init()).
|
|
//
|
|
// Not to be confused with POSIX CLOCKS_PER_SEC, as used by clock(3); "XSI
|
|
// requires that [POSIX] CLOCKS_PER_SEC equals 1000000 independent of the
|
|
// actual resolution" - clock(3).
|
|
CLOCKS_PER_SEC = 100
|
|
)
|
|
|
|
// CPU clock types for use with clock_gettime(2) et al.
|
|
//
|
|
// The 29 most significant bits of a 32 bit clock ID are either a PID or a FD.
|
|
//
|
|
// Bits 1 and 0 give the type: PROF=0, VIRT=1, SCHED=2, or FD=3.
|
|
//
|
|
// Bit 2 indicates whether a cpu clock refers to a thread or a process.
|
|
const (
|
|
CPUCLOCK_PROF = 0
|
|
CPUCLOCK_VIRT = 1
|
|
CPUCLOCK_SCHED = 2
|
|
CPUCLOCK_MAX = 3
|
|
CLOCKFD = CPUCLOCK_MAX
|
|
|
|
CPUCLOCK_CLOCK_MASK = 3
|
|
CPUCLOCK_PERTHREAD_MASK = 4
|
|
)
|
|
|
|
// Clock identifiers for use with clock_gettime(2), clock_getres(2),
|
|
// clock_nanosleep(2).
|
|
const (
|
|
CLOCK_REALTIME = 0
|
|
CLOCK_MONOTONIC = 1
|
|
CLOCK_PROCESS_CPUTIME_ID = 2
|
|
CLOCK_THREAD_CPUTIME_ID = 3
|
|
CLOCK_MONOTONIC_RAW = 4
|
|
CLOCK_REALTIME_COARSE = 5
|
|
CLOCK_MONOTONIC_COARSE = 6
|
|
CLOCK_BOOTTIME = 7
|
|
CLOCK_REALTIME_ALARM = 8
|
|
CLOCK_BOOTTIME_ALARM = 9
|
|
)
|
|
|
|
// Flags for clock_nanosleep(2).
|
|
const (
|
|
TIMER_ABSTIME = 1
|
|
)
|
|
|
|
// Flags for timerfd syscalls (timerfd_create(2), timerfd_settime(2)).
|
|
const (
|
|
// TFD_CLOEXEC is a timerfd_create flag.
|
|
TFD_CLOEXEC = O_CLOEXEC
|
|
|
|
// TFD_NONBLOCK is a timerfd_create flag.
|
|
TFD_NONBLOCK = O_NONBLOCK
|
|
|
|
// TFD_TIMER_ABSTIME is a timerfd_settime flag.
|
|
TFD_TIMER_ABSTIME = 1
|
|
)
|
|
|
|
// The safe number of seconds you can represent by int64.
|
|
const maxSecInDuration = math.MaxInt64 / int64(time.Second)
|
|
|
|
// TimeT represents time_t in <time.h>. It represents time in seconds.
|
|
type TimeT int64
|
|
|
|
// NsecToTimeT translates nanoseconds to TimeT (seconds).
|
|
func NsecToTimeT(nsec int64) TimeT {
|
|
return TimeT(nsec / 1e9)
|
|
}
|
|
|
|
// Timespec represents struct timespec in <time.h>.
|
|
//
|
|
// +marshal
|
|
type Timespec struct {
|
|
Sec int64
|
|
Nsec int64
|
|
}
|
|
|
|
// Unix returns the second and nanosecond.
|
|
func (ts Timespec) Unix() (sec int64, nsec int64) {
|
|
return int64(ts.Sec), int64(ts.Nsec)
|
|
}
|
|
|
|
// ToTime returns the Go time.Time representation.
|
|
func (ts Timespec) ToTime() time.Time {
|
|
return time.Unix(ts.Sec, ts.Nsec)
|
|
}
|
|
|
|
// ToNsec returns the nanosecond representation.
|
|
func (ts Timespec) ToNsec() int64 {
|
|
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
|
|
}
|
|
|
|
// ToNsecCapped returns the safe nanosecond representation.
|
|
func (ts Timespec) ToNsecCapped() int64 {
|
|
if ts.Sec > maxSecInDuration {
|
|
return math.MaxInt64
|
|
}
|
|
return ts.ToNsec()
|
|
}
|
|
|
|
// ToDuration returns the safe nanosecond representation as time.Duration.
|
|
func (ts Timespec) ToDuration() time.Duration {
|
|
return time.Duration(ts.ToNsecCapped())
|
|
}
|
|
|
|
// Valid returns whether the timespec contains valid values.
|
|
func (ts Timespec) Valid() bool {
|
|
return !(ts.Sec < 0 || ts.Nsec < 0 || ts.Nsec >= int64(time.Second))
|
|
}
|
|
|
|
// NsecToTimespec translates nanoseconds to Timespec.
|
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
|
ts.Sec = nsec / 1e9
|
|
ts.Nsec = nsec % 1e9
|
|
return
|
|
}
|
|
|
|
// DurationToTimespec translates time.Duration to Timespec.
|
|
func DurationToTimespec(dur time.Duration) Timespec {
|
|
return NsecToTimespec(dur.Nanoseconds())
|
|
}
|
|
|
|
// SizeOfTimeval is the size of a Timeval struct in bytes.
|
|
const SizeOfTimeval = 16
|
|
|
|
// Timeval represents struct timeval in <time.h>.
|
|
//
|
|
// +marshal
|
|
type Timeval struct {
|
|
Sec int64
|
|
Usec int64
|
|
}
|
|
|
|
// ToNsecCapped returns the safe nanosecond representation.
|
|
func (tv Timeval) ToNsecCapped() int64 {
|
|
if tv.Sec > maxSecInDuration {
|
|
return math.MaxInt64
|
|
}
|
|
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3
|
|
}
|
|
|
|
// ToDuration returns the safe nanosecond representation as a time.Duration.
|
|
func (tv Timeval) ToDuration() time.Duration {
|
|
return time.Duration(tv.ToNsecCapped())
|
|
}
|
|
|
|
// ToTime returns the Go time.Time representation.
|
|
func (tv Timeval) ToTime() time.Time {
|
|
return time.Unix(tv.Sec, tv.Usec*1e3)
|
|
}
|
|
|
|
// NsecToTimeval translates nanosecond to Timeval.
|
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
|
nsec += 999 // round up to microsecond
|
|
tv.Sec = nsec / 1e9
|
|
tv.Usec = nsec % 1e9 / 1e3
|
|
return
|
|
}
|
|
|
|
// DurationToTimeval translates time.Duration to Timeval.
|
|
func DurationToTimeval(dur time.Duration) Timeval {
|
|
return NsecToTimeval(dur.Nanoseconds())
|
|
}
|
|
|
|
// Itimerspec represents struct itimerspec in <time.h>.
|
|
type Itimerspec struct {
|
|
Interval Timespec
|
|
Value Timespec
|
|
}
|
|
|
|
// ItimerVal mimics the following struct in <sys/time.h>
|
|
// struct itimerval {
|
|
// struct timeval it_interval; /* next value */
|
|
// struct timeval it_value; /* current value */
|
|
// };
|
|
type ItimerVal struct {
|
|
Interval Timeval
|
|
Value Timeval
|
|
}
|
|
|
|
// ClockT represents type clock_t.
|
|
type ClockT int64
|
|
|
|
// ClockTFromDuration converts time.Duration to clock_t.
|
|
func ClockTFromDuration(d time.Duration) ClockT {
|
|
return ClockT(d / ClockTick)
|
|
}
|
|
|
|
// Tms represents struct tms, used by times(2).
|
|
type Tms struct {
|
|
UTime ClockT
|
|
STime ClockT
|
|
CUTime ClockT
|
|
CSTime ClockT
|
|
}
|
|
|
|
// TimerID represents type timer_t, which identifies a POSIX per-process
|
|
// interval timer.
|
|
type TimerID int32
|
|
|
|
// StatxTimestamp represents struct statx_timestamp.
|
|
//
|
|
// +marshal
|
|
type StatxTimestamp struct {
|
|
Sec int64
|
|
Nsec uint32
|
|
_ int32
|
|
}
|
|
|
|
// ToNsec returns the nanosecond representation.
|
|
func (sxts StatxTimestamp) ToNsec() int64 {
|
|
return int64(sxts.Sec)*1e9 + int64(sxts.Nsec)
|
|
}
|
|
|
|
// ToNsecCapped returns the safe nanosecond representation.
|
|
func (sxts StatxTimestamp) ToNsecCapped() int64 {
|
|
if sxts.Sec > maxSecInDuration {
|
|
return math.MaxInt64
|
|
}
|
|
return sxts.ToNsec()
|
|
}
|
|
|
|
// NsecToStatxTimestamp translates nanoseconds to StatxTimestamp.
|
|
func NsecToStatxTimestamp(nsec int64) (ts StatxTimestamp) {
|
|
return StatxTimestamp{
|
|
Sec: nsec / 1e9,
|
|
Nsec: uint32(nsec % 1e9),
|
|
}
|
|
}
|
|
|
|
// Utime represents struct utimbuf used by utimes(2).
|
|
//
|
|
// +marshal
|
|
type Utime struct {
|
|
Actime int64
|
|
Modtime int64
|
|
}
|