1 /* 2 * Copyright (c) International Business Machines Corp., 2005 3 * Copyright (c) Wipro Technologies Ltd, 2005. All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 * 17 * AUTHORS: 18 * Prashant P Yendigeri <prashant.yendigeri (at) wipro.com> 19 * Robbie Williamson <robbiew (at) us.ibm.com> 20 * 21 * DESCRIPTION 22 * This is a Phase I test for the pselect01(2) system call. 23 * It is intended to provide a limited exposure of the system call. 24 * 25 **********************************************************/ 26 27 #include <stdio.h> 28 #include <fcntl.h> 29 #include <sys/select.h> 30 #include <sys/time.h> 31 #include <sys/types.h> 32 #include <time.h> 33 #include <unistd.h> 34 #include <errno.h> 35 36 #include "tst_test.h" 37 #include "tst_timer.h" 38 39 struct tcase { 40 struct timespec tv; 41 unsigned int iterations; 42 }; 43 44 static unsigned int monotonic_resolution; 45 46 static struct tcase tcases[] = { 47 {{0, 1000000}, 500}, 48 {{0, 2000000}, 500}, 49 {{0, 10000000}, 300}, 50 {{0, 100000000}, 1}, 51 {{1, 0}, 1}, 52 }; 53 54 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 55 56 /* 57 * The threshold per one syscall is computed as a sum of: 58 * 59 * 250 us - accomodates for context switches, etc. 60 * 2*monotonic_resolution - accomodates for granurality of the CLOCK_MONOTONIC 61 * slack_per_scall - 0.1% of the sleep capped on 100ms 62 * which is slack allowed in kernel 63 * 64 * We also allow for outliners, i.e. add some number to the threshold in case 65 * that the number of iteration is small. For large enoung number of iterations 66 * outliners are averaged out. 67 */ 68 static int compute_threshold(long long requested_us, unsigned int iterations) 69 { 70 unsigned int slack_per_scall = MIN(100000, requested_us / 1000); 71 72 return (250 + 2 * monotonic_resolution + slack_per_scall) * iterations 73 + (iterations > 1 ? 0 : 1500); 74 } 75 76 static void verify_pselect(unsigned int n) 77 { 78 fd_set readfds; 79 struct timespec tv; 80 long long requested_us, slept_us = 0; 81 unsigned int i; 82 int threshold; 83 struct tcase *t = &tcases[n]; 84 85 tst_res(TINFO, "pselect() sleeping for %li secs %li nsec %i iterations", 86 t->tv.tv_sec, t->tv.tv_nsec, t->iterations); 87 88 for (i = 0; i < t->iterations; i++) { 89 long long elapsed_us; 90 91 FD_ZERO(&readfds); 92 FD_SET(0, &readfds); 93 94 tv = t->tv; 95 96 tst_timer_start(CLOCK_MONOTONIC); 97 pselect(0, &readfds, NULL, NULL, &tv, NULL); 98 tst_timer_stop(); 99 100 elapsed_us = tst_timer_elapsed_us(); 101 102 if (elapsed_us >= 10 * tst_timespec_to_us(t->tv) 103 && elapsed_us > 3 * monotonic_resolution) { 104 tst_res(TINFO, 105 "Found outliner took %lli us, expected %lli us", 106 elapsed_us, tst_timespec_to_us(t->tv)); 107 } 108 109 slept_us += elapsed_us; 110 } 111 112 requested_us = tst_timespec_to_us(t->tv) * t->iterations; 113 threshold = compute_threshold(tst_timespec_to_us(t->tv), t->iterations); 114 115 if (t->iterations > 1) { 116 tst_res(TINFO, "Mean sleep time %.2f us, expected %lli us, threshold %.2f", 117 1.00 * slept_us / t->iterations, 118 tst_timespec_to_us(t->tv), 1.00 * threshold / t->iterations); 119 } 120 121 if (slept_us < requested_us) { 122 tst_res(TFAIL, 123 "pselect() woken up too early %llius, expected %llius", 124 slept_us, requested_us); 125 return; 126 } 127 128 if (slept_us - requested_us > threshold) { 129 tst_res(TFAIL, 130 "pselect() slept for too long %llius, expected %llius, threshold %i", 131 slept_us, requested_us, threshold); 132 return; 133 } 134 135 tst_res(TPASS, "pselect() slept for %llius, requested %llius, treshold %i", 136 slept_us, requested_us, threshold); 137 } 138 139 static void setup(void) 140 { 141 struct timespec t; 142 143 clock_getres(CLOCK_MONOTONIC, &t); 144 145 tst_res(TINFO, "CLOCK_MONOTONIC resolution %li ns", (long)t.tv_nsec); 146 147 monotonic_resolution = t.tv_nsec / 1000; 148 } 149 150 static struct tst_test test = { 151 .tid = "pselect01", 152 .test = verify_pselect, 153 .setup = setup, 154 .tcnt = ARRAY_SIZE(tcases), 155 }; 156