^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* Measure mqueue timeout latency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * by: john stultz (john.stultz@linaro.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) Copyright Linaro 2013
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Inspired with permission from example test by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Romain Francoise <romain@orebokech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Licensed under the GPLv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * To build:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * $ gcc mqueue-lat.c -o mqueue-lat -lrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This program is free software: you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * the Free Software Foundation, either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sys/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <mqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "../kselftest.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define NSEC_PER_SEC 1000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TARGET_TIMEOUT 100000000 /* 100ms in nanoseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) long long timespec_sub(struct timespec a, struct timespec b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct timespec timespec_add(struct timespec ts, unsigned long long ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ts.tv_nsec += ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) while (ts.tv_nsec >= NSEC_PER_SEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ts.tv_nsec -= NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ts.tv_sec++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int mqueue_lat_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) mqd_t q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct mq_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct timespec start, end, now, target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int i, count, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) q = mq_open("/foo", O_CREAT | O_RDONLY, 0666, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (q < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) perror("mq_open");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mq_getattr(q, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) count = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) clock_gettime(CLOCK_MONOTONIC, &start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) char buf[attr.mq_msgsize];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) clock_gettime(CLOCK_REALTIME, &now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) target = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) target = timespec_add(now, TARGET_TIMEOUT); /* 100ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ret = mq_timedreceive(q, buf, sizeof(buf), NULL, &target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (ret < 0 && errno != ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) perror("mq_timedreceive");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) clock_gettime(CLOCK_MONOTONIC, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mq_close(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if ((timespec_sub(start, end)/count) > TARGET_TIMEOUT + UNRESONABLE_LATENCY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) printf("Mqueue latency : ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ret = mqueue_lat_test();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) printf("[FAILED]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) printf("[OK]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return ksft_exit_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }