master: Add some remarks and a utility function

snuglas via Sbcl-commits <[email protected]> Thu, 30 Apr 2026 22:49:12 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  9b67e9100dfd518747d61d3a1fd8b986d09120d6 (commit)
      from  84d5a7b46b4637ec27bd537a3125001d4e0bface (commit)

- Log -----------------------------------------------------------------
commit 9b67e9100dfd518747d61d3a1fd8b986d09120d6
Author: Douglas Katzman <[email protected]>
Date:   Thu Apr 30 18:44:54 2026 -0400

    Add some remarks and a utility function
---
 src/code/target-thread.lisp  |  8 ++++++++
 src/code/thread-structs.lisp | 20 ++++++++++++++++++++
 src/runtime/sunos-os.c       |  1 +
 tests/threads.pure.lisp      |  5 +++++
 4 files changed, 34 insertions(+)

diff --git a/src/code/target-thread.lisp b/src/code/target-thread.lisp
index cc7c8e412..51e253633 100644
--- a/src/code/target-thread.lisp
+++ b/src/code/target-thread.lisp
@@ -13,6 +13,7 @@
 
 ;;; symbols to protect from tree-shaker, for some tests
 (export '(%thread-local-references
+          %thread-from-tid
           get-spinlock
           release-spinlock
           spinlock
@@ -294,6 +295,13 @@ an error in that case."
          (let ((new (avl-insert old addr ,thread)))
            (when (eq old (setq old (sb-ext:cas *all-threads* old new))) (return)))))))
 
+(defun %thread-from-tid (os-tid)
+  (declare (type (unsigned-byte 32) os-tid))
+  (avltree-filter (lambda (node &aux (thread (avlnode-data node)))
+                    (when (= (thread-os-tid thread) os-tid)
+                      (return-from %thread-from-tid thread)))
+                  *all-threads*))
+
 (defun vmthread-name (vmthread)
   (binding* ((node (avl-find (vmthread-id->addr vmthread) *all-threads*) :exit-if-null)
              (thread (avlnode-data node) :exit-if-null)
diff --git a/src/code/thread-structs.lisp b/src/code/thread-structs.lisp
index cea4666b6..0ab169d80 100644
--- a/src/code/thread-structs.lisp
+++ b/src/code/thread-structs.lisp
@@ -27,6 +27,18 @@
 ;;; compete for a mutex, the pthread code seems to do a better job at reducing
 ;;; cycles spent in the OS.
 
+;;; Mutexes could be equipped with telemetry compatible with absl::Mutex.
+;;; Specifically, we'd like to know the "Induced wait" which is the sum of CPU cycles
+;;; a lock owner caused other threads to wait. It's tricky to report because measurement
+;;; is performed in the waiting thread (the "victim" of wait) but reporting should occur
+;;; in the "culprit" thread so that the call stack accurately reflects the function
+;;; whose fault it is that there was induced wait time. absl mutex can do this because
+;;; it is acutely aware of the queue of waiters, and it knows which waiter it wakes.
+;;; SBCL mutex can't, because we defer everything to the OS. But the delay time can be
+;;; handed off to -some- waker using a slot of the mutex, which stastically should result
+;;; in the right effect. To keep struct size unchanged, the owner ID and futex word
+;;; must be packed into a single raw slot. (None of this is implemented yet!)
+
 (sb-xc:defstruct (mutex (:constructor make-mutex (&key name))
                         (:copier nil))
   "Mutex type."
@@ -110,6 +122,14 @@ in future versions."
   ;; This value is 0 if the thread is not considered alive, though the pthread
   ;; may be running its termination code (unlinking from all_threads etc)
   (primitive-thread 0 :type sb-vm:word)
+  ;; It is absolutely critical that our OS thread identifiers take no more than 32 bits
+  ;; if #+sb-futex is present. So don't go changing this slot just because you feel like.
+  ;; * macOS (mach_port_t): unsigned int
+  ;; * FreeBSD (thr_self): thr_self writes a long to its its pointer arg,
+  ;;     however LWP IDs occupy a smaller range that can be cast to int
+  ;; * NetBSD (_lwp_self): lwpid_t which is int32_t
+  ;; * Linux (gettid): 32-bit pid_t
+  ;; * Windows (GetCurrentThreadId): 32-bit DWORD
   ;; Caution: the identified thread may have exited by the time you've read this slot
   (os-tid 0 :type (unsigned-byte 32) :read-only t)
   ;; This is a redundant copy of the pthread identifier from the primitive thread.
diff --git a/src/runtime/sunos-os.c b/src/runtime/sunos-os.c
index 0d1902564..16b197360 100644
--- a/src/runtime/sunos-os.c
+++ b/src/runtime/sunos-os.c
@@ -24,6 +24,7 @@
 
 #include "gc.h"
 
+// Allegedly this could use thr_self() or _lwp_self() both of which are 32-bit
 int sb_GetTID() { return 0; } // this doesn't affect anything
 
 void os_init() {}
diff --git a/tests/threads.pure.lisp b/tests/threads.pure.lisp
index d06aab37e..030e8cfd4 100644
--- a/tests/threads.pure.lisp
+++ b/tests/threads.pure.lisp
@@ -317,3 +317,8 @@
       (assert (string= (first results) "newname"))
       (assert (find "finalizer" (second results) :test 'string=))
       (assert (find "testme" (second results) :test 'string=)))))
+
+(with-test (:name :thread-from-tid)
+  (let ((tid (sb-thread:thread-os-tid *current-thread*)))
+    (when (plusp tid) ; SunOS returns 0
+      (assert (eq (sb-thread:%thread-from-tid tid) *current-thread*)))))

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL