void state_add_cleanup(STATE, OBJECT cls, state_cleanup_func func) { int type = N2I(class_get_object_type(cls)); state->type_info[type].cleanup = func; // printf("Registered cleanup for %p\n", module_get_name(cls)); class_set_needs_cleanup(cls, Qtrue); }
OBJECT float_coerce(STATE, OBJECT value) { if(FIXNUM_P(value)) { return float_new(state, (double)N2I(value)); } else if(BIGNUM_P(value)) { return float_new(state, bignum_to_double(state, value)); } return value; }
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); }
int cpu_event_cancel_event(STATE, OBJECT oid) { native_int id = N2I(oid); struct thread_info *ti = (struct thread_info*)state->thread_infos; struct thread_info *tnext; while(ti) { tnext = ti->next; if(ti->id == id) { _cpu_event_unregister_info(state, ti); return TRUE; } ti = tnext; } return FALSE; }
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; }
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; }