LCOV - app.info - xpcom/ds/TimeStamp_posix.cpp

LCOV - code coverage report
| Current view: | directory - xpcom/ds - TimeStamp_posix.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 54 | 45 | 83.3 %
| Date: | 2012-04-21 | Functions: | 15 | 12 | 80.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is the Mozilla Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2009
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *  Chris Jones <jones.chris.g@gmail.com>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : //
          40                 : // Implement TimeStamp::Now() with POSIX clocks.
          41                 : //
          42                 : // The "tick" unit for POSIX clocks is simply a nanosecond, as this is
          43                 : // the smallest unit of time representable by struct timespec.  That
          44                 : // doesn't mean that a nanosecond is the resolution of TimeDurations
          45                 : // obtained with this API; see TimeDuration::Resolution;
          46                 : //
          47                 :
          48                 : #include <time.h>
          49                 :
          50                 : #include "mozilla/TimeStamp.h"
          51                 :
          52                 : // Estimate of the smallest duration of time we can measure.
          53                 : static PRUint64 sResolution;
          54                 : static PRUint64 sResolutionSigDigs;
          55                 :
          56                 : static const PRUint16 kNsPerUs   =       1000;
          57                 : static const PRUint64 kNsPerMs   =    1000000;
          58                 : static const PRUint64 kNsPerSec  = 1000000000;
          59                 : static const double kNsPerMsd    =    1000000.0;
          60                 : static const double kNsPerSecd   = 1000000000.0;
          61                 :
          62                 : static PRUint64
          63         1868269 : TimespecToNs(const struct timespec& ts)
          64                 : {
          65         1868269 :   PRUint64 baseNs = PRUint64(ts.tv_sec) * kNsPerSec;
          66         1868269 :   return baseNs + PRUint64(ts.tv_nsec);
          67                 : }
          68                 :
          69                 : static PRUint64
          70         1867367 : ClockTimeNs()
          71                 : {
          72                 :   struct timespec ts;
          73                 :   // this can't fail: we know &ts is valid, and TimeStamp::Init()
          74                 :   // checks that CLOCK_MONOTONIC is supported (and aborts if not)
          75         1867367 :   clock_gettime(CLOCK_MONOTONIC, &ts);
          76                 :
          77                 :   // tv_sec is defined to be relative to an arbitrary point in time,
          78                 :   // but it would be madness for that point in time to be earlier than
          79                 :   // the Epoch.  So we can safely assume that even if time_t is 32
          80                 :   // bits, tv_sec won't overflow while the browser is open.  Revisit
          81                 :   // this argument if we're still building with 32-bit time_t around
          82                 :   // the year 2037.
          83         1867367 :   return TimespecToNs(ts);
          84                 : }
          85                 :
          86                 : static PRUint64
          87            1396 : ClockResolutionNs()
          88                 : {
          89                 :   // NB: why not rely on clock_getres()?  Two reasons: (i) it might
          90                 :   // lie, and (ii) it might return an "ideal" resolution that while
          91                 :   // theoretically true, could never be measured in practice.  Since
          92                 :   // clock_gettime() likely involves a system call on your platform,
          93                 :   // the "actual" timing resolution shouldn't be lower than syscall
          94                 :   // overhead.
          95                 :
          96            1396 :   PRUint64 start = ClockTimeNs();
          97            1396 :   PRUint64 end = ClockTimeNs();
          98            1396 :   PRUint64 minres = (end - start);
          99                 :
         100                 :   // 10 total trials is arbitrary: what we're trying to avoid by
         101                 :   // looping is getting unlucky and being interrupted by a context
         102                 :   // switch or signal, or being bitten by paging/cache effects
         103           13960 :   for (int i = 0; i < 9; ++i) {
         104           12564 :     start = ClockTimeNs();
         105           12564 :     end = ClockTimeNs();
         106                 :
         107           12564 :     PRUint64 candidate = (start - end);
         108           12564 :     if (candidate < minres)
         109              75 :       minres = candidate;
         110                 :   }
         111                 :
         112            1396 :   if (0 == minres) {
         113                 :     // measurable resolution is either incredibly low, ~1ns, or very
         114                 :     // high.  fall back on clock_getres()
         115                 :     struct timespec ts;
         116             902 :     if (0 == clock_getres(CLOCK_MONOTONIC, &ts)) {
         117             902 :       minres = TimespecToNs(ts);
         118                 :     }
         119                 :   }
         120                 :
         121            1396 :   if (0 == minres) {
         122                 :     // clock_getres probably failed.  fall back on NSPR's resolution
         123                 :     // assumption
         124               0 :     minres = 1 * kNsPerMs;
         125                 :   }
         126                 :
         127            1396 :   return minres;
         128                 : }
         129                 :
         130                 :
         131                 : namespace mozilla {
         132                 :
         133                 : double
         134          890408 : TimeDuration::ToSeconds() const
         135                 : {
         136          890408 :   return double(mValue) / kNsPerSecd;
         137                 : }
         138                 :
         139                 : double
         140               0 : TimeDuration::ToSecondsSigDigits() const
         141                 : {
         142                 :   // don't report a value < mResolution ...
         143               0 :   PRInt64 valueSigDigs = sResolution * (mValue / sResolution);
         144                 :   // and chop off insignificant digits
         145               0 :   valueSigDigs = sResolutionSigDigs * (valueSigDigs / sResolutionSigDigs);
         146               0 :   return double(valueSigDigs) / kNsPerSecd;
         147                 : }
         148                 :
         149                 : TimeDuration
         150           73347 : TimeDuration::FromMilliseconds(double aMilliseconds)
         151                 : {
         152           73347 :   return TimeDuration::FromTicks(aMilliseconds * kNsPerMsd);
         153                 : }
         154                 :
         155                 : TimeDuration
         156               0 : TimeDuration::Resolution()
         157                 : {
         158               0 :   return TimeDuration::FromTicks(PRInt64(sResolution));
         159                 : }
         160                 :
         161                 : struct TimeStampInitialization
         162                 : {
         163            1396 :   TimeStampInitialization() {
         164            1396 :     TimeStamp::Startup();
         165            1396 :   }
         166            1419 :   ~TimeStampInitialization() {
         167            1419 :     TimeStamp::Shutdown();
         168            1419 :   }
         169                 : };
         170                 :
         171            1396 : static TimeStampInitialization initOnce;
         172                 : static bool gInitialized = false;
         173                 :
         174                 : nsresult
         175            1396 : TimeStamp::Startup()
         176                 : {
         177            1396 :   if (gInitialized)
         178               0 :     return NS_OK;
         179                 :
         180                 :   struct timespec dummy;
         181            1396 :   if (0 != clock_gettime(CLOCK_MONOTONIC, &dummy))
         182               0 :       NS_RUNTIMEABORT("CLOCK_MONOTONIC is absent!");
         183                 :
         184            1396 :   sResolution = ClockResolutionNs();
         185                 :
         186                 :   // find the number of significant digits in sResolution, for the
         187                 :   // sake of ToSecondsSigDigits()
         188           14794 :   for (sResolutionSigDigs = 1;
         189                 :        !(sResolutionSigDigs == sResolution
         190           14794 :          || 10*sResolutionSigDigs > sResolution);
         191                 :        sResolutionSigDigs *= 10);
         192                 :
         193            1396 :   gInitialized = true;
         194            1396 :   return NS_OK;
         195                 : }
         196                 :
         197                 : void
         198            1419 : TimeStamp::Shutdown()
         199                 : {
         200            1419 : }
         201                 :
         202                 : TimeStamp
         203         1839447 : TimeStamp::Now()
         204                 : {
         205         1839447 :   return TimeStamp(ClockTimeNs());
         206                 : }
         207                 :
         208            4188 : }

Generated by: LCOV version 1.7