summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-20 22:25:40 +0300
committerPaul Buetow <paul@buetow.org>2026-05-20 22:25:40 +0300
commit7a9839917461b12c810329ccb8fd3c6de06902d2 (patch)
tree7e68d52cec796d8a4d7b5110ba87cdce48a0fcb9 /cmd
parent271af607921ceabc640271c475a66e45b9460d3f (diff)
d7: add POSIX mq syscall kind/classification and coverage
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ioworkload/scenario_mq.go144
-rw-r--r--cmd/ioworkload/scenarios.go1
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,