ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [NothinkToDo] ThreadSafeRuby
@ 2002-07-31 15:27 Michal Rokos
  2002-07-31 16:23 ` ts
  0 siblings, 1 reply; 2+ messages in thread
From: Michal Rokos @ 2002-07-31 15:27 UTC (permalink / raw
  To: ruby-core

Hi,

	today I get a little bored, so I started to play with POSIX
	threads.

	My idea is to bring "real" threads to Ruby and also make Ruby
	thread safe. My thoughts go like this: make OS dependent threads
	and choose them in ./configure stage: ./configure
	--with-threads=
		POSIX (aka pthreads)
		SW (software - current implementation)
		...
		Windows
		...

	As a 1st step I started to play with locking. Following diff
	shows where I'm playing. Do you think that this would be useful
	or shall I do something else? :-)

		Michal

diff -urN ruby/ruby.h ruby-my/ruby.h
--- ruby/ruby.h	2002-05-14 07:22:26.000000000 +0100
+++ ruby-my/ruby.h	2002-07-31 15:29:41.000000000 +0100
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include "defines.h"
+#include "thread.h"
 
 #ifdef HAVE_STDLIB_H
 # include <stdlib.h>
@@ -271,9 +272,10 @@
 
 VALUE rb_newobj _((void));
 #define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
-#define OBJSETUP(obj,c,t) do {\
+#define OBJSETUP(obj, c, t) do {\
     RBASIC(obj)->flags = (t);\
     RBASIC(obj)->klass = (c);\
+    LOCK_INIT(RBASIC(obj)->lck);\
     if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
 } while (0)
 #define CLONESETUP(clone,obj) do {\
@@ -289,6 +291,7 @@
 struct RBasic {
     unsigned long flags;
     VALUE klass;
+    lock_t lck;
 };
 
 struct RObject {
@@ -453,6 +456,11 @@
 #define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
 #define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(n))
 
+#define rb_lock_wr(obj) LOCK_WR(RBASIC((obj))->lck)
+#define rb_lock_rd(obj) LOCK_RD(RBASIC((obj))->lck)
+#define rb_unlock_rd(obj) UNLOCK_RD(RBASIC((obj))->lck)
+#define rb_unlock_wr(obj) UNLOCK_WR(RBASIC((obj))->lck)
+
 void rb_glob _((char*,void(*)(const char*,VALUE),VALUE));
 void rb_globi _((char*,void(*)(const char*,VALUE),VALUE));
 
diff -urN ruby/thread.h ruby-my/thread.h
--- ruby/thread.h	1970-01-01 01:00:00.000000000 +0100
+++ ruby-my/thread.h	2002-07-31 15:26:55.000000000 +0100
@@ -0,0 +1,21 @@
+#if !defined(THREAD_H)
+#define THREAD_H
+
+#define _GNU_SOURCE 1
+#include <pthread.h>
+
+#define lock_t pthread_rwlock_t
+#define LOCK_INIT(lock) pthread_rwlock_init(&(lock), NULL)
+//	PTHREAD_RWLOCK_INITIALIZER)
+#define LOCK_RD(lock) pthread_rwlock_rdlock(&(lock))
+#define UNLOCK_RD(lock) pthread_rwlock_unlock(&(lock))
+#define LOCK_WR(lock) pthread_rwlock_wrlock(&(lock))
+#define UNLOCK_WR(lock) pthread_rwlock_unlock(&(lock))
+
+#define mutex_t pthread_mutex_t
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define MUTEX_LOCK(mutex) pthread_mutex_lock((mutex))
+#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock((mutex))
+
+#endif
+
diff -urN ruby/gc.c ruby-my/gc.c
--- ruby/gc.c	2002-07-26 09:52:56.000000000 +0100
+++ ruby-my/gc.c	2002-07-31 13:03:58.000000000 +0100
@@ -155,7 +155,6 @@
 
 extern int ruby_in_compile;
 static int dont_gc;
-static int during_gc;
 static int need_call_final = 0;
 static st_table *finalizer_table = 0;
 
@@ -251,6 +250,7 @@
     } as;
 } RVALUE;
 
+static mutex_t mutex = MUTEX_INITIALIZER;
 static RVALUE *freelist = 0;
 static RVALUE *deferred_final_list = 0;
 
@@ -317,10 +317,15 @@
 {
     VALUE obj;
 
-    if (!freelist) rb_gc();
+    MUTEX_LOCK(&mutex);
+    if (!freelist) {
+	MUTEX_UNLOCK(&mutex);
+	rb_gc();
+    }
 
     obj = (VALUE)freelist;
     freelist = freelist->as.free.next;
+    MUTEX_UNLOCK(&mutex);
     MEMZERO((void*)obj, RVALUE, 1);
     return obj;
 }
@@ -919,8 +924,10 @@
     if (freed < FREE_MIN) {
 	add_heap();
     }
+/*
+ * TODO: check this
     during_gc = 0;
-
+ */
     /* clear finalization list */
     if (final_list) {
 	RVALUE *tmp;
@@ -1130,19 +1137,18 @@
     jmp_buf save_regs_gc_mark;
     SET_STACK_END;
 
-    if (dont_gc || during_gc) {
+    MUTEX_LOCK(&mutex);
+    if (dont_gc) {
 	if (!freelist || malloc_memories > GC_MALLOC_LIMIT) {
 	    malloc_memories = 0;
 	    add_heap();
 	}
+	MUTEX_UNLOCK(&mutex);
 	return;
     }
 
     malloc_memories = 0;
 
-    if (during_gc) return;
-    during_gc++;
-
     init_mark_stack();
     
     /* mark frame stack */
@@ -1197,6 +1203,7 @@
 	}
     }
     gc_sweep();
+    MUTEX_UNLOCK(&mutex);
 }
 
 VALUE
diff -urN ruby/array.c ruby-my/array.c
--- ruby/array.c	2002-07-18 14:06:48.000000000 +0100
+++ ruby-my/array.c	2002-07-31 15:48:16.000000000 +0100
@@ -48,11 +48,19 @@
 rb_ary_modify_check(ary)
     VALUE ary;
 {
-    if (OBJ_FROZEN(ary)) rb_error_frozen("array");
-    if (FL_TEST(ary, ARY_TMPLOCK))
+    rb_lock_wr(ary);
+    if (OBJ_FROZEN(ary)) {
+	rb_unlock_wr(ary);
+	rb_error_frozen("array");
+    }	    
+    if (FL_TEST(ary, ARY_TMPLOCK)) {
+	rb_unlock_wr(ary);
 	rb_raise(rb_eTypeError, "can't modify array during sort");
-    if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
+    }
+    if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4) {
+	rb_unlock_wr(ary);
 	rb_raise(rb_eSecurityError, "Insecure: can't modify array");
+    }
 }
 
 static void
@@ -81,8 +89,12 @@
 rb_ary_frozen_p(ary)
     VALUE ary;
 {
-    if (FL_TEST(ary, FL_FREEZE|ARY_TMPLOCK))
+    rb_lock_rd(ary);
+    if (FL_TEST(ary, FL_FREEZE|ARY_TMPLOCK)) {
+	rb_unlock_rd(ary);
 	return Qtrue;
+    }
+    rb_unlock_rd(ary);
     return Qfalse;
 }
 
@@ -221,6 +233,7 @@
 	if (rb_block_given_p()) {
 	    rb_warning("given block not used");
 	}
+	rb_unlock_wr(ary);
 	return ary;
     }
 
@@ -228,15 +241,18 @@
 	val = rb_check_convert_type(size, T_ARRAY, "Array", "to_ary");
 	if (!NIL_P(val)) {
 	    rb_ary_replace(ary, val);
+	    rb_unlock_wr(ary);
 	    return ary;
 	}
     }
 
     len = NUM2LONG(size);
     if (len < 0) {
+	rb_unlock_wr(ary);
 	rb_raise(rb_eArgError, "negative array size");
     }
     if (len > 0 && len * sizeof(VALUE) <= 0) {
+	rb_unlock_wr(ary);
 	rb_raise(rb_eArgError, "array size too big");
     }
     if (len > RARRAY(ary)->aux.capa) {
@@ -247,6 +263,7 @@
 	long i;
 
 	if (argc > 1) {
+	    rb_unlock_wr(ary);
 	    rb_raise(rb_eArgError, "wrong number of arguments");
 	}
 	for (i=0; i<len; i++) {
@@ -258,7 +275,7 @@
 	memfill(RARRAY(ary)->ptr, len, val);
 	RARRAY(ary)->len = len;
     }
-
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -292,6 +309,7 @@
     if (idx < 0) {
 	idx += RARRAY(ary)->len;
 	if (idx < 0) {
+	    rb_unlock_wr(ary);
 	    rb_raise(rb_eIndexError, "index %ld out of array",
 		    idx - RARRAY(ary)->len);
 	}
@@ -314,6 +332,7 @@
 	RARRAY(ary)->len = idx + 1;
     }
     RARRAY(ary)->ptr[idx] = val;
+    rb_unlock_wr(ary);
 }
 
 VALUE
@@ -344,15 +363,22 @@
 rb_ary_pop(ary)
     VALUE ary;
 {
+    VALUE item;
+    
     rb_ary_modify_check(ary);
-    if (RARRAY(ary)->len == 0) return Qnil;
+    if (RARRAY(ary)->len == 0) {
+	rb_unlock_wr(ary);
+	return Qnil;
+    }
     if (!FL_TEST(ary, ELTS_SHARED) &&
 	    RARRAY(ary)->len * 2 < RARRAY(ary)->aux.capa &&
 	    RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
 	RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
 	REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
     }
-    return RARRAY(ary)->ptr[--RARRAY(ary)->len];
+    item = RARRAY(ary)->ptr[--RARRAY(ary)->len];
+    rb_unlock_wr(ary);
+    return item;
 }
 
 static void
@@ -378,12 +404,15 @@
     VALUE top;
 
     rb_ary_modify_check(ary);
-    if (RARRAY(ary)->len == 0) return Qnil;
+    if (RARRAY(ary)->len == 0) {
+	rb_unlock_wr(ary);
+	return Qnil;
+    }
     top = RARRAY(ary)->ptr[0];
     ary_make_shared(ary);
     RARRAY(ary)->ptr++;		/* shift ptr */
     RARRAY(ary)->len--;
-
+    rb_unlock_wr(ary);
     return top;
 }
 
@@ -407,6 +436,7 @@
     RARRAY(ary)->len++;
     RARRAY(ary)->ptr[0] = item;
 
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -685,6 +715,7 @@
 	}
 	MEMMOVE(RARRAY(ary)->ptr + beg, RARRAY(rpl)->ptr, VALUE, rlen);
     }
+    rb_unlock_wr(ary);
 }
 
 static VALUE
@@ -1034,7 +1065,10 @@
     VALUE tmp;
 
     rb_ary_modify(ary);
-    if (RARRAY(ary)->len <= 1) return ary;
+    if (RARRAY(ary)->len <= 1) {
+	rb_unlock_wr(ary);
+	return ary;
+    }
 
     p1 = RARRAY(ary)->ptr;
     p2 = p1 + RARRAY(ary)->len - 1;	/* points last item */
@@ -1044,7 +1078,7 @@
 	*p1++ = *p2;
 	*p2-- = tmp;
     }
-
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1115,7 +1149,6 @@
 sort_unlock(ary)
     VALUE ary;
 {
-    FL_UNSET(ary, ARY_TMPLOCK);
     return ary;
 }
 
@@ -1124,10 +1157,12 @@
     VALUE ary;
 {
     rb_ary_modify(ary);
-    if (RARRAY(ary)->len <= 1) return ary;
-
-    FL_SET(ary, ARY_TMPLOCK);	/* prohibit modification during sort */
+    if (RARRAY(ary)->len <= 1) {
+	rb_unlock_wr(ary);
+	return ary;
+    }
     rb_ensure(sort_internal, ary, sort_unlock, ary);
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1169,6 +1204,7 @@
     for (i = 0; i < RARRAY(ary)->len; i++) {
 	RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]);
     }
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1216,8 +1252,10 @@
     }
     if (RARRAY(ary)->len == i2) {
 	if (rb_block_given_p()) {
+	    rb_unlock_wr(ary);
 	    return rb_yield(item);
 	}
+	rb_unlock_wr(ary);
 	return Qnil;
     }
 
@@ -1227,7 +1265,7 @@
 	RARRAY(ary)->aux.capa = i2 * 2;
 	REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
     }
-
+    rb_unlock_wr(ary);
     return item;
 }
 
@@ -1240,10 +1278,16 @@
     VALUE del;
 
     rb_ary_modify(ary);
-    if (pos >= len) return Qnil;
+    if (pos >= len) {
+	rb_unlock_wr(ary);
+	return Qnil;
+    }
     if (pos < 0) {
 	pos += len;
-	if (pos < 0) return Qnil;
+	if (pos < 0) {
+	    rb_unlock_wr(ary);
+	    return Qnil;
+	}
     }
 
     del = RARRAY(ary)->ptr[pos];
@@ -1252,6 +1296,7 @@
     }
     RARRAY(ary)->len = pos;
 
+    rb_unlock_wr(ary);
     return del;
 }
 
@@ -1281,13 +1326,14 @@
 	}
 	arg2 = rb_ary_subseq(ary, pos, len);
 	rb_ary_update(ary, pos, len, Qnil);	/* Qnil/rb_ary_new2(0) */
+	rb_unlock_wr(ary);
 	return arg2;
     }
 
     if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) {
 	goto delete_pos_len;
     }
-
+    rb_unlock_wr(ary);
     return rb_ary_delete_at(ary, NUM2LONG(arg1));
 }
 
@@ -1305,9 +1351,12 @@
 	}
 	i2++;
     }
-    if (RARRAY(ary)->len == i2) return Qnil;
+    if (RARRAY(ary)->len == i2) {
+	rb_unlock_wr(ary);
+	return Qnil;
+    }
     RARRAY(ary)->len = i2;
-
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1348,6 +1397,7 @@
 	RARRAY(ary)->aux.capa = ARY_DEFAULT_SIZE * 2;
 	REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
     }
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1414,6 +1464,7 @@
 	    *p++ = item;
 	}
     }
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1706,7 +1757,7 @@
 	p++;
     }
     RARRAY(ary)->len = (q - RARRAY(ary)->ptr);
-
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1734,11 +1785,12 @@
 	else *p++ = *t++;
     }
     if (RARRAY(ary)->len == (p - RARRAY(ary)->ptr)) {
+	rb_unlock_wr(ary);
 	return Qnil;
     }
     RARRAY(ary)->len = RARRAY(ary)->aux.capa = (p - RARRAY(ary)->ptr);
     REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
-
+    rb_unlock_wr(ary);
     return ary;
 }
 
@@ -1817,6 +1869,7 @@
 	}
 	i++;
     }
+    rb_unlock_wr(ary);
     if (mod == 0) return Qnil;
     return ary;
 }

-- 
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Michal Rokos                         Czech Technical University, Prague
E-mail:m.rokos@sh.cvut.cz      ICQ:36118339      Jabber:majkl@jabber.cz
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [NothinkToDo] ThreadSafeRuby
  2002-07-31 15:27 [NothinkToDo] ThreadSafeRuby Michal Rokos
@ 2002-07-31 16:23 ` ts
  0 siblings, 0 replies; 2+ messages in thread
From: ts @ 2002-07-31 16:23 UTC (permalink / raw
  To: ruby-core; +Cc: ruby-core

>>>>> "M" == Michal Rokos <m.rokos@sh.cvut.cz> writes:

M>  struct RBasic {
M>      unsigned long flags;
M>      VALUE klass;
M> +    lock_t lck;
M>  };
 
 be carefull with this and see  [ruby-talk:5956] 

  * currently each internal structure sizes are made strictly less
    than 5 pointer size for space efficiency.



Guy Decoux

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-07-31 16:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-07-31 15:27 [NothinkToDo] ThreadSafeRuby Michal Rokos
2002-07-31 16:23 ` ts

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).