MagickCore  7.1.1-43
Convert, Edit, Or Compose Bitmap Images
timer.c
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 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 % https://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/image-private.h"
47 #include "MagickCore/locale_.h"
48 #include "MagickCore/log.h"
49 #include "MagickCore/memory_.h"
50 #include "MagickCore/memory-private.h"
51 #include "MagickCore/nt-base-private.h"
52 #include "MagickCore/registry.h"
53 #include "MagickCore/resource_.h"
54 #include "MagickCore/string-private.h"
55 #include "MagickCore/timer.h"
56 #include "MagickCore/timer-private.h"
57 
58 /*
59  Define declarations.
60 */
61 #if !defined(CLOCKS_PER_SEC)
62 #define CLOCKS_PER_SEC 100
63 #endif
64 
65 /*
66  Forward declarations.
67 */
68 static double
69  UserTime(void);
70 
71 static void
72  StopTimer(TimerInfo *);
73 
74 /*
75  Static declarations.
76 */
77 static ssize_t
78  date_precision = -1;
79 
80 /*
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 % %
83 % %
84 % %
85 % A c q u i r e T i m e r I n f o %
86 % %
87 % %
88 % %
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90 %
91 % AcquireTimerInfo() initializes the TimerInfo structure. It effectively
92 % creates a stopwatch and starts it.
93 %
94 % The format of the AcquireTimerInfo method is:
95 %
96 % TimerInfo *AcquireTimerInfo(void)
97 %
98 */
99 MagickExport TimerInfo *AcquireTimerInfo(void)
100 {
101  TimerInfo
102  *timer_info;
103 
104  timer_info=(TimerInfo *) AcquireCriticalMemory(sizeof(*timer_info));
105  (void) memset(timer_info,0,sizeof(*timer_info));
106  timer_info->signature=MagickCoreSignature;
107  GetTimerInfo(timer_info);
108  return(timer_info);
109 }
110 
111 /*
112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 % %
114 % %
115 % %
116 % C o n t i n u e T i m e r %
117 % %
118 % %
119 % %
120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 %
122 % ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
123 % counting from the last StartTimer() onwards.
124 %
125 % The format of the ContinueTimer method is:
126 %
127 % MagickBooleanType ContinueTimer(TimerInfo *time_info)
128 %
129 % A description of each parameter follows.
130 %
131 % o time_info: Time statistics structure.
132 %
133 */
134 MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
135 {
136  assert(time_info != (TimerInfo *) NULL);
137  assert(time_info->signature == MagickCoreSignature);
138  if (time_info->state == UndefinedTimerState)
139  return(MagickFalse);
140  if (time_info->state == StoppedTimerState)
141  {
142  time_info->user.total-=time_info->user.stop-time_info->user.start;
143  time_info->elapsed.total-=time_info->elapsed.stop-
144  time_info->elapsed.start;
145  }
146  time_info->state=RunningTimerState;
147  return(MagickTrue);
148 }
149 
150 /*
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 % %
153 % %
154 % %
155 % D e s t r o y T i m e r I n f o %
156 % %
157 % %
158 % %
159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160 %
161 % DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
162 %
163 % The format of the DestroyTimerInfo method is:
164 %
165 % TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
166 %
167 % A description of each parameter follows:
168 %
169 % o timer_info: The cipher context.
170 %
171 */
172 MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
173 {
174  assert(timer_info != (TimerInfo *) NULL);
175  assert(timer_info->signature == MagickCoreSignature);
176  timer_info->signature=(~MagickCoreSignature);
177  timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
178  return(timer_info);
179 }
180 
181 /*
182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 % %
184 % %
185 % %
186 + E l a p s e d T i m e %
187 % %
188 % %
189 % %
190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191 %
192 % ElapsedTime() returns the elapsed time (in seconds) since the last call to
193 % StartTimer().
194 %
195 % The format of the ElapsedTime method is:
196 %
197 % double ElapsedTime()
198 %
199 */
200 static double ElapsedTime(void)
201 {
202 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME)
203 #define NANOSECONDS_PER_SECOND 1000000000.0
204 #if defined(CLOCK_HIGHRES)
205 # define CLOCK_ID CLOCK_HIGHRES
206 #elif defined(CLOCK_MONOTONIC_RAW)
207 # define CLOCK_ID CLOCK_MONOTONIC_RAW
208 #elif defined(CLOCK_MONOTONIC_PRECISE)
209 # define CLOCK_ID CLOCK_MONOTONIC_PRECISE
210 #elif defined(CLOCK_MONOTONIC)
211 # define CLOCK_ID CLOCK_MONOTONIC
212 #else
213 # define CLOCK_ID CLOCK_REALTIME
214 #endif
215 
216  struct timespec
217  timer;
218 
219  (void) clock_gettime(CLOCK_ID,&timer);
220  return((double) timer.tv_sec+timer.tv_nsec/NANOSECONDS_PER_SECOND);
221 #elif defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
222  struct tms
223  timer;
224 
225  return((double) times(&timer)/sysconf(_SC_CLK_TCK));
226 #else
227 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
228  return(NTElapsedTime());
229 #else
230  return((double) clock()/CLOCKS_PER_SEC);
231 #endif
232 #endif
233 }
234 
235 /*
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % %
238 % %
239 % %
240 % F o r m a t M a g i c k T i m e %
241 % %
242 % %
243 % %
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 %
246 % FormatMagickTime() returns the specified time in the Internet date/time
247 % format and the length of the timestamp.
248 %
249 % The format of the FormatMagickTime method is:
250 %
251 % ssize_t FormatMagickTime(const time_t time,const size_t length,
252 % char *timestamp)
253 %
254 % A description of each parameter follows.
255 %
256 % o time: the time since the Epoch (00:00:00 UTC, January 1, 1970),
257 % measured in seconds.
258 %
259 % o length: the maximum length of the string.
260 %
261 % o timestamp: Return the Internet date/time here.
262 %
263 */
264 MagickExport ssize_t FormatMagickTime(const time_t time,const size_t length,
265  char *timestamp)
266 {
267  ssize_t
268  count;
269 
270  struct tm
271  utc_time;
272 
273  assert(timestamp != (char *) NULL);
274  if (date_precision == -1)
275  {
276  char
277  *limit;
278 
279  date_precision=0;
280  limit=GetEnvironmentValue("MAGICK_DATE_PRECISION");
281  if (limit != (char *) NULL)
282  {
283  date_precision=StringToInteger(limit);
284  limit=DestroyString(limit);
285  }
286  }
287  GetMagickUTCTime(&time,&utc_time);
288  count=FormatLocaleString(timestamp,length,
289  "%04d-%02d-%02dT%02d:%02d:%02d%+03d:00",utc_time.tm_year+1900,
290  utc_time.tm_mon+1,utc_time.tm_mday,utc_time.tm_hour,utc_time.tm_min,
291  utc_time.tm_sec,0);
292  if ((date_precision > 0) && (date_precision < (ssize_t) strlen(timestamp)))
293  timestamp[date_precision]='\0';
294  return(count);
295 }
296 
297 /*
298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299 % %
300 % %
301 % %
302 % G e t E l a p s e d T i m e %
303 % %
304 % %
305 % %
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 %
308 % GetElapsedTime() returns the elapsed time (in seconds) passed between the
309 % start and stop events. If the stopwatch is still running, it is stopped
310 % first.
311 %
312 % The format of the GetElapsedTime method is:
313 %
314 % double GetElapsedTime(TimerInfo *time_info)
315 %
316 % A description of each parameter follows.
317 %
318 % o time_info: Timer statistics structure.
319 %
320 */
321 MagickExport double GetElapsedTime(TimerInfo *time_info)
322 {
323  assert(time_info != (TimerInfo *) NULL);
324  assert(time_info->signature == MagickCoreSignature);
325  if (time_info->state == UndefinedTimerState)
326  return(0.0);
327  if (time_info->state == RunningTimerState)
328  StopTimer(time_info);
329  return(time_info->elapsed.total);
330 }
331 
332 /*
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % %
335 % %
336 % %
337 + G e t M a g i c k T i m e %
338 % %
339 % %
340 % %
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 %
343 % GetMagickTime() returns the time as the number of seconds since the Epoch.
344 %
345 % The format of the GetMagickTime method is:
346 %
347 % time_t GetElapsedTime(void)
348 %
349 */
350 MagickExport time_t GetMagickTime(void)
351 {
352  static time_t
353  magick_epoch = (time_t) 0;
354 
355  static MagickBooleanType
356  epoch_initialized = MagickFalse;
357 
358  if (epoch_initialized == MagickFalse)
359  {
360  const char
361  *source_date_epoch;
362 
363  source_date_epoch=getenv("SOURCE_DATE_EPOCH");
364  if (source_date_epoch != (const char *) NULL)
365  {
366  time_t
367  epoch;
368 
369  epoch=(time_t) StringToMagickOffsetType(source_date_epoch,100.0);
370  if ((epoch > 0) && (epoch <= time((time_t *) NULL)))
371  magick_epoch=epoch;
372  }
373  epoch_initialized=MagickTrue;
374  }
375  if (magick_epoch != 0)
376  return(magick_epoch);
377  return(time((time_t *) NULL));
378 }
379 
380 /*
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 % %
383 % %
384 % %
385 + G e t T i m e r I n f o %
386 % %
387 % %
388 % %
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 %
391 % GetTimerInfo() initializes the TimerInfo structure.
392 %
393 % The format of the GetTimerInfo method is:
394 %
395 % void GetTimerInfo(TimerInfo *time_info)
396 %
397 % A description of each parameter follows.
398 %
399 % o time_info: Timer statistics structure.
400 %
401 */
402 MagickExport void GetTimerInfo(TimerInfo *time_info)
403 {
404  /*
405  Create a stopwatch and start it.
406  */
407  assert(time_info != (TimerInfo *) NULL);
408  (void) memset(time_info,0,sizeof(*time_info));
409  time_info->state=UndefinedTimerState;
410  time_info->signature=MagickCoreSignature;
411  StartTimer(time_info,MagickTrue);
412 }
413 
414 /*
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 % %
417 % %
418 % %
419 % G e t U s e r T i m e %
420 % %
421 % %
422 % %
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 %
425 % GetUserTime() returns the User time (user and system) by the operating
426 % system (in seconds) between the start and stop events. If the stopwatch is
427 % still running, it is stopped first.
428 %
429 % The format of the GetUserTime method is:
430 %
431 % double GetUserTime(TimerInfo *time_info)
432 %
433 % A description of each parameter follows.
434 %
435 % o time_info: Timer statistics structure.
436 %
437 */
438 MagickExport double GetUserTime(TimerInfo *time_info)
439 {
440  assert(time_info != (TimerInfo *) NULL);
441  assert(time_info->signature == MagickCoreSignature);
442  if (time_info->state == UndefinedTimerState)
443  return(0.0);
444  if (time_info->state == RunningTimerState)
445  StopTimer(time_info);
446  return(time_info->user.total);
447 }
448 
449 /*
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 % %
452 % %
453 % %
454 % R e s e t T i m e r %
455 % %
456 % %
457 % %
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 %
460 % ResetTimer() resets the stopwatch.
461 %
462 % The format of the ResetTimer method is:
463 %
464 % void ResetTimer(TimerInfo *time_info)
465 %
466 % A description of each parameter follows.
467 %
468 % o time_info: Timer statistics structure.
469 %
470 */
471 MagickExport void ResetTimer(TimerInfo *time_info)
472 {
473  assert(time_info != (TimerInfo *) NULL);
474  assert(time_info->signature == MagickCoreSignature);
475  StopTimer(time_info);
476  time_info->elapsed.stop=0.0;
477  time_info->user.stop=0.0;
478 }
479 
480 /*
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % %
483 % %
484 % %
485 % S e t M a g i c k D a t e P r e c i s i o n %
486 % %
487 % %
488 % %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 %
491 % SetMagickDatePrecision() sets the pseudo-random number generator secret key.
492 %
493 % The format of the SetMagickDatePrecision method is:
494 %
495 % void SetMagickDatePrecision(const unsigned long precision)
496 %
497 % A description of each parameter follows:
498 %
499 % o key: the date precision.
500 %
501 */
502 MagickPrivate void SetMagickDatePrecision(const unsigned long precision)
503 {
504  date_precision=(ssize_t) precision;
505 }
506 
507 /*
508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509 % %
510 % %
511 % %
512 + S t a r t T i m e r %
513 % %
514 % %
515 % %
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517 %
518 % StartTimer() starts the stopwatch.
519 %
520 % The format of the StartTimer method is:
521 %
522 % void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
523 %
524 % A description of each parameter follows.
525 %
526 % o time_info: Timer statistics structure.
527 %
528 % o reset: If reset is MagickTrue, then the stopwatch is reset prior to
529 % starting. If reset is MagickFalse, then timing is continued without
530 % resetting the stopwatch.
531 %
532 */
533 MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
534 {
535  assert(time_info != (TimerInfo *) NULL);
536  assert(time_info->signature == MagickCoreSignature);
537  if (reset != MagickFalse)
538  {
539  /*
540  Reset the stopwatch before starting it.
541  */
542  time_info->user.total=0.0;
543  time_info->elapsed.total=0.0;
544  }
545  if (time_info->state != RunningTimerState)
546  {
547  time_info->elapsed.start=ElapsedTime();
548  time_info->user.start=UserTime();
549  }
550  time_info->state=RunningTimerState;
551 }
552 
553 /*
554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555 % %
556 % %
557 % %
558 + S t o p T i m e r %
559 % %
560 % %
561 % %
562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563 %
564 % StopTimer() stops the stopwatch.
565 %
566 % The format of the StopTimer method is:
567 %
568 % void StopTimer(TimerInfo *time_info)
569 %
570 % A description of each parameter follows.
571 %
572 % o time_info: Timer statistics structure.
573 %
574 */
575 static void StopTimer(TimerInfo *time_info)
576 {
577  assert(time_info != (TimerInfo *) NULL);
578  assert(time_info->signature == MagickCoreSignature);
579  time_info->elapsed.stop=ElapsedTime();
580  time_info->user.stop=UserTime();
581  if (time_info->state == RunningTimerState)
582  {
583  time_info->user.total+=time_info->user.stop-
584  time_info->user.start+MagickEpsilon;
585  time_info->elapsed.total+=time_info->elapsed.stop-
586  time_info->elapsed.start+MagickEpsilon;
587  }
588  time_info->state=StoppedTimerState;
589 }
590 
591 /*
592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 % %
594 % %
595 % %
596 + U s e r T i m e %
597 % %
598 % %
599 % %
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601 %
602 % UserTime() returns the total time the process has been scheduled (in
603 % seconds) since the last call to StartTimer().
604 %
605 % The format of the UserTime method is:
606 %
607 % double UserTime()
608 %
609 */
610 static double UserTime(void)
611 {
612 #if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
613  struct tms
614  timer;
615 
616  (void) times(&timer);
617  return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
618 #else
619 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
620  return(NTElapsedTime());
621 #else
622  return((double) clock()/CLOCKS_PER_SEC);
623 #endif
624 #endif
625 }
_TimerInfo
Definition: timer.h:40