mirror of
https://github.com/golang/go.git
synced 2025-05-30 11:51:34 +00:00
{net,os/user,plugin}: eliminate unnecessary C round-trips
We're making two extra round-trips to C to malloc and free strings that originate in Go and don't escape. Skip those round-trips by allocating null-terminated slices in Go memory instead. Change-Id: I9e4c5ad999a7924ba50b82293c52073ec75518be Reviewed-on: https://go-review.googlesource.com/56530 Run-TryBot: Bryan Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
6711fa70ce
commit
d5b0ec858b
@ -12,7 +12,6 @@ package net
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
*/
|
*/
|
||||||
@ -95,15 +94,14 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (port int, err error) {
|
func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (port int, err error) {
|
||||||
s := C.CString(service)
|
cservice := make([]byte, len(service)+1)
|
||||||
// Lowercase the service name in the C-allocated memory.
|
copy(cservice, service)
|
||||||
for i := 0; i < len(service); i++ {
|
// Lowercase the C service name.
|
||||||
bp := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + uintptr(i)))
|
for i, b := range cservice[:len(service)] {
|
||||||
*bp = lowerASCII(*bp)
|
cservice[i] = lowerASCII(b)
|
||||||
}
|
}
|
||||||
var res *C.struct_addrinfo
|
var res *C.struct_addrinfo
|
||||||
defer C.free(unsafe.Pointer(s))
|
gerrno, err := C.getaddrinfo(nil, (*C.char)(unsafe.Pointer(&cservice[0])), hints, &res)
|
||||||
gerrno, err := C.getaddrinfo(nil, s, hints, &res)
|
|
||||||
if gerrno != 0 {
|
if gerrno != 0 {
|
||||||
switch gerrno {
|
switch gerrno {
|
||||||
case C.EAI_SYSTEM:
|
case C.EAI_SYSTEM:
|
||||||
@ -145,10 +143,10 @@ func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error) {
|
|||||||
hints.ai_flags = cgoAddrInfoFlags
|
hints.ai_flags = cgoAddrInfoFlags
|
||||||
hints.ai_socktype = C.SOCK_STREAM
|
hints.ai_socktype = C.SOCK_STREAM
|
||||||
|
|
||||||
h := C.CString(name)
|
h := make([]byte, len(name)+1)
|
||||||
defer C.free(unsafe.Pointer(h))
|
copy(h, name)
|
||||||
var res *C.struct_addrinfo
|
var res *C.struct_addrinfo
|
||||||
gerrno, err := C.getaddrinfo(h, nil, &hints, &res)
|
gerrno, err := C.getaddrinfo((*C.char)(unsafe.Pointer(&h[0])), nil, &hints, &res)
|
||||||
if gerrno != 0 {
|
if gerrno != 0 {
|
||||||
switch gerrno {
|
switch gerrno {
|
||||||
case C.EAI_SYSTEM:
|
case C.EAI_SYSTEM:
|
||||||
|
@ -52,8 +52,8 @@ func current() (*User, error) {
|
|||||||
func lookupUser(username string) (*User, error) {
|
func lookupUser(username string) (*User, error) {
|
||||||
var pwd C.struct_passwd
|
var pwd C.struct_passwd
|
||||||
var result *C.struct_passwd
|
var result *C.struct_passwd
|
||||||
nameC := C.CString(username)
|
nameC := make([]byte, len(username)+1)
|
||||||
defer C.free(unsafe.Pointer(nameC))
|
copy(nameC, username)
|
||||||
|
|
||||||
buf := alloc(userBuffer)
|
buf := alloc(userBuffer)
|
||||||
defer buf.free()
|
defer buf.free()
|
||||||
@ -63,7 +63,7 @@ func lookupUser(username string) (*User, error) {
|
|||||||
// passing a size_t to getpwnam_r, because for unknown
|
// passing a size_t to getpwnam_r, because for unknown
|
||||||
// reasons passing a size_t to getpwnam_r doesn't work on
|
// reasons passing a size_t to getpwnam_r doesn't work on
|
||||||
// Solaris.
|
// Solaris.
|
||||||
return syscall.Errno(C.mygetpwnam_r(nameC,
|
return syscall.Errno(C.mygetpwnam_r((*C.char)(unsafe.Pointer(&nameC[0])),
|
||||||
&pwd,
|
&pwd,
|
||||||
(*C.char)(buf.ptr),
|
(*C.char)(buf.ptr),
|
||||||
C.size_t(buf.size),
|
C.size_t(buf.size),
|
||||||
@ -140,11 +140,11 @@ func lookupGroup(groupname string) (*Group, error) {
|
|||||||
|
|
||||||
buf := alloc(groupBuffer)
|
buf := alloc(groupBuffer)
|
||||||
defer buf.free()
|
defer buf.free()
|
||||||
cname := C.CString(groupname)
|
cname := make([]byte, len(groupname)+1)
|
||||||
defer C.free(unsafe.Pointer(cname))
|
copy(cname, groupname)
|
||||||
|
|
||||||
err := retryWithBuffer(buf, func() syscall.Errno {
|
err := retryWithBuffer(buf, func() syscall.Errno {
|
||||||
return syscall.Errno(C.mygetgrnam_r(cname,
|
return syscall.Errno(C.mygetgrnam_r((*C.char)(unsafe.Pointer(&cname[0])),
|
||||||
&grp,
|
&grp,
|
||||||
(*C.char)(buf.ptr),
|
(*C.char)(buf.ptr),
|
||||||
C.size_t(buf.size),
|
C.size_t(buf.size),
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
/*
|
/*
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdlib.h>
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
@ -25,12 +24,12 @@ func listGroups(u *User) ([]string, error) {
|
|||||||
return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid)
|
return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid)
|
||||||
}
|
}
|
||||||
userGID := C.gid_t(ug)
|
userGID := C.gid_t(ug)
|
||||||
nameC := C.CString(u.Username)
|
nameC := make([]byte, len(u.Username)+1)
|
||||||
defer C.free(unsafe.Pointer(nameC))
|
copy(nameC, u.Username)
|
||||||
|
|
||||||
n := C.int(256)
|
n := C.int(256)
|
||||||
gidsC := make([]C.gid_t, n)
|
gidsC := make([]C.gid_t, n)
|
||||||
rv := getGroupList(nameC, userGID, &gidsC[0], &n)
|
rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n)
|
||||||
if rv == -1 {
|
if rv == -1 {
|
||||||
// More than initial buffer, but now n contains the correct size.
|
// More than initial buffer, but now n contains the correct size.
|
||||||
const maxGroups = 2048
|
const maxGroups = 2048
|
||||||
@ -38,7 +37,7 @@ func listGroups(u *User) ([]string, error) {
|
|||||||
return nil, fmt.Errorf("user: list groups for %s: member of more than %d groups", u.Username, maxGroups)
|
return nil, fmt.Errorf("user: list groups for %s: member of more than %d groups", u.Username, maxGroups)
|
||||||
}
|
}
|
||||||
gidsC = make([]C.gid_t, n)
|
gidsC = make([]C.gid_t, n)
|
||||||
rv := getGroupList(nameC, userGID, &gidsC[0], &n)
|
rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n)
|
||||||
if rv == -1 {
|
if rv == -1 {
|
||||||
return nil, fmt.Errorf("user: list groups for %s failed (changed groups?)", u.Username)
|
return nil, fmt.Errorf("user: list groups for %s failed (changed groups?)", u.Username)
|
||||||
}
|
}
|
||||||
|
@ -81,16 +81,16 @@ func pathToPrefix(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func open(name string) (*Plugin, error) {
|
func open(name string) (*Plugin, error) {
|
||||||
cPath := (*C.char)(C.malloc(C.PATH_MAX + 1))
|
cPath := make([]byte, C.PATH_MAX+1)
|
||||||
defer C.free(unsafe.Pointer(cPath))
|
cRelName := make([]byte, len(name)+1)
|
||||||
|
copy(cRelName, name)
|
||||||
cRelName := C.CString(name)
|
if C.realpath(
|
||||||
defer C.free(unsafe.Pointer(cRelName))
|
(*C.char)(unsafe.Pointer(&cRelName[0])),
|
||||||
if C.realpath(cRelName, cPath) == nil {
|
(*C.char)(unsafe.Pointer(&cPath[0]))) == nil {
|
||||||
return nil, errors.New("plugin.Open(" + name + "): realpath failed")
|
return nil, errors.New("plugin.Open(" + name + "): realpath failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
filepath := C.GoString(cPath)
|
filepath := C.GoString((*C.char)(unsafe.Pointer(&cPath[0])))
|
||||||
|
|
||||||
pluginsMu.Lock()
|
pluginsMu.Lock()
|
||||||
if p := plugins[filepath]; p != nil {
|
if p := plugins[filepath]; p != nil {
|
||||||
@ -99,7 +99,7 @@ func open(name string) (*Plugin, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
var cErr *C.char
|
var cErr *C.char
|
||||||
h := C.pluginOpen(cPath, &cErr)
|
h := C.pluginOpen((*C.char)(unsafe.Pointer(&cPath[0])), &cErr)
|
||||||
if h == 0 {
|
if h == 0 {
|
||||||
pluginsMu.Unlock()
|
pluginsMu.Unlock()
|
||||||
return nil, errors.New("plugin.Open: " + C.GoString(cErr))
|
return nil, errors.New("plugin.Open: " + C.GoString(cErr))
|
||||||
@ -127,9 +127,11 @@ func open(name string) (*Plugin, error) {
|
|||||||
plugins[filepath] = p
|
plugins[filepath] = p
|
||||||
pluginsMu.Unlock()
|
pluginsMu.Unlock()
|
||||||
|
|
||||||
initStr := C.CString(pluginpath + ".init")
|
initStr := make([]byte, len(pluginpath)+6)
|
||||||
initFuncPC := C.pluginLookup(h, initStr, &cErr)
|
copy(initStr, pluginpath)
|
||||||
C.free(unsafe.Pointer(initStr))
|
copy(initStr[len(pluginpath):], ".init")
|
||||||
|
|
||||||
|
initFuncPC := C.pluginLookup(h, (*C.char)(unsafe.Pointer(&initStr[0])), &cErr)
|
||||||
if initFuncPC != nil {
|
if initFuncPC != nil {
|
||||||
initFuncP := &initFuncPC
|
initFuncP := &initFuncPC
|
||||||
initFunc := *(*func())(unsafe.Pointer(&initFuncP))
|
initFunc := *(*func())(unsafe.Pointer(&initFuncP))
|
||||||
@ -144,9 +146,12 @@ func open(name string) (*Plugin, error) {
|
|||||||
delete(syms, symName)
|
delete(syms, symName)
|
||||||
symName = symName[1:]
|
symName = symName[1:]
|
||||||
}
|
}
|
||||||
cname := C.CString(pathToPrefix(pluginpath) + "." + symName)
|
|
||||||
p := C.pluginLookup(h, cname, &cErr)
|
fullName := pathToPrefix(pluginpath) + "." + symName
|
||||||
C.free(unsafe.Pointer(cname))
|
cname := make([]byte, len(fullName)+1)
|
||||||
|
copy(cname, fullName)
|
||||||
|
|
||||||
|
p := C.pluginLookup(h, (*C.char)(unsafe.Pointer(&cname[0])), &cErr)
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return nil, errors.New("plugin.Open: could not find symbol " + symName + ": " + C.GoString(cErr))
|
return nil, errors.New("plugin.Open: could not find symbol " + symName + ": " + C.GoString(cErr))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user