1 /*
2  * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 /** \file
19  * \brief Fill in statistics structure (Linux version)
20  */
21 
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 #include <sys/utsname.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include "timeBlk.h"
28 #include "fioMacros.h"
29 
30 union ieee {
31   double d;
32   int i[2];
33 };
34 
35 extern void *__fort_sbrk(int);
36 
37 /* these little routines had to go somewhere, so here they are. */
38 
39 void
__fort_setarg(void)40 __fort_setarg(void)
41 {
42 }
43 
nodename(s)44 static void nodename(s) char *s;
45 {
46   struct utsname u0;
47 
48   uname(&u0);
49   strcpy(s, u0.nodename);
50 }
51 
__fort_gettb(t)52 void __fort_gettb(t) struct tb *t;
53 {
54   struct timeval tv0;
55   struct timezone tz0;
56   struct rusage rs0, rc0;
57 
58   /* Use an approximation here to avoid using inexact arithmetic */
59   unsigned long long tapprox;
60   union ieee v;
61 
62   gettimeofday(&tv0, &tz0);
63   getrusage(RUSAGE_SELF, &rs0);
64   getrusage(RUSAGE_CHILDREN, &rc0);
65   v.i[0] = 0;
66   v.i[1] = 0x3d700000;                       /* 2 ** -40 */
67   tapprox = (unsigned long long)tv0.tv_usec; /* around 2**30 */
68   tapprox = tapprox * 1099512UL;             /* mpy by a 21 bit value */
69   tapprox &= 0xfffffffffffc0000ULL;          /* Lop off enough to be exact */
70   t->r = (double)tv0.tv_sec + v.d * (double)tapprox;
71   /* printf("BDL %d %d %22.15le\n",tv0.tv_sec,tv0.tv_usec,t->r); */
72 
73   tapprox = rs0.ru_utime.tv_usec;
74   tapprox = tapprox * 1099512UL;
75   tapprox &= 0xfffffffffffc0000ULL;
76   t->u = (double)rs0.ru_utime.tv_sec + v.d * (double)tapprox;
77 
78   tapprox = rs0.ru_stime.tv_usec;
79   tapprox = tapprox * 1099512UL;
80   tapprox &= 0xfffffffffffc0000ULL;
81   t->s = (double)rs0.ru_stime.tv_sec + v.d * (double)tapprox;
82 
83   tapprox = rc0.ru_utime.tv_usec;
84   tapprox = tapprox * 1099512UL;
85   tapprox &= 0xfffffffffffc0000ULL;
86   t->u += (double)rc0.ru_utime.tv_sec + v.d * (double)tapprox;
87 
88   tapprox = rc0.ru_stime.tv_usec;
89   tapprox = tapprox * 1099512UL;
90   tapprox &= 0xfffffffffffc0000ULL;
91   t->s += (double)rc0.ru_stime.tv_sec + v.d * (double)tapprox;
92   t->maxrss = rs0.ru_maxrss;
93   t->minflt = rs0.ru_minflt;
94   t->majflt = rs0.ru_majflt;
95   t->nsignals = rs0.ru_nsignals;
96   t->nvcsw = rs0.ru_nvcsw;
97   t->nivcsw = rs0.ru_nivcsw;
98   t->sbrk = (double)((long)sbrk(0));
99   t->gsbrk = (GET_DIST_HEAPZ == 0 ? 0.0 : (double)((long)__fort_sbrk(0)));
100   nodename(t->host);
101 }
102 
103 static double first = 0.0;
104 
105 double
__fort_second()106 __fort_second()
107 {
108   struct timeval v;
109   struct timezone t;
110   double d;
111   int s;
112 
113   s = gettimeofday(&v, &t);
114   if (s == -1) {
115     __fort_abortp("gettimeofday");
116   }
117   d = (double)v.tv_sec + (double)v.tv_usec / 1000000;
118   if (first == 0.0) {
119     first = d;
120   }
121   return (d - first);
122 }
123 
124 void
__fort_set_second(double d)125 __fort_set_second(double d)
126 {
127   first = d;
128 }
129