changeset 497: |
bcf772e86fbc |
parent: |
cde5360295cd
|
child: |
da17bf652e48 |
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Mon, 01 Jul 2024 20:48:11 -0400 |
permissions: |
-rw-r--r-- |
description: |
add std/task, some fixes and added cli/tools/systemd |
1 ;;; threads.lisp --- Multi-thread utilities 7 ;; mostly yoinked from sb-thread and friends 10 (in-package :std/thread) 12 ;; (sb-thread:thread-os-tid sb-thread:*current-thread*) 13 ;; sb-thread:interrupt-thread 16 (defun thread-support-p () (member :thread-support *features*)) 18 (eval-when (:compile-toplevel) 19 (defun print-top-level (msg) 20 (sb-thread:make-thread 22 (format #.*standard-output* msg))) 25 (defun find-thread-by-id (id) 26 "Search for thread by ID which must be an u64. On success returns the thread itself or nil." 27 (find id (sb-thread::list-all-threads) :test '= :key 'thread-os-tid)) 29 (defun find-thread (name) 30 "Find a thread by name." 31 (find name (sb-thread::list-all-threads) :test 'equal :key 'thread-name)) 33 (defun thread-key-list () 34 (sb-thread::avltree-filter #'sb-thread::avlnode-key sb-thread::*all-threads*)) 36 (defun thread-id-list () 37 (sb-thread::avltree-filter (lambda (th) (thread-os-tid (sb-thread::avlnode-data th))) sb-thread::*all-threads*)) 39 (defun thread-count () 40 (sb-thread::avl-count sb-thread::*all-threads*)) 42 (defun make-threads (n fn &key (name "thread")) 43 (declare (type fixnum n)) 45 collect (make-thread fn :name (format nil "~A-~D" name i)))) 47 (defun parse-lambda-list-names (ll) 48 (multiple-value-bind (idx _ args) (sb-int:parse-lambda-list ll) 49 (declare (ignore idx _)) 56 (defmacro with-threads ((n &key args) &body body) 57 `(make-threads ,n (lambda (,@args) (declare (ignorable ,@(parse-lambda-list-names args))) ,@body))) 59 (defun finish-threads (&rest threads) 60 (let ((threads (flatten threads))) 62 (mapc #'join-thread threads) 63 (dolist (thread threads) 64 (when (thread-alive-p thread) 65 (terminate-thread thread)))))) 67 (defun timed-join-thread (thread timeout) 68 (declare (type thread thread) (type float timeout)) 69 (handler-case (sb-sys:with-deadline (:seconds timeout) 70 (join-thread thread :default :aborted)) 75 (join-thread *current-thread*)) 77 (defun kill-thread (thread) 78 (when (thread-alive-p thread) 80 (terminate-thread thread)))) 82 ;; (sb-vm::primitive-object-slots (sb-vm::primitive-object 'sb-vm::thread)) 83 (defun init-session (&optional (thread *current-thread*)) (sb-thread::new-session thread)) 85 ;; (sb-thread::with-progressive-timeout (timet :seconds 4) (dotimes (i 4000) (print (timet)))) 87 ;; (describe sb-thread::*session*) 89 ;; make-listener-thread 91 ;; with-progressive-timeout 95 (let* ((slots (sb-vm::primitive-object-slots #1=(sb-vm::primitive-object 'sb-vm::thread))) 96 (sap (current-thread-sap)) 97 (thread-obj-len (sb-vm::primitive-object-length #1#)) 98 (names (make-array thread-obj-len :initial-element ""))) 99 (loop for slot across slots 101 (setf (aref names (sb-vm::slot-offset slot)) (sb-vm::slot-name slot))) 102 (flet ((safely-read (sap offset &aux (bits (sb-vm::sap-ref-word sap offset))) 103 (cond ((eql bits sb-vm:no-tls-value-marker) :no-tls-value) 104 ((eql (logand bits sb-vm:widetag-mask) sb-vm:unbound-marker-widetag) :unbound) 105 (t (sb-vm::sap-ref-lispobj sap offset)))) 107 (declare (type fixnum sym)) 108 (let ((*print-right-margin* 128) 110 (format t " ~3d ~30a : ~s~%" 111 #+sb-thread (ash sym (- sb-vm:word-shift)) 113 #+sb-thread (sb-vm:symbol-from-tls-index sym) 116 (format t "~&TLS: (base=~x)~%" (sb-vm::sap-int sap)) 117 (loop for tlsindex from sb-vm:n-word-bytes below 118 #+sb-thread (ash sb-vm::*free-tls-index* sb-vm:n-fixnum-tag-bits) 119 #-sb-thread (ash thread-obj-len sb-vm:word-shift) 120 by sb-vm:n-word-bytes 122 (unless (<= sb-vm::thread-allocator-histogram-slot 123 (ash tlsindex (- sb-vm:word-shift)) 124 (1- sb-vm::thread-lisp-thread-slot)) 125 (let ((thread-slot-name 126 (if (< tlsindex (ash thread-obj-len sb-vm:word-shift)) 127 (aref names (ash tlsindex (- sb-vm:word-shift)))))) 128 (if (and thread-slot-name (sb-vm::neq thread-slot-name 'sb-vm::lisp-thread)) 129 (format t " ~3d ~30a : #x~x~%" (ash tlsindex (- sb-vm:word-shift)) 130 thread-slot-name (sb-vm::sap-ref-word sap tlsindex)) 131 (let ((val (safely-read sap tlsindex))) 132 (unless (eq val :no-tls-value) 133 (show tlsindex val))))))) 134 (let ((from (sb-vm::descriptor-sap sb-vm:*binding-stack-start*)) 135 (to (sb-vm::binding-stack-pointer-sap))) 136 (format t "~%Binding stack: (depth ~d)~%" 137 (/ (sb-vm::sap- to from) (* sb-vm:binding-size sb-vm:n-word-bytes))) 139 (when (sb-vm::sap>= from to) (return)) 140 (let ((val (safely-read from 0)) 141 (sym #+sb-thread (sb-vm::sap-ref-word from sb-vm:n-word-bytes) ; a TLS index 142 #-sb-thread (sb-vm::sap-ref-lispobj from sb-vm:n-word-bytes))) 144 (setq from (sb-vm::sap+ from (* sb-vm:binding-size sb-vm:n-word-bytes)))))))) 146 (defun wait-for-threads (threads) 147 (map 'list (lambda (thread) (sb-thread:join-thread thread :default nil)) threads) 148 (not (some #'sb-thread:thread-alive-p threads))) 150 (defun process-all-interrupts (&optional (thread sb-thread:*current-thread*)) 151 (sb-ext:wait-for (null (sb-thread::thread-interruptions thread))))