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; }
static int native_thread_create(rb_thread_t *th) { int err = 0; if (use_cached_thread(th)) { thread_debug("create (use cached thread): %p\n", th); } else { pthread_attr_t attr; size_t stack_size = 512 * 1024; /* 512KB */ size_t space; #ifdef PTHREAD_STACK_MIN if (stack_size < PTHREAD_STACK_MIN) { stack_size = PTHREAD_STACK_MIN * 2; } #endif space = stack_size/5; if (space > 1024*1024) space = 1024*1024; th->machine_stack_maxsize = stack_size - space; #ifdef __ia64 th->machine_stack_maxsize /= 2; th->machine_register_stack_maxsize = th->machine_stack_maxsize; #endif CHECK_ERR(pthread_attr_init(&attr)); #ifdef PTHREAD_STACK_MIN thread_debug("create - stack size: %lu\n", (unsigned long)stack_size); CHECK_ERR(pthread_attr_setstacksize(&attr, stack_size)); #endif CHECK_ERR(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED)); CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); rb_objc_retain((void *)th); err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th); thread_debug("create: %p (%d)", th, err); CHECK_ERR(pthread_attr_destroy(&attr)); if (!err) { pthread_cond_init(&th->native_thread_data.sleep_cond, 0); } else { st_delete_wrap(th->vm->living_threads, th->self); th->status = THREAD_KILLED; rb_raise(rb_eThreadError, "can't create Thread (%d)", err); } } return err; }
const void * rb_objc_retain_ni(const void *addr) { return rb_objc_retain((void *)addr); }
void Init_Proc(void) { /* Proc */ rb_cProc = rb_define_class("Proc", rb_cObject); rb_undef_alloc_func(rb_cProc); rb_define_singleton_method(rb_cProc, "new", rb_proc_s_new, -1); rb_define_method(rb_cProc, "call", proc_call, -1); rb_define_method(rb_cProc, "[]", proc_call, -1); rb_define_method(rb_cProc, "yield", proc_call, -1); rb_define_method(rb_cProc, "to_proc", proc_to_proc, 0); rb_define_method(rb_cProc, "arity", proc_arity, 0); rb_define_method(rb_cProc, "clone", proc_clone, 0); rb_define_method(rb_cProc, "dup", proc_dup, 0); rb_define_method(rb_cProc, "==", proc_eq, 1); rb_define_method(rb_cProc, "eql?", proc_eq, 1); rb_define_method(rb_cProc, "hash", proc_hash, 0); rb_define_method(rb_cProc, "to_s", proc_to_s, 0); rb_define_method(rb_cProc, "lambda?", proc_lambda_p, 0); rb_define_method(rb_cProc, "binding", proc_binding, 0); rb_define_method(rb_cProc, "curry", proc_curry, -1); /* Exceptions */ rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError); rb_define_method(rb_eLocalJumpError, "exit_value", localjump_xvalue, 0); rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0); rb_eSysStackError = rb_define_class("SystemStackError", rb_eException); sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep"); OBJ_TAINT(sysstack_error); rb_register_mark_object(sysstack_error); rb_objc_retain((void *)sysstack_error); /* utility functions */ rb_define_global_function("proc", rb_block_proc, 0); rb_define_global_function("lambda", proc_lambda, 0); /* Method */ rb_cMethod = rb_define_class("Method", rb_cObject); rb_undef_alloc_func(rb_cMethod); rb_undef_method(CLASS_OF(rb_cMethod), "new"); rb_define_method(rb_cMethod, "==", method_eq, 1); rb_define_method(rb_cMethod, "eql?", method_eq, 1); rb_define_method(rb_cMethod, "hash", method_hash, 0); rb_define_method(rb_cMethod, "clone", method_clone, 0); rb_define_method(rb_cMethod, "call", rb_method_call, -1); rb_define_method(rb_cMethod, "[]", rb_method_call, -1); rb_define_method(rb_cMethod, "arity", method_arity_m, 0); rb_define_method(rb_cMethod, "inspect", method_inspect, 0); rb_define_method(rb_cMethod, "to_s", method_inspect, 0); rb_define_method(rb_cMethod, "to_proc", method_proc, 0); rb_define_method(rb_cMethod, "receiver", method_receiver, 0); rb_define_method(rb_cMethod, "name", method_name, 0); rb_define_method(rb_cMethod, "owner", method_owner, 0); rb_define_method(rb_cMethod, "unbind", method_unbind, 0); rb_define_method(rb_mKernel, "method", rb_obj_method, 1); rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1); /* UnboundMethod */ rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject); rb_undef_alloc_func(rb_cUnboundMethod); rb_undef_method(CLASS_OF(rb_cUnboundMethod), "new"); rb_define_method(rb_cUnboundMethod, "==", method_eq, 1); rb_define_method(rb_cUnboundMethod, "eql?", method_eq, 1); rb_define_method(rb_cUnboundMethod, "hash", method_hash, 0); rb_define_method(rb_cUnboundMethod, "clone", method_clone, 0); rb_define_method(rb_cUnboundMethod, "arity", method_arity_m, 0); rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0); rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0); rb_define_method(rb_cUnboundMethod, "name", method_name, 0); rb_define_method(rb_cUnboundMethod, "owner", method_owner, 0); rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1); /* Module#*_method */ rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1); rb_define_method(rb_cModule, "public_instance_method", rb_mod_public_instance_method, 1); rb_define_private_method(rb_cModule, "define_method", rb_mod_define_method, -1); #if WITH_OBJC rb_define_private_method(rb_cModule, "ib_action", rb_mod_objc_ib_action, 1); #endif /* Kernel */ rb_define_method(rb_mKernel, "define_singleton_method", rb_obj_define_method, -1); }