diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-20 22:25:40 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-20 22:25:40 +0300 |
| commit | 7a9839917461b12c810329ccb8fd3c6de06902d2 (patch) | |
| tree | 7e68d52cec796d8a4d7b5110ba87cdce48a0fcb9 /cmd | |
| parent | 271af607921ceabc640271c475a66e45b9460d3f (diff) | |
d7: add POSIX mq syscall kind/classification and coverage
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/ioworkload/scenario_mq.go | 144 | ||||
| -rw-r--r-- | cmd/ioworkload/scenarios.go | 1 |
2 files changed, 145 insertions, 0 deletions
diff --git a/cmd/ioworkload/scenario_mq.go b/cmd/ioworkload/scenario_mq.go new file mode 100644 index 0000000..8b627a7 --- /dev/null +++ b/cmd/ioworkload/scenario_mq.go @@ -0,0 +1,144 @@ +package main + +import ( + "errors" + "fmt" + "os" + "syscall" + "time" + "unsafe" +) + +const ( + mqPayload = "ior-mq-payload" +) + +type mqAttr struct { + Flags int64 + Maxmsg int64 + Msgsize int64 + Curmsgs int64 + Pad [4]int64 +} + +func mqPosixBasic() error { + name := fmt.Sprintf("/ior-mq-%d-%d", os.Getpid(), time.Now().UnixNano()) + attr := mqAttr{Maxmsg: 8, Msgsize: 128} + mqd, err := mqOpen(name, syscall.O_CREAT|syscall.O_EXCL|syscall.O_RDWR, 0o600, &attr) + if err != nil { + return err + } + defer syscall.Close(mqd) //nolint:errcheck + defer mqUnlink(name) //nolint:errcheck + + if err := mqNotify(mqd); err != nil { + return err + } + if err := mqGetsetattr(mqd); err != nil { + return err + } + + deadline := time.Now().Add(2 * time.Second) + if err := mqTimedsend(mqd, []byte(mqPayload), 0, deadline); err != nil { + return err + } + + buf := make([]byte, 128) + n, err := mqTimedreceive(mqd, buf, deadline) + if err != nil { + return err + } + if got := string(buf[:n]); got != mqPayload { + return fmt.Errorf("mq_timedreceive payload = %q, want %q", got, mqPayload) + } + return nil +} + +func mqOpen(name string, flags int, mode uint32, attr *mqAttr) (int, error) { + ptr, err := syscall.BytePtrFromString(name) + if err != nil { + return 0, fmt.Errorf("queue name: %w", err) + } + fd, _, errno := syscall.Syscall6( + syscall.SYS_MQ_OPEN, + uintptr(unsafe.Pointer(ptr)), + uintptr(flags), + uintptr(mode), + uintptr(unsafe.Pointer(attr)), + 0, + 0, + ) + if errno != 0 { + return 0, fmt.Errorf("mq_open: %w", errno) + } + return int(fd), nil +} + +func mqUnlink(name string) error { + ptr, err := syscall.BytePtrFromString(name) + if err != nil { + return fmt.Errorf("queue name: %w", err) + } + _, _, errno := syscall.Syscall(syscall.SYS_MQ_UNLINK, uintptr(unsafe.Pointer(ptr)), 0, 0) + if errno != 0 { + return fmt.Errorf("mq_unlink: %w", errno) + } + return nil +} + +func mqNotify(mqd int) error { + _, _, errno := syscall.Syscall(syscall.SYS_MQ_NOTIFY, uintptr(mqd), 0, 0) + if errno == 0 || errors.Is(errno, syscall.EINVAL) { + return nil + } + return fmt.Errorf("mq_notify: %w", errno) +} + +func mqGetsetattr(mqd int) error { + var old mqAttr + _, _, errno := syscall.Syscall( + syscall.SYS_MQ_GETSETATTR, + uintptr(mqd), + 0, + uintptr(unsafe.Pointer(&old)), + ) + if errno != 0 { + return fmt.Errorf("mq_getsetattr: %w", errno) + } + return nil +} + +func mqTimedsend(mqd int, payload []byte, priority uint32, deadline time.Time) error { + ts := syscall.NsecToTimespec(deadline.UnixNano()) + _, _, errno := syscall.Syscall6( + syscall.SYS_MQ_TIMEDSEND, + uintptr(mqd), + uintptr(unsafe.Pointer(&payload[0])), + uintptr(len(payload)), + uintptr(priority), + uintptr(unsafe.Pointer(&ts)), + 0, + ) + if errno != 0 { + return fmt.Errorf("mq_timedsend: %w", errno) + } + return nil +} + +func mqTimedreceive(mqd int, buf []byte, deadline time.Time) (int, error) { + ts := syscall.NsecToTimespec(deadline.UnixNano()) + var prio uint32 + n, _, errno := syscall.Syscall6( + syscall.SYS_MQ_TIMEDRECEIVE, + uintptr(mqd), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(len(buf)), + uintptr(unsafe.Pointer(&prio)), + uintptr(unsafe.Pointer(&ts)), + 0, + ) + if errno != 0 { + return 0, fmt.Errorf("mq_timedreceive: %w", errno) + } + return int(n), nil +} diff --git a/cmd/ioworkload/scenarios.go b/cmd/ioworkload/scenarios.go index 79d4e6d..7ca5aa4 100644 --- a/cmd/ioworkload/scenarios.go +++ b/cmd/ioworkload/scenarios.go @@ -34,6 +34,7 @@ var scenarios = map[string]func() error{ "pipe2-basic": pipe2Basic, "eventfd-basic": eventfdBasic, "eventfd2-basic": eventfd2Basic, + "mq-posix-basic": mqPosixBasic, "mountfs-management": mountfsManagement, "polling-epoll": pollingEpoll, "sleep-syscalls": sleepSyscalls, |
