From e83eb988ee51a103ddc7b3b6e5271eced0a330c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Thu, 22 Mar 2001 19:14:41 -0800
Subject: [PATCH] experimental code for SMP, does nothing exciting yet

Rev: src/acconfig.h:1.83
Rev: src/array.h:1.32
Rev: src/configure.in:1.508
Rev: src/global.h:1.59
Rev: src/mapping.h:1.35
Rev: src/multiset.h:1.17
Rev: src/object.h:1.60
Rev: src/pike_cpulib.h:1.1
Rev: src/program.h:1.121
Rev: src/stralloc.h:1.60
Rev: src/svalue.h:1.82
---
 src/acconfig.h    |  5 ++++-
 src/array.h       |  4 ++--
 src/configure.in  |  4 +++-
 src/global.h      |  4 ++--
 src/mapping.h     |  4 ++--
 src/multiset.h    |  4 ++--
 src/object.h      |  4 ++--
 src/pike_cpulib.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 src/program.h     |  4 ++--
 src/stralloc.h    |  4 ++--
 src/svalue.h      | 38 ++++++++++++++++++++++++++++++------
 11 files changed, 102 insertions(+), 22 deletions(-)
 create mode 100644 src/pike_cpulib.h

diff --git a/src/acconfig.h b/src/acconfig.h
index f93ce09115..dceb1c57f9 100644
--- a/src/acconfig.h
+++ b/src/acconfig.h
@@ -1,5 +1,5 @@
 /*
- * $Id: acconfig.h,v 1.82 2001/03/13 04:09:18 hubbe Exp $
+ * $Id: acconfig.h,v 1.83 2001/03/23 03:14:39 hubbe Exp $
  */
 #ifndef MACHINE_H
 #define MACHINE_H
@@ -36,6 +36,9 @@
 /* Define this to enable the internal bignum conversion */
 #undef AUTO_BIGNUM
 
+/* Define this to enable experimental code for multicpu machines */
+#define PIKE_RUN_UNLOCKED
+
 /* Define this if you want to enable the shared nodes mode of the optimizer. */
 #undef SHARED_NODES
 
diff --git a/src/array.h b/src/array.h
index 41a5850e26..5a278bac12 100644
--- a/src/array.h
+++ b/src/array.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: array.h,v 1.31 2001/02/03 01:02:51 mast Exp $
+ * $Id: array.h,v 1.32 2001/03/23 03:14:39 hubbe Exp $
  */
 #ifndef ARRAY_H
 #define ARRAY_H
@@ -78,7 +78,7 @@ extern struct array *gc_internal_array;
 #define PIKE_ARRAY_OP_SUB PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A ,PIKE_ARRAY_OP_SKIP_B)
 
 
-#define free_array(V) do{ struct array *v_=(V); debug_malloc_touch(v_); if(!--v_->refs) really_free_array(v_); }while(0)
+#define free_array(V) do{ struct array *v_=(V); debug_malloc_touch(v_); if(!sub_ref(v_)) really_free_array(v_); }while(0)
 
 #define allocate_array(X) low_allocate_array((X),0)
 #define allocate_array_no_init(X,Y) low_allocate_array((X),(Y))
diff --git a/src/configure.in b/src/configure.in
index c9af4202aa..1c3a7b6f04 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1,4 +1,4 @@
-AC_REVISION("$Id: configure.in,v 1.507 2001/03/23 01:05:41 grubba Exp $")
+AC_REVISION("$Id: configure.in,v 1.508 2001/03/23 03:14:39 hubbe Exp $")
 AC_INIT(interpret.c)
 AC_CONFIG_HEADER(machine.h)
 
@@ -878,6 +878,8 @@ AC_ARG_WITH(security,    [  --with-security        enable internal pike security
 AC_ARG_WITH(bignums,     [  --without-bignums      disable internal conversion to bignums],[],[with_bignums=yes])
 AC_ARG_WITH(shared-nodes,[  --without-shared-nodes disable the SHARED_NODES mode of the optimizer],[],[with_shared_nodes=yes])
 
+AC_ARG_WITH(shared-nodes,[  --without-lock         Enable experimental code for multicpu machines.],[ AC_DEFINE(PIKE_RUN_UNLOCKED) ],[])
+
 # This makes configure default to --without-Perl
 # Remove this when the Perl module stops crashing and hanging. -Hubbe
 AC_ARG_WITH(perl,        [  --with-perl            enable the embedded Perl module (EXPERIMENTAL)],[],
diff --git a/src/global.h b/src/global.h
index df658160d3..8c0796c338 100644
--- a/src/global.h
+++ b/src/global.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: global.h,v 1.58 2001/03/04 15:27:53 mirar Exp $
+ * $Id: global.h,v 1.59 2001/03/23 03:14:40 hubbe Exp $
  */
 #ifndef GLOBAL_H
 #define GLOBAL_H
@@ -377,7 +377,7 @@ static inline long PTRDIFF_T_TO_LONG(ptrdiff_t x)
 
 #include "port.h"
 #include "dmalloc.h"
-
+#include "pike_cpulib.h"
 
 #ifdef BUFSIZ
 #define PROT_STDIO(x) PROT(x)
diff --git a/src/mapping.h b/src/mapping.h
index 3969d6e2c1..d25b987509 100644
--- a/src/mapping.h
+++ b/src/mapping.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: mapping.h,v 1.34 2000/12/16 05:45:44 marcus Exp $
+ * $Id: mapping.h,v 1.35 2001/03/23 03:14:40 hubbe Exp $
  */
 #ifndef MAPPING_H
 #define MAPPING_H
@@ -70,7 +70,7 @@ extern struct mapping *gc_internal_mapping;
 #define MAPPING_LOOP(m) \
   for((e=0) DO_IF_DMALLOC( ?0:(debug_malloc_touch(m),debug_malloc_touch(m->data))) ;e<m->data->hashsize;e++) for(k=m->data->hash[e];k;k=k->next)
 
-#define free_mapping(M) do{ struct mapping *m_=(M); debug_malloc_touch(m_); if(!--m_->refs) really_free_mapping(m_); }while(0)
+#define free_mapping(M) do{ struct mapping *m_=(M); debug_malloc_touch(m_); if(!sub_ref(m_)) really_free_mapping(m_); }while(0)
 
 #define free_mapping_data(M) do{ \
  struct mapping_data *md_=(M); \
diff --git a/src/multiset.h b/src/multiset.h
index f73477da3e..ae0a6e67a9 100644
--- a/src/multiset.h
+++ b/src/multiset.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: multiset.h,v 1.16 2000/12/16 05:24:41 marcus Exp $
+ * $Id: multiset.h,v 1.17 2001/03/23 03:14:40 hubbe Exp $
  */
 #ifndef MULTISET_H
 #define MULTISET_H
@@ -25,7 +25,7 @@ struct multiset
 extern struct multiset *first_multiset;
 extern struct multiset *gc_internal_multiset;
 
-#define free_multiset(L) do{ struct multiset *l_=(L); debug_malloc_touch(l_); if(!--l_->refs) really_free_multiset(l_); }while(0)
+#define free_multiset(L) do{ struct multiset *l_=(L); debug_malloc_touch(l_); if(!sub_ref(l_)) really_free_multiset(l_); }while(0)
 
 #define l_sizeof(L) ((L)->ind->size)
 
diff --git a/src/object.h b/src/object.h
index 8deaec1e37..4b9737cb77 100644
--- a/src/object.h
+++ b/src/object.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: object.h,v 1.59 2001/03/20 19:27:33 hubbe Exp $
+ * $Id: object.h,v 1.60 2001/03/23 03:14:40 hubbe Exp $
  */
 #ifndef OBJECT_H
 #define OBJECT_H
@@ -43,7 +43,7 @@ extern struct program *master_program;
 extern struct program *magic_index_program;
 extern struct program *magic_set_index_program;
 
-#define free_object(O) do{ struct object *o_=(O); debug_malloc_touch(o_); debug_malloc_touch(o_->storage); if(!--o_->refs) schedule_really_free_object(o_); }while(0)
+#define free_object(O) do{ struct object *o_=(O); debug_malloc_touch(o_); debug_malloc_touch(o_->storage); if(!sub_ref(o_)) schedule_really_free_object(o_); }while(0)
 
 #define LOW_GET_GLOBAL(O,I,ID) ((O)->storage+INHERIT_FROM_INT((O)->prog, (I))->storage_offset+(ID)->func.offset)
 #define GET_GLOBAL(O,I) LOW_GET_GLOBAL(O,I,ID_FROM_INT((O)->prog,I))
diff --git a/src/pike_cpulib.h b/src/pike_cpulib.h
new file mode 100644
index 0000000000..974a292444
--- /dev/null
+++ b/src/pike_cpulib.h
@@ -0,0 +1,49 @@
+#ifndef PIKE_CPULIB_H
+#define PIKE_CPULIB_H
+
+
+/* Autoconf this? */
+#if defined(__i386__) && defined(__GNUC__)
+
+#define PIKE_HAS_COMPARE_AND_SWAP
+
+static inline int
+pike_atomic_compare_and_swap (INT32 *p, INT32 oldval, INT32 newval)
+{
+  char ret;
+  INT32 readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+			: "=q" (ret), "=m" (*p), "=a" (readval)
+			: "r" (newval), "m" (*p), "a" (oldval)
+			: "memory");
+  return ret;
+}
+
+#endif
+
+
+
+
+#ifdef PIKE_HAS_COMPARE_AND_SWAP
+static inline INT32 pike_atomic_add_ref(INT32 *ref)
+{
+  INT32 oldrefs;
+  do 
+    oldrefs=*ref;
+  while(! pike_atomic_compare_and_swap(ref, oldrefs, oldrefs+1));
+  return oldrefs;
+}
+
+static inline INT32 pike_atomic_sub_ref(INT32 *ref)
+{
+  INT32 oldrefs;
+  do 
+    oldrefs=*ref;
+  while(! pike_atomic_compare_and_swap(ref, oldrefs, oldrefs-1));
+  return oldrefs-1;
+}
+
+#endif
+
+#endif
diff --git a/src/program.h b/src/program.h
index 2d7978dda8..666d46b499 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.120 2001/03/20 02:45:51 hubbe Exp $
+ * $Id: program.h,v 1.121 2001/03/23 03:14:41 hubbe Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -315,7 +315,7 @@ struct program
 
 #define FIND_LFUN(P,N) ( dmalloc_touch(struct program *,(P))->flags & PROGRAM_FIXED?((P)->lfuns[(N)]):low_find_lfun((P), (N)) )
 
-#define free_program(p) do{ struct program *_=(p); debug_malloc_touch(_); if(!--_->refs) really_free_program(_); }while(0)
+#define free_program(p) do{ struct program *_=(p); debug_malloc_touch(_); if(!sub_ref(_)) really_free_program(_); }while(0)
 
 
 extern struct object *error_handler;
diff --git a/src/stralloc.h b/src/stralloc.h
index 7dadef8a47..8459231b1d 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: stralloc.h,v 1.59 2001/02/02 20:36:23 mast Exp $
+ * $Id: stralloc.h,v 1.60 2001/03/23 03:14:41 hubbe Exp $
  */
 #ifndef STRALLOC_H
 #define STRALLOC_H
@@ -39,7 +39,7 @@ struct string_builder
 PMOD_EXPORT struct pike_string *debug_findstring(const struct pike_string *foo);
 #endif
 
-#define free_string(s) do{ struct pike_string *_=(s); debug_malloc_touch(_); if(--_->refs<=0) really_free_string(_); }while(0)
+#define free_string(s) do{ struct pike_string *_=(s); debug_malloc_touch(_); if(sub_ref(_)<=0) really_free_string(_); }while(0)
 
 #define my_hash_string(X) ((size_t)(X))
 #define my_order_strcmp(X,Y) ((char *)(X)-(char *)(Y))
diff --git a/src/svalue.h b/src/svalue.h
index a33bfb28c8..07fe19a00a 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: svalue.h,v 1.81 2001/03/19 00:41:20 grubba Exp $
+ * $Id: svalue.h,v 1.82 2001/03/23 03:14:41 hubbe Exp $
  */
 #ifndef SVALUE_H
 #define SVALUE_H
@@ -53,6 +53,11 @@ struct processing
   void *pointer_a, *pointer_b;
 };
 
+struct ref_dummy
+{
+  INT32 refs;
+};
+
 union anything
 {
   struct callable *efun;
@@ -64,6 +69,7 @@ union anything
   struct pike_string *string;
   struct pike_type *type;
   INT32 *refs;
+  struct ref_dummy *dummy;
   INT_TYPE integer;
   FLOAT_TYPE float_number;
   struct svalue *lval;   /* only used on stack */
@@ -264,6 +270,16 @@ do{ \
   } \
 }while(0)
 
+
+#ifdef PIKE_RUN_UNLOCKED
+#define add_ref(X) pike_atomic_add_ref(&(X)->refs)
+#define sub_ref(X) pike_atomic_sub_ref(&(X)->refs)
+#else
+#define add_ref(X) (X)->refs++
+#define sub_ref(X) (X)->refs--
+#endif
+
+
 #ifdef PIKE_DEBUG
 PMOD_EXPORT extern void describe(void *); /* defined in gc.c */
 #define check_type(T) if(T > MAX_TYPE && T!=T_LVALUE && T!=T_SHORT_LVALUE && T!=T_VOID && T!=T_DELETED && T!=T_ARRAY_LVALUE) fatal("Type error: %d\n",T)
@@ -303,13 +319,23 @@ static inline union anything *dmalloc_check_union(union anything *u,int type, ch
   return u;
 }
 
+#undef add_ref
+#undef sub_ref
+
+#ifdef PIKE_RUN_UNLOCKED
+#define add_ref(X) pike_atomic_add_ref((INT32 *)debug_malloc_pass( &((X)->refs)))
+#define sub_ref(X) pike_atomic_sub_ref((INT32 *)debug_malloc_pass( &((X)->refs)))
+#else
 #define add_ref(X) ((INT32 *)debug_malloc_pass( &((X)->refs)))[0]++
+#define sub_ref(X) ((INT32 *)debug_malloc_pass( &((X)->refs)))[0]--
+#endif
+
+
 #else
 #define dmalloc_check_svalue(S,L) (S)
 #define dmalloc_check_union(U,T,L) (U)
-#define add_ref(X) (X)->refs++
-#endif
 
+#endif
 
 #else
 
@@ -319,15 +345,15 @@ static inline union anything *dmalloc_check_union(union anything *u,int type, ch
 #define check_refs2(S,T)
 #define dmalloc_check_svalue(S,L) (S)
 #define dmalloc_check_union(U,T,L) (U)
-#define add_ref(X) (X)->refs++
+
 
 #endif
 
 #define swap_svalues(X,Y) do { struct svalue *_a=(X),*_b=(Y),_tmp; _tmp=*_a; *_a=*_b; *_b=_tmp; }while(0)
 #define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE) { debug_malloc_touch(_s->u.refs); if(--*(_s->u.refs) <=0) { really_free_svalue(_s); } DO_IF_DMALLOC(_s->u.refs=(void *)-1;)  }}while(0)
 #define free_short_svalue(X,T) do { union anything *_s=(X); TYPE_T _t=(T); check_type(_t); check_refs2(_s,_t); if(_t<=MAX_REF_TYPE && _s->refs) if(--*(_s->refs) <= 0) { really_free_short_svalue(_s,_t); } DO_IF_DMALLOC(_s->refs=(void *)-1;) }while(0)
-#define add_ref_svalue(X) do { struct svalue *_tmp=(X); check_type(_tmp->type); check_refs(_tmp); if(_tmp->type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp->u.refs); _tmp->u.refs[0]++; } }while(0)
-#define assign_svalue_no_free(X,Y) do { struct svalue _tmp, *_to=(X), *_from=(Y); check_type(_from->type); check_refs(_from);  *_to=_tmp=*_from; if(_tmp.type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp.u.refs); _tmp.u.refs[0]++; } }while(0)
+#define add_ref_svalue(X) do { struct svalue *_tmp=(X); check_type(_tmp->type); check_refs(_tmp); if(_tmp->type <= MAX_REF_TYPE) { add_ref(_tmp->u.dummy); } }while(0)
+#define assign_svalue_no_free(X,Y) do { struct svalue _tmp, *_to=(X), *_from=(Y); check_type(_from->type); check_refs(_from);  *_to=_tmp=*_from; if(_tmp.type <= MAX_REF_TYPE) { add_ref(_tmp.u.dummy); } }while(0)
 #define assign_svalue(X,Y) do { struct svalue *_to2=(X), *_from2=(Y); if (_to2 != _from2) { free_svalue(_to2); assign_svalue_no_free(_to2, _from2); }  }while(0)
 
 extern struct svalue dest_ob_zero;
-- 
GitLab