+
+;;;; COUNTER object
+;;;;
+;;;; Thread safe, and reasonably fast: in common case increment is just an
+;;;; ATOMIC-INCF, in overflow case grab a lock and increment overflow counter.
+
+(defconstant +most-positive-word+ (1- (expt 2 sb-vm:n-word-bits)))
+
+(declaim (inline make-counter))
+(defstruct (counter (:copier nil))
+ (count 0 :type sb-vm:word)
+ (overflow 0 :type unsigned-byte)
+ (overflow-lock (sb-thread::make-spinlock) :type sb-thread::spinlock))
+
+(defun incf-counter (counter delta)
+ ;; When running multi-threaded we can easily get negative numbers for the
+ ;; cons-counter. Don't count them at all.
+ (when (plusp delta)
+ ;; ATOMIC-INCF is restricted to signed-word, but delta can be bigger: first
+ ;; count the number of full overflows...
+ (loop while (>= delta +most-positive-word+)
+ do (sb-thread::with-spinlock ((counter-overflow-lock counter))
+ (incf (counter-overflow counter) 1))
+ (decf delta +most-positive-word+))
+ (flet ((%incf (d)
+ (let ((prev (atomic-incf (counter-count counter) d)))
+ (when (< (logand +most-positive-word+ (+ prev d)) prev)
+ (sb-thread::with-spinlock ((counter-overflow-lock counter))
+ (incf (counter-overflow counter)))))))
+ (if (typep delta '(signed-byte 32))
+ (%incf delta)
+ ;; ...and if delta is still too big, split it into four parts: they
+ ;; are guaranteed to fit into a signed word.
+ (let ((quarter (truncate delta 4)))
+ (%incf quarter)
+ (%incf quarter)
+ (%incf quarter)
+ (%incf quarter)))))
+ counter)
+
+(defun counter->integer (counter)
+ (+ (counter-count counter)
+ (* (counter-overflow counter)
+ +most-positive-word+)))
+\f
+;;;; High resolution timer
+
+;;; FIXME: High resolution this is not. Build a microsecond-accuracy version
+;;; on top of unix-getrusage, maybe.