@@ -50,7 +50,7 @@ static int64_t KernelBootTimeInNanoseconds() {
50
50
if (rc != 0 ) {
51
51
return 0 ;
52
52
}
53
- return (int64_t )boottime.tv_sec * NSEC_PER_MSEC + (int64_t )boottime.tv_usec ;
53
+ return (int64_t )boottime.tv_sec * NSEC_PER_SEC + (int64_t )boottime.tv_usec * NSEC_PER_USEC ;
54
54
}
55
55
56
56
/* * Returns value of gettimeofday, in nanoseconds.
@@ -60,17 +60,18 @@ static int64_t KernelBootTimeInNanoseconds() {
60
60
* @return The value of gettimeofday, in nanoseconds.
61
61
*/
62
62
static int64_t UptimeInNanoseconds () {
63
- int64_t before_now ;
64
- int64_t after_now ;
63
+ int64_t before_now_nsec ;
64
+ int64_t after_now_nsec ;
65
65
struct timeval now;
66
66
67
- before_now = KernelBootTimeInNanoseconds ();
67
+ before_now_nsec = KernelBootTimeInNanoseconds ();
68
68
// Addresses a race condition in which the system time has updated, but the boottime has not.
69
69
do {
70
70
gettimeofday (&now, NULL );
71
- after_now = KernelBootTimeInNanoseconds ();
72
- } while (after_now != before_now);
73
- return (int64_t )now.tv_sec * NSEC_PER_MSEC + (int64_t )now.tv_usec - before_now;
71
+ after_now_nsec = KernelBootTimeInNanoseconds ();
72
+ } while (after_now_nsec != before_now_nsec);
73
+ return (int64_t )now.tv_sec * NSEC_PER_SEC + (int64_t )now.tv_usec * NSEC_PER_USEC -
74
+ before_now_nsec;
74
75
}
75
76
76
77
// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE.
@@ -79,8 +80,8 @@ @implementation GDTCORClock
79
80
- (instancetype )init {
80
81
self = [super init ];
81
82
if (self) {
82
- _kernelBootTime = KernelBootTimeInNanoseconds ();
83
- _uptime = UptimeInNanoseconds ();
83
+ _kernelBootTimeNanoseconds = KernelBootTimeInNanoseconds ();
84
+ _uptimeNanoseconds = UptimeInNanoseconds ();
84
85
_timeMillis =
85
86
(int64_t )((CFAbsoluteTimeGetCurrent () + kCFAbsoluteTimeIntervalSince1970 ) * NSEC_PER_USEC);
86
87
CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem ();
@@ -102,21 +103,26 @@ + (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture {
102
103
103
104
- (BOOL )isAfter : (GDTCORClock *)otherClock {
104
105
// These clocks are trivially comparable when they share a kernel boot time.
105
- if (_kernelBootTime == otherClock->_kernelBootTime ) {
106
+ if (_kernelBootTimeNanoseconds == otherClock->_kernelBootTimeNanoseconds ) {
106
107
int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) -
107
108
(otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds );
108
109
return timeDiff > 0 ;
109
110
} else {
110
- int64_t kernelBootTimeDiff = otherClock->_kernelBootTime - _kernelBootTime;
111
+ int64_t kernelBootTimeDiff =
112
+ otherClock->_kernelBootTimeNanoseconds - _kernelBootTimeNanoseconds;
111
113
// This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO
112
114
// is returned. This can be altered by changing the system time and rebooting.
113
115
return kernelBootTimeDiff < 0 ? YES : NO ;
114
116
}
115
117
}
116
118
119
+ - (int64_t )uptimeMilliseconds {
120
+ return self.uptimeNanoseconds / NSEC_PER_MSEC;
121
+ }
122
+
117
123
- (NSUInteger )hash {
118
- return [@(_kernelBootTime ) hash ] ^ [@(_uptime) hash ] ^ [@(_timeMillis ) hash ] ^
119
- [@(_timezoneOffsetSeconds) hash ];
124
+ return [@(_kernelBootTimeNanoseconds ) hash ] ^ [@(_uptimeNanoseconds ) hash ] ^
125
+ [@(_timeMillis) hash ] ^ [@( _timezoneOffsetSeconds) hash ];
120
126
}
121
127
122
128
- (BOOL )isEqual : (id )object {
@@ -134,7 +140,7 @@ - (BOOL)isEqual:(id)object {
134
140
/* * NSKeyedCoder key for _kernelBootTime ivar. */
135
141
static NSString *const kGDTCORClockKernelBootTime = @" GDTCORClockKernelBootTime" ;
136
142
137
- /* * NSKeyedCoder key for _uptime ivar. */
143
+ /* * NSKeyedCoder key for _uptimeNanoseconds ivar. */
138
144
static NSString *const kGDTCORClockUptime = @" GDTCORClockUptime" ;
139
145
140
146
+ (BOOL )supportsSecureCoding {
@@ -144,21 +150,31 @@ + (BOOL)supportsSecureCoding {
144
150
- (instancetype )initWithCoder : (NSCoder *)aDecoder {
145
151
self = [super init ];
146
152
if (self) {
147
- // TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and
148
- // uptimeMillis ivars
153
+ // TODO: If the kernelBootTimeNanoseconds is more recent, we need to change the kernel boot time
154
+ // and uptimeMillis ivars
149
155
_timeMillis = [aDecoder decodeInt64ForKey: kGDTCORClockTimeMillisKey ];
150
156
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey: kGDTCORClockTimezoneOffsetSeconds ];
151
- _kernelBootTime = [aDecoder decodeInt64ForKey: kGDTCORClockKernelBootTime ];
152
- _uptime = [aDecoder decodeInt64ForKey: kGDTCORClockUptime ];
157
+ _kernelBootTimeNanoseconds = [aDecoder decodeInt64ForKey: kGDTCORClockKernelBootTime ];
158
+ _uptimeNanoseconds = [aDecoder decodeInt64ForKey: kGDTCORClockUptime ];
153
159
}
154
160
return self;
155
161
}
156
162
157
163
- (void )encodeWithCoder : (NSCoder *)aCoder {
158
164
[aCoder encodeInt64: _timeMillis forKey: kGDTCORClockTimeMillisKey ];
159
165
[aCoder encodeInt64: _timezoneOffsetSeconds forKey: kGDTCORClockTimezoneOffsetSeconds ];
160
- [aCoder encodeInt64: _kernelBootTime forKey: kGDTCORClockKernelBootTime ];
161
- [aCoder encodeInt64: _uptime forKey: kGDTCORClockUptime ];
166
+ [aCoder encodeInt64: _kernelBootTimeNanoseconds forKey: kGDTCORClockKernelBootTime ];
167
+ [aCoder encodeInt64: _uptimeNanoseconds forKey: kGDTCORClockUptime ];
168
+ }
169
+
170
+ #pragma mark - Deprecated properties
171
+
172
+ - (int64_t )kernelBootTime {
173
+ return self.kernelBootTimeNanoseconds ;
174
+ }
175
+
176
+ - (int64_t )uptime {
177
+ return self.uptimeNanoseconds ;
162
178
}
163
179
164
180
@end
0 commit comments