diff --git a/src/acconfig.h b/src/acconfig.h index f93ce091151a20cc4ed46d6aa2892935372ebc65..dceb1c57f9d08f7b89c6747aef99cc0a227e032a 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 41a5850e267f89a5a914aac2d39e521e44fa0c0e..5a278bac1205ada46c16c6146c6ea3150bc7f942 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 c9af4202aa4057a903fa98256673d1224f516a58..1c3a7b6f0447f5fe2c7dd4d9af3f0b14c18d0dc3 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 df658160d3e29c55b54e260202fabf67dc94c274..8c0796c33805a69042b6557af81e6152c9abf4ff 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 3969d6e2c18119a6eea47433e8e1f2bbaa070457..d25b987509ccb677e106f207a3115105c8b32007 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 f73477da3eef92211c8445f6d3507883fc9f83d2..ae0a6e67a9ac43e4facdb6d7e7d759387f550595 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 8deaec1e37bd00a10d02ad33f6378990d40a67ab..4b9737cb778e9111fb3391d15ac1278d354741a3 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 0000000000000000000000000000000000000000..974a29244463a5222a5d76c4bd5a034aa26177eb --- /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 2d7978dda8d485f1d66b84bc899f4882e075cecd..666d46b4996cae4a67b06f99b45c8fe4cc8e5204 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 7dadef8a472ee46877d85858d6404093a2c74b92..8459231b1d671511ed6b0d1cc2e2b8f5edf511c8 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 a33bfb28c81a8fc299875f50af6fed6ca90af8ea..07fe19a00a96622071bb5f4888d2fdc50b9b212c 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;