Changeset 15453


Ignore:
Timestamp:
Aug 31, 2012, 9:20:02 PM (8 years ago)
Author:
gb
Message:

%NANOSLEEP: work around a bug in some versions of #_nanosleep on
Darwin. (The bug was introduced in an early prerelease of 10.5
and is still present in some versions of 10.6 but seems to be fixed
in later OS releases.)

An earlier attempt to work around the bug was incorrect; this version
tries to detect invalid "remaining seconds" by refusing to sleep for
more than ... oh, 30 years are so. Very large numbers of remaining
seconds after an interrupt can be treated as "a negative 32-bit number
of remaining seconds, zero-extended", which can in turn be treated as
"we slept long enough."

(A consequence is that attempts to sleep for more than ~30 years will
sleep for ~30 years. Let them report it ...)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/level-1/l1-lisp-threads.lisp

    r15358 r15453  
    4040#-windows-target
    4141(defun %nanosleep (seconds nanoseconds)
     42  #+(and darwin-target 64-bit-target)
     43  (when (> seconds #x3fffffff)          ;over 30 years in seconds
     44    (setq seconds #x3fffffff))
    4245  (with-process-whostate ("Sleep")
    4346    (rlet ((a :timespec)
     
    4851             (bptr b))
    4952        (loop
    50           (let* ((result
    51                   (external-call #+darwin-target "_nanosleep"
    52                                  #-darwin-target "nanosleep"
    53                                  :address aptr
    54                                  :address bptr
    55                                  :signed-fullword)))
     53          (let* ((result (#_nanosleep aptr bptr)))
    5654            (declare (type (signed-byte 32) result))
    5755            (if (and (< result 0)
    5856                     (eql (%get-errno) (- #$EINTR)))
    59               (psetq aptr bptr bptr aptr)
     57              (progn
     58                ;; Some versions of OSX have a bug: if the call to #_nanosleep
     59                ;; is interrupted near the time when the timeout would
     60                ;; have occurred, the "remaining time" is computed as
     61                ;; a negative value and, on 64-bit platforms, zero-extended.
     62                #+(and darwin-target 64-bit-target)
     63                (when (>= (pref bptr :timespec.tv_sec) #x80000000)
     64                  (return))
     65                (psetq aptr bptr bptr aptr))
    6066              (return))))))))
    6167
Note: See TracChangeset for help on using the changeset viewer.