1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                    TTTTT  IIIII  M   M  EEEEE  RRRR                         %
7%                      T      I    MM MM  E      R   R                        %
8%                      T      I    M M M  EEE    RRRR                         %
9%                      T      I    M   M  E      R R                          %
10%                      T    IIIII  M   M  EEEEE  R  R                         %
11%                                                                             %
12%                                                                             %
13%                         MagickCore Timing Methods                           %
14%                                                                             %
15%                             Software Design                                 %
16%                                  Cristy                                     %
17%                              January 1993                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%  Contributed by Bill Radcliffe and Bob Friesenhahn.
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "MagickCore/studio.h"
44#include "MagickCore/exception.h"
45#include "MagickCore/exception-private.h"
46#include "MagickCore/log.h"
47#include "MagickCore/memory_.h"
48#include "MagickCore/nt-base-private.h"
49#include "MagickCore/timer.h"
50
51/*
52  Define declarations.
53*/
54#if !defined(CLOCKS_PER_SEC)
55#define CLOCKS_PER_SEC  100
56#endif
57
58/*
59  Forward declarations.
60*/
61static double
62  UserTime(void);
63
64static void
65  StopTimer(TimerInfo *);
66
67/*
68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69%                                                                             %
70%                                                                             %
71%                                                                             %
72%   A c q u i r e T i m e r I n f o                                           %
73%                                                                             %
74%                                                                             %
75%                                                                             %
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77%
78%  AcquireTimerInfo() initializes the TimerInfo structure.  It effectively
79%  creates a stopwatch and starts it.
80%
81%  The format of the AcquireTimerInfo method is:
82%
83%      TimerInfo *AcquireTimerInfo(void)
84%
85*/
86MagickExport TimerInfo *AcquireTimerInfo(void)
87{
88  TimerInfo
89    *timer_info;
90
91  timer_info=(TimerInfo *) AcquireMagickMemory(sizeof(*timer_info));
92  if (timer_info == (TimerInfo *) NULL)
93    ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
94  (void) ResetMagickMemory(timer_info,0,sizeof(*timer_info));
95  timer_info->signature=MagickCoreSignature;
96  GetTimerInfo(timer_info);
97  return(timer_info);
98}
99
100/*
101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102%                                                                             %
103%                                                                             %
104%                                                                             %
105%   C o n t i n u e T i m e r                                                 %
106%                                                                             %
107%                                                                             %
108%                                                                             %
109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110%
111%  ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
112%  counting from the last StartTimer() onwards.
113%
114%  The format of the ContinueTimer method is:
115%
116%      MagickBooleanType ContinueTimer(TimerInfo *time_info)
117%
118%  A description of each parameter follows.
119%
120%    o  time_info: Time statistics structure.
121%
122*/
123MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
124{
125  assert(time_info != (TimerInfo *) NULL);
126  assert(time_info->signature == MagickCoreSignature);
127  if (time_info->state == UndefinedTimerState)
128    return(MagickFalse);
129  if (time_info->state == StoppedTimerState)
130    {
131      time_info->user.total-=time_info->user.stop-time_info->user.start;
132      time_info->elapsed.total-=time_info->elapsed.stop-
133        time_info->elapsed.start;
134    }
135  time_info->state=RunningTimerState;
136  return(MagickTrue);
137}
138
139/*
140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141%                                                                             %
142%                                                                             %
143%                                                                             %
144%   D e s t r o y T i m e r I n f o                                           %
145%                                                                             %
146%                                                                             %
147%                                                                             %
148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149%
150%  DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
151%
152%  The format of the DestroyTimerInfo method is:
153%
154%      TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
155%
156%  A description of each parameter follows:
157%
158%    o timer_info: The cipher context.
159%
160*/
161MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
162{
163  assert(timer_info != (TimerInfo *) NULL);
164  assert(timer_info->signature == MagickCoreSignature);
165  timer_info->signature=(~MagickCoreSignature);
166  timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
167  return(timer_info);
168}
169
170/*
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%                                                                             %
173%                                                                             %
174%                                                                             %
175+   E l a p s e d T i m e                                                     %
176%                                                                             %
177%                                                                             %
178%                                                                             %
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180%
181%  ElapsedTime() returns the elapsed time (in seconds) since the last call to
182%  StartTimer().
183%
184%  The format of the ElapsedTime method is:
185%
186%      double ElapsedTime()
187%
188*/
189static double ElapsedTime(void)
190{
191#if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
192  struct tms
193    timer;
194
195  return((double) times(&timer)/sysconf(_SC_CLK_TCK));
196#else
197#if defined(MAGICKCORE_WINDOWS_SUPPORT)
198  return(NTElapsedTime());
199#else
200  return((double) clock()/CLOCKS_PER_SEC);
201#endif
202#endif
203}
204
205/*
206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207%                                                                             %
208%                                                                             %
209%                                                                             %
210%   G e t E l a p s e d T i m e                                               %
211%                                                                             %
212%                                                                             %
213%                                                                             %
214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215%
216%  GetElapsedTime() returns the elapsed time (in seconds) passed between the
217%  start and stop events. If the stopwatch is still running, it is stopped
218%  first.
219%
220%  The format of the GetElapsedTime method is:
221%
222%      double GetElapsedTime(TimerInfo *time_info)
223%
224%  A description of each parameter follows.
225%
226%    o  time_info: Timer statistics structure.
227%
228*/
229MagickExport double GetElapsedTime(TimerInfo *time_info)
230{
231  assert(time_info != (TimerInfo *) NULL);
232  assert(time_info->signature == MagickCoreSignature);
233  if (time_info->state == UndefinedTimerState)
234    return(0.0);
235  if (time_info->state == RunningTimerState)
236    StopTimer(time_info);
237  return(time_info->elapsed.total);
238}
239
240/*
241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242%                                                                             %
243%                                                                             %
244%                                                                             %
245+   G e t T i m e r I n f o                                                   %
246%                                                                             %
247%                                                                             %
248%                                                                             %
249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250%
251%  GetTimerInfo() initializes the TimerInfo structure.
252%
253%  The format of the GetTimerInfo method is:
254%
255%      void GetTimerInfo(TimerInfo *time_info)
256%
257%  A description of each parameter follows.
258%
259%    o  time_info: Timer statistics structure.
260%
261*/
262MagickExport void GetTimerInfo(TimerInfo *time_info)
263{
264  /*
265    Create a stopwatch and start it.
266  */
267  assert(time_info != (TimerInfo *) NULL);
268  (void) ResetMagickMemory(time_info,0,sizeof(*time_info));
269  time_info->state=UndefinedTimerState;
270  time_info->signature=MagickCoreSignature;
271  StartTimer(time_info,MagickTrue);
272}
273
274/*
275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276%                                                                             %
277%                                                                             %
278%                                                                             %
279%   G e t U s e r T i m e                                                     %
280%                                                                             %
281%                                                                             %
282%                                                                             %
283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284%
285%  GetUserTime() returns the User time (user and system) by the operating
286%  system (in seconds) between the start and stop events. If the stopwatch is
287%  still running, it is stopped first.
288%
289%  The format of the GetUserTime method is:
290%
291%      double GetUserTime(TimerInfo *time_info)
292%
293%  A description of each parameter follows.
294%
295%    o  time_info: Timer statistics structure.
296%
297*/
298MagickExport double GetUserTime(TimerInfo *time_info)
299{
300  assert(time_info != (TimerInfo *) NULL);
301  assert(time_info->signature == MagickCoreSignature);
302  if (time_info->state == UndefinedTimerState)
303    return(0.0);
304  if (time_info->state == RunningTimerState)
305    StopTimer(time_info);
306  return(time_info->user.total);
307}
308
309/*
310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311%                                                                             %
312%                                                                             %
313%                                                                             %
314%   R e s e t T i m e r                                                       %
315%                                                                             %
316%                                                                             %
317%                                                                             %
318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319%
320%  ResetTimer() resets the stopwatch.
321%
322%  The format of the ResetTimer method is:
323%
324%      void ResetTimer(TimerInfo *time_info)
325%
326%  A description of each parameter follows.
327%
328%    o  time_info: Timer statistics structure.
329%
330*/
331MagickExport void ResetTimer(TimerInfo *time_info)
332{
333  assert(time_info != (TimerInfo *) NULL);
334  assert(time_info->signature == MagickCoreSignature);
335  StopTimer(time_info);
336  time_info->elapsed.stop=0.0;
337  time_info->user.stop=0.0;
338}
339
340/*
341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342%                                                                             %
343%                                                                             %
344%                                                                             %
345+   S t a r t T i m e r                                                       %
346%                                                                             %
347%                                                                             %
348%                                                                             %
349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350%
351%  StartTimer() starts the stopwatch.
352%
353%  The format of the StartTimer method is:
354%
355%      void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
356%
357%  A description of each parameter follows.
358%
359%    o  time_info: Timer statistics structure.
360%
361%    o  reset: If reset is MagickTrue, then the stopwatch is reset prior to
362%       starting.  If reset is MagickFalse, then timing is continued without
363%       resetting the stopwatch.
364%
365*/
366MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
367{
368  assert(time_info != (TimerInfo *) NULL);
369  assert(time_info->signature == MagickCoreSignature);
370  if (reset != MagickFalse)
371    {
372      /*
373        Reset the stopwatch before starting it.
374      */
375      time_info->user.total=0.0;
376      time_info->elapsed.total=0.0;
377    }
378  if (time_info->state != RunningTimerState)
379    {
380      time_info->elapsed.start=ElapsedTime();
381      time_info->user.start=UserTime();
382    }
383  time_info->state=RunningTimerState;
384}
385
386/*
387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388%                                                                             %
389%                                                                             %
390%                                                                             %
391+   S t o p T i m e r                                                         %
392%                                                                             %
393%                                                                             %
394%                                                                             %
395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396%
397%  StopTimer() stops the stopwatch.
398%
399%  The format of the StopTimer method is:
400%
401%      void StopTimer(TimerInfo *time_info)
402%
403%  A description of each parameter follows.
404%
405%    o  time_info: Timer statistics structure.
406%
407*/
408static void StopTimer(TimerInfo *time_info)
409{
410  assert(time_info != (TimerInfo *) NULL);
411  assert(time_info->signature == MagickCoreSignature);
412  time_info->elapsed.stop=ElapsedTime();
413  time_info->user.stop=UserTime();
414  if (time_info->state == RunningTimerState)
415    {
416      time_info->user.total+=time_info->user.stop-
417        time_info->user.start+MagickEpsilon;
418      time_info->elapsed.total+=time_info->elapsed.stop-
419        time_info->elapsed.start+MagickEpsilon;
420    }
421  time_info->state=StoppedTimerState;
422}
423
424/*
425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426%                                                                             %
427%                                                                             %
428%                                                                             %
429+   U s e r T i m e                                                           %
430%                                                                             %
431%                                                                             %
432%                                                                             %
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434%
435%  UserTime() returns the total time the process has been scheduled (in
436%  seconds) since the last call to StartTimer().
437%
438%  The format of the UserTime method is:
439%
440%      double UserTime()
441%
442*/
443static double UserTime(void)
444{
445#if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
446  struct tms
447    timer;
448
449  (void) times(&timer);
450  return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
451#else
452#if defined(MAGICKCORE_WINDOWS_SUPPORT)
453  return(NTUserTime());
454#else
455  return((double) clock()/CLOCKS_PER_SEC);
456#endif
457#endif
458}
459