changeset 664: | 4d8451fe5423 |
parent: | da17bf652e48 |
author: | Richard Westhaver <ellis@rwest.io> |
date: | Sun, 22 Sep 2024 01:02:49 -0400 |
permissions: | -rw-r--r-- |
description: | moved web to lib/web, added dat/css |
5 | 1 | ;;; threads.lisp --- Multi-thread utilities |
2 | ||
3 | ;; Threading Macros |
|
4 | ||
5 | ;;; Commentary: |
|
6 | ||
7 | ;; mostly yoinked from sb-thread and friends |
|
8 | ||
9 | ;;; Code: |
|
291 | 10 | (in-package :std/thread) |
5 | 11 | |
261 | 12 | ;; (sb-thread:thread-os-tid sb-thread:*current-thread*) |
13 | ;; sb-thread:interrupt-thread |
|
14 | ||
664
4d8451fe5423
moved web to lib/web, added dat/css
Richard Westhaver <ellis@rwest.io>
parents:
514
diff
changeset
|
15 | ;;; Conditions |
4d8451fe5423
moved web to lib/web, added dat/css
Richard Westhaver <ellis@rwest.io>
parents:
514
diff
changeset
|
16 | (define-condition std-thread-error (thread-error) ()) |
4d8451fe5423
moved web to lib/web, added dat/css
Richard Westhaver <ellis@rwest.io>
parents:
514
diff
changeset
|
17 | |
492
dc0cc9c69789
ephemeral worker threads
Richard Westhaver <ellis@rwest.io>
parents:
454
diff
changeset
|
18 | ;;; Utils |
5 | 19 | (defun thread-support-p () (member :thread-support *features*)) |
20 | ||
21 | (eval-when (:compile-toplevel) |
|
492
dc0cc9c69789
ephemeral worker threads
Richard Westhaver <ellis@rwest.io>
parents:
454
diff
changeset
|
22 | (defun print-top-level (msg) |
5 | 23 | (sb-thread:make-thread |
24 | (lambda () |
|
25 | (format #.*standard-output* msg))) |
|
26 | nil)) |
|
118
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
27 | |
119 | 28 | (defun find-thread-by-id (id) |
118
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
29 | "Search for thread by ID which must be an u64. On success returns the thread itself or nil." |
437
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
30 | (find id (sb-thread::list-all-threads) :test '= :key 'thread-os-tid)) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
31 | |
454 | 32 | (defun find-thread (name) |
33 | "Find a thread by name." |
|
34 | (find name (sb-thread::list-all-threads) :test 'equal :key 'thread-name)) |
|
35 | ||
437
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
36 | (defun thread-key-list () |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
37 | (sb-thread::avltree-filter #'sb-thread::avlnode-key sb-thread::*all-threads*)) |
118
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
38 | |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
39 | (defun thread-id-list () |
437
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
40 | (sb-thread::avltree-filter (lambda (th) (thread-os-tid (sb-thread::avlnode-data th))) sb-thread::*all-threads*)) |
118
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
41 | |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
42 | (defun thread-count () |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
43 | (sb-thread::avl-count sb-thread::*all-threads*)) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
44 | |
119 | 45 | (defun make-threads (n fn &key (name "thread")) |
227 | 46 | (declare (type fixnum n)) |
47 | (loop for i below n |
|
118
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
48 | collect (make-thread fn :name (format nil "~A-~D" name i)))) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
49 | |
437
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
50 | (defun parse-lambda-list-names (ll) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
51 | (multiple-value-bind (idx _ args) (sb-int:parse-lambda-list ll) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
52 | (declare (ignore idx _)) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
53 | (loop for a in args |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
54 | collect |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
55 | (etypecase a |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
56 | (atom a) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
57 | (cons (car a)))))) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
58 | |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
59 | (defmacro with-threads ((n &key args) &body body) |
83f8623a6ec3
std work, renamed :disabled in deftest to :skip
Richard Westhaver <ellis@rwest.io>
parents:
336
diff
changeset
|
60 | `(make-threads ,n (lambda (,@args) (declare (ignorable ,@(parse-lambda-list-names args))) ,@body))) |
119 | 61 | |
62 | (defun finish-threads (&rest threads) |
|
63 | (let ((threads (flatten threads))) |
|
64 | (unwind-protect |
|
65 | (mapc #'join-thread threads) |
|
66 | (dolist (thread threads) |
|
67 | (when (thread-alive-p thread) |
|
182 | 68 | (terminate-thread thread)))))) |
119 | 69 | |
70 | (defun timed-join-thread (thread timeout) |
|
227 | 71 | (declare (type thread thread) (type float timeout)) |
118
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
72 | (handler-case (sb-sys:with-deadline (:seconds timeout) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
73 | (join-thread thread :default :aborted)) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
74 | (sb-ext:timeout () |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
75 | :timeout))) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
76 | |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
77 | (defun hang () |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
78 | (join-thread *current-thread*)) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
79 | |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
80 | (defun kill-thread (thread) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
81 | (when (thread-alive-p thread) |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
82 | (ignore-errors |
b828a3caa758
object library stuff, removed DOT - api doesnt jive.
ellis <ellis@rwest.io>
parents:
96
diff
changeset
|
83 | (terminate-thread thread)))) |
119 | 84 | |
227 | 85 | ;; (sb-vm::primitive-object-slots (sb-vm::primitive-object 'sb-vm::thread)) |
261 | 86 | (defun init-session (&optional (thread *current-thread*)) (sb-thread::new-session thread)) |
87 | ||
88 | ;; (sb-thread::with-progressive-timeout (timet :seconds 4) (dotimes (i 4000) (print (timet)))) |
|
89 | ||
90 | ;; (describe sb-thread::*session*) |
|
91 | ||
92 | ;; make-listener-thread |
|
93 | ||
94 | ;; with-progressive-timeout |
|
227 | 95 | |
119 | 96 | ;; from sb-thread |
97 | (defun dump-thread () |
|
227 | 98 | (let* ((slots (sb-vm::primitive-object-slots #1=(sb-vm::primitive-object 'sb-vm::thread))) |
119 | 99 | (sap (current-thread-sap)) |
227 | 100 | (thread-obj-len (sb-vm::primitive-object-length #1#)) |
119 | 101 | (names (make-array thread-obj-len :initial-element ""))) |
102 | (loop for slot across slots |
|
103 | do |
|
104 | (setf (aref names (sb-vm::slot-offset slot)) (sb-vm::slot-name slot))) |
|
105 | (flet ((safely-read (sap offset &aux (bits (sb-vm::sap-ref-word sap offset))) |
|
106 | (cond ((eql bits sb-vm:no-tls-value-marker) :no-tls-value) |
|
107 | ((eql (logand bits sb-vm:widetag-mask) sb-vm:unbound-marker-widetag) :unbound) |
|
108 | (t (sb-vm::sap-ref-lispobj sap offset)))) |
|
109 | (show (sym val) |
|
227 | 110 | (declare (type fixnum sym)) |
119 | 111 | (let ((*print-right-margin* 128) |
112 | (*print-lines* 4)) |
|
113 | (format t " ~3d ~30a : ~s~%" |
|
114 | #+sb-thread (ash sym (- sb-vm:word-shift)) |
|
115 | #-sb-thread 0 |
|
116 | #+sb-thread (sb-vm:symbol-from-tls-index sym) |
|
117 | #-sb-thread sym |
|
118 | val)))) |
|
119 | (format t "~&TLS: (base=~x)~%" (sb-vm::sap-int sap)) |
|
120 | (loop for tlsindex from sb-vm:n-word-bytes below |
|
121 | #+sb-thread (ash sb-vm::*free-tls-index* sb-vm:n-fixnum-tag-bits) |
|
122 | #-sb-thread (ash thread-obj-len sb-vm:word-shift) |
|
123 | by sb-vm:n-word-bytes |
|
124 | do |
|
125 | (unless (<= sb-vm::thread-allocator-histogram-slot |
|
126 | (ash tlsindex (- sb-vm:word-shift)) |
|
127 | (1- sb-vm::thread-lisp-thread-slot)) |
|
128 | (let ((thread-slot-name |
|
129 | (if (< tlsindex (ash thread-obj-len sb-vm:word-shift)) |
|
130 | (aref names (ash tlsindex (- sb-vm:word-shift)))))) |
|
131 | (if (and thread-slot-name (sb-vm::neq thread-slot-name 'sb-vm::lisp-thread)) |
|
132 | (format t " ~3d ~30a : #x~x~%" (ash tlsindex (- sb-vm:word-shift)) |
|
133 | thread-slot-name (sb-vm::sap-ref-word sap tlsindex)) |
|
134 | (let ((val (safely-read sap tlsindex))) |
|
135 | (unless (eq val :no-tls-value) |
|
136 | (show tlsindex val))))))) |
|
137 | (let ((from (sb-vm::descriptor-sap sb-vm:*binding-stack-start*)) |
|
138 | (to (sb-vm::binding-stack-pointer-sap))) |
|
139 | (format t "~%Binding stack: (depth ~d)~%" |
|
140 | (/ (sb-vm::sap- to from) (* sb-vm:binding-size sb-vm:n-word-bytes))) |
|
141 | (loop |
|
142 | (when (sb-vm::sap>= from to) (return)) |
|
143 | (let ((val (safely-read from 0)) |
|
144 | (sym #+sb-thread (sb-vm::sap-ref-word from sb-vm:n-word-bytes) ; a TLS index |
|
145 | #-sb-thread (sb-vm::sap-ref-lispobj from sb-vm:n-word-bytes))) |
|
146 | (show sym val)) |
|
147 | (setq from (sb-vm::sap+ from (* sb-vm:binding-size sb-vm:n-word-bytes)))))))) |
|
162 | 148 | |
274
5f782d361e08
threads and db tweaks. fixed a tricky macro error caused by string-case, dat/html now works.
Richard Westhaver <ellis@rwest.io>
parents:
261
diff
changeset
|
149 | (defun wait-for-threads (threads) |
278 | 150 | (map 'list (lambda (thread) (sb-thread:join-thread thread :default nil)) threads) |
274
5f782d361e08
threads and db tweaks. fixed a tricky macro error caused by string-case, dat/html now works.
Richard Westhaver <ellis@rwest.io>
parents:
261
diff
changeset
|
151 | (not (some #'sb-thread:thread-alive-p threads))) |
5f782d361e08
threads and db tweaks. fixed a tricky macro error caused by string-case, dat/html now works.
Richard Westhaver <ellis@rwest.io>
parents:
261
diff
changeset
|
152 | (defun process-all-interrupts (&optional (thread sb-thread:*current-thread*)) |
5f782d361e08
threads and db tweaks. fixed a tricky macro error caused by string-case, dat/html now works.
Richard Westhaver <ellis@rwest.io>
parents:
261
diff
changeset
|
153 | (sb-ext:wait-for (null (sb-thread::thread-interruptions thread)))) |