summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-18 18:47:02 +0300
committerPaul Buetow <paul@buetow.org>2026-05-18 18:47:02 +0300
commit5c13a7321502c4a5767be17ed48e7cdb576deab3 (patch)
treefe155a1f8492471165762f8cf22796947149020a /cmd
parent7fb497c435596a36c0fb0bd0ecae2a84793bcc70 (diff)
j6: defer mmsg byte classification
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ioworkload/scenario_retbytes.go59
1 files changed, 59 insertions, 0 deletions
diff --git a/cmd/ioworkload/scenario_retbytes.go b/cmd/ioworkload/scenario_retbytes.go
index fa0b677..d9b2984 100644
--- a/cmd/ioworkload/scenario_retbytes.go
+++ b/cmd/ioworkload/scenario_retbytes.go
@@ -12,14 +12,24 @@ import (
const (
sysProcessVMReadv = 310
sysProcessVMWritev = 311
+ sysSendmmsg = 307
retbytesPayloadLen = 18
)
+type mmsghdr struct {
+ hdr syscall.Msghdr
+ len uint32
+ _ uint32
+}
+
// retbytesPhaseA exercises byte-classified syscalls that use generic ret_event exits.
func retbytesPhaseA() error {
if err := retbytesSocketIO(); err != nil {
return err
}
+ if err := retbytesBatchSocketIO(); err != nil {
+ return err
+ }
if err := retbytesSendfile(); err != nil {
return err
}
@@ -68,6 +78,44 @@ func retbytesSocketIO() error {
return nil
}
+func retbytesBatchSocketIO() error {
+ fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
+ if err != nil {
+ return fmt.Errorf("batch socketpair: %w", err)
+ }
+ defer syscall.Close(fds[0])
+ defer syscall.Close(fds[1])
+
+ payloadA := []byte("batch-one")
+ payloadB := []byte("batch-two")
+ sendMsgs := mmsgSlice(payloadA, payloadB)
+ n, _, errno := syscall.Syscall6(sysSendmmsg, uintptr(fds[0]), uintptr(unsafe.Pointer(&sendMsgs[0])), uintptr(len(sendMsgs)), 0, 0, 0)
+ if errno != 0 {
+ return fmt.Errorf("sendmmsg: %w", errno)
+ }
+ if n != uintptr(len(sendMsgs)) {
+ return fmt.Errorf("sendmmsg sent %d messages, want %d", n, len(sendMsgs))
+ }
+ runtime.KeepAlive(payloadA)
+ runtime.KeepAlive(payloadB)
+ runtime.KeepAlive(sendMsgs)
+
+ recvA := make([]byte, len(payloadA))
+ recvB := make([]byte, len(payloadB))
+ recvMsgs := mmsgSlice(recvA, recvB)
+ n, _, errno = syscall.Syscall6(syscall.SYS_RECVMMSG, uintptr(fds[1]), uintptr(unsafe.Pointer(&recvMsgs[0])), uintptr(len(recvMsgs)), 0, 0, 0)
+ if errno != 0 {
+ return fmt.Errorf("recvmmsg: %w", errno)
+ }
+ if n != uintptr(len(recvMsgs)) {
+ return fmt.Errorf("recvmmsg received %d messages, want %d", n, len(recvMsgs))
+ }
+ runtime.KeepAlive(recvA)
+ runtime.KeepAlive(recvB)
+ runtime.KeepAlive(recvMsgs)
+ return nil
+}
+
func retbytesSendfile() error {
dir, cleanup, err := makeTempDir("retbytes-sendfile")
if err != nil {
@@ -202,6 +250,17 @@ func openPayloadFile(path string) (int, error) {
return fd, nil
}
+func mmsgSlice(bufs ...[]byte) []mmsghdr {
+ msgs := make([]mmsghdr, len(bufs))
+ iovs := make([]syscall.Iovec, len(bufs))
+ for i := range bufs {
+ iovs[i] = syscall.Iovec{Base: &bufs[i][0], Len: uint64(len(bufs[i]))}
+ msgs[i].hdr.Iov = &iovs[i]
+ msgs[i].hdr.Iovlen = 1
+ }
+ return msgs
+}
+
func processVMReadv(pid int, local, remote []byte) (int, error) {
localIov := syscall.Iovec{Base: &local[0], Len: uint64(len(local))}
remoteIov := syscall.Iovec{Base: &remote[0], Len: uint64(len(remote))}