11.4Sad/* $NetBSD: latency2.c,v 1.4 2009/01/28 21:52:49 ad Exp $ */ 21.1Sad 31.1Sad/*- 41.4Sad * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 51.1Sad * All rights reserved. 61.1Sad * 71.1Sad * Redistribution and use in source and binary forms, with or without 81.1Sad * modification, are permitted provided that the following conditions 91.1Sad * are met: 101.1Sad * 1. Redistributions of source code must retain the above copyright 111.1Sad * notice, this list of conditions and the following disclaimer. 121.1Sad * 2. Redistributions in binary form must reproduce the above copyright 131.1Sad * notice, this list of conditions and the following disclaimer in the 141.1Sad * documentation and/or other materials provided with the distribution. 151.1Sad * 161.1Sad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Sad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Sad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Sad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Sad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Sad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Sad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Sad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Sad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Sad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Sad * POSSIBILITY OF SUCH DAMAGE. 271.1Sad */ 281.1Sad 291.1Sad/* 301.1Sad * Two threads are involved in the test. Every 100ms the first thread 311.1Sad * wakes the second. The time taken for the wakeup to arrive is 321.1Sad * measured. Ctrl-C ends the test. 331.1Sad */ 341.1Sad 351.1Sad#include <sys/mman.h> 361.1Sad#include <sys/resource.h> 371.1Sad 381.1Sad#include <pthread.h> 391.1Sad#include <stdio.h> 401.1Sad#include <stdlib.h> 411.1Sad#include <unistd.h> 421.1Sad#include <sched.h> 431.1Sad#include <limits.h> 441.1Sad#include <signal.h> 451.1Sad#include <err.h> 461.1Sad#include <lwp.h> 471.1Sad 481.1Sadpthread_barrier_t barrier; 491.1Sadstruct timespec start; 501.1Sadint done; 511.1Sadlong max = 0; 521.1Sadlong min = LONG_MAX; 531.1Sadlwpid_t lid; 541.1Sadlong sum; 551.1Sadlong samples; 561.1Sad 571.1Sadstatic void 581.1Sadsigint(int junk) 591.1Sad{ 601.1Sad 611.1Sad done = 1; 621.1Sad} 631.1Sad 641.1Sadstatic void * 651.1Sadreader(void *cookie) 661.1Sad{ 671.1Sad struct timespec end; 681.1Sad long val; 691.1Sad 701.1Sad lid = _lwp_self(); 711.1Sad 721.1Sad for (;;) { 731.1Sad (void)pthread_barrier_wait(&barrier); 741.1Sad while (_lwp_park(NULL, 0, &lid, NULL) != 0) { 751.1Sad /* nothing */ 761.1Sad } 771.1Sad clock_gettime(CLOCK_MONOTONIC, &end); 781.1Sad timespecsub(&end, &start, &end); 791.1Sad val = (long)end.tv_sec * 1000000000 + (long)end.tv_nsec; 801.1Sad printf("%ld\n", val); 811.1Sad if (val > max) 821.1Sad max = val; 831.1Sad if (val < min) 841.1Sad min = val; 851.1Sad sum += val; 861.1Sad samples++; 871.1Sad } 881.1Sad} 891.1Sad 901.1Sadint 911.1Sadmain(int argc, char *argv[]) 921.1Sad{ 931.1Sad static struct timespec delay = { 0, 100000000 }; /* 100ms */ 941.1Sad struct sched_param sp; 951.1Sad pthread_t pt; 961.1Sad cpuset_t *cs; 971.1Sad int cpuid; 981.1Sad 991.4Sad (void)setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 1001.4Sad 1011.1Sad if (geteuid() != 0) { 1021.1Sad errx(1, "run me as root"); 1031.1Sad } 1041.1Sad pthread_barrier_init(&barrier, NULL, 2); 1051.1Sad if (pthread_create(&pt, NULL, reader, NULL)) { 1061.1Sad errx(1, "pthread_create failed"); 1071.1Sad } 1081.1Sad if (mlockall(MCL_CURRENT | MCL_FUTURE)) { 1091.1Sad err(1, "mlockall"); 1101.1Sad } 1111.1Sad if (signal(SIGINT, sigint)) { 1121.1Sad err(1, "siginal"); 1131.1Sad } 1141.1Sad 1151.4Sad if (argc < 2) { 1161.4Sad cs = cpuset_create(); 1171.4Sad if (cs == NULL) { 1181.4Sad err(1, "cpuset_create"); 1191.4Sad } 1201.4Sad cpuset_zero(cs); 1211.4Sad cpuid = pthread_curcpu_np(); 1221.4Sad cpuset_set(cpuid, cs); 1231.4Sad if (_sched_setaffinity(0, 0, cpuset_size(cs), cs) < 0) { 1241.4Sad err(1, "_sched_setaffinity"); 1251.4Sad } 1261.4Sad cpuset_destroy(cs); 1271.1Sad } 1281.1Sad 1291.1Sad sp.sched_priority = sched_get_priority_max(SCHED_FIFO) - 2; 1301.1Sad if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) { 1311.1Sad errx(1, "pthread_setschedparam"); 1321.1Sad } 1331.1Sad sp.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; 1341.1Sad if (pthread_setschedparam(pt, SCHED_FIFO, &sp)) { 1351.1Sad errx(1, "pthread_setschedparam"); 1361.1Sad } 1371.1Sad 1381.1Sad do { 1391.1Sad (void)pthread_barrier_wait(&barrier); 1401.1Sad while (nanosleep(&delay, NULL) != 0) { 1411.1Sad /* nothing */ 1421.1Sad } 1431.1Sad clock_gettime(CLOCK_MONOTONIC, &start); 1441.1Sad if (_lwp_unpark(lid, &lid) != 0) { 1451.1Sad err(1, "_lwp_unpark"); 1461.1Sad } 1471.1Sad } while (!done); 1481.1Sad 1491.1Sad printf("\nmin=%ldns, max=%ldns, mean=%ldns\n", min, max, sum / samples); 1501.1Sad return 0; 1511.1Sad} 152