<commit_before>;;;; Copyright (c) 2011-2016 <NAME> <<EMAIL>>
;;;; This code is licensed under the MIT license.

(in-package :mezzano.supervisor)

(defconstant internal-time-units-per-second 1000000)

(defconstant +pit-irq+ 0)

(sys.int::defglobal *heartbeat-wait-queue*)

(sys.int::defglobal *rtc-lock*)

(sys.int::defglobal *pit-tick-rate* 0)

(sys.int::defglobal *run-time-advance*)
(sys.int::defglobal *run-time*)

(sys.int::defglobal *cpu-speed*)

;; http://wiki.osdev.org/Programmable_Interval_Timer
(defun configure-pit-tick-rate (hz)
  (let ((divisor (min #x10000 (truncate 1193180 hz))))
    (setf *pit-tick-rate* (/ 1.0 hz)
          *run-time-advance* (truncate (* *pit-tick-rate*
                                          internal-time-units-per-second)))
    ;; Channel 0. lobyte/hibyte. Square wave generator. Not BCD.
    (setf (system:io-port/8 #x43) #x36)
    ;; Write low & high bytes to channel 0.
    (setf (system:io-port/8 #x40) (ldb (byte 8 0) divisor)
          (system:io-port/8 #x40) (ldb (byte 8 8) divisor))))

(defun calibrate-tsc-1 ()
  "Return the number of cycles per second, approximately."
  (let ((initial-time *run-time*)
        (start-time nil)
        (end-time nil)
        (start-cycle nil)
        (end-cycle nil))
    ;; Wait for the start of this tick.
    (loop
       (setf start-time *run-time*)
       (when (not (eq start-time initial-time))
         (return)))
    (setf start-cycle (sys.int::tsc))
    (loop
       (setf end-time *run-time*)
       (when (not (eq end-time start-time))
         (return)))
    (setf end-cycle (sys.int::tsc))
    (let* ((cycles (- end-cycle start-cycle))
           (time (/ (float (- end-time start-time)) internal-time-units-per-second))
           (cycles-per-second (/ cycles time)))
      cycles-per-second)))

(defun calibrate-tsc ()
  (let ((n (calibrate-tsc-1)))
    (dotimes (i 5)
      (setf n (/ (+ n (calibrate-tsc-1)) 2)))
    (setf *cpu-speed* n)))

(defun initialize-time ()
  (when (not (boundp '*heartbeat-wait-queue*))
    (setf *heartbeat-wait-queue* (make-wait-queue :name "Heartbeat wait queue"))
    (setf *rtc-lock* (place-spinlock-initializer)))
  (setf *run-time* 0)
  (configure-pit-tick-rate 100)
  (i8259-hook-irq +pit-irq+ 'pit-irq-handler)
  (i8259-unmask-irq +pit-irq+)
  (calibrate-tsc))

(defun pit-irq-handler (interrupt-frame irq)
  (declare (ignore interrupt-frame irq))
  (incf *run-time* *run-time-advance*)
  (with-wait-queue-lock (*heartbeat-wait-queue*)
    (do ()
        ((null (wait-queue-head *heartbeat-wait-queue*)))
      (wake-thread (pop-wait-queue *heartbeat-wait-queue*))))<commit_msg>Use GET-INTERNAL-RUN-TIME when calibrating the x86 TSC.<commit_after>;;;; Copyright (c) 2011-2016 <NAME> <<EMAIL>>
;;;; This code is licensed under the MIT license.

(in-package :mezzano.supervisor)

(defconstant internal-time-units-per-second 1000000)

(defconstant +pit-irq+ 0)

(sys.int::defglobal *heartbeat-wait-queue*)

(sys.int::defglobal *rtc-lock*)

(sys.int::defglobal *pit-tick-rate* 0)

(sys.int::defglobal *run-time-advance*)
(sys.int::defglobal *run-time*)

(sys.int::defglobal *cpu-speed*)

;; http://wiki.osdev.org/Programmable_Interval_Timer
(defun configure-pit-tick-rate (hz)
  (let ((divisor (min #x10000 (truncate 1193180 hz))))
    (setf *pit-tick-rate* (/ 1.0 hz)
          *run-time-advance* (truncate (* *pit-tick-rate*
                                          internal-time-units-per-second)))
    ;; Channel 0. lobyte/hibyte. Square wave generator. Not BCD.
    (setf (system:io-port/8 #x43) #x36)
    ;; Write low & high bytes to channel 0.
    (setf (system:io-port/8 #x40) (ldb (byte 8 0) divisor)
          (system:io-port/8 #x40) (ldb (byte 8 8) divisor))))

(defun calibrate-tsc-1 ()
  "Return the number of cycles per second, approximately."
  (let ((initial-time (get-internal-run-time))
        (start-time nil)
        (end-time nil)
        (start-cycle nil)
        (end-cycle nil))
    ;; Wait for the start of this tick.
    (loop
       (setf start-time (get-internal-run-time))
       (when (not (eq start-time initial-time))
         (return)))
    (setf start-cycle (sys.int::tsc))
    (loop
       (setf end-time (get-internal-run-time))
       (when (not (eq end-time start-time))
         (return)))
    (setf end-cycle (sys.int::tsc))
    (let* ((cycles (- end-cycle start-cycle))
           (time (/ (float (- end-time start-time)) internal-time-units-per-second))
           (cycles-per-second (/ cycles time)))
      cycles-per-second)))

(defun calibrate-tsc ()
  (let ((n (calibrate-tsc-1)))
    (dotimes (i 5)
      (setf n (/ (+ n (calibrate-tsc-1)) 2)))
    (setf *cpu-speed* n)))

(defun initialize-time ()
  (when (not (boundp '*heartbeat-wait-queue*))
    (setf *heartbeat-wait-queue* (make-wait-queue :name "Heartbeat wait queue"))
    (setf *rtc-lock* (place-spinlock-initializer)))
  (setf *run-time* 0)
  (configure-pit-tick-rate 100)
  (i8259-hook-irq +pit-irq+ 'pit-irq-handler)
  (i8259-unmask-irq +pit-irq+)
  (calibrate-tsc))

(defun pit-irq-handler (interrupt-frame irq)
  (declare (ignore interrupt-frame irq))
  (incf *run-time* *run-time-advance*)
  (with-wait-queue-lock (*heartbeat-wait-queue*)
    (do ()
        ((null (wait-queue-head *heartbeat-wait-queue*)))
      (wake-thread (pop-wait-queue *heartbeat-wait-queue*))))
{'fraction_non_alphanumeric': 0.1781619996241308, 'fraction_numerical': 0.02480736703627138, 'mean_word_length': 2.9161147902869757, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6137613', 'n_tokens_mistral': 2069, 'n_tokens_neox': 1934, 'n_words': 441}