示例#1
0
/*
 * Holds thread execution while another thread is active.
 *
 * Thanks to this, all threads are "frozen" while the user is typing commands.
 */
void
acquire_lock(debug_context_t * dc)
{
  while ((!NIL_P(locker) && locker != rb_thread_current())
         || CTX_FL_TEST(dc, CTX_FL_SUSPEND))
  {
    add_to_locked(rb_thread_current());
    rb_thread_stop();

    if (CTX_FL_TEST(dc, CTX_FL_SUSPEND))
      CTX_FL_SET(dc, CTX_FL_WAS_RUNNING);
  }

  locker = rb_thread_current();
}
示例#2
0
/*
 * call-seq:
 *   Kernel.each_backtrace_frame( & block )
 *
 * Return array of hashes with object and method frame information for backtrace.
 * Specifying number_of_frames will cause only the last number_of_frames to be returned.
 * Kernel.backtrace returns all frames including the current context (__method__/__callee__).
 */
VALUE rb_RPRuby_Sender_Kernel_each_backtrace_frame(  int    argc,
                          VALUE*  args,
                          VALUE  rb_self )  {

  rb_thread_t*      c_thread          = (rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current());
  //  Get the current frame - we're doing a backtrace, so our current working frame to start is the first previous thread
  rb_control_frame_t*    c_current_context_frame    = RUBY_VM_PREVIOUS_CONTROL_FRAME( RUBY_VM_PREVIOUS_CONTROL_FRAME( c_thread->cfp ) );
  
  //  c_top_of_control_frame describes the top edge of the stack trace
  //  set c_top_of_control_frame to the first frame in <main>
    rb_control_frame_t*    c_top_of_control_frame  =  RUBY_VM_NEXT_CONTROL_FRAME( RUBY_VM_NEXT_CONTROL_FRAME( (void *)( c_thread->stack + c_thread->stack_size ) ) );
  
  VALUE  rb_stored_backtrace_array  =  Qnil;
  
  //  if we were passed a stored backtrace array, use it
  if (  argc == 1
    &&  TYPE( args[ 0 ] ) == T_ARRAY )  {
    rb_stored_backtrace_array  =  args[ 0 ];
  }
        
  //  for each control frame:
    while ( c_current_context_frame < c_top_of_control_frame ) {

    VALUE  rb_frame_hash;
    //  if we are using a stored backtrace we don't need to ask for a new hash
    if ( rb_stored_backtrace_array == Qnil )  {
      rb_frame_hash  =  rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(  & c_current_context_frame );
    }
    else {
      rb_frame_hash  =  rb_ary_shift( rb_stored_backtrace_array );
    }

    if ( rb_frame_hash == Qnil )  {
      break;
    }
    
    //  if we try to iterate using an Enumerator we will lose our context
    if ( ! rb_block_given_p() )  {
      
      //  we solve this by assuming that the desired context is the moment when each_backtrace_frame is called
      //  this allows us to store the backtrace and iterate it as we want
      //  the only downside is that we have to get the entire backtrace first in order to store it
      rb_stored_backtrace_array  =  rb_RPRuby_Sender_Kernel_backtrace(  0,
                                        NULL,
                                        rb_self );
    
      RETURN_ENUMERATOR( rb_self, 1, & rb_stored_backtrace_array );
    }
    
    //  otherwise, yield the block
    rb_yield( rb_frame_hash );
    
    //  only move the frame if we are not using a stored backtrace
    if ( rb_stored_backtrace_array == Qnil )  {
      c_current_context_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_current_context_frame );    
    }
  }
  
  return Qnil;
}
示例#3
0
static VALUE
queue_do_pop(VALUE self, int should_block)
{
    struct waiting_delete args;
    args.waiting = GET_QUEUE_WAITERS(self);
    args.th	 = rb_thread_current();

    while (queue_length(self) == 0) {
	if (!should_block) {
	    rb_raise(rb_eThreadError, "queue empty");
	}
	else if (queue_closed_p(self)) {
	    return queue_closed_result(self);
	}
	else {
	    assert(queue_length(self) == 0);
	    assert(queue_closed_p(self) == 0);

	    rb_ary_push(args.waiting, args.th);
	    rb_ensure(queue_sleep, (VALUE)0, queue_delete_from_waiting, (VALUE)&args);
	}
    }

    return rb_ary_shift(GET_QUEUE_QUE(self));
}
示例#4
0
文件: context.c 项目: gwright/rbczmq
static VALUE rb_czmq_ctx_socket(VALUE obj, VALUE type)
{
    VALUE socket;
    int socket_type;
    struct nogvl_socket_args args;
    zmq_sock_wrapper *sock = NULL;
    errno = 0;
    ZmqGetContext(obj);
    if (TYPE(type) != T_FIXNUM && TYPE(type) != T_SYMBOL) rb_raise(rb_eTypeError, "wrong socket type %s (expected Fixnum or Symbol)", RSTRING_PTR(rb_obj_as_string(type)));
    socket_type = FIX2INT((SYMBOL_P(type)) ? rb_const_get_at(rb_mZmq, rb_to_id(type)) : type);

    socket = Data_Make_Struct(rb_czmq_ctx_socket_klass(socket_type), zmq_sock_wrapper, rb_czmq_mark_sock, rb_czmq_free_sock_gc, sock);
    args.ctx = ctx->ctx;
    args.type = socket_type;
    sock->socket = (void*)rb_thread_blocking_region(rb_czmq_nogvl_socket_new, (void *)&args, RUBY_UBF_IO, 0);
    ZmqAssertObjOnAlloc(sock->socket, sock);
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
    sock->str_buffer = zlist_new();
    sock->frame_buffer = zlist_new();
    sock->msg_buffer = zlist_new();
#endif
    sock->handler = Qnil;
    sock->flags = 0;
    sock->ctx = ctx->ctx;
    sock->verbose = FALSE;
    sock->state = ZMQ_SOCKET_PENDING;
    sock->endpoint = Qnil;
    sock->thread = rb_thread_current();
    sock->recv_timeout = ZMQ_SOCKET_DEFAULT_TIMEOUT;
    sock->send_timeout = ZMQ_SOCKET_DEFAULT_TIMEOUT;
    rb_obj_call_init(socket, 0, NULL);
    return socket;
}
示例#5
0
/**
 * enable_line_trace_for_thread
 * Turn on line event trace for current thread. Also set a flag
 * "gcloud_line_trace_set" to Qtrue in current thread's thread variable.
 */
static VALUE
enable_line_trace_for_thread(VALUE self)
{
    VALUE current_thread;
    VALUE thread_variables_hash;
    VALUE line_trace_set;
    ID locals_id;
    ID line_trace_thread_id;
    VALUE line_trace_thread_flag;

    CONST_ID(locals_id, "locals");
    CONST_ID(line_trace_thread_id, "gcloud_line_trace_set");
    line_trace_thread_flag = ID2SYM(line_trace_thread_id);

    current_thread = rb_thread_current();
    thread_variables_hash = rb_ivar_get(current_thread, locals_id);
    line_trace_set = rb_hash_aref(thread_variables_hash, line_trace_thread_flag);

    if (!RTEST(line_trace_set)) {
        rb_thread_add_event_hook(current_thread, line_trace_callback, RUBY_EVENT_LINE, self);
        rb_hash_aset(thread_variables_hash, line_trace_thread_flag, Qtrue);
    }

    return Qnil;
}
示例#6
0
/**
 *  disable_return_trace_for_thread
 *  Turn off return events trace hook for a given thread. If no thread is given, it
 *  turns off line event trace hook in current thread. It only takes action if
 *  the thread has a thread variable "gcloud_return_trace_set" that's true.
 */
static VALUE
disable_return_trace_for_thread(VALUE thread)
{
    VALUE thread_variables_hash;
    VALUE return_trace_set;
    ID locals_id;
    ID return_trace_thread_id;
    VALUE return_trace_thread_flag;

    CONST_ID(locals_id, "locals");
    CONST_ID(return_trace_thread_id, "gcloud_return_trace_set");
    return_trace_thread_flag = ID2SYM(return_trace_thread_id);

    if (!RTEST(thread)) {
        thread = rb_thread_current();
    }
    thread_variables_hash = rb_ivar_get(thread, locals_id);
    return_trace_set = rb_hash_aref(thread_variables_hash, return_trace_thread_flag);

    if (RTEST(return_trace_set)) {
        rb_thread_remove_event_hook(thread, (rb_event_hook_func_t)return_trace_callback);
        rb_hash_aset(thread_variables_hash, return_trace_thread_flag, Qfalse);
    }

    return Qnil;
}
示例#7
0
static VALUE blocking_function_execute(blocking_region_arg_t *arg)
{
    oci8_svcctx_t *svcctx = arg->svcctx;
    void *(*func)(void *) = arg->func;
    void *data = arg->data;
    struct timeval tv;
    sword rv;

    tv.tv_sec = 0;
    tv.tv_usec = 10000;
    svcctx->executing_thread = rb_thread_current();
    while ((rv = (sword)(VALUE)func(data)) == OCI_STILL_EXECUTING) {
        rb_thread_wait_for(tv);
        if (tv.tv_usec < 500000)
            tv.tv_usec <<= 1;
    }
    if (rv == OCI_ERROR) {
        if (oci8_get_error_code(oci8_errhp) == 1013) {
            OCIReset(svcctx->base.hp.ptr, oci8_errhp);
            svcctx->executing_thread = Qnil;
            rb_raise(eOCIBreak, "Canceled by user request.");
        }
    }
    svcctx->executing_thread = Qnil;
    return rv;
}
示例#8
0
static VALUE frame_count(VALUE self)
{
  rb_thread_t *th;
  GetThreadPtr(rb_thread_current(), th);

  rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
  rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);

  int i = 1;
  while (cfp < limit_cfp) {
    cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);

    if (cfp >= limit_cfp)
      return INT2FIX(i);

    // skip invalid frames
    if (!valid_frame_p(cfp, limit_cfp))
      cfp = find_valid_frame(cfp, limit_cfp);

    if (!cfp)
      break;

    i++;
  }

  return INT2FIX(i);
}
示例#9
0
static VALUE
lock_mutex(Mutex *mutex)
{
    VALUE current;
    current = rb_thread_current();

    rb_thread_critical = 1;

    if (!MUTEX_LOCKED_P(mutex)) {
	mutex->owner = current;
    }
    else {
	do {
	    wait_list(&mutex->waiting);
	    rb_thread_critical = 1;
	    if (!MUTEX_LOCKED_P(mutex)) {
		mutex->owner = current;
		break;
	    }
	} while (mutex->owner != current);
    }

    rb_thread_critical = 0;
    return Qnil;
}
示例#10
0
/**
 * enable_return_trace_for_thread
 * Turn on return events trace for current thread. Also set a flag
 * "gcloud_return_trace_set" to Qtrue in current thread's thread variable.
 */
static VALUE
enable_return_trace_for_thread(VALUE self)
{
    VALUE current_thread;
    VALUE thread_variables_hash;
    VALUE return_trace_set;

    ID locals_id;
    ID return_trace_thread_id;
    VALUE return_trace_thread_flag;

    CONST_ID(locals_id, "locals");
    CONST_ID(return_trace_thread_id, "gcloud_return_trace_set");
    return_trace_thread_flag = ID2SYM(return_trace_thread_id);

    current_thread = rb_thread_current();
    thread_variables_hash = rb_ivar_get(current_thread, locals_id);
    return_trace_set = rb_hash_aref(thread_variables_hash, return_trace_thread_flag);

    if (!RTEST(return_trace_set)) {
        rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)return_trace_callback, RETURN_TRACEPOINT_EVENTS, self, RUBY_EVENT_HOOK_FLAG_RAW_ARG | RUBY_EVENT_HOOK_FLAG_SAFE);
        rb_hash_aset(thread_variables_hash, return_trace_thread_flag, Qtrue);
    }

    return Qnil;
}
示例#11
0
static VALUE
rb_enable_method_trace_for_thread(VALUE self)
{
    VALUE current_thread;
    VALUE thread_variables_hash;
    VALUE trace_set;
    VALUE evaluator;
    ID current_evaluator_id;
    ID locals_id;
    ID eval_trace_thread_id;
    VALUE eval_trace_thread_flag;

    CONST_ID(current_evaluator_id, "current");
    CONST_ID(locals_id, "locals");
    CONST_ID(eval_trace_thread_id, "gcloud_eval_trace_set");
    eval_trace_thread_flag = ID2SYM(eval_trace_thread_id);

    current_thread = rb_thread_current();
    thread_variables_hash = rb_ivar_get(current_thread, locals_id);
    trace_set = rb_hash_aref(thread_variables_hash, eval_trace_thread_flag);
    evaluator = rb_funcall(self, current_evaluator_id, 0);

    if (!RTEST(trace_set)) {
        rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)eval_trace_callback, RUBY_EVENT_CALL | RUBY_EVENT_C_CALL, evaluator, RUBY_EVENT_HOOK_FLAG_RAW_ARG | RUBY_EVENT_HOOK_FLAG_SAFE);
        rb_hash_aset(thread_variables_hash, eval_trace_thread_flag, Qtrue);
    }

    return Qnil;
}
示例#12
0
// default behavior of async (doesn't accept Symbol)
// call-seq:
//      async { }
//      async Proc.new
static VALUE
kern_async(int argc, VALUE *argv, VALUE self)
{
    VALUE obj;
    rb_proc_t *proc;
    rb_iseq_t *niseq;

    rb_scan_args(argc, argv, "01", &obj);
    if (!NIL_P(obj)) {
        if (!rb_obj_is_proc(obj)) {
            VALUE thread = rb_thread_current();
            rb_thread_t * th;
            TypedData_Get_Struct(thread, rb_thread_t, RTYPEDDATA_TYPE(thread), th);
            if (self == th->vm->top_self) {
                return mod_async(CLASS_OF(self), obj);
            } else {
                rb_raise(rb_eTypeError, "wrong argument type (expected Proc)");
            }
        }
    } else if (rb_block_given_p()) {
        obj = rb_block_proc();
    } else {
        rb_raise(rb_eArgError, "Proc or block is required");
    }

    proc = (rb_proc_t *)DATA_PTR(obj);

    // うーーー
    niseq = transform(obj);
    proc->block.iseq = niseq;

    return obj;
}
示例#13
0
static VALUE
wait_list_inner(List *list)
{
    push_list(list, rb_thread_current());
    rb_thread_stop();
    return Qnil;
}
示例#14
0
static VALUE
wait_list_cleanup(List *list)
{
    /* cleanup in case of spurious wakeups */
    remove_one(list, rb_thread_current());
    return Qnil;
}
示例#15
0
static VALUE
dnssd_service_stop(VALUE self) {
  VALUE thread;
  DNSServiceRef *client;

  get(cDNSSDService, self, DNSServiceRef, client);

  RDATA(self)->data = NULL;

  if (client == NULL)
    rb_raise(eDNSSDError, "service is already stopped");

  thread = rb_ivar_get(self, dnssd_iv_thread);
  rb_ivar_set(self, dnssd_iv_continue, Qfalse);

  if (!NIL_P(thread) && thread != rb_thread_current()) {
    rb_thread_run(thread);
    rb_funcall(thread, dnssd_id_join, 0);
  }

  dnssd_service_free_client(client);

  rb_ivar_set(self, dnssd_iv_type, Qnil);

  return self;
}
示例#16
0
VALUE rho_ruby_current_thread()
{
    if ( ruby_native_thread_p() != 1 )
        return 0;

    return rb_thread_current();
}
示例#17
0
static VALUE
rb_szqueue_push(int argc, VALUE *argv, VALUE self)
{
    struct waiting_delete args;
    int should_block = szqueue_push_should_block(argc, argv);
    args.waiting = GET_SZQUEUE_WAITERS(self);
    args.th      = rb_thread_current();

    while (queue_length(self) >= GET_SZQUEUE_ULONGMAX(self)) {
	if (!should_block) {
	    rb_raise(rb_eThreadError, "queue full");
	}
	else if (queue_closed_p(self)) {
	    goto closed;
	}
	else {
	    rb_ary_push(args.waiting, args.th);
	    rb_ensure((VALUE (*)())rb_thread_sleep_deadly, (VALUE)0, queue_delete_from_waiting, (VALUE)&args);
	}
    }

    if (queue_closed_p(self)) {
      closed:
	raise_closed_queue_error(self);
    }

    return queue_do_push(self, argv[0]);
}
示例#18
0
static VALUE application_initialize(VALUE self, VALUE args) {
    if (rb_thread_main() != rb_thread_current()) {
        rb_raise(rb_eThreadError, "Initializing QML::Application outside the main thread");
    }

    application_t *data;
    TypedData_Get_Struct(self, application_t, &data_type, data);

    if (rb_type(args) != T_ARRAY) {
        rb_raise(rb_eTypeError, "Expected Array");
    }

    args = rb_ary_concat(rb_ary_new_from_args(1, rb_argv0), args);

    int argc = RARRAY_LEN(args);
    char **argv = malloc(argc * sizeof(char *));

    for (int i = 0; i < argc; ++i) {
        VALUE arg = RARRAY_AREF(args, i);
        argv[i] = rb_string_value_cstr(&arg);
    }

    data->application = qmlbind_application_new(argc, argv);

    return self;
}
示例#19
0
rb_control_frame_t* RPRuby_internal_framePriorTo( rb_control_frame_t* c_control_frame )  {
  
  rb_thread_t*      c_thread          = (rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current());
  rb_control_frame_t*    c_prior_control_frame    = NULL;
  //  get the current frame pointer
  if ( c_control_frame == NULL )  {
    c_control_frame  = c_thread->cfp;
  }
  
    if ( ( c_prior_control_frame = rb_vm_get_ruby_level_next_cfp( c_thread, c_control_frame ) ) != 0) {
    
    //  not sure why we have to call this a second time after it was called at the end of rb_vm_get_ruby_level_next_cfp,
    //  but for some reason it seems to be necessary
    c_prior_control_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_prior_control_frame );

    }
  else {
    c_prior_control_frame = NULL;
  }
  
  //  if we have a nil object we've passed main, we're done
  if ( c_prior_control_frame->self == Qnil )  {
    return NULL;
  }

  return c_prior_control_frame;
  
}
示例#20
0
static VALUE
rb_disable_method_trace_for_thread(VALUE self)
{
    VALUE current_thread;
    VALUE thread_variables_hash;
    VALUE trace_set;
    ID locals_id;
    ID eval_trace_thread_id;
    VALUE eval_trace_thread_flag;

    CONST_ID(locals_id, "locals");
    CONST_ID(eval_trace_thread_id, "gcloud_eval_trace_set");
    eval_trace_thread_flag = ID2SYM(eval_trace_thread_id);

    current_thread = rb_thread_current();
    thread_variables_hash = rb_ivar_get(current_thread, locals_id);
    trace_set = rb_hash_aref(thread_variables_hash, eval_trace_thread_flag);

    if (RTEST(trace_set)) {
        rb_thread_remove_event_hook(current_thread, (rb_event_hook_func_t)eval_trace_callback);
        rb_hash_aset(thread_variables_hash, eval_trace_thread_flag, Qfalse);
    }

    return Qnil;
}
示例#21
0
static VALUE
cb_unset_tracer(VALUE self) {
  if(rb_iv_get(self, "@tracer_set")) {
    rb_thread_remove_event_hook(rb_thread_current(), trace_line_handler_ext);
    rb_iv_set(self, "@tracer_set", Qfalse);
  }
  return Qnil;
}
示例#22
0
/**
 * rb_disable_traces_for_thread
 * It disables line tracing and return event tracing for current thread.
 */
static VALUE
rb_disable_traces_for_thread(VALUE self)
{
    VALUE thread = rb_thread_current();
    disable_line_trace_for_thread(thread);
    disable_return_trace_for_thread(thread);

    return Qnil;
}
示例#23
0
/*
 *  call-seq:
 *    Byebug.lock -> Thread.current
 *
 *  Locks global switch to reserve execution to current thread exclusively.
 */
static VALUE
Lock(VALUE self)
{
  debug_context_t *dc;
  VALUE context;

  UNUSED(self);

  if (!is_living_thread(rb_thread_current()))
    rb_raise(rb_eRuntimeError, "Current thread is dead!");

  thread_context_lookup(rb_thread_current(), &context);
  Data_Get_Struct(context, debug_context_t, dc);

  acquire_lock(dc);

  return locker;
}
示例#24
0
static VALUE
chdir_yield(struct chdir_data *args)
{
    dir_chdir(args->new_path);
    args->done = Qtrue;
    chdir_blocking++;
    if (chdir_thread == Qnil)
	chdir_thread = rb_thread_current();
    return rb_yield(args->new_path);
}
示例#25
0
文件: rhoruby.c 项目: KlearXos/rhodes
VALUE rho_ruby_current_thread()
{
    if (!rho_ruby_is_started())
        return 0;

    if ( ruby_native_thread_p() != 1 )
        return 0;

    return rb_thread_current();
}
示例#26
0
static inline const rb_data_type_t *
threadptr_data_type(void)
{
  static const rb_data_type_t *thread_data_type;
  if (!thread_data_type) {
    VALUE current_thread = rb_thread_current();
    thread_data_type = RTYPEDDATA_TYPE(current_thread);
  }
  return thread_data_type;
}
示例#27
0
static VALUE
cb_set_tracer(VALUE self) {
  if(!rb_iv_get(self, "@tracer_set")) {
    // NOTE: We are using rb_add_event_hook opposed to rb_tracepoint_new for 1.9.X compat
    // not using higher level C functions of set_trace_func to avoid extra overhead we don't need since we only need the RUBY_EVENT_LINE hook as well as only needing file / line number opposed to everything else.
    rb_thread_add_event_hook(rb_thread_current(), trace_line_handler_ext, RUBY_EVENT_LINE, 0);
    rb_iv_set(self, "@tracer_set", Qtrue);
  }
  return Qnil;
}
示例#28
0
文件: monitor.c 项目: keiju/xthread
VALUE
rb_xthread_monitor_enter_for_cond(VALUE self, long count)
{
  xthread_monitor_t *mon;
  VALUE th = rb_thread_current();
  
  GetXThreadMonitorPtr(self, mon);

  mon->owner = th;
  mon->count = count;
}
示例#29
0
static void
wait_condvar(ConditionVariable *condvar, Mutex *mutex)
{
    //rb_thread_critical = 1;
    if (rb_thread_current() != mutex->owner) {
        //rb_thread_critical = 0;
        rb_raise(private_eThreadError, "not owner of the synchronization mutex");
    }
    unlock_mutex_inner(mutex);
    rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex, (VALUE)mutex);
}
示例#30
0
/*
 *  call-seq:
 *    Byebug.current_context -> context
 *
 *  Returns the current context.
 *    <i>Note:</i> Byebug.current_context.thread == Thread.current
 */
static VALUE
Current_context(VALUE self)
{
  VALUE context;

  UNUSED(self);

  thread_context_lookup(rb_thread_current(), &context);

  return context;
}