static void create_gc_hooks(void) { int i; logger->hooks[0] = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_GC_START, gc_start_i, logger); logger->hooks[1] = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_GC_END_MARK, gc_end_mark_i, logger); logger->hooks[2] = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_GC_END_SWEEP, gc_end_sweep_i, logger); /* mark for GC */ for (i=0; i<3; i++) rb_gc_register_mark_object(logger->hooks[i]); }
static VALUE install() { rb_event_flag_t events = RUBY_INTERNAL_EVENT_GC_START | RUBY_INTERNAL_EVENT_GC_END_MARK | RUBY_INTERNAL_EVENT_GC_END_SWEEP; if (_oobgc.installed) return Qfalse; if (!_oobgc.tpval) { _oobgc.tpval = rb_tracepoint_new(0, events, gc_event_i, (void *)0); rb_ivar_set(mOOB, rb_intern("tpval"), _oobgc.tpval); } rb_tracepoint_enable(_oobgc.tpval); /* rb_gc_stat() requires memory allocation for symbol creation only at * first time. If rb_gc_stat() was called during GC at first time by * tracepoint, memory allocation caused crash. We call rb_gc_stat() here * for symbol creation. */ rb_gc_stat(sym_total_allocated_object); _oobgc.installed = 1; return Qtrue; }
static VALUE start_stat_server(int argc, VALUE *argv, VALUE self) { VALUE pub_port; VALUE request_port; int bind_result, pub_port_int, req_port_int; char zmq_endpoint[21], zmq_request_endpoint[21]; server_instance = self; rb_scan_args(argc, argv, "02", &pub_port, &request_port); pub_port_int = FIX2INT(pub_port); req_port_int = FIX2INT(request_port); if(pub_port_int != 0 || request_port != 0) { zmq_context = zmq_ctx_new(); } if(pub_port_int != 0) { sprintf(zmq_endpoint, "tcp://127.0.0.1:%d", FIX2INT(pub_port)); zmq_publisher = zmq_socket(zmq_context, ZMQ_PUB); bind_result = zmq_bind(zmq_publisher, zmq_endpoint); if(bind_result != 0) return Qfalse; } if(req_port_int != 0) { sprintf(zmq_request_endpoint, "tcp://127.0.0.1:%d", FIX2INT(request_port)); zmq_response_socket = zmq_socket(zmq_context, ZMQ_REP); bind_result = zmq_bind(zmq_response_socket, zmq_request_endpoint); if(bind_result != 0) return Qfalse; items[0].socket = zmq_response_socket; items[0].events = ZMQ_POLLIN; } // Creates a list which aggregates messages message_list_new(); logger = get_trace_logger(); logger->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, logger); logger->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, logger); rb_gc_register_mark_object(logger->newobj_trace); rb_gc_register_mark_object(logger->freeobj_trace); create_gc_hooks(); return Qtrue; }
static VALUE set_gc_hook(rb_event_flag_t event) { VALUE tpval; // TODO - need to prevent applying the same tracepoint multiple times? tpval = rb_tracepoint_new(0, event, tracepoint_handler, 0); rb_tracepoint_enable(tpval); return tpval; }
static VALUE stackprof_start(int argc, VALUE *argv, VALUE self) { struct sigaction sa; struct itimerval timer; VALUE opts = Qnil, mode = Qnil, interval = Qnil; if (_stackprof.running) return Qfalse; rb_scan_args(argc, argv, "0:", &opts); if (RTEST(opts)) { mode = rb_hash_aref(opts, sym_mode); interval = rb_hash_aref(opts, sym_interval); } if (!RTEST(mode)) mode = sym_wall; if (!_stackprof.frames) { _stackprof.frames = st_init_numtable(); _stackprof.overall_signals = 0; _stackprof.overall_samples = 0; _stackprof.during_gc = 0; } if (mode == sym_object) { if (!RTEST(interval)) interval = INT2FIX(1); objtracer = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, stackprof_newobj_handler, 0); rb_tracepoint_enable(objtracer); } else if (mode == sym_wall || mode == sym_cpu) { if (!RTEST(interval)) interval = INT2FIX(1000); sa.sa_sigaction = stackprof_signal_handler; sa.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(mode == sym_wall ? SIGALRM : SIGPROF, &sa, NULL); timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = NUM2LONG(interval); timer.it_value = timer.it_interval; setitimer(mode == sym_wall ? ITIMER_REAL : ITIMER_PROF, &timer, 0); } else if (mode == sym_custom) { /* sampled manually */ interval = Qnil; } else { rb_raise(rb_eArgError, "unknown profiler mode"); } _stackprof.running = 1; _stackprof.mode = mode; _stackprof.interval = interval; return Qtrue; }
/** * register_tracepoint * Helper function to create a new tracepoint and set the instance varaible on * tracer if it doesn't exist already. Returns the existing tracepoint or the * newly created tracepoint. */ static VALUE register_tracepoint(VALUE self, int event, const char *instance_variable_name, void (*call_back_func)(VALUE, void *)) { VALUE tracepoint = rb_iv_get(self, instance_variable_name); if (event && !RTEST(tracepoint)) { tracepoint = rb_tracepoint_new(Qnil, event, call_back_func, (void *)self); rb_iv_set(self, instance_variable_name, tracepoint); } return tracepoint; }
static void register_tracepoints(VALUE self) { int i; VALUE traces = tracepoints; UNUSED(self); if (NIL_P(traces)) { int line_msk = RUBY_EVENT_LINE; int call_msk = RUBY_EVENT_CALL; int ret_msk = RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN; int end_msk = RUBY_EVENT_END; int raw_call_msk = RUBY_EVENT_C_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS; int raw_ret_msk = RUBY_EVENT_C_RETURN; int raise_msk = RUBY_EVENT_RAISE; VALUE tpLine = rb_tracepoint_new(Qnil, line_msk, line_event, 0); VALUE tpCall = rb_tracepoint_new(Qnil, call_msk, call_event, 0); VALUE tpReturn = rb_tracepoint_new(Qnil, ret_msk, return_event, 0); VALUE tpEnd = rb_tracepoint_new(Qnil, end_msk, end_event, 0); VALUE tpCCall = rb_tracepoint_new(Qnil, raw_call_msk, raw_call_event, 0); VALUE tpCReturn = rb_tracepoint_new(Qnil, raw_ret_msk, raw_return_event, 0); VALUE tpRaise = rb_tracepoint_new(Qnil, raise_msk, raise_event, 0); traces = rb_ary_new(); rb_ary_push(traces, tpLine); rb_ary_push(traces, tpCall); rb_ary_push(traces, tpReturn); rb_ary_push(traces, tpEnd); rb_ary_push(traces, tpCCall); rb_ary_push(traces, tpCReturn); rb_ary_push(traces, tpRaise); tracepoints = traces; } for (i = 0; i < RARRAY_LENINT(traces); i++) rb_tracepoint_enable(rb_ary_entry(traces, i)); }