diff options
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/ioworkload/scenario_retbytes.go | 59 |
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))} |
