162306a36Sopenharmony_ci/* Measure mqueue timeout latency 262306a36Sopenharmony_ci * by: john stultz (john.stultz@linaro.org) 362306a36Sopenharmony_ci * (C) Copyright Linaro 2013 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Inspired with permission from example test by: 662306a36Sopenharmony_ci * Romain Francoise <romain@orebokech.com> 762306a36Sopenharmony_ci * Licensed under the GPLv2 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * To build: 1062306a36Sopenharmony_ci * $ gcc mqueue-lat.c -o mqueue-lat -lrt 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * This program is free software: you can redistribute it and/or modify 1362306a36Sopenharmony_ci * it under the terms of the GNU General Public License as published by 1462306a36Sopenharmony_ci * the Free Software Foundation, either version 2 of the License, or 1562306a36Sopenharmony_ci * (at your option) any later version. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful, 1862306a36Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 1962306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2062306a36Sopenharmony_ci * GNU General Public License for more details. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <stdio.h> 2462306a36Sopenharmony_ci#include <stdlib.h> 2562306a36Sopenharmony_ci#include <time.h> 2662306a36Sopenharmony_ci#include <sys/time.h> 2762306a36Sopenharmony_ci#include <sys/timex.h> 2862306a36Sopenharmony_ci#include <string.h> 2962306a36Sopenharmony_ci#include <signal.h> 3062306a36Sopenharmony_ci#include <errno.h> 3162306a36Sopenharmony_ci#include <mqueue.h> 3262306a36Sopenharmony_ci#include "../kselftest.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define NSEC_PER_SEC 1000000000ULL 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define TARGET_TIMEOUT 100000000 /* 100ms in nanoseconds */ 3762306a36Sopenharmony_ci#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cilong long timespec_sub(struct timespec a, struct timespec b) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec; 4562306a36Sopenharmony_ci return ret; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistruct timespec timespec_add(struct timespec ts, unsigned long long ns) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci ts.tv_nsec += ns; 5162306a36Sopenharmony_ci while (ts.tv_nsec >= NSEC_PER_SEC) { 5262306a36Sopenharmony_ci ts.tv_nsec -= NSEC_PER_SEC; 5362306a36Sopenharmony_ci ts.tv_sec++; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci return ts; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciint mqueue_lat_test(void) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci mqd_t q; 6262306a36Sopenharmony_ci struct mq_attr attr; 6362306a36Sopenharmony_ci struct timespec start, end, now, target; 6462306a36Sopenharmony_ci int i, count, ret; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci q = mq_open("/foo", O_CREAT | O_RDONLY, 0666, NULL); 6762306a36Sopenharmony_ci if (q < 0) { 6862306a36Sopenharmony_ci perror("mq_open"); 6962306a36Sopenharmony_ci return -1; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci mq_getattr(q, &attr); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci count = 100; 7562306a36Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &start); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (i = 0; i < count; i++) { 7862306a36Sopenharmony_ci char buf[attr.mq_msgsize]; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &now); 8162306a36Sopenharmony_ci target = now; 8262306a36Sopenharmony_ci target = timespec_add(now, TARGET_TIMEOUT); /* 100ms */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci ret = mq_timedreceive(q, buf, sizeof(buf), NULL, &target); 8562306a36Sopenharmony_ci if (ret < 0 && errno != ETIMEDOUT) { 8662306a36Sopenharmony_ci perror("mq_timedreceive"); 8762306a36Sopenharmony_ci return -1; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &end); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci mq_close(q); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if ((timespec_sub(start, end)/count) > TARGET_TIMEOUT + UNRESONABLE_LATENCY) 9562306a36Sopenharmony_ci return -1; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return 0; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciint main(int argc, char **argv) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci int ret; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci printf("Mqueue latency : "); 10562306a36Sopenharmony_ci fflush(stdout); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci ret = mqueue_lat_test(); 10862306a36Sopenharmony_ci if (ret < 0) { 10962306a36Sopenharmony_ci printf("[FAILED]\n"); 11062306a36Sopenharmony_ci return ksft_exit_fail(); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci printf("[OK]\n"); 11362306a36Sopenharmony_ci return ksft_exit_pass(); 11462306a36Sopenharmony_ci} 115