]> git.saurik.com Git - apple/xnu.git/blobdiff - libsyscall/wrappers/mach_approximate_time.s
xnu-4570.1.46.tar.gz
[apple/xnu.git] / libsyscall / wrappers / mach_approximate_time.s
index 7ef3336f745a82d29280770bde2f370061a64cb0..f1e6ed8714b6462ed68b290d7fef77e0d16fe467 100644 (file)
 #include <sys/appleapiopts.h>
 #include <machine/cpu_capabilities.h>
 
-#if   defined(__i386__)
+#if defined(__arm__)
+
+       .text
+       .align  2
+       .globl  _mach_approximate_time
+_mach_approximate_time:
+
+       movw    r0, #((_COMM_PAGE_APPROX_TIME_SUPPORTED>>0)&0x0FFFF)
+       movt    r0, #((_COMM_PAGE_APPROX_TIME_SUPPORTED>>16)&0x0FFFF)
+       ldrb    r0, [r0]                // load COMM_PAGE_APPROX_TIME_SUPPORTED
+       cmp     r0, #1                  // check if approx time is supported
+        
+        bne      _mach_absolute_time   // if not supported, fall through to
+                                       //   absolute_time
+
+       movw    r2, #((_COMM_PAGE_APPROX_TIME>>0)&0x0FFFF)
+       movt    r2, #((_COMM_PAGE_APPROX_TIME>>16)&0x0FFFF)
+
+        // at this point, r2->COMM_PAGE_APPROX_TIME, which is a 64-bit value.
+        // Since this is a 32-bit architecture, and the commpage is readonly,
+        // there is no "guaranteed" atomic way to read all 64-bits with
+        // hardware protection. Even the ldrd instruction is not guaranteed to
+        // complete atomically. The solution is to use a 32-bit high/low/high
+        // read with a consistency check on the high bits. To further
+        // complicate things, reading the same location in memory back to back
+        // could trigger a predictive read, which would defeat the purpose of
+        // doing the consistency check so we insert a data memory barrier to
+        // prevent this.
+_consistency_check:
+        ldr     r1, [r2,#4]            // load high
+        ldr     r0, [r2]               // load low
+        dsb                            // avoid predictive reads that could
+                                       //   be invalid if interrupted
+        ldr     r3, [r2,#4]            // load high again
+        cmp     r1, r3                 // check that high1 == high2
+       bne     _consistency_check      // try again if not
+        bx      lr
+
+#elif defined(__i386__)
 
        .text
        .align  4, 0x90