// Copyright 2013 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.

// +build aix darwin dragonfly freebsd linux netbsd openbsd windows solaris

package poll

import (
	
	
	
	
	_  // for go:linkname
)

// runtimeNano returns the current value of the runtime clock in nanoseconds.
//go:linkname runtimeNano runtime.nanotime
func runtimeNano() int64

func runtime_pollServerInit()
func runtime_pollOpen( uintptr) (uintptr, int)
func runtime_pollClose( uintptr)
func runtime_pollWait( uintptr,  int) int
func runtime_pollWaitCanceled( uintptr,  int) int
func runtime_pollReset( uintptr,  int) int
func runtime_pollSetDeadline( uintptr,  int64,  int)
func runtime_pollUnblock( uintptr)
func runtime_isPollServerDescriptor( uintptr) bool

type pollDesc struct {
	runtimeCtx uintptr
}

var serverInit sync.Once

func ( *pollDesc) ( *FD) error {
	serverInit.Do(runtime_pollServerInit)
	,  := runtime_pollOpen(uintptr(.Sysfd))
	if  != 0 {
		if  != 0 {
			runtime_pollUnblock()
			runtime_pollClose()
		}
		return errnoErr(syscall.Errno())
	}
	.runtimeCtx = 
	return nil
}

func ( *pollDesc) () {
	if .runtimeCtx == 0 {
		return
	}
	runtime_pollClose(.runtimeCtx)
	.runtimeCtx = 0
}

// Evict evicts fd from the pending list, unblocking any I/O running on fd.
func ( *pollDesc) () {
	if .runtimeCtx == 0 {
		return
	}
	runtime_pollUnblock(.runtimeCtx)
}

func ( *pollDesc) ( int,  bool) error {
	if .runtimeCtx == 0 {
		return nil
	}
	 := runtime_pollReset(.runtimeCtx, )
	return convertErr(, )
}

func ( *pollDesc) ( bool) error {
	return .prepare('r', )
}

func ( *pollDesc) ( bool) error {
	return .prepare('w', )
}

func ( *pollDesc) ( int,  bool) error {
	if .runtimeCtx == 0 {
		return errors.New("waiting for unsupported file type")
	}
	 := runtime_pollWait(.runtimeCtx, )
	return convertErr(, )
}

func ( *pollDesc) ( bool) error {
	return .wait('r', )
}

func ( *pollDesc) ( bool) error {
	return .wait('w', )
}

func ( *pollDesc) ( int) {
	if .runtimeCtx == 0 {
		return
	}
	runtime_pollWaitCanceled(.runtimeCtx, )
}

func ( *pollDesc) () bool {
	return .runtimeCtx != 0
}

// Error values returned by runtime_pollReset and runtime_pollWait.
// These must match the values in runtime/netpoll.go.
const (
	pollNoError        = 0
	pollErrClosing     = 1
	pollErrTimeout     = 2
	pollErrNotPollable = 3
)

func convertErr( int,  bool) error {
	switch  {
	case pollNoError:
		return nil
	case pollErrClosing:
		return errClosing()
	case pollErrTimeout:
		return ErrDeadlineExceeded
	case pollErrNotPollable:
		return ErrNotPollable
	}
	println("unreachable: ", )
	panic("unreachable")
}

// SetDeadline sets the read and write deadlines associated with fd.
func ( *FD) ( time.Time) error {
	return setDeadlineImpl(, , 'r'+'w')
}

// SetReadDeadline sets the read deadline associated with fd.
func ( *FD) ( time.Time) error {
	return setDeadlineImpl(, , 'r')
}

// SetWriteDeadline sets the write deadline associated with fd.
func ( *FD) ( time.Time) error {
	return setDeadlineImpl(, , 'w')
}

func setDeadlineImpl( *FD,  time.Time,  int) error {
	var  int64
	if !.IsZero() {
		 = int64(time.Until())
		if  == 0 {
			 = -1 // don't confuse deadline right now with no deadline
		}
	}
	if  := .incref();  != nil {
		return 
	}
	defer .decref()
	if .pd.runtimeCtx == 0 {
		return ErrNoDeadline
	}
	runtime_pollSetDeadline(.pd.runtimeCtx, , )
	return nil
}

// IsPollDescriptor reports whether fd is the descriptor being used by the poller.
// This is only used for testing.
func ( uintptr) bool {
	return runtime_isPollServerDescriptor()
}