Skip to content

Commit d5b0ec8

Browse files
author
Bryan C. Mills
committed
{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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 6711fa7 commit d5b0ec8

File tree

4 files changed

+38
-36
lines changed

4 files changed

+38
-36
lines changed

src/net/cgo_unix.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ package net
1212
#include <sys/socket.h>
1313
#include <netinet/in.h>
1414
#include <netdb.h>
15-
#include <stdlib.h>
1615
#include <unistd.h>
1716
#include <string.h>
1817
*/
@@ -95,15 +94,14 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err
9594
}
9695

9796
func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (port int, err error) {
98-
s := C.CString(service)
99-
// Lowercase the service name in the C-allocated memory.
100-
for i := 0; i < len(service); i++ {
101-
bp := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + uintptr(i)))
102-
*bp = lowerASCII(*bp)
97+
cservice := make([]byte, len(service)+1)
98+
copy(cservice, service)
99+
// Lowercase the C service name.
100+
for i, b := range cservice[:len(service)] {
101+
cservice[i] = lowerASCII(b)
103102
}
104103
var res *C.struct_addrinfo
105-
defer C.free(unsafe.Pointer(s))
106-
gerrno, err := C.getaddrinfo(nil, s, hints, &res)
104+
gerrno, err := C.getaddrinfo(nil, (*C.char)(unsafe.Pointer(&cservice[0])), hints, &res)
107105
if gerrno != 0 {
108106
switch gerrno {
109107
case C.EAI_SYSTEM:
@@ -145,10 +143,10 @@ func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error) {
145143
hints.ai_flags = cgoAddrInfoFlags
146144
hints.ai_socktype = C.SOCK_STREAM
147145

148-
h := C.CString(name)
149-
defer C.free(unsafe.Pointer(h))
146+
h := make([]byte, len(name)+1)
147+
copy(h, name)
150148
var res *C.struct_addrinfo
151-
gerrno, err := C.getaddrinfo(h, nil, &hints, &res)
149+
gerrno, err := C.getaddrinfo((*C.char)(unsafe.Pointer(&h[0])), nil, &hints, &res)
152150
if gerrno != 0 {
153151
switch gerrno {
154152
case C.EAI_SYSTEM:

src/os/user/cgo_lookup_unix.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ func current() (*User, error) {
5252
func lookupUser(username string) (*User, error) {
5353
var pwd C.struct_passwd
5454
var result *C.struct_passwd
55-
nameC := C.CString(username)
56-
defer C.free(unsafe.Pointer(nameC))
55+
nameC := make([]byte, len(username)+1)
56+
copy(nameC, username)
5757

5858
buf := alloc(userBuffer)
5959
defer buf.free()
@@ -63,7 +63,7 @@ func lookupUser(username string) (*User, error) {
6363
// passing a size_t to getpwnam_r, because for unknown
6464
// reasons passing a size_t to getpwnam_r doesn't work on
6565
// Solaris.
66-
return syscall.Errno(C.mygetpwnam_r(nameC,
66+
return syscall.Errno(C.mygetpwnam_r((*C.char)(unsafe.Pointer(&nameC[0])),
6767
&pwd,
6868
(*C.char)(buf.ptr),
6969
C.size_t(buf.size),
@@ -140,11 +140,11 @@ func lookupGroup(groupname string) (*Group, error) {
140140

141141
buf := alloc(groupBuffer)
142142
defer buf.free()
143-
cname := C.CString(groupname)
144-
defer C.free(unsafe.Pointer(cname))
143+
cname := make([]byte, len(groupname)+1)
144+
copy(cname, groupname)
145145

146146
err := retryWithBuffer(buf, func() syscall.Errno {
147-
return syscall.Errno(C.mygetgrnam_r(cname,
147+
return syscall.Errno(C.mygetgrnam_r((*C.char)(unsafe.Pointer(&cname[0])),
148148
&grp,
149149
(*C.char)(buf.ptr),
150150
C.size_t(buf.size),

src/os/user/listgroups_unix.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
/*
1616
#include <unistd.h>
1717
#include <sys/types.h>
18-
#include <stdlib.h>
1918
*/
2019
import "C"
2120

@@ -25,20 +24,20 @@ func listGroups(u *User) ([]string, error) {
2524
return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid)
2625
}
2726
userGID := C.gid_t(ug)
28-
nameC := C.CString(u.Username)
29-
defer C.free(unsafe.Pointer(nameC))
27+
nameC := make([]byte, len(u.Username)+1)
28+
copy(nameC, u.Username)
3029

3130
n := C.int(256)
3231
gidsC := make([]C.gid_t, n)
33-
rv := getGroupList(nameC, userGID, &gidsC[0], &n)
32+
rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n)
3433
if rv == -1 {
3534
// More than initial buffer, but now n contains the correct size.
3635
const maxGroups = 2048
3736
if n > maxGroups {
3837
return nil, fmt.Errorf("user: list groups for %s: member of more than %d groups", u.Username, maxGroups)
3938
}
4039
gidsC = make([]C.gid_t, n)
41-
rv := getGroupList(nameC, userGID, &gidsC[0], &n)
40+
rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n)
4241
if rv == -1 {
4342
return nil, fmt.Errorf("user: list groups for %s failed (changed groups?)", u.Username)
4443
}

src/plugin/plugin_dlopen.go

+19-14
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,16 @@ func pathToPrefix(s string) string {
8181
}
8282

8383
func open(name string) (*Plugin, error) {
84-
cPath := (*C.char)(C.malloc(C.PATH_MAX + 1))
85-
defer C.free(unsafe.Pointer(cPath))
86-
87-
cRelName := C.CString(name)
88-
defer C.free(unsafe.Pointer(cRelName))
89-
if C.realpath(cRelName, cPath) == nil {
84+
cPath := make([]byte, C.PATH_MAX+1)
85+
cRelName := make([]byte, len(name)+1)
86+
copy(cRelName, name)
87+
if C.realpath(
88+
(*C.char)(unsafe.Pointer(&cRelName[0])),
89+
(*C.char)(unsafe.Pointer(&cPath[0]))) == nil {
9090
return nil, errors.New("plugin.Open(" + name + "): realpath failed")
9191
}
9292

93-
filepath := C.GoString(cPath)
93+
filepath := C.GoString((*C.char)(unsafe.Pointer(&cPath[0])))
9494

9595
pluginsMu.Lock()
9696
if p := plugins[filepath]; p != nil {
@@ -99,7 +99,7 @@ func open(name string) (*Plugin, error) {
9999
return p, nil
100100
}
101101
var cErr *C.char
102-
h := C.pluginOpen(cPath, &cErr)
102+
h := C.pluginOpen((*C.char)(unsafe.Pointer(&cPath[0])), &cErr)
103103
if h == 0 {
104104
pluginsMu.Unlock()
105105
return nil, errors.New("plugin.Open: " + C.GoString(cErr))
@@ -127,9 +127,11 @@ func open(name string) (*Plugin, error) {
127127
plugins[filepath] = p
128128
pluginsMu.Unlock()
129129

130-
initStr := C.CString(pluginpath + ".init")
131-
initFuncPC := C.pluginLookup(h, initStr, &cErr)
132-
C.free(unsafe.Pointer(initStr))
130+
initStr := make([]byte, len(pluginpath)+6)
131+
copy(initStr, pluginpath)
132+
copy(initStr[len(pluginpath):], ".init")
133+
134+
initFuncPC := C.pluginLookup(h, (*C.char)(unsafe.Pointer(&initStr[0])), &cErr)
133135
if initFuncPC != nil {
134136
initFuncP := &initFuncPC
135137
initFunc := *(*func())(unsafe.Pointer(&initFuncP))
@@ -144,9 +146,12 @@ func open(name string) (*Plugin, error) {
144146
delete(syms, symName)
145147
symName = symName[1:]
146148
}
147-
cname := C.CString(pathToPrefix(pluginpath) + "." + symName)
148-
p := C.pluginLookup(h, cname, &cErr)
149-
C.free(unsafe.Pointer(cname))
149+
150+
fullName := pathToPrefix(pluginpath) + "." + symName
151+
cname := make([]byte, len(fullName)+1)
152+
copy(cname, fullName)
153+
154+
p := C.pluginLookup(h, (*C.char)(unsafe.Pointer(&cname[0])), &cErr)
150155
if p == nil {
151156
return nil, errors.New("plugin.Open: could not find symbol " + symName + ": " + C.GoString(cErr))
152157
}

0 commit comments

Comments
 (0)