1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2002 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* Group Bull & IBM Corporation */ 21f08c3bdfSopenharmony_ci/* 11/20/2002 Port to LTP robbiew@us.ibm.com */ 22f08c3bdfSopenharmony_ci/* jacky.malcles@bull.net */ 23f08c3bdfSopenharmony_ci/* IBM Corporation */ 24f08c3bdfSopenharmony_ci/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */ 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci/* 27f08c3bdfSopenharmony_ci * fptest01.c -- Floating point test. 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * It is taken from a benchmark called "barsim". 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * If the computation arrives at the expected values this routine 32f08c3bdfSopenharmony_ci * prints a "passed" message and exits 0. If an incorrect value is 33f08c3bdfSopenharmony_ci * computed a "failed" message is printed and the routine exits 1. 34f08c3bdfSopenharmony_ci */ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#include <stdio.h> 37f08c3bdfSopenharmony_ci#include <errno.h> 38f08c3bdfSopenharmony_ci#include <math.h> 39f08c3bdfSopenharmony_ci#include <stdlib.h> 40f08c3bdfSopenharmony_ci#include <unistd.h> 41f08c3bdfSopenharmony_ci#include <sys/types.h> 42f08c3bdfSopenharmony_ci#include <sys/stat.h> 43f08c3bdfSopenharmony_ci#include <fcntl.h> 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci#define MAGIC1 1632.796126 46f08c3bdfSopenharmony_ci#define DIFF1 0.001 47f08c3bdfSopenharmony_ci#define MAGIC2 0.777807 48f08c3bdfSopenharmony_ci#define DIFF2 0.001 49f08c3bdfSopenharmony_ci#define EVENTMX 256 50f08c3bdfSopenharmony_ci#define BIG 1.e50 51f08c3bdfSopenharmony_ci#define FALSE 0 52f08c3bdfSopenharmony_ci#define TRUE 1 53f08c3bdfSopenharmony_ci#define TRYCRIT 1 54f08c3bdfSopenharmony_ci#define ENTERCRIT 2 55f08c3bdfSopenharmony_ci#define LEAVECRIT 3 56f08c3bdfSopenharmony_ci#define ATBARRIER 4 57f08c3bdfSopenharmony_ci#define ENTERWORK 5 58f08c3bdfSopenharmony_ci#define LEAVEWORK 6 59f08c3bdfSopenharmony_ci#define NULLEVENT 999 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci/** LTP Port **/ 62f08c3bdfSopenharmony_ci#include "test.h" 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_cichar *TCID = "fptest01"; /* Test program identifier. */ 65f08c3bdfSopenharmony_ciint TST_TOTAL = 1; /* Total number of test cases. */ 66f08c3bdfSopenharmony_ci/**************/ 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_cistruct event { 69f08c3bdfSopenharmony_ci int proc; 70f08c3bdfSopenharmony_ci int type; 71f08c3bdfSopenharmony_ci double time; 72f08c3bdfSopenharmony_ci}; 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_cistatic int init(void); 75f08c3bdfSopenharmony_cistatic int doevent(struct event *); 76f08c3bdfSopenharmony_cistatic int term(void); 77f08c3bdfSopenharmony_cistatic int addevent(int, int, double); 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_cistatic void gaussinit(double, double); 80f08c3bdfSopenharmony_cistatic double gauss(void); 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_cistruct event eventtab[EVENTMX]; 83f08c3bdfSopenharmony_cistruct event rtrevent; 84f08c3bdfSopenharmony_ciint waiting[EVENTMX]; /* array of waiting processors */ 85f08c3bdfSopenharmony_ciint nwaiting; /* number of waiting processors */ 86f08c3bdfSopenharmony_cidouble global_time; /* global clock */ 87f08c3bdfSopenharmony_cidouble lsttime; /* time used for editing */ 88f08c3bdfSopenharmony_cidouble dtc, dts, alpha; /* timing parameters */ 89f08c3bdfSopenharmony_ciint nproc; /* number of processors */ 90f08c3bdfSopenharmony_ciint barcnt; /* number of processors ATBARRIER */ 91f08c3bdfSopenharmony_ciint ncycle; /* number of cycles completed */ 92f08c3bdfSopenharmony_ciint ncycmax; /* number of cycles to run */ 93f08c3bdfSopenharmony_ciint critfree; /* TRUE if critical section not occupied */ 94f08c3bdfSopenharmony_ciint gcount; /* # calls to gauss */ 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic struct event *nextevent(void); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ciint main(void) 99f08c3bdfSopenharmony_ci{ 100f08c3bdfSopenharmony_ci struct event *ev; 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci nproc = 128; 103f08c3bdfSopenharmony_ci ncycmax = 10; 104f08c3bdfSopenharmony_ci dtc = 0.01; 105f08c3bdfSopenharmony_ci dts = 0.0; 106f08c3bdfSopenharmony_ci alpha = 0.1; 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci init(); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci while ((ev = nextevent()) != NULL) { 111f08c3bdfSopenharmony_ci doevent(ev); 112f08c3bdfSopenharmony_ci } 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci term(); 115f08c3bdfSopenharmony_ci tst_resm(TPASS, "PASS"); 116f08c3bdfSopenharmony_ci tst_exit(); 117f08c3bdfSopenharmony_ci} 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci/* 120f08c3bdfSopenharmony_ci initialize all processes to "entering work section" 121f08c3bdfSopenharmony_ci*/ 122f08c3bdfSopenharmony_cistatic int init(void) 123f08c3bdfSopenharmony_ci{ 124f08c3bdfSopenharmony_ci int p; 125f08c3bdfSopenharmony_ci double dtw, dtwsig; 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci ncycle = 0; 128f08c3bdfSopenharmony_ci global_time = 0; 129f08c3bdfSopenharmony_ci lsttime = 0; 130f08c3bdfSopenharmony_ci barcnt = 0; 131f08c3bdfSopenharmony_ci nwaiting = 0; 132f08c3bdfSopenharmony_ci critfree = TRUE; 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci dtw = 1. / nproc; /* mean process work time */ 135f08c3bdfSopenharmony_ci dtwsig = dtw * alpha; /* std deviation of work time */ 136f08c3bdfSopenharmony_ci gaussinit(dtw, dtwsig); 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci for (p = 1; p <= nproc; p++) { 139f08c3bdfSopenharmony_ci eventtab[p].type = NULLEVENT; 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci for (p = 1; p <= nproc; p++) { 143f08c3bdfSopenharmony_ci addevent(ENTERWORK, p, global_time); 144f08c3bdfSopenharmony_ci } 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci return (0); 147f08c3bdfSopenharmony_ci} 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci/* 150f08c3bdfSopenharmony_ci print edit quantities 151f08c3bdfSopenharmony_ci*/ 152f08c3bdfSopenharmony_cistatic int term(void) 153f08c3bdfSopenharmony_ci{ 154f08c3bdfSopenharmony_ci double avgspd; 155f08c3bdfSopenharmony_ci double t_total = 0.0; 156f08c3bdfSopenharmony_ci double v; 157f08c3bdfSopenharmony_ci int i; 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci for (i = 0; i < nproc; i++) 160f08c3bdfSopenharmony_ci t_total += eventtab[i].time; 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci avgspd = ncycle / global_time; 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci v = t_total - MAGIC1; 165f08c3bdfSopenharmony_ci if (v < 0.0) 166f08c3bdfSopenharmony_ci v *= -1.0; 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci if (v > DIFF1) { 169f08c3bdfSopenharmony_ci tst_resm(TFAIL, "FAIL"); 170f08c3bdfSopenharmony_ci v = t_total - MAGIC1; 171f08c3bdfSopenharmony_ci tst_resm(TINFO, "t_total = %.15f\n", t_total); 172f08c3bdfSopenharmony_ci tst_resm(TINFO, "expected %.15f\n", MAGIC1); 173f08c3bdfSopenharmony_ci tst_resm(TINFO, "diff = %.15f\n", v); 174f08c3bdfSopenharmony_ci tst_exit(); 175f08c3bdfSopenharmony_ci } 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci v = avgspd - MAGIC2; 178f08c3bdfSopenharmony_ci if (v < 0.0) 179f08c3bdfSopenharmony_ci v *= -1.0; 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci if (v > DIFF2) { 182f08c3bdfSopenharmony_ci tst_resm(TFAIL, "FAIL"); 183f08c3bdfSopenharmony_ci v = avgspd - MAGIC2; 184f08c3bdfSopenharmony_ci tst_resm(TINFO, "avgspd = %.15f\n", avgspd); 185f08c3bdfSopenharmony_ci tst_resm(TINFO, "expected %.15f\n", MAGIC2); 186f08c3bdfSopenharmony_ci tst_resm(TINFO, "diff = %.15f\n", v); 187f08c3bdfSopenharmony_ci tst_exit(); 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci return (0); 190f08c3bdfSopenharmony_ci} 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci/* 193f08c3bdfSopenharmony_ci add an event to the event queue 194f08c3bdfSopenharmony_ci*/ 195f08c3bdfSopenharmony_cistatic int addevent(int type, int proc, double t) 196f08c3bdfSopenharmony_ci{ 197f08c3bdfSopenharmony_ci int i; 198f08c3bdfSopenharmony_ci int ok = FALSE; 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci for (i = 1; i <= nproc; i++) { 201f08c3bdfSopenharmony_ci if (eventtab[i].type == NULLEVENT) { 202f08c3bdfSopenharmony_ci eventtab[i].type = type; 203f08c3bdfSopenharmony_ci eventtab[i].proc = proc; 204f08c3bdfSopenharmony_ci eventtab[i].time = t; 205f08c3bdfSopenharmony_ci ok = TRUE; 206f08c3bdfSopenharmony_ci break; 207f08c3bdfSopenharmony_ci } 208f08c3bdfSopenharmony_ci } 209f08c3bdfSopenharmony_ci if (ok) 210f08c3bdfSopenharmony_ci return (0); 211f08c3bdfSopenharmony_ci else 212f08c3bdfSopenharmony_ci tst_brkm(TBROK, NULL, "No room for event"); 213f08c3bdfSopenharmony_ci return (0); 214f08c3bdfSopenharmony_ci} 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci/* 217f08c3bdfSopenharmony_ci get earliest event in event queue 218f08c3bdfSopenharmony_ci*/ 219f08c3bdfSopenharmony_cistatic struct event *nextevent(void) 220f08c3bdfSopenharmony_ci{ 221f08c3bdfSopenharmony_ci double mintime = BIG; 222f08c3bdfSopenharmony_ci int imin = 0; 223f08c3bdfSopenharmony_ci int i; 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci for (i = 1; i <= nproc; i++) { 226f08c3bdfSopenharmony_ci if (eventtab[i].type != NULLEVENT && eventtab[i].time < mintime) { 227f08c3bdfSopenharmony_ci imin = i; 228f08c3bdfSopenharmony_ci mintime = eventtab[i].time; 229f08c3bdfSopenharmony_ci } 230f08c3bdfSopenharmony_ci } 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_ci if (imin) { 233f08c3bdfSopenharmony_ci rtrevent.type = eventtab[imin].type; 234f08c3bdfSopenharmony_ci rtrevent.proc = eventtab[imin].proc; 235f08c3bdfSopenharmony_ci rtrevent.time = eventtab[imin].time; 236f08c3bdfSopenharmony_ci eventtab[imin].type = NULLEVENT; 237f08c3bdfSopenharmony_ci return (&rtrevent); 238f08c3bdfSopenharmony_ci } else 239f08c3bdfSopenharmony_ci return (NULL); 240f08c3bdfSopenharmony_ci} 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_ci/* 243f08c3bdfSopenharmony_ci add a processor to the waiting queue 244f08c3bdfSopenharmony_ci*/ 245f08c3bdfSopenharmony_cistatic int addwaiting(int p) 246f08c3bdfSopenharmony_ci{ 247f08c3bdfSopenharmony_ci waiting[++nwaiting] = p; 248f08c3bdfSopenharmony_ci return (0); 249f08c3bdfSopenharmony_ci} 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci/* 252f08c3bdfSopenharmony_ci remove the next processor from the waiting queue 253f08c3bdfSopenharmony_ci*/ 254f08c3bdfSopenharmony_cistatic int getwaiting(void) 255f08c3bdfSopenharmony_ci{ 256f08c3bdfSopenharmony_ci if (nwaiting) 257f08c3bdfSopenharmony_ci return (waiting[nwaiting--]); 258f08c3bdfSopenharmony_ci else 259f08c3bdfSopenharmony_ci return (0); 260f08c3bdfSopenharmony_ci} 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_cistatic double dtcrit(void) 263f08c3bdfSopenharmony_ci{ 264f08c3bdfSopenharmony_ci return (dtc); 265f08c3bdfSopenharmony_ci} 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_cistatic double dtspinoff(void) 268f08c3bdfSopenharmony_ci{ 269f08c3bdfSopenharmony_ci return (dts); 270f08c3bdfSopenharmony_ci} 271f08c3bdfSopenharmony_ci 272f08c3bdfSopenharmony_cistatic double dtwork(void) 273f08c3bdfSopenharmony_ci{ 274f08c3bdfSopenharmony_ci return (gauss()); 275f08c3bdfSopenharmony_ci} 276f08c3bdfSopenharmony_ci 277f08c3bdfSopenharmony_ci/* 278f08c3bdfSopenharmony_ci take the action prescribed by 'ev', update the clock, and 279f08c3bdfSopenharmony_ci generate any subsequent events 280f08c3bdfSopenharmony_ci*/ 281f08c3bdfSopenharmony_cistatic int doevent(struct event *ev) 282f08c3bdfSopenharmony_ci{ 283f08c3bdfSopenharmony_ci double nxttime; 284f08c3bdfSopenharmony_ci int i, p, proc; 285f08c3bdfSopenharmony_ci 286f08c3bdfSopenharmony_ci global_time = ev->time; 287f08c3bdfSopenharmony_ci proc = ev->proc; 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_ci switch (ev->type) { 290f08c3bdfSopenharmony_ci case TRYCRIT: 291f08c3bdfSopenharmony_ci if (critfree == TRUE) 292f08c3bdfSopenharmony_ci addevent(ENTERCRIT, proc, global_time); 293f08c3bdfSopenharmony_ci else 294f08c3bdfSopenharmony_ci addwaiting(proc); 295f08c3bdfSopenharmony_ci break; 296f08c3bdfSopenharmony_ci case ENTERCRIT: 297f08c3bdfSopenharmony_ci critfree = FALSE; 298f08c3bdfSopenharmony_ci nxttime = global_time + dtcrit(); 299f08c3bdfSopenharmony_ci addevent(LEAVECRIT, proc, nxttime); 300f08c3bdfSopenharmony_ci break; 301f08c3bdfSopenharmony_ci case LEAVECRIT: 302f08c3bdfSopenharmony_ci critfree = TRUE; 303f08c3bdfSopenharmony_ci addevent(ATBARRIER, proc, global_time); 304f08c3bdfSopenharmony_ci if ((p = getwaiting()) != 0) { 305f08c3bdfSopenharmony_ci nxttime = global_time; 306f08c3bdfSopenharmony_ci addevent(ENTERCRIT, p, nxttime); 307f08c3bdfSopenharmony_ci } 308f08c3bdfSopenharmony_ci break; 309f08c3bdfSopenharmony_ci case ATBARRIER: 310f08c3bdfSopenharmony_ci barcnt++; 311f08c3bdfSopenharmony_ci if (barcnt == nproc) { 312f08c3bdfSopenharmony_ci nxttime = global_time; 313f08c3bdfSopenharmony_ci for (i = 1; i <= nproc; i++) { 314f08c3bdfSopenharmony_ci nxttime += dtspinoff(); 315f08c3bdfSopenharmony_ci addevent(ENTERWORK, i, nxttime); 316f08c3bdfSopenharmony_ci } 317f08c3bdfSopenharmony_ci barcnt = 0; 318f08c3bdfSopenharmony_ci ncycle++; 319f08c3bdfSopenharmony_ci } 320f08c3bdfSopenharmony_ci break; 321f08c3bdfSopenharmony_ci case ENTERWORK: 322f08c3bdfSopenharmony_ci nxttime = global_time + dtwork(); 323f08c3bdfSopenharmony_ci if (ncycle < ncycmax) 324f08c3bdfSopenharmony_ci addevent(LEAVEWORK, proc, nxttime); 325f08c3bdfSopenharmony_ci break; 326f08c3bdfSopenharmony_ci case LEAVEWORK: 327f08c3bdfSopenharmony_ci addevent(TRYCRIT, proc, global_time); 328f08c3bdfSopenharmony_ci break; 329f08c3bdfSopenharmony_ci default: 330f08c3bdfSopenharmony_ci tst_brkm(TBROK, NULL, "Illegal event"); 331f08c3bdfSopenharmony_ci break; 332f08c3bdfSopenharmony_ci } 333f08c3bdfSopenharmony_ci return (0); 334f08c3bdfSopenharmony_ci} 335f08c3bdfSopenharmony_ci 336f08c3bdfSopenharmony_cistatic int alternator = 1; 337f08c3bdfSopenharmony_cistatic double mean; 338f08c3bdfSopenharmony_cistatic double stdev; 339f08c3bdfSopenharmony_cistatic double u1, u2; 340f08c3bdfSopenharmony_cistatic double twopi; 341f08c3bdfSopenharmony_ci 342f08c3bdfSopenharmony_cistatic void gaussinit(double m, double s) 343f08c3bdfSopenharmony_ci{ 344f08c3bdfSopenharmony_ci mean = m; 345f08c3bdfSopenharmony_ci stdev = s; 346f08c3bdfSopenharmony_ci twopi = 2. * acos((double)-1.0); 347f08c3bdfSopenharmony_ci u1 = twopi / 400.0; 348f08c3bdfSopenharmony_ci u2 = twopi / 500.0; 349f08c3bdfSopenharmony_ci} 350f08c3bdfSopenharmony_ci 351f08c3bdfSopenharmony_cistatic double gauss(void) 352f08c3bdfSopenharmony_ci{ 353f08c3bdfSopenharmony_ci double x1, x2; 354f08c3bdfSopenharmony_ci 355f08c3bdfSopenharmony_ci gcount++; 356f08c3bdfSopenharmony_ci 357f08c3bdfSopenharmony_ci u1 += u2; 358f08c3bdfSopenharmony_ci if (u1 > 0.99) 359f08c3bdfSopenharmony_ci u1 = twopi / 500.0; 360f08c3bdfSopenharmony_ci u2 += u1; 361f08c3bdfSopenharmony_ci if (u2 > 0.99) 362f08c3bdfSopenharmony_ci u2 = twopi / 400.0; 363f08c3bdfSopenharmony_ci 364f08c3bdfSopenharmony_ci if (alternator == 1) { 365f08c3bdfSopenharmony_ci alternator = -1; 366f08c3bdfSopenharmony_ci x1 = sqrt(-2.0 * log(u1)) * cos(twopi * u2); 367f08c3bdfSopenharmony_ci return (mean + stdev * x1); 368f08c3bdfSopenharmony_ci } else { 369f08c3bdfSopenharmony_ci alternator = 1; 370f08c3bdfSopenharmony_ci x2 = sqrt(-2.0 * log(u1)) * sin(twopi * u2); 371f08c3bdfSopenharmony_ci return (mean + stdev * x2); 372f08c3bdfSopenharmony_ci } 373f08c3bdfSopenharmony_ci} 374