netpoll_epoll.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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 linux
  5. package runtime
  6. import "unsafe"
  7. func epollcreate(size int32) int32
  8. func epollcreate1(flags int32) int32
  9. //go:noescape
  10. func epollctl(epfd, op, fd int32, ev *epollevent) int32
  11. //go:noescape
  12. func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
  13. func closeonexec(fd int32)
  14. var (
  15. epfd int32 = -1 // epoll descriptor
  16. netpolllasterr int32
  17. )
  18. func netpollinit() {
  19. epfd = epollcreate1(_EPOLL_CLOEXEC)
  20. if epfd >= 0 {
  21. return
  22. }
  23. epfd = epollcreate(1024)
  24. if epfd >= 0 {
  25. closeonexec(epfd)
  26. return
  27. }
  28. println("netpollinit: failed to create epoll descriptor", -epfd)
  29. gothrow("netpollinit: failed to create descriptor")
  30. }
  31. func netpollopen(fd uintptr, pd *pollDesc) int32 {
  32. var ev epollevent
  33. ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET
  34. *(**pollDesc)(unsafe.Pointer(&ev.data)) = pd
  35. return -epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev)
  36. }
  37. func netpollclose(fd uintptr) int32 {
  38. var ev epollevent
  39. return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev)
  40. }
  41. func netpollarm(pd *pollDesc, mode int) {
  42. gothrow("unused")
  43. }
  44. // polls for ready network connections
  45. // returns list of goroutines that become runnable
  46. func netpoll(block bool) (gp *g) {
  47. if epfd == -1 {
  48. return
  49. }
  50. waitms := int32(-1)
  51. if !block {
  52. waitms = 0
  53. }
  54. var events [128]epollevent
  55. retry:
  56. n := epollwait(epfd, &events[0], int32(len(events)), waitms)
  57. if n < 0 {
  58. if n != -_EINTR && n != netpolllasterr {
  59. netpolllasterr = n
  60. println("runtime: epollwait on fd", epfd, "failed with", -n)
  61. }
  62. goto retry
  63. }
  64. for i := int32(0); i < n; i++ {
  65. ev := &events[i]
  66. if ev.events == 0 {
  67. continue
  68. }
  69. var mode int32
  70. if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 {
  71. mode += 'r'
  72. }
  73. if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 {
  74. mode += 'w'
  75. }
  76. if mode != 0 {
  77. pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
  78. netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
  79. }
  80. }
  81. if block && gp == nil {
  82. goto retry
  83. }
  84. return gp
  85. }