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@wipro.com>
19 * Robbie Williamson <robbiew@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 #include <stdint.h>
36
37 #include "test.h"
38 #include "safe_macros.h"
39
40 static void setup(void);
41 static void cleanup(void);
42
43 TCID_DEFINE(pselect01);
44 int TST_TOTAL = 9;
45
46 #define FILENAME "pselect01_test"
47 #define LOOP_COUNT 4
48
49 static int fd;
50
pselect_verify(void)51 static void pselect_verify(void)
52 {
53 fd_set readfds;
54 struct timespec tv, tv_start, tv_end;
55 long real_nsec, total_nsec;
56 double real_sec;
57 int total_sec, retval;
58 FD_ZERO(&readfds);
59 FD_SET(fd, &readfds);
60 tv.tv_sec = 0;
61 tv.tv_nsec = 0;
62
63 retval = pselect(fd, &readfds, 0, 0, &tv, NULL);
64 if (retval >= 0)
65 tst_resm(TPASS, "pselect() succeeded retval=%i", retval);
66 else
67 tst_resm(TFAIL | TERRNO, "pselect() failed unexpectedly");
68
69 for (total_sec = 1; total_sec <= LOOP_COUNT; total_sec++) {
70 FD_ZERO(&readfds);
71 FD_SET(0, &readfds);
72
73 tv.tv_sec = total_sec;
74 tv.tv_nsec = 0;
75
76 tst_resm(TINFO,
77 "Testing basic pselect sanity,Sleeping for %jd secs",
78 (intmax_t) tv.tv_sec);
79 clock_gettime(CLOCK_MONOTONIC, &tv_start);
80 pselect(0, &readfds, NULL, NULL, &tv, NULL);
81 clock_gettime(CLOCK_MONOTONIC, &tv_end);
82
83 real_sec = (0.5 + (tv_end.tv_sec - tv_start.tv_sec +
84 1e-9 * (tv_end.tv_nsec - tv_start.tv_nsec)));
85 if (abs(real_sec - total_sec) < 0.2 * total_sec)
86 tst_resm(TPASS, "Sleep time was correct "
87 "(%lf/%d < 20 %%)", real_sec, total_sec);
88 else
89 tst_resm(TFAIL, "Sleep time was incorrect (%d/%lf "
90 ">= 20%%)", total_sec, real_sec);
91 }
92
93 #ifdef DEBUG
94 tst_resm(TINFO, "Now checking nsec sleep precision");
95 #endif
96 for (total_nsec = 1e8; total_nsec <= LOOP_COUNT * 1e8;
97 total_nsec += 1e8) {
98 FD_ZERO(&readfds);
99 FD_SET(0, &readfds);
100
101 tv.tv_sec = 0;
102 tv.tv_nsec = total_nsec;
103
104 tst_resm(TINFO,
105 "Testing basic pselect sanity,Sleeping for %ld nano secs",
106 tv.tv_nsec);
107 clock_gettime(CLOCK_MONOTONIC, &tv_start);
108 pselect(0, &readfds, NULL, NULL, &tv, NULL);
109 clock_gettime(CLOCK_MONOTONIC, &tv_end);
110
111 real_nsec = (tv_end.tv_sec - tv_start.tv_sec) * 1e9 +
112 tv_end.tv_nsec - tv_start.tv_nsec;
113
114 /* allow 20% error */
115 if (abs(real_nsec - tv.tv_nsec) < 0.2 * total_nsec) {
116 tst_resm(TPASS, "Sleep time was correct");
117 } else {
118 tst_resm(TWARN,
119 "This test could fail if the system was under load");
120 tst_resm(TWARN,
121 "due to the limitation of the way it calculates the");
122 tst_resm(TWARN, "system call execution time.");
123 tst_resm(TFAIL,
124 "Sleep time was incorrect:%ld nsec vs expected %ld nsec",
125 real_nsec, total_nsec);
126 }
127 }
128 }
129
main(int argc,char * argv[])130 int main(int argc, char *argv[])
131 {
132 int lc;
133
134 tst_parse_opts(argc, argv, NULL, NULL);
135
136 setup();
137
138 for (lc = 0; TEST_LOOPING(lc); lc++) {
139 tst_count = 0;
140 pselect_verify();
141 }
142
143 cleanup();
144 tst_exit();
145 }
146
setup(void)147 static void setup(void)
148 {
149 tst_sig(NOFORK, DEF_HANDLER, cleanup);
150 tst_timer_check(CLOCK_MONOTONIC);
151 tst_tmpdir();
152
153 fd = SAFE_OPEN(cleanup, FILENAME, O_CREAT | O_RDWR, 0777);
154
155 TEST_PAUSE;
156 }
157
cleanup(void)158 static void cleanup(void)
159 {
160 if (fd && close(fd))
161 tst_resm(TWARN | TERRNO, "close() failed");
162
163 tst_rmdir();
164 }
165