Coverage Report

Created: 2026-07-20 07:19

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