Issue 1:
Overview

At this time, there is no mechanism for socket types outside of the standard library to access the runtime network poller. This proposal, if accepted, would enable a resolution to issue #10565. This would enable packages outside of the standard library to take advantage of the runtime network poller, instead of implementing their own network polling mechanism.

Proposed Change

I propose adding a new API to package net which enables registration of arbitrary sockets for use with the runtime network poller. The design of this API is based upon a comment from @rsc found here: #11492 (comment).

It seems to me that the net package should just keep using (and providing) only FileConn but perhaps we can put a registration mechanism in package syscall to let clients register converters between sockaddrs and net.Addr for non-standard sockaddr types.

This is what I was able to come up with after a little bit of experimentation. Parameter list is to be determined, but this is what I was able to get working with my prototype on a Linux system. Efforts will be made to make this mechanism as generic and cross-platform friendly as possible, but it may not be implemented immediately on non-UNIX platforms. From what I can tell, syscall.Sockaddr does appear to be available on all platforms.

package net

// Registration mechanism, perhaps called in init() or main() when a
// socket is first initalized.
func RegisterSocket(
family int,
sockaddr syscall.Sockaddr,
addr Addr,
convertSockaddr func(syscall.Sockaddr) Addr,
convertNetAddr func(Addr) syscall.Sockaddr,
)

// Generic net.Conn and net.PacketConn implementation which embeds the
// internal net.conn type. Checks for registered socket hooks to determine
// validity of sent and received net.Addr implementations.
type SocketConn struct {
conn
}

Example

Using a modified version of package net, I was able to gain access to the runtime network poller and

simplify my raw sockets package code to something like the following:

// Called in init() in package raw
net.RegisterSocket(
syscall.AF_PACKET,
&syscall.SockaddrLinklayer{},
&Addr{},
// internal conversion functions for syscall.SockaddrLinklayer <-> raw.Addr
convertSockaddr,
convertNetAddr,
)

sock, _ := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, proto)
_ = syscall.Bind(sock, &syscall.SockaddrLinklayer{
Protocol: pbe,
Ifindex: ifi.Index,
})
f := os.NewFile(uintptr(sock), "linklayer")
// c is type net.SocketConn, backed by raw socket (uses raw.Addr for addressing)
c := net.FilePacketConn(f)

Summary

The runtime network poller is an excellent mechanism, and enabling access to it will allow the future development of packages for raw ethernet sockets, netlink sockets, and other platform-specific socket types.

If this proposal is accepted, I'd happily seek guidance from @mikioh regarding creating the best possible API for this feature. In addition, this would enable me to contribute code from my raw ethernet socket package as a resolution to #8432.

Questions and comments appreciated, and thanks for your time.

/cc @rsc @mikioh

Issue 2:
Even though the 386 has a 4-byte word size, some instructions move
data in larger chunks. In particular float64 loads move 8 bytes and
some SSE2 operations (as yet unused) move even larger amounts.
A float64 load from an only-4-byte-aligned address is significantly
more expensive than one from a 8-byte-aligned address. The same
is probably true of SSE2 too.

We should make sure that data symbols >32 bits (e.g., float64 constants)
are aligned on 8-byte boundaries in the data segment. (Fairly easy.)

We should also make sure that the stack pointer can be relied upon to be
8-byte aligned (harder), by making stack frame sizes = -4 mod 8
(the caller PC will add 4 more) and starting new goroutines with a
properly aligned stack pointer.

It might be worth using 16 bytes for the stack alignment. OS X requires
that for their own ABI, presumably because it matters for SSE2.