Message:
Hello golan...@googlegroups.com,
I'd like you to review this change to
https://go.googlecode.com/hg/
Description:
os: implement UserTime/SystemTime on windows
Fixes issue 3145.
Please review this at http://codereview.appspot.com/5721044/
Affected files:
M src/pkg/os/exec_plan9.go
M src/pkg/os/exec_windows.go
M src/pkg/syscall/syscall_windows.go
M src/pkg/syscall/zsyscall_windows_386.go
M src/pkg/syscall/zsyscall_windows_amd64.go
M src/pkg/syscall/ztypes_windows.go
Index: src/pkg/os/exec_plan9.go
===================================================================
--- a/src/pkg/os/exec_plan9.go
+++ b/src/pkg/os/exec_plan9.go
@@ -144,13 +144,11 @@
}
// UserTime returns the user CPU time of the exited process and its
children.
-// It is always reported as 0 on Windows.
func (p *ProcessState) UserTime() time.Duration {
return time.Duration(p.status.Time[0]) * time.Millisecond
}
// SystemTime returns the system CPU time of the exited process and its
children.
-// It is always reported as 0 on Windows.
func (p *ProcessState) SystemTime() time.Duration {
return time.Duration(p.status.Time[1]) * time.Millisecond
}
Index: src/pkg/os/exec_windows.go
===================================================================
--- a/src/pkg/os/exec_windows.go
+++ b/src/pkg/os/exec_windows.go
@@ -30,9 +30,14 @@
if e != nil {
return nil, NewSyscallError("GetExitCodeProcess", e)
}
+ var u syscall.Rusage
+ e = syscall.GetProcessTimes(syscall.Handle(p.handle), &u.CreationTime,
&u.ExitTime, &u.KernelTime, &u.UserTime)
+ if e != nil {
+ return nil, NewSyscallError("GetProcessTimes", e)
+ }
p.done = true
defer p.Release()
- return &ProcessState{p.Pid, syscall.WaitStatus{Status: s, ExitCode: ec},
new(syscall.Rusage)}, nil
+ return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
}
// Signal sends a signal to the Process.
@@ -86,14 +91,17 @@
}
}
-// UserTime returns the user CPU time of the exited process and its
children.
-// For now, it is always reported as 0 on Windows.
-func (p *ProcessState) UserTime() time.Duration {
- return 0
+func ftToDuration(ft *syscall.Filetime) time.Duration {
+ n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in
100-nanosecond intervals
+ return time.Duration(n*100) * time.Nanosecond
}
-// SystemTime returns the system CPU time of the exited process and its
children.
-// For now, it is always reported as 0 on Windows.
+// UserTime returns the user CPU time of the exited process.
+func (p *ProcessState) UserTime() time.Duration {
+ return ftToDuration(&p.rusage.UserTime)
+}
+
+// SystemTime returns the system CPU time of the exited process.
func (p *ProcessState) SystemTime() time.Duration {
- return 0
+ return ftToDuration(&p.rusage.KernelTime)
}
Index: src/pkg/syscall/syscall_windows.go
===================================================================
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -151,6 +151,7 @@
//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
//sys GetStartupInfo(startupInfo *StartupInfo) (err error) =
GetStartupInfoW
//sys GetCurrentProcess() (pseudoHandle Handle, err error)
+//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime
*Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle,
hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess
uint32, bInheritHandle bool, dwOptions uint32) (err error)
//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event
uint32, err error) [failretval==0xffffffff]
//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) =
GetTempPathW
@@ -601,10 +602,14 @@
}
// Invented structures to support what package os expects.
-type Rusage struct{}
+type Rusage struct {
+ CreationTime Filetime
+ ExitTime Filetime
+ KernelTime Filetime
+ UserTime Filetime
+}
type WaitStatus struct {
- Status uint32
ExitCode uint32
}
Index: src/pkg/syscall/zsyscall_windows_386.go
===================================================================
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ b/src/pkg/syscall/zsyscall_windows_386.go
@@ -55,6 +55,7 @@
procGetExitCodeProcess =
modkernel32.NewProc("GetExitCodeProcess")
procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW")
procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess")
+ procGetProcessTimes = modkernel32.NewProc("GetProcessTimes")
procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
procWaitForSingleObject =
modkernel32.NewProc("WaitForSingleObject")
procGetTempPathW = modkernel32.NewProc("GetTempPathW")
@@ -597,6 +598,18 @@
return
}
+func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime
*Filetime, kernelTime *Filetime, userTime *Filetime) (err error) {
+ r1, _, e1 := Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle),
uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)),
uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0)
+ if int(r1) == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle,
hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess
uint32, bInheritHandle bool, dwOptions uint32) (err error) {
var _p0 uint32
if bInheritHandle {
Index: src/pkg/syscall/zsyscall_windows_amd64.go
===================================================================
--- a/src/pkg/syscall/zsyscall_windows_amd64.go
+++ b/src/pkg/syscall/zsyscall_windows_amd64.go
@@ -55,6 +55,7 @@
procGetExitCodeProcess =
modkernel32.NewProc("GetExitCodeProcess")
procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW")
procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess")
+ procGetProcessTimes = modkernel32.NewProc("GetProcessTimes")
procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
procWaitForSingleObject =
modkernel32.NewProc("WaitForSingleObject")
procGetTempPathW = modkernel32.NewProc("GetTempPathW")
@@ -597,6 +598,18 @@
return
}
+func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime
*Filetime, kernelTime *Filetime, userTime *Filetime) (err error) {
+ r1, _, e1 := Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle),
uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)),
uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0)
+ if int(r1) == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = EINVAL
+ }
+ }
+ return
+}
+
func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle,
hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess
uint32, bInheritHandle bool, dwOptions uint32) (err error) {
var _p0 uint32
if bInheritHandle {
Index: src/pkg/syscall/ztypes_windows.go
===================================================================
--- a/src/pkg/syscall/ztypes_windows.go
+++ b/src/pkg/syscall/ztypes_windows.go
@@ -252,6 +252,8 @@
HighDateTime uint32
}
+// Nanoseconds returns Filetime ft in nanoseconds
+// since Epoch (00:00:00 UTC, January 1, 1970).
func (ft *Filetime) Nanoseconds() int64 {
// 100-nanosecond intervals since January 1, 1601
nsec := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime)
I submitted my CL so you'll need to sync and merge a little. Sorry.
os: implement UserTime/SystemTime on windows
Fixes issue 3145.
R=golang-dev, rsc
CC=golang-dev
http://codereview.appspot.com/5721044