예제 #1
0
OBJECT float_compare(STATE, double a, double b) {
  if(a < b) {
    return I2N(-1);
  } else if(a > b) {
    return I2N(1);
  }
  return I2N(0);
}
예제 #2
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);
}
예제 #3
0
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;
}
예제 #4
0
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;
  }
}
예제 #5
0
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);
}
예제 #6
0
파일: ffi_util.c 프로젝트: kwatch/rubinius
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);
}
예제 #7
0
파일: setup.c 프로젝트: kwatch/rubinius
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();
}
예제 #8
0
파일: library.c 프로젝트: kwatch/rubinius
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;
}
예제 #9
0
파일: bootstrap.c 프로젝트: kwatch/rubinius
/* 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);

}