Post

Replies

Boosts

Views

Activity

Reply to How to make sysctl and gettimeofday thread-safe in Swift?
@eskimo With regards the your previous post, that’s some convoluted code you’ve got going on here. I see what it’s trying to do, and it’s theoretically useful, but in practice the chances of a time change between the calls to currentTime() and bootTime() are vanishingly small. I understand the chances of it happening is small but just trying to prevent any unexpected bugs happening later on. If there is no problem with this implementation, then I am going to use it instead of clock_gettime & CLOCK_MONOTONIC_RAW since it may not return the correct uptime since the device is rebooted. There are some things to be aware of here. The first is that your use of CLOCK_MONOTONIC_RAW is not 100% compliant with the docs. The clock_gettime man page says “tracking the time since an arbitrary point”, and there’s no guarantee that this arbitrary point is the boot time. In practice on Apple platforms it is (modulo the next point), but it’s something to keep in mind. To confirm my understanding, you are saying the arbitrary point in CLOCK_MONOTONIC_RAW may not be the boot time, right? Therefore, the uptime that it returns may not be accurate? The second point relates to the concept of boot time. What is that time? Is it the time that the CPU starts? Or the time that the boot loader starts? Or the time that the kernel starts? And so on. This is further complicated by various edge cases, for example, our systems can do a user space restart without actually restarting the kernel. What I want to get is the time when the iOS device last rebooted
Apr ’24
Reply to How to make sysctl and gettimeofday thread-safe in Swift?
@eskimo I have also found another code snippet that can get system uptime using another API, clock_gettime(CLOCK_MONOTONIC_RAW, &uptime). Source: https://stackoverflow.com/a/45068046/23930754 Is the code snippet below thread-safe and free from race condition? If compared this code snippet with the code snippet (repeat loop & sysctl) above, which one of them would you recommend me to use based on its reliability and time accuracy given that I am using it to sync time in iOS with offset from the ntp time server? static func systemUptime() -> TimeInterval { var uptime = timespec() if 0 != clock_gettime(CLOCK_MONOTONIC_RAW, &uptime) { fatalError("Could not execute clock_gettime, errno: \(errno)") } let uptimeInNanoSeconds = UInt64(uptime.tv_sec * 1_000_000_000) + UInt64(uptime.tv_nsec) let uptimeInSeconds = TimeInterval(uptimeInNanoSeconds) / TimeInterval(NSEC_PER_SEC) return uptimeInSeconds }
Apr ’24
Reply to How to make sysctl and gettimeofday thread-safe in Swift?
@eskimo @endecotp Sorry for the misunderstanding! Some APIs are atomic, that is, they can be called from any thread at any time but they are still subject to races. Is there a way that I can prevent the race condition that you mentioned here? After some researches, I have found the Objective-C code posted in StackOverFlow that claims to prevent the race condition when getting up time. Link: https://stackoverflow.com/a/40497811 I have converted it to Swift below, is it true that the code below can prevent the race condition? static func systemUptime() -> TimeInterval { var now: TimeInterval var beforeNow: Double var afterNow = bootTime() var i = 0 repeat { assert(i < 10, "systemUpTime loop repeats more than 10 times") beforeNow = afterNow now = currentTime() afterNow = bootTime() i += 1 } while (afterNow != beforeNow) assert(now >= beforeNow, "inconsistent clock state: system time precedes boot time") return now - beforeNow } private static func bootTime() -> Double { var mib = [CTL_KERN, KERN_BOOTTIME] var size = MemoryLayout<timeval>.stride var bootTime = timeval() let bootTimeError = sysctl(&mib, u_int(mib.count), &bootTime, &size, nil, 0) != 0 assert(!bootTimeError, "system clock error: kernel boot time unavailable") return Double(bootTime.tv_sec) + Double(bootTime.tv_usec) / 1_000_000 } func currentTime() -> TimeInterval { var current = timeval() let systemTimeError = gettimeofday(&current, nil) != 0 assert(!systemTimeError, "system clock error: system time unavailable") return Double(current.tv_sec) + Double(current.tv_usec) / 1_000_000 }
Apr ’24