mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Minor flipcall refactoring.
PiperOrigin-RevId: 342768550
This commit is contained in:
+59
-26
@@ -40,17 +40,41 @@ func (ep *Endpoint) ctrlInit(opts ...EndpointOption) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ctrlHandshakeRequest struct{}
|
||||
|
||||
type ctrlHandshakeResponse struct{}
|
||||
|
||||
func (ep *Endpoint) ctrlConnect() error {
|
||||
if err := ep.enterFutexWait(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := ep.futexConnect(&ctrlHandshakeRequest{})
|
||||
ep.exitFutexWait()
|
||||
return err
|
||||
defer ep.exitFutexWait()
|
||||
|
||||
// Write the connection request.
|
||||
w := ep.NewWriter()
|
||||
if err := json.NewEncoder(w).Encode(struct{}{}); err != nil {
|
||||
return fmt.Errorf("error writing connection request: %v", err)
|
||||
}
|
||||
*ep.dataLen() = w.Len()
|
||||
|
||||
// Exchange control with the server.
|
||||
if err := ep.futexSetPeerActive(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ep.futexWakePeer(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ep.futexWaitUntilActive(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the connection response.
|
||||
var resp struct{}
|
||||
respLen := atomic.LoadUint32(ep.dataLen())
|
||||
if respLen > ep.dataCap {
|
||||
return fmt.Errorf("invalid connection response length %d (maximum %d)", respLen, ep.dataCap)
|
||||
}
|
||||
if err := json.NewDecoder(ep.NewReader(respLen)).Decode(&resp); err != nil {
|
||||
return fmt.Errorf("error reading connection response: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *Endpoint) ctrlWaitFirst() error {
|
||||
@@ -59,52 +83,61 @@ func (ep *Endpoint) ctrlWaitFirst() error {
|
||||
}
|
||||
defer ep.exitFutexWait()
|
||||
|
||||
// Wait for the handshake request.
|
||||
if err := ep.futexSwitchFromPeer(); err != nil {
|
||||
// Wait for the connection request.
|
||||
if err := ep.futexWaitUntilActive(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the handshake request.
|
||||
// Read the connection request.
|
||||
reqLen := atomic.LoadUint32(ep.dataLen())
|
||||
if reqLen > ep.dataCap {
|
||||
return fmt.Errorf("invalid handshake request length %d (maximum %d)", reqLen, ep.dataCap)
|
||||
return fmt.Errorf("invalid connection request length %d (maximum %d)", reqLen, ep.dataCap)
|
||||
}
|
||||
var req ctrlHandshakeRequest
|
||||
var req struct{}
|
||||
if err := json.NewDecoder(ep.NewReader(reqLen)).Decode(&req); err != nil {
|
||||
return fmt.Errorf("error reading handshake request: %v", err)
|
||||
return fmt.Errorf("error reading connection request: %v", err)
|
||||
}
|
||||
|
||||
// Write the handshake response.
|
||||
// Write the connection response.
|
||||
w := ep.NewWriter()
|
||||
if err := json.NewEncoder(w).Encode(ctrlHandshakeResponse{}); err != nil {
|
||||
return fmt.Errorf("error writing handshake response: %v", err)
|
||||
if err := json.NewEncoder(w).Encode(struct{}{}); err != nil {
|
||||
return fmt.Errorf("error writing connection response: %v", err)
|
||||
}
|
||||
*ep.dataLen() = w.Len()
|
||||
|
||||
// Return control to the client.
|
||||
raceBecomeInactive()
|
||||
if err := ep.futexSwitchToPeer(); err != nil {
|
||||
if err := ep.futexSetPeerActive(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ep.futexWakePeer(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for the first non-handshake message.
|
||||
return ep.futexSwitchFromPeer()
|
||||
// Wait for the first non-connection message.
|
||||
return ep.futexWaitUntilActive()
|
||||
}
|
||||
|
||||
func (ep *Endpoint) ctrlRoundTrip() error {
|
||||
if err := ep.futexSwitchToPeer(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ep.enterFutexWait(); err != nil {
|
||||
return err
|
||||
}
|
||||
err := ep.futexSwitchFromPeer()
|
||||
ep.exitFutexWait()
|
||||
return err
|
||||
defer ep.exitFutexWait()
|
||||
|
||||
if err := ep.futexSetPeerActive(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ep.futexWakePeer(); err != nil {
|
||||
return err
|
||||
}
|
||||
return ep.futexWaitUntilActive()
|
||||
}
|
||||
|
||||
func (ep *Endpoint) ctrlWakeLast() error {
|
||||
return ep.futexSwitchToPeer()
|
||||
if err := ep.futexSetPeerActive(); err != nil {
|
||||
return err
|
||||
}
|
||||
return ep.futexWakePeer()
|
||||
}
|
||||
|
||||
func (ep *Endpoint) enterFutexWait() error {
|
||||
|
||||
@@ -41,11 +41,11 @@ const (
|
||||
)
|
||||
|
||||
func (ep *Endpoint) connState() *uint32 {
|
||||
return (*uint32)((unsafe.Pointer)(ep.packet))
|
||||
return (*uint32)(unsafe.Pointer(ep.packet))
|
||||
}
|
||||
|
||||
func (ep *Endpoint) dataLen() *uint32 {
|
||||
return (*uint32)((unsafe.Pointer)(ep.packet + 4))
|
||||
return (*uint32)(unsafe.Pointer(ep.packet + 4))
|
||||
}
|
||||
|
||||
// Data returns the datagram part of ep's packet window as a byte slice.
|
||||
@@ -63,7 +63,7 @@ func (ep *Endpoint) dataLen() *uint32 {
|
||||
// all.
|
||||
func (ep *Endpoint) Data() []byte {
|
||||
var bs []byte
|
||||
bsReflect := (*reflect.SliceHeader)((unsafe.Pointer)(&bs))
|
||||
bsReflect := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
|
||||
bsReflect.Data = ep.packet + PacketHeaderBytes
|
||||
bsReflect.Len = int(ep.dataCap)
|
||||
bsReflect.Cap = int(ep.dataCap)
|
||||
@@ -76,12 +76,12 @@ var ioSync int64
|
||||
|
||||
func raceBecomeActive() {
|
||||
if sync.RaceEnabled {
|
||||
sync.RaceAcquire((unsafe.Pointer)(&ioSync))
|
||||
sync.RaceAcquire(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
}
|
||||
|
||||
func raceBecomeInactive() {
|
||||
if sync.RaceEnabled {
|
||||
sync.RaceReleaseMerge((unsafe.Pointer)(&ioSync))
|
||||
sync.RaceReleaseMerge(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
}
|
||||
|
||||
+10
-40
@@ -17,7 +17,6 @@
|
||||
package flipcall
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
@@ -26,55 +25,26 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
)
|
||||
|
||||
func (ep *Endpoint) futexConnect(req *ctrlHandshakeRequest) (ctrlHandshakeResponse, error) {
|
||||
var resp ctrlHandshakeResponse
|
||||
|
||||
// Write the handshake request.
|
||||
w := ep.NewWriter()
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
return resp, fmt.Errorf("error writing handshake request: %v", err)
|
||||
func (ep *Endpoint) futexSetPeerActive() error {
|
||||
if atomic.CompareAndSwapUint32(ep.connState(), ep.activeState, ep.inactiveState) {
|
||||
return nil
|
||||
}
|
||||
*ep.dataLen() = w.Len()
|
||||
|
||||
// Exchange control with the server.
|
||||
if err := ep.futexSwitchToPeer(); err != nil {
|
||||
return resp, err
|
||||
switch cs := atomic.LoadUint32(ep.connState()); cs {
|
||||
case csShutdown:
|
||||
return ShutdownError{}
|
||||
default:
|
||||
return fmt.Errorf("unexpected connection state before FUTEX_WAKE: %v", cs)
|
||||
}
|
||||
if err := ep.futexSwitchFromPeer(); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Read the handshake response.
|
||||
respLen := atomic.LoadUint32(ep.dataLen())
|
||||
if respLen > ep.dataCap {
|
||||
return resp, fmt.Errorf("invalid handshake response length %d (maximum %d)", respLen, ep.dataCap)
|
||||
}
|
||||
if err := json.NewDecoder(ep.NewReader(respLen)).Decode(&resp); err != nil {
|
||||
return resp, fmt.Errorf("error reading handshake response: %v", err)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (ep *Endpoint) futexSwitchToPeer() error {
|
||||
// Update connection state to indicate that the peer should be active.
|
||||
if !atomic.CompareAndSwapUint32(ep.connState(), ep.activeState, ep.inactiveState) {
|
||||
switch cs := atomic.LoadUint32(ep.connState()); cs {
|
||||
case csShutdown:
|
||||
return ShutdownError{}
|
||||
default:
|
||||
return fmt.Errorf("unexpected connection state before FUTEX_WAKE: %v", cs)
|
||||
}
|
||||
}
|
||||
|
||||
// Wake the peer's Endpoint.futexSwitchFromPeer().
|
||||
func (ep *Endpoint) futexWakePeer() error {
|
||||
if err := ep.futexWakeConnState(1); err != nil {
|
||||
return fmt.Errorf("failed to FUTEX_WAKE peer Endpoint: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *Endpoint) futexSwitchFromPeer() error {
|
||||
func (ep *Endpoint) futexWaitUntilActive() error {
|
||||
for {
|
||||
switch cs := atomic.LoadUint32(ep.connState()); cs {
|
||||
case ep.activeState:
|
||||
|
||||
Reference in New Issue
Block a user