Commit d5b0ec85 authored by Bryan C. Mills's avatar Bryan C. Mills Committed by Bryan Mills

{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: default avatarIan Lance Taylor <iant@golang.org>
parent 6711fa70
...@@ -12,7 +12,6 @@ package net ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 ( ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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))
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment