wingo pushed a commit to branch wip-whippet
in repository guile.

commit f47fe6e7520348a8cf254947a08750c6f6889c3c
Author: Andy Wingo <wi...@pobox.com>
AuthorDate: Fri Jun 13 11:45:55 2025 +0200

    Convert mutexes, condition vars to statically-allocated tc16
    
    * libguile/scm.h: Add statically allocated tc16s for condvars and
    mutexes.
    * libguile/threads.c: Adapt to declare tag inline to struct scm_cond and
    struct scm_mutex.
    * libguile/threads.h: Expose printing procedures internally.
    * module/oop/goops.scm:
    * libguile/goops.c: Fix to statically allocate condition variable and
    mutex classes.
    * libguile/eq.c:
    * libguile/print.c: Adapt.
---
 libguile/eq.c        |   3 ++
 libguile/goops.c     |   8 ++++
 libguile/print.c     |   6 +++
 libguile/scm.h       |  13 ++++++
 libguile/threads.c   | 129 ++++++++++++++++++++++++++++++---------------------
 libguile/threads.h   |  11 ++---
 module/oop/goops.scm |   7 +--
 7 files changed, 112 insertions(+), 65 deletions(-)

diff --git a/libguile/eq.c b/libguile/eq.c
index 059954620..813c86563 100644
--- a/libguile/eq.c
+++ b/libguile/eq.c
@@ -388,6 +388,9 @@ scm_equal_p (SCM x, SCM y)
         {
         case scm_tc16_charset:
           return scm_from_bool (scm_i_char_sets_equal (x, y));
+        case scm_tc16_condition_variable:
+        case scm_tc16_mutex:
+          return SCM_BOOL_F;
         default:
           abort ();
         }
diff --git a/libguile/goops.c b/libguile/goops.c
index 4a4fbad99..b07180f39 100644
--- a/libguile/goops.c
+++ b/libguile/goops.c
@@ -139,6 +139,8 @@ static SCM class_finalizer;
 static SCM class_ephemeron;
 static SCM class_ephemeron_table;
 static SCM class_character_set;
+static SCM class_condition_variable;
+static SCM class_mutex;
 
 static struct scm_ephemeron_table *vtable_class_map;
 static SCM pre_goops_vtables = SCM_EOL;
@@ -345,6 +347,10 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
               {
               case scm_tc16_charset:
                 return class_character_set;
+              case scm_tc16_condition_variable:
+                return class_condition_variable;
+              case scm_tc16_mutex:
+                return class_mutex;
               default:
                 abort ();
               }
@@ -980,6 +986,8 @@ SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 
0, 0, 0,
   class_ephemeron = scm_variable_ref (scm_c_lookup ("<ephemeron>"));
   class_ephemeron_table = scm_variable_ref (scm_c_lookup 
("<ephemeron-table>"));
   class_character_set = scm_variable_ref (scm_c_lookup ("<character-set>"));
+  class_condition_variable = scm_variable_ref (scm_c_lookup 
("<condition-variable>"));
+  class_mutex = scm_variable_ref (scm_c_lookup ("<mutex>"));
 
   create_smob_classes ();
   create_struct_classes ();
diff --git a/libguile/print.c b/libguile/print.c
index 1ab762058..40d35adb6 100644
--- a/libguile/print.c
+++ b/libguile/print.c
@@ -792,6 +792,12 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
               case scm_tc16_charset:
                 scm_i_print_char_set (exp, port, pstate);
                 break;
+              case scm_tc16_condition_variable:
+                scm_i_print_condition_variable (exp, port, pstate);
+                break;
+              case scm_tc16_mutex:
+                scm_i_print_mutex (exp, port, pstate);
+                break;
               default:
                 abort ();
             }
diff --git a/libguile/scm.h b/libguile/scm.h
index 0ef18a139..1b3533a6d 100644
--- a/libguile/scm.h
+++ b/libguile/scm.h
@@ -509,6 +509,19 @@ typedef uintptr_t scm_t_bits;
 
 /* Objects with scm_tc7_ext.  */
 #define scm_tc16_charset               0x007f
+#define scm_tc16_condition_variable    0x017f
+#define scm_tc16_mutex                 0x027f
+/*
+#define scm_tc16_continuation          0x067f
+#define scm_tc16_directory             0x077f
+#define scm_tc16_hook                  0x097f
+#define scm_tc16_macro                 0x0a7f
+#define scm_tc16_malloc                        0x0b7f
+#define scm_tc16_port_with_print_state 0x0d7f
+#define scm_tc16_promise               0x0e7f
+#define scm_tc16_random_state          0x0f7f
+#define scm_tc16_regexp                        0x107f
+*/
 
 /* Definitions for tc16: */
 #define SCM_TYP16(x)           (0xffff & SCM_CELL_TYPE (x))
diff --git a/libguile/threads.c b/libguile/threads.c
index 5780a9481..0f9fae929 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -74,6 +74,15 @@
 
 
 
+#define SCM_MUTEXP(x)     SCM_HAS_TYP16 (x, scm_tc16_mutex)
+#define SCM_CONDVARP(x)       SCM_SMOB_PREDICATE (scm_tc16_condition_variable, 
x)
+#define SCM_VALIDATE_CONDVAR(_pos, _obj)                       \
+  SCM_ASSERT_TYPE (SCM_CONDVARP (_obj), (_obj), (_pos), FUNC_NAME, "condvar")
+#define SCM_VALIDATE_MUTEX(_pos, _obj)                 \
+  SCM_ASSERT_TYPE (SCM_MUTEXP (_obj), (_obj), (_pos), FUNC_NAME, "mutex")
+
+
+
 #if 0
 /* FIXME: For the moment, the bodies of thread objects are traced
    conservatively; only bdw, heap-conservative-mmc, and
@@ -952,7 +961,7 @@ enum scm_mutex_kind {
 };
 
 struct scm_mutex {
-  scm_i_pthread_mutex_t lock;
+  scm_t_bits tag_and_flags;
   /* The thread that owns this mutex, or #f if the mutex is unlocked.  */
   SCM owner;
   /* Queue of threads waiting for this mutex.  */
@@ -960,16 +969,32 @@ struct scm_mutex {
   /* For SCM_MUTEX_RECURSIVE (and only SCM_MUTEX_RECURSIVE), the
      recursive lock count.  The first lock does not count.  */
   int level;
+  scm_i_pthread_mutex_t lock;
 };
 
-#define SCM_MUTEXP(x)     SCM_SMOB_PREDICATE (scm_tc16_mutex, x)
-#define SCM_MUTEX_DATA(x) ((struct scm_mutex *) SCM_SMOB_DATA (x))
-#define SCM_MUTEX_KIND(x) ((enum scm_mutex_kind) (SCM_SMOB_FLAGS (x) & 0x3))
+static struct scm_mutex*
+scm_to_mutex (SCM x)
+{
+  if (!SCM_MUTEXP (x)) abort ();
+  return (struct scm_mutex*) SCM_UNPACK_POINTER (x);
+}
 
-static int
-scm_mutex_print (SCM mx, SCM port, scm_print_state *pstate SCM_UNUSED)
+static SCM
+scm_from_mutex (struct scm_mutex *m)
+{
+  return SCM_PACK_POINTER (m);
+}
+
+static enum scm_mutex_kind
+mutex_kind (struct scm_mutex *m)
+{
+  return m->tag_and_flags >> 16;
+}
+
+int
+scm_i_print_mutex (SCM mx, SCM port, scm_print_state *pstate SCM_UNUSED)
 {
-  struct scm_mutex *m = SCM_MUTEX_DATA (mx);
+  struct scm_mutex *m = scm_to_mutex (mx);
   scm_puts ("#<mutex ", port);
   scm_uintprint ((scm_t_bits)m, 16, port);
   scm_puts (">", port);
@@ -1003,14 +1028,15 @@ SCM_DEFINE (scm_make_mutex_with_kind, "make-mutex", 0, 
1, 0,
     }
 
   m = scm_gc_malloc (sizeof (struct scm_mutex), "mutex");
+  m->tag_and_flags = scm_tc16_mutex | (mkind << 16);
+  m->owner = SCM_BOOL_F;
+  m->waiting = make_queue ();
+  m->level = 0;
   /* Because PTHREAD_MUTEX_INITIALIZER is static, it's plain old data,
      and so we can just copy it.  */
   memcpy (&m->lock, &lock, sizeof (m->lock));
-  m->owner = SCM_BOOL_F;
-  m->level = 0;
-  m->waiting = make_queue ();
 
-  return scm_new_smob (scm_tc16_mutex | (mkind << 16), (scm_t_bits) m);
+  return scm_from_mutex (m);
 }
 #undef FUNC_NAME
 
@@ -1113,7 +1139,7 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
   SCM ret;
 
   SCM_VALIDATE_MUTEX (1, mutex);
-  m = SCM_MUTEX_DATA (mutex);
+  m = scm_to_mutex (mutex);
 
   if (! SCM_UNBNDP (timeout) && ! scm_is_false (timeout))
     {
@@ -1123,7 +1149,7 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
 
   /* Specialized lock_mutex implementations according to the mutex
      kind.  */
-  switch (SCM_MUTEX_KIND (mutex))
+  switch (mutex_kind (m))
     {
     case SCM_MUTEX_STANDARD:
       ret = lock_mutex (SCM_MUTEX_STANDARD, m, t, waittime);
@@ -1138,8 +1164,6 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
       abort ();
     }
 
-  scm_remember_upto_here_1 (mutex);
-
   return ret;
 }
 #undef FUNC_NAME
@@ -1220,11 +1244,11 @@ SCM_DEFINE (scm_unlock_mutex, "unlock-mutex", 1, 0, 0, 
(SCM mutex),
 
   SCM_VALIDATE_MUTEX (1, mutex);
 
-  m = SCM_MUTEX_DATA (mutex);
+  m = scm_to_mutex (mutex);
 
   /* Specialized unlock_mutex implementations according to the mutex
      kind.  */
-  switch (SCM_MUTEX_KIND (mutex))
+  switch (mutex_kind (m))
     {
     case SCM_MUTEX_STANDARD:
       unlock_mutex (SCM_MUTEX_STANDARD, m, t);
@@ -1239,8 +1263,6 @@ SCM_DEFINE (scm_unlock_mutex, "unlock-mutex", 1, 0, 0, 
(SCM mutex),
       abort ();
     }
 
-  scm_remember_upto_here_1 (mutex);
-
   return SCM_BOOL_T;
 }
 #undef FUNC_NAME
@@ -1263,7 +1285,7 @@ SCM_DEFINE (scm_mutex_owner, "mutex-owner", 1, 0, 0,
   struct scm_mutex *m = NULL;
 
   SCM_VALIDATE_MUTEX (1, mx);
-  m = SCM_MUTEX_DATA (mx);
+  m = scm_to_mutex (mx);
   scm_i_pthread_mutex_lock (&m->lock);
   owner = m->owner;
   scm_i_pthread_mutex_unlock (&m->lock);
@@ -1278,9 +1300,10 @@ SCM_DEFINE (scm_mutex_level, "mutex-level", 1, 0, 0,
 #define FUNC_NAME s_scm_mutex_level
 {
   SCM_VALIDATE_MUTEX (1, mx);
-  if (SCM_MUTEX_KIND (mx) == SCM_MUTEX_RECURSIVE)
-    return scm_from_int (SCM_MUTEX_DATA (mx)->level + 1);
-  else if (scm_is_eq (SCM_MUTEX_DATA (mx)->owner, SCM_BOOL_F))
+  struct scm_mutex *m = scm_to_mutex (mx);
+  if (mutex_kind (m) == SCM_MUTEX_RECURSIVE)
+    return scm_from_int (m->level + 1);
+  else if (scm_is_eq (m->owner, SCM_BOOL_F))
     return SCM_INUM0;
   else
     return SCM_INUM1;
@@ -1293,7 +1316,7 @@ SCM_DEFINE (scm_mutex_locked_p, "mutex-locked?", 1, 0, 0,
 #define FUNC_NAME s_scm_mutex_locked_p
 {
   SCM_VALIDATE_MUTEX (1, mx);
-  if (scm_is_eq (SCM_MUTEX_DATA (mx)->owner, SCM_BOOL_F))
+  if (scm_is_eq (scm_to_mutex (mx)->owner, SCM_BOOL_F))
     return SCM_BOOL_F;
   else
     return SCM_BOOL_T;
@@ -1304,17 +1327,30 @@ SCM_DEFINE (scm_mutex_locked_p, "mutex-locked?", 1, 0, 
0,
 
 
 struct scm_cond {
-  scm_i_pthread_mutex_t lock;
+  scm_t_bits tag;
   SCM waiting;               /* the threads waiting for this condition. */
+  /* FIXME: Using one cond with multiple mutexes may race on the waiting
+     list.  */
 };
 
-#define SCM_CONDVARP(x)       SCM_SMOB_PREDICATE (scm_tc16_condvar, x)
-#define SCM_CONDVAR_DATA(x)   ((struct scm_cond *) SCM_SMOB_DATA (x))
+static struct scm_cond*
+scm_to_condvar (SCM x)
+{
+  if (!SCM_CONDVARP (x)) abort ();
+  return (struct scm_cond*) SCM_UNPACK_POINTER (x);
+}
 
-static int
-scm_cond_print (SCM cv, SCM port, scm_print_state *pstate SCM_UNUSED)
+static SCM
+scm_from_condvar (struct scm_cond *c)
 {
-  struct scm_cond *c = SCM_CONDVAR_DATA (cv);
+  return SCM_PACK_POINTER (c);
+}
+
+int
+scm_i_print_condition_variable (SCM cv, SCM port,
+                                scm_print_state *pstate SCM_UNUSED)
+{
+  struct scm_cond *c = scm_to_condvar (cv);
   scm_puts ("#<condition-variable ", port);
   scm_uintprint ((scm_t_bits)c, 16, port);
   scm_puts (">", port);
@@ -1326,14 +1362,11 @@ SCM_DEFINE (scm_make_condition_variable, 
"make-condition-variable", 0, 0, 0,
            "Make a new condition variable.")
 #define FUNC_NAME s_scm_make_condition_variable
 {
-  struct scm_cond *c;
-  SCM cv;
-
-  c = scm_gc_malloc (sizeof (struct scm_cond), "condition variable");
-  c->waiting = SCM_EOL;
-  SCM_NEWSMOB (cv, scm_tc16_condvar, (scm_t_bits) c);
+  struct scm_cond *c =
+    scm_gc_malloc (sizeof (struct scm_cond), "condition variable");
+  c->tag = scm_tc16_condition_variable;
   c->waiting = make_queue ();
-  return cv;
+  return scm_from_condvar (c);
 }
 #undef FUNC_NAME
 
@@ -1455,8 +1488,8 @@ SCM_DEFINE (scm_timed_wait_condition_variable, 
"wait-condition-variable", 2, 1,
   SCM_VALIDATE_CONDVAR (1, cond);
   SCM_VALIDATE_MUTEX (2, mutex);
 
-  c = SCM_CONDVAR_DATA (cond);
-  m = SCM_MUTEX_DATA (mutex);
+  c = scm_to_condvar (cond);
+  m = scm_to_mutex (mutex);
 
   if (!SCM_UNBNDP (timeout))
     {
@@ -1466,7 +1499,7 @@ SCM_DEFINE (scm_timed_wait_condition_variable, 
"wait-condition-variable", 2, 1,
 
   /* Specialized timed_wait implementations according to the mutex
      kind.  */
-  switch (SCM_MUTEX_KIND (mutex))
+  switch (mutex_kind (m))
     {
     case SCM_MUTEX_STANDARD:
       ret = timed_wait (SCM_MUTEX_STANDARD, m, c, t, waittime);
@@ -1481,8 +1514,6 @@ SCM_DEFINE (scm_timed_wait_condition_variable, 
"wait-condition-variable", 2, 1,
       abort ();
     }
 
-  scm_remember_upto_here_2 (mutex, cond);
-
   return ret;
 }
 #undef FUNC_NAME
@@ -1494,7 +1525,7 @@ SCM_DEFINE (scm_signal_condition_variable, 
"signal-condition-variable", 1, 0, 0,
 {
   struct scm_cond *c;
   SCM_VALIDATE_CONDVAR (1, cv);
-  c = SCM_CONDVAR_DATA (cv);
+  c = scm_to_condvar (cv);
   unblock_from_queue (c->waiting);
   return SCM_BOOL_T;
 }
@@ -1507,7 +1538,7 @@ SCM_DEFINE (scm_broadcast_condition_variable, 
"broadcast-condition-variable", 1,
 {
   struct scm_cond *c;
   SCM_VALIDATE_CONDVAR (1, cv);
-  c = SCM_CONDVAR_DATA (cv);
+  c = scm_to_condvar (cv);
   while (scm_is_true (unblock_from_queue (c->waiting)))
     ;
   return SCM_BOOL_T;
@@ -1831,9 +1862,6 @@ scm_threads_prehistory (struct gc_mutator *mut, struct 
gc_stack_addr base)
   guilify_self_1 (mut, base, 0);
 }
 
-scm_t_bits scm_tc16_mutex;
-scm_t_bits scm_tc16_condvar;
-
 static void
 scm_init_ice_9_threads (void *unused)
 {
@@ -1853,13 +1881,6 @@ scm_init_ice_9_threads (void *unused)
 void
 scm_init_threads ()
 {
-  scm_tc16_mutex = scm_make_smob_type ("mutex", sizeof (struct scm_mutex));
-  scm_set_smob_print (scm_tc16_mutex, scm_mutex_print);
-
-  scm_tc16_condvar = scm_make_smob_type ("condition-variable",
-                                        sizeof (struct scm_cond));
-  scm_set_smob_print (scm_tc16_condvar, scm_cond_print);
-
   default_dynamic_state = SCM_BOOL_F;
   guilify_self_2 (scm_i_make_initial_dynamic_state ());
   threads_initialized_p = 1;
diff --git a/libguile/threads.h b/libguile/threads.h
index 918e87c41..731085cc0 100644
--- a/libguile/threads.h
+++ b/libguile/threads.h
@@ -52,10 +52,6 @@
 
 
 
-/* smob tags for the thread datatypes */
-SCM_API scm_t_bits scm_tc16_mutex;
-SCM_API scm_t_bits scm_tc16_condvar;
-
 struct scm_thread_wake_data;
 struct gc_mutator;
 
@@ -144,10 +140,6 @@ scm_thread_handle (struct scm_thread *thread)
 
 #define SCM_VALIDATE_THREAD(pos, a) \
   SCM_ASSERT_TYPE (SCM_I_IS_THREAD (a), (a), (pos), FUNC_NAME, "thread")
-#define SCM_VALIDATE_MUTEX(pos, a) \
-  scm_assert_smob_type (scm_tc16_mutex, (a))
-#define SCM_VALIDATE_CONDVAR(pos, a) \
-  scm_assert_smob_type (scm_tc16_condvar, (a))
 
 SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data,
                              scm_t_catch_handler handler, void *handler_data);
@@ -161,6 +153,9 @@ SCM_INTERNAL void scm_init_threads_default_dynamic_state 
(void);
 SCM_INTERNAL void scm_i_dynwind_pthread_mutex_lock_block_asyncs 
(scm_i_pthread_mutex_t *mutex);
 
 SCM_INTERNAL int scm_i_print_thread (SCM t, SCM port, scm_print_state *pstate);
+SCM_INTERNAL int scm_i_print_mutex (SCM m, SCM port, scm_print_state *pstate);
+SCM_INTERNAL int scm_i_print_condition_variable (SCM cv, SCM port,
+                                                 scm_print_state *pstate);
 
 SCM_API SCM scm_call_with_new_thread (SCM thunk, SCM handler);
 SCM_API SCM scm_yield (void);
diff --git a/module/oop/goops.scm b/module/oop/goops.scm
index 203c7fc0e..b2f37064b 100644
--- a/module/oop/goops.scm
+++ b/module/oop/goops.scm
@@ -71,6 +71,7 @@
             <fluid> <dynamic-state> <frame> <vm> <vm-continuation>
             <keyword> <syntax> <atomic-box> <thread> <bitvector>
             <finalizer> <ephemeron> <ephemeron-table> <character-set>
+            <mutex> <condition-variable>
 
             ;; Numbers.
             <number> <complex> <real> <integer> <fraction>
@@ -82,7 +83,7 @@
             ;; corresponding classes, which may be obtained via class-of,
             ;; once you have an instance.  Perhaps FIXME to provide a
             ;; smob-type-name->class procedure.
-            <promise> <mutex> <condition-variable>
+            <promise>
             <regexp> <hook> <random-state>
             <directory> <array>
             <dynamic-object> <macro>
@@ -1083,6 +1084,8 @@ slots as we go."
 (define-standard-class <ephemeron> (<top>))
 (define-standard-class <ephemeron-table> (<top>))
 (define-standard-class <character-set> (<top>))
+(define-standard-class <condition-variable> (<top>))
+(define-standard-class <mutex> (<top>))
 (define-standard-class <thread> (<top>))
 (define-standard-class <number> (<top>))
 (define-standard-class <complex> (<number>))
@@ -3531,8 +3534,6 @@ var{initargs}."
 ;;;
 
 (define <promise> (find-subclass <top> '<promise>))
-(define <mutex> (find-subclass <top> '<mutex>))
-(define <condition-variable> (find-subclass <top> '<condition-variable>))
 (define <regexp> (find-subclass <top> '<regexp>))
 (define <hook> (find-subclass <top> '<hook>))
 (define <bitvector> (find-subclass <top> '<bitvector>))

Reply via email to