1 /*  ncbitime.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  ncbitime.c
27 *
28 * Author:  Ostell, Kans
29 *
30 * Version Creation Date:  1/1/90
31 *
32 * $Revision: 6.3 $
33 *
34 * File Description:
35 *   misc portable routines for
36 *   dates, times, timers
37 *
38 * Modifications:
39 * --------------------------------------------------------------------------
40 * $Log: ncbitime.c,v $
41 * Revision 6.3  2006/10/19 16:58:26  lavr
42 * Cache clock rate instead of requesting it each time on OS_UNIX
43 *
44 * Revision 6.2  2001/01/19 20:26:12  kans
45 * support for OS_UNIX_DARWIN (contributed by William Van Etten)
46 *
47 * Revision 6.1  1997/10/29 02:45:09  vakatov
48 * Type castings to pass through the C++ compiler
49 *
50 * Revision 6.0  1997/08/25 18:17:21  madden
51 * Revision changed to 6.0
52 *
53 * Revision 5.7  1997/07/17 16:09:31  vakatov
54 * Encapsulated "NCBI_months" global variable into a {function + cpp macros}
55 *
56 * Revision 5.6  1996/12/03 21:48:33  vakatov
57 * Adopted for 32-bit MS-Windows DLLs
58 *
59  * Revision 5.5  1996/11/25  19:05:52  vakatov
60  * Made Nlm_GetDayTime() MT-safe
61  *
62  * Revision 5.3  1996/09/17  15:23:25  sad
63  * Corrected compilation problem under SunOS 4 related with CLK_TCK constant
64  *
65  * Revision 5.2  1996/09/16  20:19:57  kans
66  * structures cannot be empty, so needed to add #else condition in two places
67  *
68  * Revision 5.1  1996/09/16  19:37:19  sad
69  * Added set of functions for measuring CPU time.
70  * Added StopWatch set of functions.
71  *
72 * 04-15-93 Schuler     Changed _cdecl to LIBCALL
73 *
74 * ==========================================================================
75 */
76 
77 #include <ncbi.h>
78 #include <ncbithr.h>
79 #include <ncbiwin.h>
80 
81 #ifdef OS_UNIX
82 #include <sys/times.h>
83 #include <unistd.h>
84 #endif
85 
86 static char *STATIC__NCBI_months[12] = {
87   "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
x_NCBI_months(void)88 NLM_EXTERN char **x_NCBI_months(void)  { return &STATIC__NCBI_months[0]; }
89 
90 static char *ampm[2] = { "AM", "PM" };
91 
92 
93 /*****************************************************************************
94 *
95 *   Nlm_GetSecs()
96 *   	returns computer time in seconds - for timing purposes only
97 *
98 *****************************************************************************/
Nlm_GetSecs(void)99 NLM_EXTERN time_t LIBCALL  Nlm_GetSecs (void)
100 {
101   return time(NULL);
102 }
103 
104 /*****************************************************************************
105 *
106 *   Nlm_GetDayTime(DayTimePtr)
107 *
108 *****************************************************************************/
Nlm_GetDayTime(Nlm_DayTimePtr dtp)109 NLM_EXTERN Nlm_Boolean LIBCALL  Nlm_GetDayTime (Nlm_DayTimePtr dtp)
110 {
111 #if (defined(SOLARIS_THREADS_AVAIL)  ||  defined(POSIX_THREADS_AVAIL)  ||  defined(WIN32)) && !defined(OS_UNIX_DARWIN)
112   time_t t = time( NULL );
113 #ifdef WIN32
114   static TNlmMutex localtime_lock;
115   if (NlmMutexLockEx( &localtime_lock ) != 0)
116     abort();
117   *dtp = *localtime( &t );
118   NlmMutexUnlock( localtime_lock );
119 #else
120   localtime_r(&t, dtp);
121 #endif
122   return TRUE;
123 
124 #else
125   time_t ltime;
126   struct tm *dt;
127   Nlm_MemFill ((Nlm_VoidPtr) dtp, 0, sizeof(Nlm_DayTime));
128 	time(&ltime);
129   if ((dt = localtime (&ltime)) != NULL)
130  	{
131         Nlm_MemCopy ((Nlm_VoidPtr) dtp, (Nlm_VoidPtr) dt, sizeof (struct tm));
132         return TRUE;
133     }
134     return FALSE;
135 #endif
136 }
137 
138 /*****************************************************************************
139 *
140 *   Nlm_DayTimeStr(buf, date, time)
141 *   	fills buffer with formatted date and/or time
142 *   	date requires a 13 character buffer
143 *       time requeres a 10 character buffer
144 *   	data and time takes 23
145 *
146 *       eg.   "Jan 28, 1988 12:59 PM"
147 *
148 *****************************************************************************/
Nlm_DayTimeStr(Nlm_CharPtr buf,Nlm_Boolean nlm_date,Nlm_Boolean nlm_time)149 NLM_EXTERN Nlm_Boolean LIBCALL  Nlm_DayTimeStr (Nlm_CharPtr buf, Nlm_Boolean nlm_date, Nlm_Boolean nlm_time)
150 
151 {
152 	Nlm_DayTime dt;
153 	char localbuf[30];
154 	int pm;
155 
156 	buf[0] = '\0';
157 
158 	if ( ! Nlm_GetDayTime(&dt))
159 		return FALSE;
160 
161 	if (nlm_date)
162 	{
163 		sprintf (localbuf, "%s %d, %d", NCBI_months [dt.tm_mon],
164                     dt.tm_mday, dt.tm_year + 1900);
165 		StringCpy (buf, localbuf);
166 	}
167 	if (nlm_time)
168 	{
169 		pm = 1;
170 		if (dt.tm_hour == 0)
171 		{
172 			dt.tm_hour = 12;
173 			pm = 0;
174 		}
175 		else if (dt.tm_hour < 12)
176 			pm = 0;
177 		else if (dt.tm_hour > 12)
178 			dt.tm_hour -= 12;
179 
180 	    sprintf (localbuf, "%3d:%2d %s", dt.tm_hour, dt.tm_min, ampm[pm]);
181 		if (dt.tm_min < 10)
182 			localbuf[4] = '0';
183 		StringCat (buf, localbuf);
184 	}
185 	return TRUE;
186 }
187 
188 struct _StopWatch {
189 #if defined(WIN32)
190     FILETIME	start;
191     FILETIME	stop;
192 #elif defined(OS_UNIX)
193     clock_t	start;
194     clock_t	stop;
195     clock_t	rate;
196 #else
197     int         dummy;
198 #endif
199 };
200 typedef struct _StopWatch Nlm_StopWatch;
201 
Nlm_StopWatchNew(void)202 NLM_EXTERN Nlm_StopWatchPtr Nlm_StopWatchNew(void)
203 {
204 #if defined(WIN32) || defined(OS_UNIX)
205     Nlm_StopWatchPtr pSW = (Nlm_StopWatchPtr)Nlm_MemNew(sizeof(Nlm_StopWatch));
206 #  if defined(OS_UNIX)
207     if (pSW != NULL)
208       pSW->rate = sysconf(_SC_CLK_TCK);
209 #  endif
210     return pSW;
211 #else
212     ErrPostEx(SEV_WARNING, 0, 0,
213 	"StopWatch is not implemented for this platform");
214     return NULL;
215 #endif
216 }
217 
Nlm_StopWatchFree(Nlm_StopWatchPtr pStopWatch)218 NLM_EXTERN Nlm_StopWatchPtr Nlm_StopWatchFree(Nlm_StopWatchPtr pStopWatch)
219 {
220 #if defined(WIN32) || defined(OS_UNIX)
221     return (Nlm_StopWatchPtr) Nlm_MemFree(pStopWatch);
222 #else
223     ErrPostEx(SEV_WARNING, 0, 0,
224 	"StopWatch is not implemented for this platform");
225     return NULL;
226 #endif
227 }
228 
Nlm_StopWatchStart(Nlm_StopWatchPtr pSW)229 NLM_EXTERN Nlm_StopWatchPtr Nlm_StopWatchStart(Nlm_StopWatchPtr pSW)
230 {
231 #if defined(WIN32)
232     SYSTEMTIME	systime;
233 
234     GetSystemTime(&systime);
235     SystemTimeToFileTime(&systime, &pSW->start);
236 #elif defined(OS_UNIX)
237     struct tms	foo;
238 
239     pSW->start = times(&foo);
240 #else
241     ErrPostEx(SEV_WARNING, 0, 0,
242 	"StopWatch is not implemented for this platform");
243 #endif
244     return pSW;
245 }
246 
Nlm_StopWatchStop(Nlm_StopWatchPtr pSW)247 NLM_EXTERN Nlm_StopWatchPtr Nlm_StopWatchStop(Nlm_StopWatchPtr pSW)
248 {
249 #if defined(WIN32)
250     SYSTEMTIME	systime;
251 
252     GetSystemTime(&systime);
253     SystemTimeToFileTime(&systime, &pSW->stop);
254 #elif defined(OS_UNIX)
255     struct tms	foo;
256 
257     pSW->stop = times(&foo);
258 #else
259     ErrPostEx(SEV_WARNING, 0, 0,
260 	"StopWatch is not implemented for this platform");
261 #endif
262     return pSW;
263 }
264 
Nlm_GetElapsedTime(Nlm_StopWatchPtr pSW)265 NLM_EXTERN Nlm_FloatHi Nlm_GetElapsedTime(Nlm_StopWatchPtr pSW)
266 {
267     Nlm_FloatHi	res = 0;
268 #if defined(WIN32)
269     FILETIME	ft;
270 
271     if (pSW->start.dwLowDateTime > pSW->stop.dwLowDateTime) {
272 	ft.dwLowDateTime = (0xFFFFFFFFL - pSW->start.dwLowDateTime) + 1
273 	    + pSW->stop.dwLowDateTime;
274 	ft.dwHighDateTime =
275 	    pSW->stop.dwHighDateTime - pSW->start.dwHighDateTime - 1;
276     } else {
277 	ft.dwLowDateTime =
278 	    pSW->stop.dwLowDateTime - pSW->start.dwLowDateTime;
279 	ft.dwHighDateTime =
280 	    pSW->stop.dwHighDateTime - pSW->start.dwHighDateTime;
281     }
282 
283     return res = (Nlm_FloatHi)ft.dwHighDateTime/5000000L*0x80000000L +
284 	(Nlm_FloatHi)ft.dwLowDateTime/10000000L;
285 #elif defined(OS_UNIX)
286     res = ((Nlm_FloatHi)pSW->stop - pSW->start) / pSW->rate;
287 #else
288     ErrPostEx(SEV_WARNING, 0, 0,
289 	"StopWatch is not implemented for this platform");
290 #endif
291 
292     return res;
293 }
294 
295 
296 struct _CPUTime {
297 #if defined(WIN32)
298 	FILETIME	crtime;
299 	FILETIME	extime;
300 	FILETIME	systime;
301 	FILETIME	usrtime;
302 #elif defined(OS_UNIX)
303     struct tms	times;
304     clock_t    rate;
305 #else
306     int         dummy;
307 #endif
308 };
309 
310 typedef struct _CPUTime Nlm_CPUTime;
311 
Nlm_CPUTimeMeasure(void)312 NLM_EXTERN Nlm_CPUTimePtr Nlm_CPUTimeMeasure(void)
313 {
314 #if defined(WIN32) || defined(OS_UNIX)
315   Nlm_CPUTimePtr pTime = (Nlm_CPUTimePtr) Nlm_MemNew(sizeof(Nlm_CPUTime));
316   if (pTime != NULL) {
317 #endif
318 
319 #if defined(WIN32)
320     GetProcessTimes(GetCurrentProcess(),
321                     &pTime->crtime,
322                     &pTime->extime,
323                     &pTime->systime,
324                     &pTime->usrtime
325                     );
326 #elif defined(OS_UNIX)
327     times(&pTime->times);
328     pTime->rate = sysconf(_SC_CLK_TCK);
329 #else
330     ErrPostEx(SEV_WARNING, 0, 0,
331               "CPU time measuring is not implemented for this platform");
332     return NULL;
333 #endif
334 
335 #if defined(WIN32) || defined(OS_UNIX)
336     }
337 
338     return pTime;
339 #endif
340 }
341 
Nlm_CPUTimeFree(Nlm_CPUTimePtr pTime)342 NLM_EXTERN Nlm_CPUTimePtr Nlm_CPUTimeFree(Nlm_CPUTimePtr pTime)
343 {
344 #if defined(WIN32) || defined(OS_UNIX)
345   return (Nlm_CPUTimePtr) Nlm_MemFree(pTime);
346 #else
347   ErrPostEx(SEV_WARNING, 0, 0,
348             "CPU time measuring is not implemented for this platform");
349   return NULL;
350 #endif
351 }
352 
Nlm_CPUTimeGetSys(Nlm_CPUTimePtr pTime)353 NLM_EXTERN Nlm_FloatHi Nlm_CPUTimeGetSys(Nlm_CPUTimePtr pTime)
354 {
355 #if defined(WIN32)
356   return (Nlm_FloatHi)pTime->systime.dwHighDateTime * 0x80000000L/5000000L
357 		+ (Nlm_FloatHi)pTime->systime.dwLowDateTime / 10000000L;
358 #elif defined(OS_UNIX)
359   return (Nlm_FloatHi)pTime->times.tms_stime / pTime->rate;
360 #else
361   ErrPostEx(SEV_WARNING, 0, 0,
362             "CPU time measuring is not implemented for this platform");
363   return 0;
364 #endif
365 }
366 
Nlm_CPUTimeGetUser(Nlm_CPUTimePtr pTime)367 NLM_EXTERN Nlm_FloatHi Nlm_CPUTimeGetUser(Nlm_CPUTimePtr pTime)
368 {
369 #if defined(WIN32)
370   return (Nlm_FloatHi)pTime->usrtime.dwHighDateTime * 0x80000000L/5000000L
371     + (Nlm_FloatHi)pTime->usrtime.dwLowDateTime / 10000000L;
372 #elif defined(OS_UNIX)
373   return (Nlm_FloatHi)pTime->times.tms_utime / pTime->rate;
374 #else
375   ErrPostEx(SEV_WARNING, 0, 0,
376             "CPU time measuring is not implemented for this platform");
377   return 0;
378 #endif
379 }
380 
381