fd_poll_runtime.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. // +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
  5. package net
  6. import (
  7. "sync"
  8. "syscall"
  9. "time"
  10. )
  11. // runtimeNano returns the current value of the runtime clock in nanoseconds.
  12. func runtimeNano() int64
  13. func runtime_pollServerInit()
  14. func runtime_pollOpen(fd uintptr) (uintptr, int)
  15. func runtime_pollClose(ctx uintptr)
  16. func runtime_pollWait(ctx uintptr, mode int) int
  17. func runtime_pollWaitCanceled(ctx uintptr, mode int) int
  18. func runtime_pollReset(ctx uintptr, mode int) int
  19. func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
  20. func runtime_pollUnblock(ctx uintptr)
  21. type pollDesc struct {
  22. runtimeCtx uintptr
  23. }
  24. var serverInit sync.Once
  25. func (pd *pollDesc) Init(fd *netFD) error {
  26. serverInit.Do(runtime_pollServerInit)
  27. ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
  28. if errno != 0 {
  29. return syscall.Errno(errno)
  30. }
  31. pd.runtimeCtx = ctx
  32. return nil
  33. }
  34. func (pd *pollDesc) Close() {
  35. if pd.runtimeCtx == 0 {
  36. return
  37. }
  38. runtime_pollClose(pd.runtimeCtx)
  39. pd.runtimeCtx = 0
  40. }
  41. func (pd *pollDesc) Lock() {
  42. }
  43. func (pd *pollDesc) Unlock() {
  44. }
  45. func (pd *pollDesc) Wakeup() {
  46. }
  47. // Evict evicts fd from the pending list, unblocking any I/O running on fd.
  48. // Return value is whether the pollServer should be woken up.
  49. func (pd *pollDesc) Evict() bool {
  50. if pd.runtimeCtx == 0 {
  51. return false
  52. }
  53. runtime_pollUnblock(pd.runtimeCtx)
  54. return false
  55. }
  56. func (pd *pollDesc) Prepare(mode int) error {
  57. res := runtime_pollReset(pd.runtimeCtx, mode)
  58. return convertErr(res)
  59. }
  60. func (pd *pollDesc) PrepareRead() error {
  61. return pd.Prepare('r')
  62. }
  63. func (pd *pollDesc) PrepareWrite() error {
  64. return pd.Prepare('w')
  65. }
  66. func (pd *pollDesc) Wait(mode int) error {
  67. res := runtime_pollWait(pd.runtimeCtx, mode)
  68. return convertErr(res)
  69. }
  70. func (pd *pollDesc) WaitRead() error {
  71. return pd.Wait('r')
  72. }
  73. func (pd *pollDesc) WaitWrite() error {
  74. return pd.Wait('w')
  75. }
  76. func (pd *pollDesc) WaitCanceled(mode int) {
  77. runtime_pollWaitCanceled(pd.runtimeCtx, mode)
  78. }
  79. func (pd *pollDesc) WaitCanceledRead() {
  80. pd.WaitCanceled('r')
  81. }
  82. func (pd *pollDesc) WaitCanceledWrite() {
  83. pd.WaitCanceled('w')
  84. }
  85. func convertErr(res int) error {
  86. switch res {
  87. case 0:
  88. return nil
  89. case 1:
  90. return errClosing
  91. case 2:
  92. return errTimeout
  93. }
  94. println("unreachable: ", res)
  95. panic("unreachable")
  96. }
  97. func (fd *netFD) setDeadline(t time.Time) error {
  98. return setDeadlineImpl(fd, t, 'r'+'w')
  99. }
  100. func (fd *netFD) setReadDeadline(t time.Time) error {
  101. return setDeadlineImpl(fd, t, 'r')
  102. }
  103. func (fd *netFD) setWriteDeadline(t time.Time) error {
  104. return setDeadlineImpl(fd, t, 'w')
  105. }
  106. func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
  107. d := runtimeNano() + int64(t.Sub(time.Now()))
  108. if t.IsZero() {
  109. d = 0
  110. }
  111. if err := fd.incref(); err != nil {
  112. return err
  113. }
  114. runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
  115. fd.decref()
  116. return nil
  117. }