...
Run Format

Source file src/internal/poll/fd_io_plan9.go

Documentation: internal/poll

  // Copyright 2016 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package poll
  
  import (
  	"runtime"
  	"sync"
  	"syscall"
  )
  
  // asyncIO implements asynchronous cancelable I/O.
  // An asyncIO represents a single asynchronous Read or Write
  // operation. The result is returned on the result channel.
  // The undergoing I/O system call can either complete or be
  // interrupted by a note.
  type asyncIO struct {
  	res chan result
  
  	// mu guards the pid field.
  	mu sync.Mutex
  
  	// pid holds the process id of
  	// the process running the IO operation.
  	pid int
  }
  
  // result is the return value of a Read or Write operation.
  type result struct {
  	n   int
  	err error
  }
  
  // newAsyncIO returns a new asyncIO that performs an I/O
  // operation by calling fn, which must do one and only one
  // interruptible system call.
  func newAsyncIO(fn func([]byte) (int, error), b []byte) *asyncIO {
  	aio := &asyncIO{
  		res: make(chan result, 0),
  	}
  	aio.mu.Lock()
  	go func() {
  		// Lock the current goroutine to its process
  		// and store the pid in io so that Cancel can
  		// interrupt it. We ignore the "hangup" signal,
  		// so the signal does not take down the entire
  		// Go runtime.
  		runtime.LockOSThread()
  		runtime_ignoreHangup()
  		aio.pid = syscall.Getpid()
  		aio.mu.Unlock()
  
  		n, err := fn(b)
  
  		aio.mu.Lock()
  		aio.pid = -1
  		runtime_unignoreHangup()
  		aio.mu.Unlock()
  
  		aio.res <- result{n, err}
  	}()
  	return aio
  }
  
  // Cancel interrupts the I/O operation, causing
  // the Wait function to return.
  func (aio *asyncIO) Cancel() {
  	aio.mu.Lock()
  	defer aio.mu.Unlock()
  	if aio.pid == -1 {
  		return
  	}
  	f, e := syscall.Open("/proc/"+itoa(aio.pid)+"/note", syscall.O_WRONLY)
  	if e != nil {
  		return
  	}
  	syscall.Write(f, []byte("hangup"))
  	syscall.Close(f)
  }
  
  // Wait for the I/O operation to complete.
  func (aio *asyncIO) Wait() (int, error) {
  	res := <-aio.res
  	return res.n, res.err
  }
  
  // The following functions, provided by the runtime, are used to
  // ignore and unignore the "hangup" signal received by the process.
  func runtime_ignoreHangup()
  func runtime_unignoreHangup()
  

View as plain text