func newFD(fd, family, proto int, net string, laddr, raddr Addr) (f *netFD, err os.Error) { if initErr != nil { return nil, initErr } onceStartServer.Do(startServer) // Associate our socket with pollserver.iocp. if _, e := syscall.CreateIoCompletionPort(int32(fd), pollserver.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", net, laddr, os.Errno(e)} } f = &netFD{ sysfd: fd, family: family, proto: proto, cr: make(chan *ioResult), cw: make(chan *ioResult), net: net, laddr: laddr, raddr: raddr, } var ls, rs string if laddr != nil { ls = laddr.String() } if raddr != nil { rs = raddr.String() } f.sysfile = os.NewFile(fd, net+":"+ls+"->"+rs) return f, nil }
func initJob() { // Create Job object and assign current process to it. jobObject, err := createJobObject(nil, nil) if err != nil { log.Printf("CreateJobObject failed: %v", err) return } if err = assignProcessToJobObject(jobObject, currentProcess); err != nil { log.Printf("AssignProcessToJobObject failed: %v", err) syscall.Close(jobObject) return } iocp, err := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1) if err != nil { log.Printf("CreateIoCompletionPort failed: %v", err) syscall.Close(jobObject) return } port := JOBOBJECT_ASSOCIATE_COMPLETION_PORT{ CompletionKey: uintptr(jobObject), CompletionPort: iocp, } err = setInformationJobObject(jobObject, JobObjectAssociateCompletionPortInformation, uintptr(unsafe.Pointer(&port)), uint32(unsafe.Sizeof(port))) if err != nil { log.Printf("SetInformationJobObject failed: %v", err) syscall.Close(jobObject) syscall.Close(iocp) return } // Read Job notifications about new "child" processes and collect them in childProcesses. go func() { var code, key uint32 var o *syscall.Overlapped for { err := syscall.GetQueuedCompletionStatus(iocp, &code, &key, &o, syscall.INFINITE) if err != nil { log.Printf("GetQueuedCompletionStatus failed: %v", err) return } if key != uint32(jobObject) { panic("Invalid GetQueuedCompletionStatus key parameter") } if code == JOB_OBJECT_MSG_NEW_PROCESS { pid := int(uintptr(unsafe.Pointer(o))) if pid == syscall.Getpid() { continue } c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) if err != nil { log.Printf("OpenProcess failed: %v", err) continue } childMu.Lock() childProcesses = append(childProcesses, c) childMu.Unlock() } } }() }
func newPollServer() (s *pollServer, err os.Error) { s = new(pollServer) var e int if s.iocp, e = syscall.CreateIoCompletionPort(-1, 0, 0, 1); e != 0 { return nil, os.NewSyscallError("CreateIoCompletionPort", e) } go s.Run() return s, nil }
func newFD(fd, family, proto int, net string) (f *netFD, err os.Error) { if initErr != nil { return nil, initErr } onceStartServer.Do(startServer) // Associate our socket with resultsrv.iocp. if _, e := syscall.CreateIoCompletionPort(int32(fd), resultsrv.iocp, 0, 0); e != 0 { return nil, os.Errno(e) } return allocFD(fd, family, proto, net), nil }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { if fd == nil || fd.sysfd == syscall.InvalidHandle { return nil, os.EINVAL } fd.incref() defer fd.decref() // Get new socket. // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(fd.family, fd.proto, 0) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Associate our new socket with IOCP. onceStartServer.Do(startServer) if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)} } // Submit accept request. var o acceptOp o.Init(fd, 'r') o.newsock = s _, err = iosrv.ExecIO(&o, 0) if err != nil { closesocket(s) return nil, err } // Inherit properties of the listening socket. e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) if e != 0 { closesocket(s) return nil, err } // Get local and peer addr out of AcceptEx buffer. var lrsa, rrsa *syscall.RawSockaddrAny var llen, rlen int32 l := uint32(unsafe.Sizeof(*lrsa)) syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &lrsa, &llen, &rrsa, &rlen) lsa, _ := lrsa.Sockaddr() rsa, _ := rrsa.Sockaddr() nfd = allocFD(s, fd.family, fd.proto, fd.net) nfd.setAddr(toAddr(lsa), toAddr(rsa)) return nfd, nil }
func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) { if initErr != nil { return nil, initErr } onceStartServer.Do(startServer) // Associate our socket with resultsrv.iocp. if _, err := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); err != nil { return nil, err } return allocFD(fd, family, proto, net), nil }
func startServer() { resultsrv = new(resultSrv) var errno int resultsrv.iocp, errno = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1) if errno != 0 { panic("CreateIoCompletionPort failed " + syscall.Errstr(errno)) } go resultsrv.Run() iosrv = new(ioSrv) iosrv.submchan = make(chan anOpIface) iosrv.canchan = make(chan anOpIface) go iosrv.ProcessRemoteIO() }
func startServer() { resultsrv = new(resultSrv) var err error resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1) if err != nil { panic("CreateIoCompletionPort: " + err.Error()) } go resultsrv.Run() iosrv = new(ioSrv) iosrv.submchan = make(chan anOpIface) iosrv.canchan = make(chan anOpIface) go iosrv.ProcessRemoteIO() }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { if err := fd.incref(false); err != nil { return nil, err } defer fd.decref() // Get new socket. s, err := sysSocket(fd.family, fd.sotype, 0) if err != nil { return nil, &OpError{"socket", fd.net, fd.laddr, err} } // Associate our new socket with IOCP. onceStartServer.Do(startServer) if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil { closesocket(s) return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err} } // Submit accept request. var o acceptOp o.Init(fd, 'r') o.newsock = s _, err = iosrv.ExecIO(&o, fd.rdeadline.value()) if err != nil { closesocket(s) return nil, err } // Inherit properties of the listening socket. err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) if err != nil { closesocket(s) return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} } // Get local and peer addr out of AcceptEx buffer. var lrsa, rrsa *syscall.RawSockaddrAny var llen, rlen int32 l := uint32(unsafe.Sizeof(*lrsa)) syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &lrsa, &llen, &rrsa, &rlen) lsa, _ := lrsa.Sockaddr() rsa, _ := rrsa.Sockaddr() netfd := allocFD(s, fd.family, fd.sotype, fd.net) netfd.setAddr(toAddr(lsa), toAddr(rsa)) return netfd, nil }
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. func NewWatcher() (*Watcher, error) { port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) if e != nil { return nil, os.NewSyscallError("CreateIoCompletionPort", e) } w := &Watcher{ port: port, watches: make(watchMap), input: make(chan *input, 1), Events: make(chan Event, 50), Errors: make(chan error), quit: make(chan chan<- error, 1), } go w.readEvents() return w, nil }
// lazyinit creates an I/O completion port and starts the main event processing // loop. This method uses Double-Checked Locking optimization. func (r *readdcw) lazyinit() (err error) { invalid := uintptr(syscall.InvalidHandle) if atomic.LoadUintptr((*uintptr)(&r.cph)) == invalid { r.Lock() defer r.Unlock() if atomic.LoadUintptr((*uintptr)(&r.cph)) == invalid { cph := syscall.InvalidHandle if cph, err = syscall.CreateIoCompletionPort(cph, 0, 0, 0); err != nil { return } r.cph, r.start = cph, true go r.loop() } } return }
// Must run within the I/O thread. func (w *Watcher) addWatch(pathname string, flags uint64) error { dir, err := getDir(pathname) if err != nil { return err } if flags&sys_FS_ONLYDIR != 0 && pathname != dir { return nil } ino, err := getIno(dir) if err != nil { return err } w.mu.Lock() watchEntry := w.watches.get(ino) w.mu.Unlock() if watchEntry == nil { if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { syscall.CloseHandle(ino.handle) return os.NewSyscallError("CreateIoCompletionPort", e) } watchEntry = &watch{ ino: ino, path: dir, names: make(map[string]uint64), } w.mu.Lock() w.watches.set(ino, watchEntry) w.mu.Unlock() flags |= provisional } else { syscall.CloseHandle(ino.handle) } if pathname == dir { watchEntry.mask |= flags } else { watchEntry.names[filepath.Base(pathname)] |= flags } if err = w.startRead(watchEntry); err != nil { return err } if pathname == dir { watchEntry.mask &= ^provisional } else { watchEntry.names[filepath.Base(pathname)] &= ^provisional } return nil }
// NOTE : Thread safe func (g *grip) register(cph syscall.Handle) (err error) { if g.handle, err = syscall.CreateFile( &g.pathw[0], syscall.FILE_LIST_DIRECTORY, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0, ); err != nil { return } if _, err = syscall.CreateIoCompletionPort(g.handle, cph, 0, 0); err != nil { syscall.CloseHandle(g.handle) return } return g.readDirChanges() }
func startServer() { resultsrv = new(resultSrv) var err error resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1) if err != nil { panic("CreateIoCompletionPort: " + err.Error()) } go resultsrv.Run() iosrv = new(ioSrv) if !canCancelIO { // Only CancelIo API is available. Lets start special goroutine // locked to an OS thread, that both starts and cancels IO. iosrv.submchan = make(chan anOpIface) iosrv.canchan = make(chan anOpIface) go iosrv.ProcessRemoteIO() } }
// NewWatcher creates and returns a Watcher. func NewWatcher() (*Watcher, error) { port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) if e != nil { return nil, os.NewSyscallError("CreateIoCompletionPort", e) } w := &Watcher{ port: port, watches: make(watchMap), fsnFlags: make(map[string]uint32), input: make(chan *input, 1), Event: make(chan *FileEvent, 50), internalEvent: make(chan *FileEvent), Error: make(chan error), quit: make(chan chan<- error, 1), } go w.readEvents() go w.purgeEvents() return w, nil }
func newFD(fd, family, proto int, net string, laddr, raddr Addr) (f *netFD, err os.Error) { if initErr != nil { return nil, initErr } onceStartServer.Do(startServer) // Associate our socket with pollserver.iocp. if _, e := syscall.CreateIoCompletionPort(int32(fd), pollserver.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", net, laddr, os.Errno(e)} } f = &netFD{ sysfd: fd, family: family, proto: proto, cr: make(chan *ioResult, 1), cw: make(chan *ioResult, 1), net: net, laddr: laddr, raddr: raddr, } runtime.SetFinalizer(f, (*netFD).Close) return f, nil }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { if fd == nil || fd.sysfd == -1 { return nil, os.EINVAL } fd.incref() defer fd.decref() // Get new socket. // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(fd.family, fd.proto, 0) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Associate our new socket with IOCP. onceStartServer.Do(startServer) if _, e = syscall.CreateIoCompletionPort(int32(s), pollserver.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)} } // Submit accept request. // Will use new unique channel here, because, unlike Read or Write, // Accept is expected to be executed by many goroutines simultaniously. var pckt ioPacket pckt.c = make(chan *ioResult) attrs, e := syscall.AcceptIOCP(fd.sysfd, s, &pckt.o) switch e { case 0: // IO completed immediately, but we need to get our completion message anyway. case syscall.ERROR_IO_PENDING: // IO started, and we have to wait for it's completion. default: closesocket(s) return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(e)} } // Wait for peer connection. r := <-pckt.c if r.errno != 0 { closesocket(s) return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(r.errno)} } // Inherit properties of the listening socket. e = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, fd.sysfd) if e != 0 { closesocket(s) return nil, &OpError{"Setsockopt", fd.net, fd.laddr, os.Errno(r.errno)} } // Get local and peer addr out of AcceptEx buffer. lsa, rsa := syscall.GetAcceptIOCPSockaddrs(attrs) // Create our netFD and return it for further use. laddr := toAddr(lsa) raddr := toAddr(rsa) f := &netFD{ sysfd: s, family: fd.family, proto: fd.proto, cr: make(chan *ioResult, 1), cw: make(chan *ioResult, 1), net: fd.net, laddr: laddr, raddr: raddr, } runtime.SetFinalizer(f, (*netFD).Close) return f, nil }