[macruby-changes] [1925] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jun 24 21:04:56 PDT 2009
Revision: 1925
http://trac.macosforge.org/projects/ruby/changeset/1925
Author: lsansonetti at apple.com
Date: 2009-06-24 21:04:55 -0700 (Wed, 24 Jun 2009)
Log Message:
-----------
more MT work
Modified Paths:
--------------
MacRuby/branches/experimental/thread.c
MacRuby/branches/experimental/vm.cpp
MacRuby/branches/experimental/vm.h
Modified: MacRuby/branches/experimental/thread.c
===================================================================
--- MacRuby/branches/experimental/thread.c 2009-06-24 19:13:48 UTC (rev 1924)
+++ MacRuby/branches/experimental/thread.c 2009-06-25 04:04:55 UTC (rev 1925)
@@ -6,8 +6,19 @@
typedef struct rb_vm_mutex {
pthread_mutex_t mutex;
+ pthread_t thread;
} rb_vm_mutex_t;
+#define assert_ok(call) \
+ do { \
+ const int __r = call; \
+ if (__r != 0) { \
+ rb_raise(rb_eRuntimeError, "pthread operation failed: error %d", \
+ __r); \
+ } \
+ } \
+ while (0)
+
VALUE rb_cThread;
VALUE rb_cMutex;
@@ -67,6 +78,7 @@
}
t->vm = rb_vm_create_vm();
+ t->value = Qundef;
// Retain the Thread object to avoid a potential GC, the corresponding
// release is done in rb_vm_thread_run().
@@ -136,11 +148,8 @@
}
rb_vm_thread_t *t = GetThreadPtr(self);
+ pthread_join(t->thread, NULL);
- if (pthread_join(t->thread, NULL) != 0) {
- rb_sys_fail("pthread_join() failed");
- }
-
return self;
}
@@ -156,10 +165,10 @@
*/
static VALUE
-thread_value(VALUE self)
+thread_value(VALUE self, SEL sel)
{
- // TODO
- return Qnil;
+ thread_join_m(self, 0, 0, NULL);
+ return GetThreadPtr(self)->value;
}
void
@@ -616,10 +625,15 @@
*/
static VALUE
-rb_thread_inspect(VALUE thread)
+rb_thread_inspect(VALUE thread, SEL sel)
{
- // TODO
- return Qnil;
+ const char *status = "unknown"; // TODO
+
+ char buf[100];
+ snprintf(buf, sizeof buf, "#<%s:%p %s>", rb_obj_classname(thread),
+ (void *)thread, status);
+
+ return rb_str_new2(buf);
}
/*
@@ -1134,22 +1148,12 @@
return Data_Wrap_Struct(rb_cMutex, NULL, NULL, t);
}
-#define GetMutex(obj) (((rb_vm_mutex_t *)DATA_PTR(obj))->mutex)
+#define GetMutexPtr(obj) ((rb_vm_mutex_t *)DATA_PTR(obj))
-#define assert_ok(call) \
- do { \
- const int __r = call; \
- if (__r != 0) { \
- rb_raise(rb_eRuntimeError, "mutex operation failed: error %d", \
- __r); \
- } \
- } \
- while (0)
-
static VALUE
mutex_initialize(VALUE self, SEL sel)
{
- assert_ok(pthread_mutex_init(&GetMutex(self), NULL));
+ assert_ok(pthread_mutex_init(&GetMutexPtr(self)->mutex, NULL));
return self;
}
@@ -1160,11 +1164,10 @@
* Returns +true+ if this lock is currently held by some thread.
*/
-VALUE
-rb_mutex_locked_p(VALUE self)
+static VALUE
+rb_mutex_locked_p(VALUE self, SEL sel)
{
- // TODO
- return Qnil;
+ return GetMutexPtr(self)->thread == 0 ? Qfalse : Qtrue;
}
/*
@@ -1178,23 +1181,34 @@
static VALUE
rb_mutex_trylock(VALUE self, SEL sel)
{
- // TODO
- return Qnil;
+ if (pthread_mutex_trylock(&GetMutexPtr(self)->mutex) == 0) {
+ GetMutexPtr(self)->thread = pthread_self();
+ return Qtrue;
+ }
+ return Qfalse;
}
/*
* call-seq:
- * mutex.lock => true or false
+ * mutex.lock => self
*
* Attempts to grab the lock and waits if it isn't available.
* Raises +ThreadError+ if +mutex+ was locked by the current thread.
*/
-VALUE
-rb_mutex_lock(VALUE self)
+static VALUE
+rb_mutex_lock(VALUE self, SEL sel)
{
- // TODO
- return Qnil;
+ pthread_t current = pthread_self();
+ rb_vm_mutex_t *m = GetMutexPtr(self);
+ if (m->thread == current) {
+ rb_raise(rb_eThreadError, "deadlock; recursive locking");
+ }
+
+ assert_ok(pthread_mutex_lock(&m->mutex));
+ m->thread = current;
+
+ return self;
}
/*
@@ -1205,11 +1219,19 @@
* Raises +ThreadError+ if +mutex+ wasn't locked by the current thread.
*/
-VALUE
-rb_mutex_unlock(VALUE self)
+static VALUE
+rb_mutex_unlock(VALUE self, SEL sel)
{
- // TODO
- return Qnil;
+ rb_vm_mutex_t *m = GetMutexPtr(self);
+ if (m->thread == 0) {
+ rb_raise(rb_eThreadError,
+ "Attempt to unlock a mutex which is not locked");
+ }
+
+ assert_ok(pthread_mutex_unlock(&m->mutex));
+ m->thread = 0;
+
+ return self;
}
/*
@@ -1239,10 +1261,10 @@
static VALUE
mutex_synchronize(VALUE self, SEL sel)
{
- assert_ok(pthread_mutex_lock(&GetMutex(self)));
+ rb_mutex_lock(self, 0);
// TODO catch exception
VALUE ret = rb_yield(Qundef);
- assert_ok(pthread_mutex_unlock(&GetMutex(self)));
+ rb_mutex_unlock(self, 0);
return ret;
}
@@ -1286,7 +1308,7 @@
rb_objc_define_method(rb_cThread, "initialize", thread_initialize, -1);
rb_define_method(rb_cThread, "raise", thread_raise_m, -1);
rb_objc_define_method(rb_cThread, "join", thread_join_m, -1);
- rb_define_method(rb_cThread, "value", thread_value, 0);
+ rb_objc_define_method(rb_cThread, "value", thread_value, 0);
rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
@@ -1306,7 +1328,7 @@
rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
rb_define_method(rb_cThread, "group", rb_thread_group, 0);
- rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
+ rb_objc_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
cThGroup = rb_define_class("ThreadGroup", rb_cObject);
rb_define_method(cThGroup, "list", thgroup_list, 0);
@@ -1317,10 +1339,10 @@
rb_cMutex = rb_define_class("Mutex", rb_cObject);
rb_objc_define_method(*(VALUE *)rb_cMutex, "alloc", mutex_s_alloc, 0);
rb_objc_define_method(rb_cMutex, "initialize", mutex_initialize, 0);
- rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
- rb_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
- rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
- rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
+ rb_objc_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
+ rb_objc_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
+ rb_objc_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
+ rb_objc_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
rb_objc_define_method(rb_cMutex, "synchronize", mutex_synchronize, 0);
Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp 2009-06-24 19:13:48 UTC (rev 1924)
+++ MacRuby/branches/experimental/vm.cpp 2009-06-25 04:04:55 UTC (rev 1925)
@@ -443,10 +443,8 @@
RoxorCore::method_node_get(IMP imp)
{
std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
- if (iter == ruby_imps.end()) {
- return NULL;
- }
- return iter->second;
+ rb_vm_method_node_t *m = iter == ruby_imps.end() ? NULL : iter->second;
+ return m;
}
extern "C"
@@ -1834,7 +1832,8 @@
}
static force_inline void
-__rb_vm_fix_args(const VALUE *argv, VALUE *new_argv, const rb_vm_arity_t &arity, int argc)
+__rb_vm_fix_args(const VALUE *argv, VALUE *new_argv,
+ const rb_vm_arity_t &arity, int argc)
{
assert(argc >= arity.min);
assert((arity.max == -1) || (argc <= arity.max));
@@ -2121,16 +2120,22 @@
inline void *
RoxorCore::gen_stub(std::string types, int argc, bool is_objc)
{
+ lock();
+
std::map<std::string, void *> &stubs = is_objc ? objc_stubs : c_stubs;
std::map<std::string, void *>::iterator iter = stubs.find(types);
- if (iter != stubs.end()) {
- return iter->second;
+ void *stub;
+ if (iter == stubs.end()) {
+ Function *f = RoxorCompiler::shared->compile_stub(types.c_str(), argc,
+ is_objc);
+ stub = (void *)compile(f);
+ stubs.insert(std::make_pair(types, stub));
}
+ else {
+ stub = iter->second;
+ }
- Function *f = RoxorCompiler::shared->compile_stub(types.c_str(), argc,
- is_objc);
- void *stub = (void *)compile(f);
- stubs.insert(std::make_pair(types, stub));
+ unlock();
return stub;
}
@@ -2295,10 +2300,8 @@
argc = real_argc;
}
}
- GET_CORE()->lock();
ocache.stub = (rb_vm_objc_stub_t *)GET_CORE()->gen_stub(types,
argc, true);
- GET_CORE()->unlock();
}
static force_inline VALUE
@@ -2833,7 +2836,7 @@
}
rb_vm_block_t *
-RoxorCore::uncache_or_create_block(NODE *key, bool *cached, int dvars_size)
+RoxorVM::uncache_or_create_block(NODE *key, bool *cached, int dvars_size)
{
std::map<NODE *, rb_vm_block_t *>::iterator iter = blocks.find(key);
@@ -2845,12 +2848,10 @@
if (iter != blocks.end()) {
rb_objc_release(iter->second);
}
-
b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
+ (sizeof(VALUE *) * dvars_size));
rb_objc_retain(b);
blocks[key] = b;
-
*cached = false;
}
else {
@@ -2878,10 +2879,8 @@
cache_key = node;
}
- GET_CORE()->lock();
-
bool cached = false;
- rb_vm_block_t *b = GET_CORE()->uncache_or_create_block(cache_key, &cached,
+ rb_vm_block_t *b = GET_VM()->uncache_or_create_block(cache_key, &cached,
dvars_size);
if (!cached) {
@@ -2892,7 +2891,9 @@
}
else {
assert(llvm_function != NULL);
+ GET_CORE()->lock();
b->imp = GET_CORE()->compile((Function *)llvm_function);
+ GET_CORE()->unlock();
b->arity = rb_vm_node_arity(node);
}
b->flags = 0;
@@ -2904,8 +2905,6 @@
assert(b->dvars_size == dvars_size);
}
- GET_CORE()->unlock();
-
b->self = self;
b->node = node;
b->parent_var_uses = parent_var_uses;
@@ -4219,7 +4218,9 @@
void
RoxorCore::register_thread(VALUE thread)
{
+ lock();
rb_ary_push(threads, thread);
+ unlock();
rb_vm_thread_t *t = GetThreadPtr(thread);
assert(pthread_setspecific(RoxorVM::vm_thread_key, t->vm) == 0);
@@ -4231,11 +4232,13 @@
void
RoxorCore::unregister_thread(VALUE thread)
{
+ lock();
if (rb_ary_delete(threads, thread) != thread) {
printf("trying to unregister a thread (%p) that was never registered!",
(void *)thread);
abort();
}
+ unlock();
rb_vm_thread_t *t = GetThreadPtr(thread);
RoxorVM *vm = (RoxorVM *)t->vm;
@@ -4257,10 +4260,12 @@
try {
rb_vm_thread_t *t = GetThreadPtr(thread);
- rb_vm_block_eval(t->body, t->argc, t->argv);
+ VALUE val = rb_vm_block_eval(t->body, t->argc, t->argv);
+ GC_WB(&t->value, val);
}
catch (...) {
// TODO handle thread-level exceptions.
+ printf("exception raised inside thread %p\n", pthread_self());
}
GET_CORE()->unregister_thread(thread);
Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h 2009-06-24 19:13:48 UTC (rev 1924)
+++ MacRuby/branches/experimental/vm.h 2009-06-25 04:04:55 UTC (rev 1925)
@@ -77,6 +77,7 @@
int argc;
const VALUE *argv;
void *vm; // an instance of RoxorVM
+ VALUE value;
} rb_vm_thread_t;
typedef struct rb_vm_outer {
@@ -478,9 +479,6 @@
// Cache to avoid compiling the same Function twice.
std::map<Function *, IMP> JITcache;
- // Cache to avoid compiling the same block twice.
- std::map<NODE *, rb_vm_block_t *> blocks;
-
// Cache to identify pure Ruby methods.
std::map<IMP, rb_vm_method_node_t *> ruby_imps;
@@ -652,9 +650,6 @@
}
}
- rb_vm_block_t *uncache_or_create_block(NODE *key, bool *cached,
- int dvars_size);
-
size_t get_sizeof(const Type *type);
size_t get_sizeof(const char *type);
bool is_large_struct_type(const Type *type);
@@ -696,6 +691,10 @@
}
private:
+ // Cache to avoid allocating the same block twice.
+ std::map<NODE *, rb_vm_block_t *> blocks;
+
+ // Keeps track of the current VM state (blocks, exceptions, bindings).
std::vector<rb_vm_block_t *> current_blocks;
std::vector<VALUE> current_exceptions;
std::vector<rb_vm_binding_t *> bindings;
@@ -765,6 +764,9 @@
return b;
}
+ rb_vm_block_t *uncache_or_create_block(NODE *key, bool *cached,
+ int dvars_size);
+
rb_vm_binding_t *current_binding(void) {
return bindings.empty()
? NULL : bindings.back();
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090624/bef76492/attachment-0001.html>
More information about the macruby-changes
mailing list