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