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:
Ian Lance Taylor 2024-12-22 21:15:30 -08:00 committed by Gopher Robot
parent caf29da4cc
commit e7c9667def
2 changed files with 17 additions and 19 deletions

View File

@ -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

View File

@ -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())
} }