OBJECT float_compare(STATE, double a, double b) { if(a < b) { return I2N(-1); } else if(a > b) { return I2N(1); } return I2N(0); }
static void _cpu_wake_channel_and_read(EV_P_ struct ev_io *ev, int revents) { STATE; size_t sz, total, offset; ssize_t i; char *buf; OBJECT ret, ba, enc; struct thread_info *ti = (struct thread_info*)ev->data; ti->state->pending_events--; state = ti->state; if(NIL_P(ti->buffer)) { ret = I2N(ti->fd); } else { ba = string_get_data(ti->buffer); enc = string_get_encoding(ti->buffer); sz = (size_t)ti->count; if(enc == SYM("buffer")) { offset = N2I(string_get_bytes(ti->buffer)); } else { offset = 0; } /* Clamp the read size so we don't overrun */ total = SIZE_OF_BODY(ba) - offset - 1; if(total < sz) { sz = total; } buf = bytearray_byte_address(state, ba); buf += offset; while(1) { i = read(ti->fd, buf, sz); if(i == 0) { ret = Qnil; } else if(i == -1) { /* If we read and got nothing, go again. We must get something. It might be better to re-schedule this in libev and try again, but libev just said SOMETHING was there... */ if(errno == EINTR) continue; ret = lookuptable_fetch(state, state->global->errno_mapping, I2N(errno)); } else { buf[i] = 0; string_set_bytes(ti->buffer, I2N(i + offset)); ret = I2N(i); } break; } } cpu_channel_send(state, ti->c, ti->channel, ret); _cpu_event_unregister_info(state, ti); }
OBJECT blokenv_s_under_context2(STATE, OBJECT cmethod, OBJECT ctx, OBJECT ctx_block) { OBJECT obj; int num_lcls = N2I(cmethod_get_local_count(cmethod)); obj = blokenv_allocate(state); blokenv_set_home(obj, ctx); blokenv_set_initial_ip(obj, I2N(0)); // We have no real last since the block gets it's own method. // Just set this very large so that comparison for bounds // checks are always true. blokenv_set_last_ip(obj, I2N(1 << 25)); blokenv_set_post_send(obj, I2N(0)); blokenv_set_home_block(obj, ctx_block); blokenv_set_method(obj, cmethod); blokenv_set_local_count(obj, I2N(num_lcls)); return obj; }
void cpu_find_waiters(STATE) { pid_t pid; int status, skip; OBJECT ret; struct thread_info *ti, *tnext; ti = (struct thread_info*)(state->thread_infos); while (ti) { if (ti->type != WAITER) { ti = ti->next; continue; } while((pid = waitpid(ti->pid, &status, WNOHANG || ti->options)) <= -1 && errno == EINTR) ; skip = 0; if (pid > 0) { if (WIFEXITED(status)) { ret = I2N(WEXITSTATUS(status)); } else { /* Could support WIFSIGNALED also. */ ret = Qtrue; } cpu_channel_send(ti->state, ti->c, ti->channel, tuple_new2(state, 2, I2N(pid), ret)); } else if (pid == -1 && errno == ECHILD) { cpu_channel_send(ti->state, ti->c, ti->channel, Qfalse); } else if (pid == 0 && (ti->options & WNOHANG)) { cpu_channel_send(ti->state, ti->c, ti->channel, Qnil); } else { skip = 1; } tnext = ti->next; if (!skip) { _cpu_event_unregister_info(ti->state, ti); } ti = tnext; } }
static OBJECT _cpu_event_register_info(STATE, struct thread_info *ti) { /* Increment and clamp. */ state->event_id = (++state->event_id & FIXNUM_WIDTH); ti->id = state->event_id; ti->prev = NULL; ti->next = state->thread_infos; if(state->thread_infos) { ((struct thread_info*)state->thread_infos)->prev = ti; } state->thread_infos = ti; return I2N(ti->id); }
OBJECT ffi_getnameinfo(STATE, struct sockaddr *sockaddr, socklen_t sockaddr_len, int flags) { char node[NI_MAXHOST], service[NI_MAXSERV]; OBJECT value, host, port, ip; int err; host = Qnil; if(!(flags & NI_NUMERICHOST)) { err = getnameinfo(sockaddr, sockaddr_len, node, NI_MAXHOST, NULL, 0, 0); if(err != 0) { return tuple_new2(state, 2, Qfalse, string_new(state, gai_strerror(err))); } host = string_new2(state, node, strlen(node)); } err = getnameinfo(sockaddr, sockaddr_len, node, NI_MAXHOST, service, NI_MAXSERV, flags | NI_NUMERICHOST | NI_NUMERICSERV); if(err != 0) { return tuple_new2(state, 2, Qfalse, string_new(state, gai_strerror(err))); } ip = string_new2(state, node, strlen(node)); port = I2N(atoi(service)); value = array_new(state, 0); array_append(state, value, I2N(sockaddr->sa_family)); array_append(state, value, port); array_append(state, value, host); array_append(state, value, ip); return tuple_new2(state, 2, Qtrue, value); }
void subtend_setup(STATE) { /* SystemData is class that just means that the body is opaque and not directly usable. It's used to store rni_nmc's native_method's */ BASIC_CLASS(data) = rbs_class_new(state, "SystemData", 0, BASIC_CLASS(object)); BASIC_CLASS(nmc) = rbs_class_new(state, "NativeMethodContext", 0, BASIC_CLASS(fastctx)); BASIC_CLASS(nmethod) = rbs_class_new(state, "NativeMethod", 0, BASIC_CLASS(cmethod)); class_set_object_type(BASIC_CLASS(nmethod), I2N(NMethodType)); ffi_dlinit(); __ffi_handle_to_self = ffi_dldefault(); /* Obtain a handle to *this process* for default */ subtend_setup_global(); state->handle_tbl = handle_table_new(); }
OBJECT subtend_load_library(STATE, cpu c, OBJECT path, OBJECT name) { dlhandle lib; char *c_path, *c_name; void (*ep)(void); char init[128] = "Init_"; char *sys_name; rni_nmc *nmc; int len; struct stat sb; char *end; nmc = NULL; /* Try to make room for 'Init_', the extension, and a null byte */ len = N2I(string_get_bytes(path)) + 21; sys_name = ALLOC_N(char, len); /* path is a string like 'ext/gzip', we turn that into 'ext/gzip.so' or whatever the library suffix is. */ c_path = rbx_string_as_cstr(state, path); strlcpy(sys_name, c_path, len); end = strrchr(sys_name, '.'); /* detect if the suffix is already there. */ if(end == NULL || strcmp(end++, LIBSUFFIX)) { strlcat(sys_name, LIBSUFFIX, len); } if(stat(sys_name, &sb) == 1) { XFREE(sys_name); return I2N(0); } /* Open it up. If this fails, then we just pretend like the library isn't there. */ lib = xdlopen(sys_name); if(!lib) { XFREE(sys_name); printf("Couldnt open '%s': %s\n", sys_name, xdlerror()); /* No need to raise an exception, it's not there. */ return I2N(0); } /* name is like 'gzip', we want 'Init_gzip' */ c_name = rbx_string_as_cstr(state, name); strlcat(init, c_name, sizeof(init)); /* Try and load the init function. */ ep = (void (*)(void))xdlsym(lib, init); if(!ep) { XFREE(sys_name); /* TODO: raise an exception that the library is missing the function. */ return I2N(1); } else { nmc = nmc_new_standalone(); /* Now we need to setup the 'global' context so that stuff like rb_define_method works. */ subtend_set_context(state, c, nmc); /* Now perform the call. */ (*ep)(); } /* * We can't close the library while there are references to the code * in it. For now, we just leak the library reference, but we need * to track it so we can clean them up at some point in the future. * */ if(nmc) XFREE(nmc); subtend_set_context(state, c, NULL); XFREE(sys_name); return Qtrue; }
/* Creates the rubinius object universe from scratch. */ void cpu_bootstrap(STATE) { OBJECT cls, obj, tmp, tmp2; int i; /* Class is created first by hand, and twittle to setup the internal recursion. */ cls = NEW_OBJECT(Qnil, CLASS_FIELDS); cls->klass = cls; class_set_instance_fields(cls, I2N(CLASS_FIELDS)); class_set_has_ivars(cls, Qtrue); class_set_object_type(cls, I2N(ClassType)); cls->obj_type = ClassType; BC(class) = cls; obj = _object_basic_class(state, Qnil); BC(object) = obj; BC(module) = _module_basic_class(state, obj); class_set_superclass(cls, BC(module)); BC(metaclass) = _metaclass_basic_class(state, cls); class_set_object_type(BC(metaclass), I2N(MetaclassType)); BC(tuple) = _tuple_basic_class(state, obj); BC(hash) = _hash_basic_class(state, obj); BC(lookuptable) = _lookuptable_basic_class(state, obj); BC(methtbl) = _methtbl_basic_class(state, BC(lookuptable)); object_create_metaclass(state, obj, cls); object_create_metaclass(state, BC(module), object_metaclass(state, obj)); object_create_metaclass(state, BC(class), object_metaclass(state, BC(module))); object_create_metaclass(state, BC(tuple), (OBJECT)0); object_create_metaclass(state, BC(hash), (OBJECT)0); object_create_metaclass(state, BC(lookuptable), (OBJECT)0); object_create_metaclass(state, BC(methtbl), (OBJECT)0); module_setup_fields(state, object_metaclass(state, obj)); module_setup_fields(state, object_metaclass(state, BC(module))); module_setup_fields(state, object_metaclass(state, BC(class))); module_setup_fields(state, object_metaclass(state, BC(tuple))); module_setup_fields(state, object_metaclass(state, BC(hash))); module_setup_fields(state, object_metaclass(state, BC(lookuptable))); module_setup_fields(state, object_metaclass(state, BC(methtbl))); BC(symbol) = _symbol_class(state, obj); BC(array) = _array_class(state, obj); BC(bytearray) = _bytearray_class(state, obj); BC(string) = _string_class(state, obj); BC(symtbl) = _symtbl_class(state, obj); BC(cmethod) = _cmethod_class(state, obj); BC(io) = _io_class(state, obj); BC(blokenv) = _blokenv_class(state, obj); BC(icache) = _icache_class(state, obj); BC(staticscope) = _staticscope_class(state, obj); class_set_object_type(BC(bytearray), I2N(ByteArrayType)); class_set_object_type(BC(string), I2N(StringType)); class_set_object_type(BC(methtbl), I2N(MTType)); class_set_object_type(BC(tuple), I2N(TupleType)); class_set_object_type(BC(hash), I2N(HashType)); class_set_object_type(BC(lookuptable), I2N(LookupTableType)); /* The symbol table */ state->global->symbols = symtbl_new(state); module_setup(state, obj, "Object"); module_setup(state, cls, "Class"); module_setup(state, BC(module), "Module"); module_setup(state, BC(metaclass), "MetaClass"); module_setup(state, BC(symbol), "Symbol"); module_setup(state, BC(tuple), "Tuple"); module_setup(state, BC(array), "Array"); module_setup(state, BC(bytearray), "ByteArray"); module_setup(state, BC(hash), "Hash"); module_setup(state, BC(lookuptable), "LookupTable"); module_setup(state, BC(string), "String"); module_setup(state, BC(symtbl), "SymbolTable"); module_setup(state, BC(methtbl), "MethodTable"); module_setup(state, BC(cmethod), "CompiledMethod"); module_setup(state, BC(io), "IO"); module_setup(state, BC(blokenv), "BlockEnvironment"); module_setup(state, BC(icache), "InlineCache"); module_setup(state, BC(staticscope), "StaticScope"); class_set_object_type(BC(array), I2N(ArrayType)); class_set_object_type(BC(cmethod), I2N(CMethodType)); class_set_object_type(BC(blokenv), I2N(BlockEnvType)); rbs_const_set(state, obj, "Symbols", state->global->symbols); BC(nil_class) = rbs_class_new(state, "NilClass", 0, obj); BC(true_class) = rbs_class_new(state, "TrueClass", 0, obj); BC(false_class) = rbs_class_new(state, "FalseClass", 0, obj); tmp = rbs_class_new(state, "Numeric", 0, obj); tmp2 = rbs_class_new(state, "Integer", 0, tmp); BC(fixnum_class) = rbs_class_new(state, "Fixnum", 0, tmp2); class_set_object_type(BC(fixnum_class), I2N(FixnumType)); BC(bignum) = rbs_class_new(state, "Bignum", 0, tmp2); class_set_object_type(BC(bignum), I2N(BignumType)); bignum_init(state); BC(floatpoint) = rbs_class_new(state, "Float", 0, tmp); class_set_object_type(BC(floatpoint), I2N(FloatType)); BC(undef_class) = rbs_class_new(state, "UndefClass", 0, obj); BC(fastctx) = rbs_class_new(state, "MethodContext", 0, obj); BC(methctx) = BC(fastctx); BC(blokctx) = rbs_class_new(state, "BlockContext", 0, BC(fastctx)); BC(task) = rbs_class_new(state, "Task", 0, obj); class_set_object_type(BC(task), I2N(TaskType)); BC(iseq) = rbs_class_new(state, "InstructionSequence", 0, BC(bytearray)); class_set_object_type(BC(iseq), I2N(ISeqType)); #define bcs(name, sup, string) BC(name) = _ ## name ## _class(state, sup); \ module_setup(state, BC(name), string); /* the special_classes C array is use do quickly calculate the class of an immediate by just indexing into the array using (obj & 0x1f) */ /* fixnum, symbol, and custom can have a number of patterns below 0x1f, so we fill them all. */ for(i = 0; i < SPECIAL_CLASS_SIZE; i += 4) { state->global->special_classes[i + 0] = Qnil; state->global->special_classes[i + 1] = BC(fixnum_class); state->global->special_classes[i + 2] = Qnil; if(((i + 3) & 0x7) == 0x3) { state->global->special_classes[i + 3] = BC(symbol); } else { state->global->special_classes[i + 3] = CUSTOM_CLASS; } } /* These only have one value, so they only need one spot in the array */ state->global->special_classes[(intptr_t)Qundef] = BC(undef_class); state->global->special_classes[(intptr_t)Qfalse] = BC(false_class); state->global->special_classes[(intptr_t)Qnil ] = BC(nil_class); state->global->special_classes[(intptr_t)Qtrue ] = BC(true_class); bcs(regexp, obj, "Regexp"); class_set_object_type(BC(regexp), I2N(RegexpType)); bcs(regexpdata, obj, "RegexpData"); class_set_object_type(BC(regexpdata), I2N(RegexpDataType)); bcs(matchdata, obj, "MatchData"); cpu_bootstrap_exceptions(state); rbs_module_new(state, "Rubinius", BC(object)); Init_list(state); Init_cpu_task(state); Init_ffi(state); regexp_init(state); selector_init(state); send_site_init(state); rbs_const_set(state, rbs_const_get(state, BASIC_CLASS(object), "Rubinius"), "Primitives", cpu_populate_prim_names(state)); state->global->external_ivars = lookuptable_new(state); }