Back to home page

OSCL-LXR

 
 

    


0001 /* Measure mqueue timeout latency
0002  *              by: john stultz (john.stultz@linaro.org)
0003  *      (C) Copyright Linaro 2013
0004  *
0005  *      Inspired with permission from example test by:
0006  *          Romain Francoise <romain@orebokech.com>
0007  *              Licensed under the GPLv2
0008  *
0009  *  To build:
0010  *  $ gcc mqueue-lat.c -o mqueue-lat -lrt
0011  *
0012  *   This program is free software: you can redistribute it and/or modify
0013  *   it under the terms of the GNU General Public License as published by
0014  *   the Free Software Foundation, either version 2 of the License, or
0015  *   (at your option) any later version.
0016  *
0017  *   This program is distributed in the hope that it will be useful,
0018  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0019  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0020  *   GNU General Public License for more details.
0021  */
0022 
0023 #include <stdio.h>
0024 #include <stdlib.h>
0025 #include <time.h>
0026 #include <sys/time.h>
0027 #include <sys/timex.h>
0028 #include <string.h>
0029 #include <signal.h>
0030 #include <errno.h>
0031 #include <mqueue.h>
0032 #include "../kselftest.h"
0033 
0034 #define NSEC_PER_SEC 1000000000ULL
0035 
0036 #define TARGET_TIMEOUT      100000000   /* 100ms in nanoseconds */
0037 #define UNRESONABLE_LATENCY 40000000    /* 40ms in nanosecs */
0038 
0039 
0040 long long timespec_sub(struct timespec a, struct timespec b)
0041 {
0042     long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
0043 
0044     ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
0045     return ret;
0046 }
0047 
0048 struct timespec timespec_add(struct timespec ts, unsigned long long ns)
0049 {
0050     ts.tv_nsec += ns;
0051     while (ts.tv_nsec >= NSEC_PER_SEC) {
0052         ts.tv_nsec -= NSEC_PER_SEC;
0053         ts.tv_sec++;
0054     }
0055     return ts;
0056 }
0057 
0058 int mqueue_lat_test(void)
0059 {
0060 
0061     mqd_t q;
0062     struct mq_attr attr;
0063     struct timespec start, end, now, target;
0064     int i, count, ret;
0065 
0066     q = mq_open("/foo", O_CREAT | O_RDONLY, 0666, NULL);
0067     if (q < 0) {
0068         perror("mq_open");
0069         return -1;
0070     }
0071     mq_getattr(q, &attr);
0072 
0073 
0074     count = 100;
0075     clock_gettime(CLOCK_MONOTONIC, &start);
0076 
0077     for (i = 0; i < count; i++) {
0078         char buf[attr.mq_msgsize];
0079 
0080         clock_gettime(CLOCK_REALTIME, &now);
0081         target = now;
0082         target = timespec_add(now, TARGET_TIMEOUT); /* 100ms */
0083 
0084         ret = mq_timedreceive(q, buf, sizeof(buf), NULL, &target);
0085         if (ret < 0 && errno != ETIMEDOUT) {
0086             perror("mq_timedreceive");
0087             return -1;
0088         }
0089     }
0090     clock_gettime(CLOCK_MONOTONIC, &end);
0091 
0092     mq_close(q);
0093 
0094     if ((timespec_sub(start, end)/count) > TARGET_TIMEOUT + UNRESONABLE_LATENCY)
0095         return -1;
0096 
0097     return 0;
0098 }
0099 
0100 int main(int argc, char **argv)
0101 {
0102     int ret;
0103 
0104     printf("Mqueue latency :                          ");
0105     fflush(stdout);
0106 
0107     ret = mqueue_lat_test();
0108     if (ret < 0) {
0109         printf("[FAILED]\n");
0110         return ksft_exit_fail();
0111     }
0112     printf("[OK]\n");
0113     return ksft_exit_pass();
0114 }