1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 
11 
12 
13 #include <sys/types.h>
14 #include <string.h>
15 #include <dx/dx.h>
16 #include <stdio.h>
17 
18 #if defined(HAVE_UNISTD_H)
19 #include <unistd.h>
20 #endif
21 #if defined(HAVE_SYS_TIME_H)
22 #include <sys/time.h>
23 #endif
24 #if defined(HAVE_SYS_TIMES_H)
25 #include <sys/times.h>
26 #endif
27 #if defined(HAVE_SYS_PARAM_H)
28 #include <sys/param.h>
29 #endif
30 #if defined(HAVE_TIME_H)
31 #include <time.h>
32 #endif
33 
34 
35 #ifndef HZ
36 #define HZ 60
37 #endif
38 
39 #define EVENTS 2000
40 
41 static
42 struct ti {
43     int trace;				/* whether to trace times or not */
44     struct _proc {
45 	struct event {			/* per event info: */
46 	    double user, sys, real;	/* time of this event */
47 	    char label[16];		/* this event's label */
48 	    int id;			/* processor on which it ran */
49 	    int global;			/* whether it is global or local */
50 	} events[EVENTS];		/* one per event */
51 	int n;				/* number of events this processor */
52 	int printed;			/* count for printing */
53 	struct last {			/* last printed event time */
54 	    double user, sys, real;	/* user, system, real times */
55 	} last;				/* per processor */
56     } *procs;				/* one per processor */
57 } *ti = NULL;				/* ptr to struct in global memory */
58 
59 
60 void
DXTraceTime(int t)61 DXTraceTime(int t)
62 {
63     static int been_here;
64     if (!been_here) {
65 	DXinitdx();
66 	been_here = 1;
67     }
68     if (ti)
69 	ti->trace = t;
70 }
71 
72 
73 /*
74  * Internal routine: get a time split, measured in
75  * seconds since the first time split
76  */
77 
78 #if ibmpvs && !paxc
79 static void
_times_svs(double * user,double * sys,double * real)80 _times_svs(double *user, double *sys, double *real)
81 {
82     static struct tms tms0;
83     struct tms tms1;
84     static double time0;
85     double time1;
86     extern double double_time();
87     static int fast;
88 
89     if (!time0) {
90 	times(&tms0);
91 	time0 = double_time();
92 	fast = getenv("SLOW")? 0 : 1;
93     }
94     if (!fast && (user || sys))
95 	times(&tms1);
96     time1 = double_time();
97     if (user)
98 	*user = fast? 0 : (float)(tms1.tms_utime-tms0.tms_utime) / HZ;
99     if (sys)
100 	*sys = fast? 0 : (float)(tms1.tms_stime-tms0.tms_stime) / HZ;
101     if (real)
102 	*real = time1-time0;
103 }
104 #endif
105 
106 #if defined(os2)  || defined(intelnt) || defined(WIN32)
107 
108 static void
_times_unix(double * user,double * sys,double * real)109 _times_unix(double *user, double *sys, double *real)
110 {
111     static clock_t time0  = 0;
112     static time_t  rtime0 = 0;
113     clock_t time1;
114     time_t  rtime1;
115     if (!time0)
116     {
117       time0  = clock();
118       rtime0 = time(0);
119     }
120     time1  = clock();
121     rtime1 = time(0);
122     if (user)
123         *user = (float)(time1) / CLOCKS_PER_SEC;
124     if (sys)
125         *sys = (float)(time1) / CLOCKS_PER_SEC;
126     if (real)
127         *real = (float)(rtime1-rtime0);
128 }
129 
130 #else
131 
132 static void
_times_unix(double * user,double * sys,double * real)133 _times_unix(double *user, double *sys, double *real)
134 {
135     static struct tms tms0;
136     struct tms tms1;
137     static int time0;
138     int time1;
139     if (!time0)
140         time0 = times(&tms0);
141     time1 = times(&tms1);
142     if (user)
143         *user = (float)(tms1.tms_utime/*-tms0.tms_utime*/) / HZ;
144     if (sys)
145         *sys = (float)(tms1.tms_stime/*-tms0.tms_stime*/) / HZ;
146     if (real)
147         *real = (float)(time1-time0) / HZ;
148 
149 }
150 #endif
151 
152 #if ibm6000 || sun4 || solaris
153 static void
_times_ibmsun4(double * user,double * sys,double * real)154 _times_ibmsun4(double *user, double *sys, double *real)
155 {
156     static struct tms tms0;
157     struct tms tms1;
158     struct timeval tp;
159     struct timezone tzp;
160     static double time0;
161     double time1;
162 
163     if (!time0) {
164 	times(&tms0);
165         gettimeofday(&tp, &tzp);
166         time0 = (double)tp.tv_sec + ((double)(unsigned)tp.tv_usec)*.000001;
167     }
168     if (user || sys)
169 	times(&tms1);
170     gettimeofday(&tp, &tzp);
171     time1 = (double)tp.tv_sec + ((double)(unsigned)tp.tv_usec)*.000001;
172     if (user)
173 	*user = (float)(tms1.tms_utime/*-tms0.tms_utime*/) / HZ;
174     if (sys)
175 	*sys = (float)(tms1.tms_stime/*-tms0.tms_stime*/) / HZ;
176     if (real)
177 	*real = time1 - time0;
178 }
179 #endif
180 
181 static void
_times(double * user,double * sys,double * real)182 _times(double *user, double *sys, double *real)
183 {
184 #if !ibm6000 && !sun4 && !solaris
185 #if ibmpvs && !paxc
186     static int been_here, svs;
187 
188     if (!been_here) {
189 	svs = getenv("GENERICI860")? 0 : 1;
190 	been_here = 1;
191     }
192 
193     if (svs)
194 	_times_svs(user, sys, real);
195     else
196 #endif
197 	_times_unix(user, sys, real);
198 #else
199     _times_ibmsun4(user, sys, real);
200 #endif
201 }
202 
203 
204 double
DXGetTime(void)205 DXGetTime(void)
206 {
207     double t;
208     _times(NULL, NULL, &t);
209     return t;
210 }
211 
212 void
DXWaitTime(double seconds)213 DXWaitTime(double seconds)
214 {
215 #if defined(intelnt) || defined(WIN32)
216     Sleep(seconds*1000);
217 #else
218 #if ibmpvs || hp700 || aviion
219 
220     double old;
221     old = DXGetTime();
222 
223     while (DXGetTime() - old < seconds)
224 	continue;
225 
226 #elif ibm6000 || sun4 || macos || linux || freebsd || cygwin
227 
228     usleep((int)(1000000.0 * seconds));
229 
230 #elif sgi
231 
232     sginap((int)(CLK_TCK * seconds));
233 
234 #else
235 
236     sleep((int)seconds);   /* this will only sleep in whole seconds */
237 
238 #endif
239 #endif
240 }
241 
242 /*
243  * time marking
244  */
245 
246 Error
_dxf_inittiming(void)247 _dxf_inittiming(void)
248 {
249     if (!ti) {
250 	ti = (struct ti *) DXAllocateZero(sizeof(struct ti));
251 	if (!ti)
252 	    return ERROR;
253 	ti->procs = (struct _proc *)
254 	    DXAllocateZero(DXProcessors(0) * sizeof(struct _proc));
255 	if (!ti->procs) {
256 	    DXFree((Pointer)ti);
257 	    return ERROR;
258 	}
259 	_times(NULL, NULL, NULL);
260     }
261     return OK;
262 }
263 
264 static
265 void
mark(char * s,int global)266 mark(char *s, int global)
267 {
268     static int been_here;
269     struct _proc *proc;
270     struct event *event;
271     int id = DXProcessorId();
272 
273     if (!been_here) {
274 	DXinitdx();
275 	been_here = 1;
276     }
277     proc = &ti->procs[id];
278     if (proc->n >= EVENTS)
279 	return;
280     event = &proc->events[proc->n++];
281     _times(&event->user, &event->sys, &event->real);
282     event->global = global;
283     strncpy(event->label, s, sizeof(event->label)-1);
284     event->label[sizeof(event->label)-1] = '\0';
285 }
286 
287 
DXMarkTime(char * s)288 void DXMarkTime       (char *s) {if (ti->trace) mark(s, 1);}
DXMarkTimeLocal(char * s)289 void DXMarkTimeLocal  (char *s) {if (ti->trace) mark(s, 0);}
DXMarkTimeX(char * s)290 void DXMarkTimeX      (char *s) {               mark(s, 1);}
DXMarkTimeLocalX(char * s)291 void DXMarkTimeLocalX (char *s) {               mark(s, 0);}
292 
293 
294 void
DXPrintTimes(void)295 DXPrintTimes(void)
296 {
297     int i, id=0;
298     static struct last glob;
299     struct _proc *proc = NULL, *p;
300     struct event *event;
301     struct last *last;
302     DXBeginLongMessage();
303 
304     for (;;) {
305 
306 	/* find latest event not yet printed */
307 	event = NULL;
308 	for (i=0, p=ti->procs;  i<DXProcessors(0);  i++, p++) {
309 	    if (p->printed < p->n) {
310 		struct event *e = &p->events[p->printed];
311 		if (!event || e->real < event->real)
312 		    id = i, proc = p, event = e;
313 	    }
314 	}
315 	if (!event)
316 	    break;
317 	proc->printed += 1;
318 	last = &proc->last;
319 
320 	if (event->global) {
321 	    /*
322 	     * Measure global real time delta from last global event.
323 	     * Measure user and system delta from last event on
324 	     * this processor.
325 	     */
326 	    DXMessage("--: %16s %10.6f+%10.6f=%10.6f (%6.2fu, %6.2fs)\n",
327 		    event->label, glob.real,event->real-glob.real, event->real,
328 		    event->user-last->user, event->sys-last->sys);
329 	    glob.real = event->real;
330 	} else {
331 	    /*
332 	     * Measure real local time delta from last event on this processor
333 	     * or last global event, whichever is more recent.  Measure user
334 	     * and sys time delta from last event on this processor.
335 	     */
336 	    double real = last->real>glob.real? last->real : glob.real;
337 	    DXMessage("%2d: %16s %10.6f+%10.6f=%10.6f (%6.2fu, %6.2fs)\n",
338 		    id, event->label, real, event->real-real, event->real,
339 		    event->user-last->user, event->sys-last->sys);
340 	}
341 	last->user = event->user;
342 	last->sys = event->sys;
343 	last->real = event->real;
344     }
345 
346     DXEndLongMessage();
347 
348     /* reset all per-processor information to 0 */
349     for (i=0, p=ti->procs; i < DXProcessors(0);  i++, p++)
350 	p->n = p->printed = 0;
351 }
352