blob: 45f622c2af12b5e56cf4c059efc22b946c03de15 [file] [log] [blame]
robbiewbd002492002-12-04 22:01:15 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiewbd002492002-12-04 22:01:15 +000018 */
19
20/* Group Bull & IBM Corporation */
21/* 11/20/2002 Port to LTP robbiew@us.ibm.com */
22/* jacky.malcles@bull.net */
23/* IBM Corporation */
robbiew4b264472003-04-25 18:22:45 +000024/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
robbiewbd002492002-12-04 22:01:15 +000025
26/*
27 * fptest02.c -- Floating point test.
28 *
29 * This is similar to fptest1. Random values are used for some of the
30 * math in routine "gauss". The value "avgspd" computed in routine
31 * "term()" should come out to a known value. If this happens this
Garrett Cooper2c282152010-12-16 00:55:50 -080032 * program prints a "passed" message and exits 0, otherwise a "failed"
robbiewbd002492002-12-04 22:01:15 +000033 * message is printed and it exits with value 1.
34 *
35 */
36
37#include <stdio.h>
robbiewa70576c2003-03-04 18:33:41 +000038#include <errno.h>
robbiewbd002492002-12-04 22:01:15 +000039#include <math.h>
40#include <stdlib.h>
41#include <unistd.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <time.h>
46
robbiew4b264472003-04-25 18:22:45 +000047#define MAGIC 0.777807
48#define DIFF 0.001
49#define EVENTMX 256
robbiewbd002492002-12-04 22:01:15 +000050#define BIG 1.e50
51#define FALSE 0
52#define TRUE 1
53#define TRYCRIT 1
54#define ENTERCRIT 2
55#define LEAVECRIT 3
56#define ATBARRIER 4
57#define ENTERWORK 5
58#define LEAVEWORK 6
59#define NULLEVENT 999
60
61/** LTP Port **/
62#include "test.h"
robbiewbd002492002-12-04 22:01:15 +000063
Wanlong Gao354ebb42012-12-07 10:10:04 +080064char *TCID = "fptest02"; /* Test program identifier. */
65int TST_TOTAL = 1; /* Total number of test cases. */
robbiewbd002492002-12-04 22:01:15 +000066/**************/
67
robbiewbd002492002-12-04 22:01:15 +000068int init();
69int doevent();
70int term();
71int addevent();
72
73void gaussinit();
74double gauss();
75
76struct event {
robbiew4b264472003-04-25 18:22:45 +000077 int proc;
78 int type;
79 double time;
Wanlong Gao354ebb42012-12-07 10:10:04 +080080};
robbiewbd002492002-12-04 22:01:15 +000081
82struct event eventtab[EVENTMX];
83struct event rtrevent;
Wanlong Gao354ebb42012-12-07 10:10:04 +080084int waiting[EVENTMX]; /* array of waiting processors */
85int nwaiting; /* number of waiting processors */
86double sgtime; /* global clock */
87double lsttime; /* time used for editing */
88double dtc, dts, alpha; /* timing parameters */
89int nproc; /* number of processors */
90int barcnt; /* number of processors ATBARRIER */
91int ncycle; /* number of cycles completed */
92int ncycmax; /* number of cycles to run */
93int critfree; /* TRUE if critical section not occupied */
robbiewbd002492002-12-04 22:01:15 +000094
95struct event *nextevent();
96
Wanlong Gao354ebb42012-12-07 10:10:04 +080097int main(argc, argv)
robbiewbd002492002-12-04 22:01:15 +000098int argc;
99char *argv[];
100{
robbiew4b264472003-04-25 18:22:45 +0000101 struct event *ev;
robbiewbd002492002-12-04 22:01:15 +0000102
robbiew4b264472003-04-25 18:22:45 +0000103 nproc = 128;
104 ncycmax = 10;
105 dtc = 0.01;
106 dts = 0.0;
107 alpha = 0.1;
robbiewbd002492002-12-04 22:01:15 +0000108
robbiew4b264472003-04-25 18:22:45 +0000109 init();
robbiewbd002492002-12-04 22:01:15 +0000110
Wanlong Gao354ebb42012-12-07 10:10:04 +0800111 while ((ev = nextevent()) != NULL) {
robbiew4b264472003-04-25 18:22:45 +0000112 doevent(ev);
113 }
robbiewbd002492002-12-04 22:01:15 +0000114
robbiew4b264472003-04-25 18:22:45 +0000115 term();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800116 tst_resm(TPASS, "PASS");
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800117 tst_exit();
robbiewbd002492002-12-04 22:01:15 +0000118}
119
120/*
robbiew4b264472003-04-25 18:22:45 +0000121 initialize all processes to "entering work section"
robbiewbd002492002-12-04 22:01:15 +0000122*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123int init()
robbiewbd002492002-12-04 22:01:15 +0000124{
robbiew4b264472003-04-25 18:22:45 +0000125 int p;
126 double dtw, dtwsig;
robbiewbd002492002-12-04 22:01:15 +0000127
Wanlong Gao354ebb42012-12-07 10:10:04 +0800128 ncycle = 0;
129 sgtime = 0;
130 lsttime = 0;
131 barcnt = 0;
132 nwaiting = 0;
133 critfree = TRUE;
robbiewbd002492002-12-04 22:01:15 +0000134
Wanlong Gao354ebb42012-12-07 10:10:04 +0800135 dtw = 1. / nproc; /* mean process work time */
136 dtwsig = dtw * alpha; /* std deviation of work time */
137 gaussinit(dtw, dtwsig, time(0));
robbiewbd002492002-12-04 22:01:15 +0000138
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 for (p = 1; p <= nproc; p++) {
robbiew4b264472003-04-25 18:22:45 +0000140 eventtab[p].type = NULLEVENT;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 }
robbiewbd002492002-12-04 22:01:15 +0000142
Wanlong Gao354ebb42012-12-07 10:10:04 +0800143 for (p = 1; p <= nproc; p++) {
144 addevent(ENTERWORK, p, sgtime);
145 }
robbiewbd002492002-12-04 22:01:15 +0000146
Wanlong Gao354ebb42012-12-07 10:10:04 +0800147 return (0);
robbiewbd002492002-12-04 22:01:15 +0000148}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800149
robbiewbd002492002-12-04 22:01:15 +0000150/*
robbiew4b264472003-04-25 18:22:45 +0000151 print edit quantities
robbiewbd002492002-12-04 22:01:15 +0000152*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153int term()
robbiewbd002492002-12-04 22:01:15 +0000154{
robbiew4b264472003-04-25 18:22:45 +0000155 double avgspd;
156 double v;
robbiewbd002492002-12-04 22:01:15 +0000157
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158 avgspd = ncycle / sgtime;
robbiew4b264472003-04-25 18:22:45 +0000159 v = avgspd - MAGIC;
160 if (v < 0.0)
161 v *= -1.0;
162 if (v > DIFF) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800163 tst_resm(TFAIL, "FAIL");
robbiew4b264472003-04-25 18:22:45 +0000164 v = avgspd - MAGIC;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800165 tst_resm(TINFO, "avgspd = %.15f\n", avgspd);
166 tst_resm(TINFO, "expected %.15f\n", MAGIC);
167 tst_resm(TINFO, "diff = %.15f\n", v);
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800168 tst_exit();
robbiew4b264472003-04-25 18:22:45 +0000169 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800170 return (0);
robbiewbd002492002-12-04 22:01:15 +0000171}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800172
robbiewbd002492002-12-04 22:01:15 +0000173/*
robbiew4b264472003-04-25 18:22:45 +0000174 add an event to the event queue
robbiewbd002492002-12-04 22:01:15 +0000175*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800176int addevent(type, proc, t)
robbiewbd002492002-12-04 22:01:15 +0000177int type, proc;
178double t;
179{
robbiew4b264472003-04-25 18:22:45 +0000180 int i;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800181 int ok = FALSE;
robbiewbd002492002-12-04 22:01:15 +0000182
Wanlong Gao354ebb42012-12-07 10:10:04 +0800183 for (i = 1; i <= nproc; i++) {
184 if (eventtab[i].type == NULLEVENT) {
185 eventtab[i].type = type;
186 eventtab[i].proc = proc;
187 eventtab[i].time = t;
188 ok = TRUE;
robbiew4b264472003-04-25 18:22:45 +0000189 break;
robbiew4b264472003-04-25 18:22:45 +0000190 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800191 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800192 if (ok)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800193 return (0);
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800194 else
195 tst_brkm(TBROK, NULL, "No room for event");
robbiewbd002492002-12-04 22:01:15 +0000196
Wanlong Gao354ebb42012-12-07 10:10:04 +0800197 return (0);
robbiewbd002492002-12-04 22:01:15 +0000198}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800199
robbiewbd002492002-12-04 22:01:15 +0000200/*
robbiew4b264472003-04-25 18:22:45 +0000201 get earliest event in event queue
robbiewbd002492002-12-04 22:01:15 +0000202*/
203struct event *nextevent()
204{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800205 double mintime = BIG;
206 int imin = 0;
robbiew4b264472003-04-25 18:22:45 +0000207 int i;
robbiewbd002492002-12-04 22:01:15 +0000208
Wanlong Gao354ebb42012-12-07 10:10:04 +0800209 for (i = 1; i <= nproc; i++) {
210 if ((eventtab[i].type != NULLEVENT)
211 && (eventtab[i].time < mintime)) {
212 imin = i;
213 mintime = eventtab[i].time;
robbiew4b264472003-04-25 18:22:45 +0000214 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800215 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800216
robbiew4b264472003-04-25 18:22:45 +0000217 if (imin) {
218 rtrevent.type = eventtab[imin].type;
219 rtrevent.proc = eventtab[imin].proc;
220 rtrevent.time = eventtab[imin].time;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800221 eventtab[imin].type = NULLEVENT;
222 return (&rtrevent);
223 } else
Cyril Hrubiscf0d6262014-09-23 14:03:31 +0200224 return (NULL);
robbiewbd002492002-12-04 22:01:15 +0000225}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800226
robbiewbd002492002-12-04 22:01:15 +0000227/*
robbiew4b264472003-04-25 18:22:45 +0000228 add a processor to the waiting queue
robbiewbd002492002-12-04 22:01:15 +0000229*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800230int addwaiting(p)
robbiewbd002492002-12-04 22:01:15 +0000231int p;
232{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800233 waiting[++nwaiting] = p;
234 return (0);
robbiewbd002492002-12-04 22:01:15 +0000235}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800236
robbiewbd002492002-12-04 22:01:15 +0000237/*
robbiew4b264472003-04-25 18:22:45 +0000238 remove the next processor from the waiting queue
robbiewbd002492002-12-04 22:01:15 +0000239*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800240int getwaiting()
robbiewbd002492002-12-04 22:01:15 +0000241{
robbiew4b264472003-04-25 18:22:45 +0000242 if (nwaiting)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800243 return (waiting[nwaiting--]);
robbiew4b264472003-04-25 18:22:45 +0000244 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800245 return (0);
robbiewbd002492002-12-04 22:01:15 +0000246}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800247
robbiewbd002492002-12-04 22:01:15 +0000248double dtcrit()
249{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800250 return (dtc);
robbiewbd002492002-12-04 22:01:15 +0000251}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800252
robbiewbd002492002-12-04 22:01:15 +0000253double dtspinoff()
254{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800255 return (dts);
robbiewbd002492002-12-04 22:01:15 +0000256}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800257
robbiewbd002492002-12-04 22:01:15 +0000258double dtwork()
259{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800260 return (gauss());
robbiewbd002492002-12-04 22:01:15 +0000261}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800262
robbiewbd002492002-12-04 22:01:15 +0000263/*
robbiew4b264472003-04-25 18:22:45 +0000264 take the action prescribed by 'ev', update the clock, and
265 generate any subsequent events
robbiewbd002492002-12-04 22:01:15 +0000266*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800267int doevent(ev)
robbiewbd002492002-12-04 22:01:15 +0000268struct event *ev;
269{
robbiew4b264472003-04-25 18:22:45 +0000270 double nxttime;
271 int i, p, proc;
robbiewbd002492002-12-04 22:01:15 +0000272
robbiew4b264472003-04-25 18:22:45 +0000273 sgtime = ev->time;
274 proc = ev->proc;
robbiewbd002492002-12-04 22:01:15 +0000275
robbiew4b264472003-04-25 18:22:45 +0000276 switch (ev->type) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800277 case TRYCRIT:
278 if (critfree == TRUE)
279 addevent(ENTERCRIT, proc, sgtime);
280 else
281 addwaiting(proc);
282 break;
283 case ENTERCRIT:
284 critfree = FALSE;
285 nxttime = sgtime + dtcrit();
286 addevent(LEAVECRIT, proc, nxttime);
287 break;
288 case LEAVECRIT:
289 critfree = TRUE;
290 addevent(ATBARRIER, proc, sgtime);
291 if ((p = getwaiting()) != 0) {
292 nxttime = sgtime;
293 addevent(ENTERCRIT, p, nxttime);
robbiew4b264472003-04-25 18:22:45 +0000294 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800295 break;
296 case ATBARRIER:
297 barcnt++;
298 if (barcnt == nproc) {
299 nxttime = sgtime;
300 for (i = 1; i <= nproc; i++) {
301 nxttime += dtspinoff();
302 addevent(ENTERWORK, i, nxttime);
303 }
304 barcnt = 0;
305 ncycle++;
306 }
307 break;
308 case ENTERWORK:
309 nxttime = sgtime + dtwork();
310 if (ncycle < ncycmax)
311 addevent(LEAVEWORK, proc, nxttime);
312 break;
313 case LEAVEWORK:
314 addevent(TRYCRIT, proc, sgtime);
315 break;
316 default:
317 tst_brkm(TBROK, NULL, "Illegal event");
318 break;
319 }
320 return (0);
robbiewbd002492002-12-04 22:01:15 +0000321}
322
Wanlong Gao354ebb42012-12-07 10:10:04 +0800323static int alternator = 1;
robbiewbd002492002-12-04 22:01:15 +0000324static double mean;
325static double stdev;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800326static double u1, u2;
robbiewbd002492002-12-04 22:01:15 +0000327static double twopi;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800328static double rnorm = 2147483647;
robbiewbd002492002-12-04 22:01:15 +0000329
Wanlong Gao354ebb42012-12-07 10:10:04 +0800330void gaussinit(m, s, seed)
331double m, s;
robbiewbd002492002-12-04 22:01:15 +0000332int seed;
333{
robbiew4b264472003-04-25 18:22:45 +0000334 srand48(seed);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800335 mean = m;
336 stdev = s;
337 twopi = 2. * acos((double)-1.0);
robbiew4b264472003-04-25 18:22:45 +0000338 return;
robbiewbd002492002-12-04 22:01:15 +0000339}
Garrett Cooper2c282152010-12-16 00:55:50 -0800340
robbiewbd002492002-12-04 22:01:15 +0000341double gauss()
342{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800343 double x1, x2;
robbiewbd002492002-12-04 22:01:15 +0000344
Wanlong Gao354ebb42012-12-07 10:10:04 +0800345 if (alternator == 1) {
robbiew4b264472003-04-25 18:22:45 +0000346 alternator = -1;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800347 u1 = lrand48() / rnorm;
348 u2 = lrand48() / rnorm;
349 x1 = sqrt(-2.0 * log(u1)) * cos(twopi * u2);
350 return (mean + stdev * x1);
351 } else {
robbiew4b264472003-04-25 18:22:45 +0000352 alternator = 1;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800353 x2 = sqrt(-2.0 * log(u1)) * sin(twopi * u2);
354 return (mean + stdev * x2);
355 }
Chris Dearmanec6edca2012-10-17 19:54:01 -0700356}