18c2ecf20Sopenharmony_ci/* Measure mqueue timeout latency 28c2ecf20Sopenharmony_ci * by: john stultz (john.stultz@linaro.org) 38c2ecf20Sopenharmony_ci * (C) Copyright Linaro 2013 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Inspired with permission from example test by: 68c2ecf20Sopenharmony_ci * Romain Francoise <romain@orebokech.com> 78c2ecf20Sopenharmony_ci * Licensed under the GPLv2 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * To build: 108c2ecf20Sopenharmony_ci * $ gcc mqueue-lat.c -o mqueue-lat -lrt 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is free software: you can redistribute it and/or modify 138c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 148c2ecf20Sopenharmony_ci * the Free Software Foundation, either version 2 of the License, or 158c2ecf20Sopenharmony_ci * (at your option) any later version. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 188c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 198c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 208c2ecf20Sopenharmony_ci * GNU General Public License for more details. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <stdio.h> 248c2ecf20Sopenharmony_ci#include <stdlib.h> 258c2ecf20Sopenharmony_ci#include <time.h> 268c2ecf20Sopenharmony_ci#include <sys/time.h> 278c2ecf20Sopenharmony_ci#include <sys/timex.h> 288c2ecf20Sopenharmony_ci#include <string.h> 298c2ecf20Sopenharmony_ci#include <signal.h> 308c2ecf20Sopenharmony_ci#include <errno.h> 318c2ecf20Sopenharmony_ci#include <mqueue.h> 328c2ecf20Sopenharmony_ci#include "../kselftest.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define NSEC_PER_SEC 1000000000ULL 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define TARGET_TIMEOUT 100000000 /* 100ms in nanoseconds */ 378c2ecf20Sopenharmony_ci#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cilong long timespec_sub(struct timespec a, struct timespec b) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec; 458c2ecf20Sopenharmony_ci return ret; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistruct timespec timespec_add(struct timespec ts, unsigned long long ns) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci ts.tv_nsec += ns; 518c2ecf20Sopenharmony_ci while (ts.tv_nsec >= NSEC_PER_SEC) { 528c2ecf20Sopenharmony_ci ts.tv_nsec -= NSEC_PER_SEC; 538c2ecf20Sopenharmony_ci ts.tv_sec++; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci return ts; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ciint mqueue_lat_test(void) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci mqd_t q; 628c2ecf20Sopenharmony_ci struct mq_attr attr; 638c2ecf20Sopenharmony_ci struct timespec start, end, now, target; 648c2ecf20Sopenharmony_ci int i, count, ret; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci q = mq_open("/foo", O_CREAT | O_RDONLY, 0666, NULL); 678c2ecf20Sopenharmony_ci if (q < 0) { 688c2ecf20Sopenharmony_ci perror("mq_open"); 698c2ecf20Sopenharmony_ci return -1; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci mq_getattr(q, &attr); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci count = 100; 758c2ecf20Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &start); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 788c2ecf20Sopenharmony_ci char buf[attr.mq_msgsize]; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &now); 818c2ecf20Sopenharmony_ci target = now; 828c2ecf20Sopenharmony_ci target = timespec_add(now, TARGET_TIMEOUT); /* 100ms */ 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci ret = mq_timedreceive(q, buf, sizeof(buf), NULL, &target); 858c2ecf20Sopenharmony_ci if (ret < 0 && errno != ETIMEDOUT) { 868c2ecf20Sopenharmony_ci perror("mq_timedreceive"); 878c2ecf20Sopenharmony_ci return -1; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &end); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci mq_close(q); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if ((timespec_sub(start, end)/count) > TARGET_TIMEOUT + UNRESONABLE_LATENCY) 958c2ecf20Sopenharmony_ci return -1; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return 0; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci int ret; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci printf("Mqueue latency : "); 1058c2ecf20Sopenharmony_ci fflush(stdout); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci ret = mqueue_lat_test(); 1088c2ecf20Sopenharmony_ci if (ret < 0) { 1098c2ecf20Sopenharmony_ci printf("[FAILED]\n"); 1108c2ecf20Sopenharmony_ci return ksft_exit_fail(); 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci printf("[OK]\n"); 1138c2ecf20Sopenharmony_ci return ksft_exit_pass(); 1148c2ecf20Sopenharmony_ci} 115