...

Source file src/pkg/internal/poll/fd_poll_runtime.go

     1	// Copyright 2013 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build aix darwin dragonfly freebsd linux netbsd openbsd windows solaris
     6	
     7	package poll
     8	
     9	import (
    10		"errors"
    11		"sync"
    12		"syscall"
    13		"time"
    14		_ "unsafe" // for go:linkname
    15	)
    16	
    17	// runtimeNano returns the current value of the runtime clock in nanoseconds.
    18	//go:linkname runtimeNano runtime.nanotime
    19	func runtimeNano() int64
    20	
    21	func runtime_pollServerInit()
    22	func runtime_pollOpen(fd uintptr) (uintptr, int)
    23	func runtime_pollClose(ctx uintptr)
    24	func runtime_pollWait(ctx uintptr, mode int) int
    25	func runtime_pollWaitCanceled(ctx uintptr, mode int) int
    26	func runtime_pollReset(ctx uintptr, mode int) int
    27	func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
    28	func runtime_pollUnblock(ctx uintptr)
    29	func runtime_isPollServerDescriptor(fd uintptr) bool
    30	
    31	type pollDesc struct {
    32		runtimeCtx uintptr
    33	}
    34	
    35	var serverInit sync.Once
    36	
    37	func (pd *pollDesc) init(fd *FD) error {
    38		serverInit.Do(runtime_pollServerInit)
    39		ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
    40		if errno != 0 {
    41			if ctx != 0 {
    42				runtime_pollUnblock(ctx)
    43				runtime_pollClose(ctx)
    44			}
    45			return errnoErr(syscall.Errno(errno))
    46		}
    47		pd.runtimeCtx = ctx
    48		return nil
    49	}
    50	
    51	func (pd *pollDesc) close() {
    52		if pd.runtimeCtx == 0 {
    53			return
    54		}
    55		runtime_pollClose(pd.runtimeCtx)
    56		pd.runtimeCtx = 0
    57	}
    58	
    59	// Evict evicts fd from the pending list, unblocking any I/O running on fd.
    60	func (pd *pollDesc) evict() {
    61		if pd.runtimeCtx == 0 {
    62			return
    63		}
    64		runtime_pollUnblock(pd.runtimeCtx)
    65	}
    66	
    67	func (pd *pollDesc) prepare(mode int, isFile bool) error {
    68		if pd.runtimeCtx == 0 {
    69			return nil
    70		}
    71		res := runtime_pollReset(pd.runtimeCtx, mode)
    72		return convertErr(res, isFile)
    73	}
    74	
    75	func (pd *pollDesc) prepareRead(isFile bool) error {
    76		return pd.prepare('r', isFile)
    77	}
    78	
    79	func (pd *pollDesc) prepareWrite(isFile bool) error {
    80		return pd.prepare('w', isFile)
    81	}
    82	
    83	func (pd *pollDesc) wait(mode int, isFile bool) error {
    84		if pd.runtimeCtx == 0 {
    85			return errors.New("waiting for unsupported file type")
    86		}
    87		res := runtime_pollWait(pd.runtimeCtx, mode)
    88		return convertErr(res, isFile)
    89	}
    90	
    91	func (pd *pollDesc) waitRead(isFile bool) error {
    92		return pd.wait('r', isFile)
    93	}
    94	
    95	func (pd *pollDesc) waitWrite(isFile bool) error {
    96		return pd.wait('w', isFile)
    97	}
    98	
    99	func (pd *pollDesc) waitCanceled(mode int) {
   100		if pd.runtimeCtx == 0 {
   101			return
   102		}
   103		runtime_pollWaitCanceled(pd.runtimeCtx, mode)
   104	}
   105	
   106	func (pd *pollDesc) pollable() bool {
   107		return pd.runtimeCtx != 0
   108	}
   109	
   110	func convertErr(res int, isFile bool) error {
   111		switch res {
   112		case 0:
   113			return nil
   114		case 1:
   115			return errClosing(isFile)
   116		case 2:
   117			return ErrTimeout
   118		case 3:
   119			return ErrNotPollable
   120		}
   121		println("unreachable: ", res)
   122		panic("unreachable")
   123	}
   124	
   125	// SetDeadline sets the read and write deadlines associated with fd.
   126	func (fd *FD) SetDeadline(t time.Time) error {
   127		return setDeadlineImpl(fd, t, 'r'+'w')
   128	}
   129	
   130	// SetReadDeadline sets the read deadline associated with fd.
   131	func (fd *FD) SetReadDeadline(t time.Time) error {
   132		return setDeadlineImpl(fd, t, 'r')
   133	}
   134	
   135	// SetWriteDeadline sets the write deadline associated with fd.
   136	func (fd *FD) SetWriteDeadline(t time.Time) error {
   137		return setDeadlineImpl(fd, t, 'w')
   138	}
   139	
   140	func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
   141		var d int64
   142		if !t.IsZero() {
   143			d = int64(time.Until(t))
   144			if d == 0 {
   145				d = -1 // don't confuse deadline right now with no deadline
   146			}
   147		}
   148		if err := fd.incref(); err != nil {
   149			return err
   150		}
   151		defer fd.decref()
   152		if fd.pd.runtimeCtx == 0 {
   153			return ErrNoDeadline
   154		}
   155		runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
   156		return nil
   157	}
   158	
   159	// IsPollDescriptor reports whether fd is the descriptor being used by the poller.
   160	// This is only used for testing.
   161	func IsPollDescriptor(fd uintptr) bool {
   162		return runtime_isPollServerDescriptor(fd)
   163	}
   164	

View as plain text