mirror of
https://github.com/golang/go.git
synced 2025-05-07 16:43:03 +00:00
os: simplify process status
Since it no longer holds a reference count, just use values. For #70907 Change-Id: I19a42583988d4f8a9133b1c837356ca0179d688c Reviewed-on: https://go-review.googlesource.com/c/go/+/638578 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
caf29da4cc
commit
e7c9667def
@ -17,21 +17,19 @@ import (
|
|||||||
// ErrProcessDone indicates a [Process] has finished.
|
// ErrProcessDone indicates a [Process] has finished.
|
||||||
var ErrProcessDone = errors.New("os: process already finished")
|
var ErrProcessDone = errors.New("os: process already finished")
|
||||||
|
|
||||||
type processStatus uint64
|
type processStatus uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// PID/handle OK to use.
|
// statusOK means that the Process is ready to use.
|
||||||
statusOK processStatus = 0
|
statusOK processStatus = iota
|
||||||
|
|
||||||
// statusDone indicates that the PID/handle should not be used because
|
// statusDone indicates that the PID/handle should not be used because
|
||||||
// the process is done (has been successfully Wait'd on).
|
// the process is done (has been successfully Wait'd on).
|
||||||
statusDone processStatus = 1 << 62
|
statusDone
|
||||||
|
|
||||||
// statusReleased indicates that the PID/handle should not be used
|
// statusReleased indicates that the PID/handle should not be used
|
||||||
// because the process is released.
|
// because the process is released.
|
||||||
statusReleased processStatus = 1 << 63
|
statusReleased
|
||||||
|
|
||||||
processStatusMask = 0x3 << 62
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Process stores the information about a process created by [StartProcess].
|
// Process stores the information about a process created by [StartProcess].
|
||||||
@ -42,7 +40,7 @@ type Process struct {
|
|||||||
//
|
//
|
||||||
// This consists of the processStatus fields,
|
// This consists of the processStatus fields,
|
||||||
// which indicate if the process is done/released.
|
// which indicate if the process is done/released.
|
||||||
state atomic.Uint64
|
state atomic.Uint32
|
||||||
|
|
||||||
// Used only when handle is nil
|
// Used only when handle is nil
|
||||||
sigMu sync.RWMutex // avoid race between wait and signal
|
sigMu sync.RWMutex // avoid race between wait and signal
|
||||||
@ -138,7 +136,7 @@ func newDoneProcess(pid int) *Process {
|
|||||||
p := &Process{
|
p := &Process{
|
||||||
Pid: pid,
|
Pid: pid,
|
||||||
}
|
}
|
||||||
p.state.Store(uint64(statusDone)) // No persistent reference, as there is no handle.
|
p.state.Store(uint32(statusDone)) // No persistent reference, as there is no handle.
|
||||||
runtime.SetFinalizer(p, (*Process).Release)
|
runtime.SetFinalizer(p, (*Process).Release)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
@ -148,9 +146,9 @@ func (p *Process) handleTransientAcquire() (uintptr, processStatus) {
|
|||||||
panic("handleTransientAcquire called in invalid mode")
|
panic("handleTransientAcquire called in invalid mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
state := p.state.Load()
|
status := processStatus(p.state.Load())
|
||||||
if state&processStatusMask != 0 {
|
if status != statusOK {
|
||||||
return 0, processStatus(state & processStatusMask)
|
return 0, status
|
||||||
}
|
}
|
||||||
h, ok := p.handle.acquire()
|
h, ok := p.handle.acquire()
|
||||||
if ok {
|
if ok {
|
||||||
@ -161,11 +159,11 @@ func (p *Process) handleTransientAcquire() (uintptr, processStatus) {
|
|||||||
// We always set the status to non-zero before closing the handle.
|
// We always set the status to non-zero before closing the handle.
|
||||||
// If we get here the status must have been set non-zero after
|
// If we get here the status must have been set non-zero after
|
||||||
// we just checked it above.
|
// we just checked it above.
|
||||||
state = p.state.Load()
|
status = processStatus(p.state.Load())
|
||||||
if state&processStatusMask == 0 {
|
if status == statusOK {
|
||||||
panic("inconsistent process status")
|
panic("inconsistent process status")
|
||||||
}
|
}
|
||||||
return 0, processStatus(state & processStatusMask)
|
return 0, status
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Process) handleTransientRelease() {
|
func (p *Process) handleTransientRelease() {
|
||||||
@ -187,7 +185,7 @@ func (p *Process) handlePersistentRelease(reason processStatus) processStatus {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
state := p.state.Load()
|
state := p.state.Load()
|
||||||
status := processStatus(state & processStatusMask)
|
status := processStatus(state)
|
||||||
if status != statusOK {
|
if status != statusOK {
|
||||||
// Both Release and successful Wait will drop the
|
// Both Release and successful Wait will drop the
|
||||||
// Process' persistent reference on the handle. We
|
// Process' persistent reference on the handle. We
|
||||||
@ -196,7 +194,7 @@ func (p *Process) handlePersistentRelease(reason processStatus) processStatus {
|
|||||||
// reference is dropped exactly once.
|
// reference is dropped exactly once.
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
if !p.state.CompareAndSwap(state, uint64(reason)) {
|
if !p.state.CompareAndSwap(state, uint32(reason)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p.handle.release()
|
p.handle.release()
|
||||||
@ -225,7 +223,7 @@ func (p *Process) pidDeactivate(reason processStatus) {
|
|||||||
// racing Release and Wait, Wait may successfully wait on the process,
|
// racing Release and Wait, Wait may successfully wait on the process,
|
||||||
// returning the wait status, while future calls error with "process
|
// returning the wait status, while future calls error with "process
|
||||||
// released" rather than "process done".
|
// released" rather than "process done".
|
||||||
p.state.CompareAndSwap(0, uint64(reason))
|
p.state.CompareAndSwap(0, uint32(reason))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcAttr holds the attributes that will be applied to a new process
|
// ProcAttr holds the attributes that will be applied to a new process
|
||||||
|
@ -14,5 +14,5 @@ var (
|
|||||||
const StatusDone = statusDone
|
const StatusDone = statusDone
|
||||||
|
|
||||||
func (p *Process) Status() processStatus {
|
func (p *Process) Status() processStatus {
|
||||||
return processStatus(p.state.Load() & processStatusMask)
|
return processStatus(p.state.Load())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user