Example #1
0
static VALUE
thread_initialize(VALUE thread, SEL sel, int argc, const VALUE *argv)
{
    if (!rb_block_given_p()) {
	rb_raise(rb_eThreadError, "must be called with a block");
    }
    rb_vm_block_t *b = rb_vm_current_block();
    assert(b != NULL);

    rb_vm_thread_t *t = GetThreadPtr(thread);
    rb_vm_thread_pre_init(t, b, argc, argv, rb_vm_create_vm());

    // The thread's group is always the parent's one.
    rb_thgroup_add(GetThreadPtr(rb_vm_current_thread())->group, thread);

    // Retain the Thread object to avoid a potential GC, the corresponding
    // release is done in rb_vm_thread_run().
    rb_objc_retain((void *)thread);

    if (pthread_create(&t->thread, NULL, (void *(*)(void *))rb_vm_thread_run,
		(void *)thread) != 0) {
	rb_sys_fail("pthread_create() failed");
    }

    return thread;
}
Example #2
0
static inline VALUE
rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope,
	bool pass_current_block)
{
    SEL sel;
    if (mid == ID_ALLOCATOR) {
	sel = selAlloc;
    }
    else {
	const char *midstr = rb_id2name(mid);
	if (argc > 0 && midstr[strlen(midstr) - 1] != ':') {
	    char buf[100];
	    snprintf(buf, sizeof buf, "%s:", midstr);
	    sel = sel_registerName(buf);
	}
	else {
	    sel = sel_registerName(midstr);
	}
    }

    void *cache = rb_vm_get_call_cache(sel);
    rb_vm_block_t *block = pass_current_block ? rb_vm_current_block() : NULL;
    return rb_vm_call_with_cache2(cache, block, recv, CLASS_OF(recv),
	    sel, argc, argv);
}
Example #3
0
File: proc.c Project: MSch/MacRuby
VALUE
rb_method_call(VALUE method, SEL sel, int argc, VALUE *argv)
{
    rb_vm_method_t *data;

    Data_Get_Struct(method, rb_vm_method_t, data);
    if (data->recv == Qundef) {
	rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    
    int safe = -1;
    if (OBJ_TAINTED(method)) {
	safe = rb_safe_level();
	if (rb_safe_level() < 4) {
	    rb_set_safe_level_force(4);
	}
    }

    VALUE result = rb_vm_method_call(data, rb_vm_current_block(), argc, argv);

    if (safe >= 0) {
	rb_set_safe_level_force(safe);
    }

    return result;
}
Example #4
0
static inline VALUE
rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope,
	bool pass_current_block)
{
    SEL sel;
    if (mid == ID_ALLOCATOR) {
	sel = selAlloc;
    }
    else {
	sel = rb_vm_id_to_sel(mid, argc);
    }
    rb_vm_block_t *block = pass_current_block ? rb_vm_current_block() : NULL;
    return rb_vm_call2(block, recv, CLASS_OF(recv), sel, argc, argv);
}
Example #5
0
static VALUE
thread_initialize(VALUE thread, SEL sel, int argc, const VALUE *argv)
{
    if (!rb_block_given_p()) {
	rb_raise(rb_eThreadError, "must be called with a block");
    }
    rb_vm_block_t *b = rb_vm_current_block();
    assert(b != NULL);

    rb_vm_thread_t *t = GetThreadPtr(thread);
    if (t->thread != 0) {
	rb_raise(rb_eThreadError, "already initialized thread");
    }
    rb_vm_thread_pre_init(t, b, argc, argv, rb_vm_create_vm());

    // The thread's group is always the parent's one.
    // The parent group might be nil (ex. if created from GCD).
    VALUE group = GetThreadPtr(rb_vm_current_thread())->group;
    if (group != Qnil) {
	thgroup_add_m(group, thread, false);
    }

    // Retain the Thread object to avoid a potential GC, the corresponding
    // release is done in rb_vm_thread_run().
    GC_RETAIN(thread);

    // Prepare attributes for the thread.
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    // Register the thread to the core. We are doing this before actually
    // running it because the current thread might perform a method poking at
    // the current registered threads (such as Kernel#sleep) right after that.
    rb_vm_register_thread(thread);

    // Launch it.
    if (pthread_create(&t->thread, &attr, (void *(*)(void *))rb_vm_thread_run,
		(void *)thread) != 0) {
	rb_sys_fail("pthread_create() failed");
    }
    pthread_attr_destroy(&attr);

    return thread;
}
Example #6
0
static rb_vm_block_t *
get_prepared_block()
{
    rb_vm_block_t *block = rb_vm_current_block();
    if (block == NULL) {
        rb_raise(rb_eArgError, "block not given");
    }
#if GCD_BLOCKS_COPY_DVARS
    block = rb_vm_dup_block(block);
    for (int i = 0; i < block->dvars_size; i++) {
    	VALUE *slot = block->dvars[i];
    	VALUE *new_slot = xmalloc(sizeof(VALUE));
    	GC_WB(new_slot, *slot);
    	GC_WB(&block->dvars[i], new_slot);
    }
#else
    rb_vm_block_make_detachable_proc(block);
#endif
    GC_RETAIN(block);
    return block;
}