[Openmcl-devel] #_clock_get_time on Darwin returning bogus values

Hans Hübner hans at huebner.org
Thu Dec 4 02:47:34 PST 2008


Gary,

thanks for your explanation.  I think what it boils down to was that I
was trying to use a timespec where a  mach_timespec is required,
right?

-Hans

On Thu, Dec 4, 2008 at 11:15, Gary Byers <gb at clozure.com> wrote:
> (RLET ((ptr type)*) &body body)
>
> stack-allocates "an instance of type", binds "ptr" to a pointer to that
> stack-allocated instance, and executes "body" with that (dynamic-extent)
> binding in effect.
>
> ? (defun foo ()
>  (rlet ((ptr-to-int :int))
>    (print ptr-to-int)
>    ;; Don't return the stack-allocated pointer, which becomes invalid
>    ;; as soon as we exit the scope of the binding.
>    nil))
> FOO
> ? (foo)
> #<A Foreign Pointer [stack-allocated] (:* (:SIGNED 32)) #x7FFFFFBFEF10> NIL
>
> ":int" is shorthand for "signed 32-bit integer" on most platforms.  (I
> should have said that RLET also sets some bits in the pointer that describe
> the type of object the pointer's pointing to, which might be handy for
> debugging.)
>
> "Allocating an instance of the foreign type :int" could also be described
> as "reserving 4 bytes on the stack."  We've said nothing about what value
> those 4 bytes will have if interpreted as an :int, and they're in fact
> pretty much random, e.g., "whatever was last in that particular stack
> address".
>
> ? (defun bar ()
>  (rlet ((ptr-to-int :int))
>    (format t "~&the value of the :int that PTR-TO-INT is pointing to is #x~x
> ."
>            (pref ptr-to-int :int))
>    nil))
> BAR
> ? (bar)
> the value of the :int that PTR-TO-INT is pointing to is #x0 .
>
> Well, in my case it happened to be 0.  YMMV.
>
> Here's another example:
>
> (def-foreign-type :intptr (:* :int)) ; necessary since PREF wants a symbol
>
> (rlet ((ptr-to-ptr-to-int :intptr))
>  (format t "~&ptr-to-ptr-to-int = ~s, what it points to = ~s"
>    ptr-to-ptr-to-int (pref ptr-to-ptr-to-int :intptr))
>  nil)
>
> ? (rlet ((ptr-to-ptr-to-int :intptr))
>  (format t "~&ptr-to-ptr-to-int = ~s, what it points to = ~s"
>    ptr-to-ptr-to-int (pref ptr-to-ptr-to-int :intptr))
>  nil)
> ptr-to-ptr-to-int = #<A Foreign Pointer [stack-allocated] (:* (:* (:SIGNED
> 32))) #x7FFFFFBFEF10>, what it points to = #<A Foreign Pointer #x3100000033>
> NIL
>
> In that case, we allocated 8 bytes (on a 64-bit machine, would have been 4
> bytes in a 32-bit lisp) of uninitialized storage, and bound
> PTR-TO-PTR-TO-INT
> to the address of those 8/4 bytes.  If we interpret those bytes as an
> address, that "address" isn't too meaningful.
>
> If we had some foreign code like:
>
> int magic_number = 17;
>
> void
> get_address_of_magic_number(int **ref)
> {
>  *ref = &magic_number;
> }
>
> an RLET form like the one in the example above might be useful:
>
> (rlet ((magic-address-ptr :intptr))
>  (exernal-call "get_address_of_magic_number" :address magic-address-ptr
> :void)
>  (let* ((magic-address (pref magic-address-ptr :intptr)))
>     (format t "magic address = ~s, contents = ~s"
>             magic-address (pref magic-address :int))))
>
> After we've called the foreign code (passing it a "pointer to a pointer to
> an int" and that code has stored a "pointer to int" where we've asked it
> to, the contents of "magic-address-ptr" would be meaningful (as a "pointer
> ot int", and the contents of that "pointer to int" would be 17.  There -are-
> widely-used C functions that follow these kinds of
> conventions, but they're fortunately rare.
>
>
> Back to your case:
>
> - a :mach_timespec is a foreign record tyype that has two 32-bit fields
> named :tv_sec and :tv_nsec; for reasons best known to Apple, tv_sec
> is unsigned and :tv_nsec is signed (though since the :tv_nsec field
> is supposed to represent the number of nanoseconds in a time value
> or interval, the value of an initialized :tv_nsec field will always
> by >= 0 and < 1000000000).
>
> Note that this is a bit different from a POSIX :timespec structure,
> where (on 64-bit OSX) the :tv_sec field is 64 bits wide (and signed.)
>
> - a :mach_timespec_t is a "pointer to a :mach_timespec".
>
> - a :clock_serv_t is an unsigned 32-bit integer
>
> The Mach function clock_get_time() takes two arguments; the first
> is a clock_serv_t used to identify the clock service, and the second
> is a :mach_timepec_t (aka, a pointer to a :mach_timespec.)
>
> So, one way to do this (assuming that we want to ignore the possibility
> that the clock service port might change, e.g., if we save an image
> and run this code in a different session or different environment):
>
> (rlet ((prealtime-clock-port :clock_serv_t))
>  (#_host_get_clock_service (#_mach_host_self) #$REALTIME_CLOCK
> prealtime-clock-port)
>  (let* ((realtime-clock-port (pref prealtime-clock-port :clock_serv_t)))
>   (defun read-clock-seconds ()
>     ;; Allocate an uninitialized :mach_timespec, bind ts to a pointer to it
>     (rlet ((ts :mach_timespec))
>       ;; ts is a "pointer to a :mach_timepsec", or "a :mach_timespec_t".
>       (let* ((err (#_clock_get_time realtime-clock-port ts)))
>         (unless (eql err  #$KERN_SUCCESS)
>            (error "Mach error reading time, code = ~s" err))
>         ;; No error, access the tv_sec field of the :mach_timespec
>         ;; that ts points to and return that value.
>         (pref ts :mach_timespec.tv_sec))))))
>
> ;;; Unless SLEEP sleeps significantly longer than 1 second, these values
> ;;; should increase by 1 on each iteration.
> ? (dotimes (i 10) (print (read-clock-seconds) (sleep 1)))
> 2939807 2939808 2939809 2939810 2939811 2939812 2939813 2939814 2939815
> 2939816
>
>
>
>
>
> (let* ((
> (defun read-clock-seconds
>
> On Thu, 4 Dec 2008, Hans Hübner wrote:
>
>> Hi,
>>
>> I'm trying to fix the problem in the deterministic profiler on Darwin.
>> The problem seems to be that the clock reading function does not
>> work.  I am using Mach timers in the profiler, and I think I'm reading
>> them correctly, but the values returned do not make sense:
>>
>> PROF> (let ((clock-port (make-record :clock_serv_t)))
>>       (#_host_get_clock_service (#_mach_host_self) #$REALTIME_CLOCK
>> clock-port)
>>       (defun read-clock-seconds ()
>>         (ccl:rlet ((ts :mach_timespec_t))
>>           (#_clock_get_time (%get-ptr clock-port) ts)
>>           (pref ts :timespec.tv_sec))))
>> READ-CLOCK-SECONDS
>> PROF> (read-clock-seconds)
>> 990852764823254945
>> PROF> (read-clock-seconds)
>> 957862257734252450
>> PROF> (read-clock-seconds)
>> 4146603814037813155
>> PROF> (lisp-implementation-version)
>> "Version 1.3-dev-r11396M-trunk  (DarwinX8664)"
>>
>> I would expect the value to be increasing (and it used to work with
>> previous releases).  Maybe something with the header generation went
>> wrong?
>>
>> Thanks,
>> Hans
>> _______________________________________________
>> Openmcl-devel mailing list
>> Openmcl-devel at clozure.com
>> http://clozure.com/mailman/listinfo/openmcl-devel
>>
>



More information about the Openmcl-devel mailing list