1/* $NetBSD: latency2.c,v 1.3 2008/06/16 01:41:21 rmind Exp $ */ 2 3/*- 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * Two threads are involved in the test. Every 100ms the first thread 31 * wakes the second. The time taken for the wakeup to arrive is 32 * measured. Ctrl-C ends the test. 33 */ 34 35#include <sys/mman.h> 36#include <sys/resource.h> 37 38#include <pthread.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <unistd.h> 42#include <sched.h> 43#include <limits.h> 44#include <signal.h> 45#include <err.h> 46#include <lwp.h> 47 48pthread_barrier_t barrier; 49struct timespec start; 50int done; 51long max = 0; 52long min = LONG_MAX; 53lwpid_t lid; 54long sum; 55long samples; 56 57static void 58sigint(int junk) 59{ 60 61 done = 1; 62} 63 64static void * 65reader(void *cookie) 66{ 67 struct timespec end; 68 long val; 69 70 lid = _lwp_self(); 71 72 for (;;) { 73 (void)pthread_barrier_wait(&barrier); 74 while (_lwp_park(NULL, 0, &lid, NULL) != 0) { 75 /* nothing */ 76 } 77 clock_gettime(CLOCK_MONOTONIC, &end); 78 timespecsub(&end, &start, &end); 79 val = (long)end.tv_sec * 1000000000 + (long)end.tv_nsec; 80 printf("%ld\n", val); 81 if (val > max) 82 max = val; 83 if (val < min) 84 min = val; 85 sum += val; 86 samples++; 87 } 88} 89 90int 91main(int argc, char *argv[]) 92{ 93 static struct timespec delay = { 0, 100000000 }; /* 100ms */ 94 struct sched_param sp; 95 pthread_t pt; 96 cpuset_t *cs; 97 int cpuid; 98 99 (void)setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 100 101 if (geteuid() != 0) { 102 errx(1, "run me as root"); 103 } 104 pthread_barrier_init(&barrier, NULL, 2); 105 if (pthread_create(&pt, NULL, reader, NULL)) { 106 errx(1, "pthread_create failed"); 107 } 108 if (mlockall(MCL_CURRENT | MCL_FUTURE)) { 109 err(1, "mlockall"); 110 } 111 if (signal(SIGINT, sigint)) { 112 err(1, "siginal"); 113 } 114 115 if (argc < 2) { 116 cs = cpuset_create(); 117 if (cs == NULL) { 118 err(1, "cpuset_create"); 119 } 120 cpuset_zero(cs); 121 cpuid = pthread_curcpu_np(); 122 cpuset_set(cpuid, cs); 123 if (_sched_setaffinity(0, 0, cpuset_size(cs), cs) < 0) { 124 err(1, "_sched_setaffinity"); 125 } 126 cpuset_destroy(cs); 127 } 128 129 sp.sched_priority = sched_get_priority_max(SCHED_FIFO) - 2; 130 if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) { 131 errx(1, "pthread_setschedparam"); 132 } 133 sp.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; 134 if (pthread_setschedparam(pt, SCHED_FIFO, &sp)) { 135 errx(1, "pthread_setschedparam"); 136 } 137 138 do { 139 (void)pthread_barrier_wait(&barrier); 140 while (nanosleep(&delay, NULL) != 0) { 141 /* nothing */ 142 } 143 clock_gettime(CLOCK_MONOTONIC, &start); 144 if (_lwp_unpark(lid, &lid) != 0) { 145 err(1, "_lwp_unpark"); 146 } 147 } while (!done); 148 149 printf("\nmin=%ldns, max=%ldns, mean=%ldns\n", min, max, sum / samples); 150 return 0; 151} 152