src/pkg/net/fd_linux.go - The Go Programming Language

Golang

Source file src/pkg/net/fd_linux.go

     1	// Copyright 2009 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	// Waiting for FDs via epoll(7).
     6	
     7	package net
     8	
     9	import (
    10		"os"
    11		"syscall"
    12	)
    13	
    14	const (
    15		readFlags  = syscall.EPOLLIN | syscall.EPOLLRDHUP
    16		writeFlags = syscall.EPOLLOUT
    17	)
    18	
    19	type pollster struct {
    20		epfd int
    21	
    22		// Events we're already waiting for
    23		// Must hold pollServer lock
    24		events map[int]uint32
    25	
    26		// An event buffer for EpollWait.
    27		// Used without a lock, may only be used by WaitFD.
    28		waitEventBuf [10]syscall.EpollEvent
    29		waitEvents   []syscall.EpollEvent
    30	
    31		// An event buffer for EpollCtl, to avoid a malloc.
    32		// Must hold pollServer lock.
    33		ctlEvent syscall.EpollEvent
    34	}
    35	
    36	func newpollster() (p *pollster, err error) {
    37		p = new(pollster)
    38		if p.epfd, err = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil {
    39			if err != syscall.ENOSYS {
    40				return nil, os.NewSyscallError("epoll_create1", err)
    41			}
    42			// The arg to epoll_create is a hint to the kernel
    43			// about the number of FDs we will care about.
    44			// We don't know, and since 2.6.8 the kernel ignores it anyhow.
    45			if p.epfd, err = syscall.EpollCreate(16); err != nil {
    46				return nil, os.NewSyscallError("epoll_create", err)
    47			}
    48			syscall.CloseOnExec(p.epfd)
    49		}
    50		p.events = make(map[int]uint32)
    51		return p, nil
    52	}
    53	
    54	func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
    55		// pollServer is locked.
    56	
    57		var already bool
    58		p.ctlEvent.Fd = int32(fd)
    59		p.ctlEvent.Events, already = p.events[fd]
    60		if !repeat {
    61			p.ctlEvent.Events |= syscall.EPOLLONESHOT
    62		}
    63		if mode == 'r' {
    64			p.ctlEvent.Events |= readFlags
    65		} else {
    66			p.ctlEvent.Events |= writeFlags
    67		}
    68	
    69		var op int
    70		if already {
    71			op = syscall.EPOLL_CTL_MOD
    72		} else {
    73			op = syscall.EPOLL_CTL_ADD
    74		}
    75		if err := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); err != nil {
    76			return false, os.NewSyscallError("epoll_ctl", err)
    77		}
    78		p.events[fd] = p.ctlEvent.Events
    79		return false, nil
    80	}
    81	
    82	func (p *pollster) StopWaiting(fd int, bits uint) {
    83		// pollServer is locked.
    84	
    85		events, already := p.events[fd]
    86		if !already {
    87			// The fd returned by the kernel may have been
    88			// cancelled already; return silently.
    89			return
    90		}
    91	
    92		// If syscall.EPOLLONESHOT is not set, the wait
    93		// is a repeating wait, so don't change it.
    94		if events&syscall.EPOLLONESHOT == 0 {
    95			return
    96		}
    97	
    98		// Disable the given bits.
    99		// If we're still waiting for other events, modify the fd
   100		// event in the kernel.  Otherwise, delete it.
   101		events &= ^uint32(bits)
   102		if int32(events)&^syscall.EPOLLONESHOT != 0 {
   103			p.ctlEvent.Fd = int32(fd)
   104			p.ctlEvent.Events = events
   105			if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil {
   106				print("Epoll modify fd=", fd, ": ", err.Error(), "\n")
   107			}
   108			p.events[fd] = events
   109		} else {
   110			if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil {
   111				print("Epoll delete fd=", fd, ": ", err.Error(), "\n")
   112			}
   113			delete(p.events, fd)
   114		}
   115	}
   116	
   117	func (p *pollster) DelFD(fd int, mode int) {
   118		// pollServer is locked.
   119	
   120		if mode == 'r' {
   121			p.StopWaiting(fd, readFlags)
   122		} else {
   123			p.StopWaiting(fd, writeFlags)
   124		}
   125	
   126		// Discard any queued up events.
   127		i := 0
   128		for i < len(p.waitEvents) {
   129			if fd == int(p.waitEvents[i].Fd) {
   130				copy(p.waitEvents[i:], p.waitEvents[i+1:])
   131				p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
   132			} else {
   133				i++
   134			}
   135		}
   136	}
   137	
   138	func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
   139		for len(p.waitEvents) == 0 {
   140			var msec int = -1
   141			if nsec > 0 {
   142				msec = int((nsec + 1e6 - 1) / 1e6)
   143			}
   144	
   145			s.Unlock()
   146			n, err := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
   147			s.Lock()
   148	
   149			if err != nil {
   150				if err == syscall.EAGAIN || err == syscall.EINTR {
   151					continue
   152				}
   153				return -1, 0, os.NewSyscallError("epoll_wait", err)
   154			}
   155			if n == 0 {
   156				return -1, 0, nil
   157			}
   158			p.waitEvents = p.waitEventBuf[0:n]
   159		}
   160	
   161		ev := &p.waitEvents[0]
   162		p.waitEvents = p.waitEvents[1:]
   163	
   164		fd = int(ev.Fd)
   165	
   166		if ev.Events&writeFlags != 0 {
   167			p.StopWaiting(fd, writeFlags)
   168			return fd, 'w', nil
   169		}
   170		if ev.Events&readFlags != 0 {
   171			p.StopWaiting(fd, readFlags)
   172			return fd, 'r', nil
   173		}
   174	
   175		// Other events are error conditions - wake whoever is waiting.
   176		events, _ := p.events[fd]
   177		if events&writeFlags != 0 {
   178			p.StopWaiting(fd, writeFlags)
   179			return fd, 'w', nil
   180		}
   181		p.StopWaiting(fd, readFlags)
   182		return fd, 'r', nil
   183	}
   184	
   185	func (p *pollster) Close() error {
   186		return os.NewSyscallError("close", syscall.Close(p.epfd))
   187	}