void factor_vm::init_factor(vm_parameters *p) { /* Kilobytes */ p->datastack_size = align_page(p->datastack_size << 10); p->retainstack_size = align_page(p->retainstack_size << 10); p->callstack_size = align_page(p->callstack_size << 10); p->callback_size = align_page(p->callback_size << 10); /* Megabytes */ p->young_size <<= 20; p->aging_size <<= 20; p->tenured_size <<= 20; p->code_size <<= 20; /* Disable GC during init as a sanity check */ gc_off = true; /* OS-specific initialization */ early_init(); const vm_char *executable_path = vm_executable_path(); if(executable_path) p->executable_path = executable_path; if(p->image_path == NULL) p->image_path = default_image_path(); srand((unsigned int)nano_count()); init_ffi(); init_contexts(p->datastack_size,p->retainstack_size,p->callstack_size); init_callbacks(p->callback_size); load_image(p); init_c_io(); init_inline_caching((int)p->max_pic_size); if(p->signals) init_signals(); if(p->console) open_console(); init_profiler(); special_objects[OBJ_CPU] = allot_alien(false_object,(cell)FACTOR_CPU_STRING); special_objects[OBJ_OS] = allot_alien(false_object,(cell)FACTOR_OS_STRING); special_objects[OBJ_CELL_SIZE] = tag_fixnum(sizeof(cell)); special_objects[OBJ_EXECUTABLE] = allot_alien(false_object,(cell)p->executable_path); special_objects[OBJ_ARGS] = false_object; special_objects[OBJ_EMBEDDED] = false_object; special_objects[OBJ_VM_COMPILER] = allot_alien(false_object,(cell)FACTOR_COMPILER_VERSION); /* We can GC now */ gc_off = false; if(!to_boolean(special_objects[OBJ_STAGE2])) prepare_boot_image(); }
void factorvm::init_factor(vm_parameters *p) { /* Kilobytes */ p->ds_size = align_page(p->ds_size << 10); p->rs_size = align_page(p->rs_size << 10); /* Megabytes */ p->young_size <<= 20; p->aging_size <<= 20; p->tenured_size <<= 20; p->code_size <<= 20; /* Disable GC during init as a sanity check */ gc_off = true; /* OS-specific initialization */ early_init(); const vm_char *executable_path = vm_executable_path(); if(executable_path) p->executable_path = executable_path; if(p->image_path == NULL) p->image_path = default_image_path(); srand(current_micros()); init_ffi(); init_stacks(p->ds_size,p->rs_size); load_image(p); init_c_io(); init_inline_caching(p->max_pic_size); init_signals(); if(p->console) open_console(); init_profiler(); userenv[CPU_ENV] = allot_alien(F,(cell)FACTOR_CPU_STRING); userenv[OS_ENV] = allot_alien(F,(cell)FACTOR_OS_STRING); userenv[CELL_SIZE_ENV] = tag_fixnum(sizeof(cell)); userenv[EXECUTABLE_ENV] = allot_alien(F,(cell)p->executable_path); userenv[ARGS_ENV] = F; userenv[EMBEDDED_ENV] = F; /* We can GC now */ gc_off = false; if(userenv[STAGE2_ENV] == F) { userenv[STACK_TRACES_ENV] = tag_boolean(p->stack_traces); do_stage1_init(); } }
int main(int argc, char const *argv[]) { #ifdef _MEM_PROFILER uint8_t checkpoint_set = 0; #endif fd_set rfds; char buffer[PIPE_BUFFER_SIZE]; int i, n; Plugin plugins[MAX_PLUGINS]; int plugins_count = 0; mrb_state *mrb; mrb_value r_output, r_plugins_list; mrb_sym output_gv_sym, plugins_to_load_gv_sym; printf("Version: %s\n", PROBE_VERSION); if( argc != 2 ){ printf("Usage: %s <config_path>\n", argv[0]); exit(1); } #ifdef _MEM_PROFILER init_profiler(); #endif config_path = argv[1]; printf("Initializing core...\n"); mrb = mrb_open_allocf(profiler_allocf, "main"); output_gv_sym = mrb_intern_cstr(mrb, "$output"); plugins_to_load_gv_sym = mrb_intern_cstr(mrb, "$plugins_to_load"); setup_api(mrb); execute_file(mrb, "plugins/main.rb"); execute_file(mrb, config_path); printf("Loading plugins...\n"); r_plugins_list = mrb_gv_get(mrb, plugins_to_load_gv_sym); for(i = 0; i< mrb_ary_len(mrb, r_plugins_list); i++){ char *path, tmp[100]; int ssize; mrb_value r_plugin_name = mrb_ary_ref(mrb, r_plugins_list, i); const char *plugin_name = mrb_string_value_cstr(mrb, &r_plugin_name); snprintf(tmp, sizeof(tmp) - 1, "plugins/%s.rb", plugin_name); ssize = strlen(tmp); path = malloc(ssize + 1); strncpy(path, tmp, ssize); path[ssize] = '\0'; if( access(path, F_OK) == -1 ){ printf("cannot open plugin file \"%s\": %s\n", path, strerror(errno)); exit(1); } init_plugin_from_file(&plugins[plugins_count], path, plugin_name); plugins_count++; } printf("Instanciating output class...\n"); r_output = mrb_gv_get(mrb, output_gv_sym); interval = mrb_fixnum(mrb_funcall(mrb, r_output, "interval", 0)); printf("Interval set to %dms\n", (int)interval); printf("Sending initial report...\n"); mrb_funcall(mrb, r_output, "send_report", 0); if (mrb->exc) { mrb_print_error(mrb); exit(1); } // start all the threads for(i= 0; i< plugins_count; i++){ // printf("== plugin %d\n", i); n = pthread_create(&plugins[i].thread, NULL, plugin_thread, (void *)&plugins[i]); if( n < 0 ){ fprintf(stderr, "create failed\n"); } } if( signal(SIGINT, clean_exit) == SIG_ERR){ perror("signal"); exit(1); } while(running){ int fds[MAX_PLUGINS]; int maxfd = 0, ai; struct timeval tv; mrb_value r_buffer; struct timeval cycle_started_at, cycle_completed_at; gettimeofday(&cycle_started_at, NULL); bzero(fds, sizeof(int) * MAX_PLUGINS); // ask every plugin to send their data for(i= 0; i< plugins_count; i++){ strcpy(buffer, "request"); if( send(plugins[i].host_pipe, buffer, strlen(buffer), 0) == -1 ){ printf("send error when writing in pipe connected to plugin '%s'\n", plugins[i].name); } fds[i] = plugins[i].host_pipe; // printf("sent request to %d\n", i); } // printf("waiting answers...\n"); // and now wait for each answer while(1){ int left = 0; FD_ZERO(&rfds); for(i = 0; i< MAX_PLUGINS; i++){ if( fds[i] != NOPLUGIN_VALUE ){ FD_SET(fds[i], &rfds); left++; if( fds[i] > maxfd ) maxfd = fds[i]; } } // printf("left: %d %d\n", left, left <= 0); if( !running || (0 == left) ) break; // substract 20ms to stay below the loop delay fill_timeout(&tv, cycle_started_at, interval - 20); // printf("before select\n"); n = select(maxfd + 1, &rfds, NULL, NULL, &tv); // printf("after select: %d\n", n); if( n > 0 ){ // find out which pipes have data for(i = 0; i< MAX_PLUGINS; i++){ if( (fds[i] != NOPLUGIN_VALUE) && FD_ISSET(fds[i], &rfds) ){ while (1){ struct timeval answered_at; n = read(fds[i], buffer, sizeof(buffer)); if( n == -1 ){ if( errno != EAGAIN ) perror("read"); break; } if( n == PIPE_BUFFER_SIZE ){ printf("PIPE_BUFFER_SIZE is too small, increase it ! (value: %d)\n", PIPE_BUFFER_SIZE); continue; } gettimeofday(&answered_at, NULL); // printf("received answer from %s in %u ms\n", (const char *) plugins[i].mrb->ud, // (uint32_t)((answered_at.tv_sec - cycle_started_at.tv_sec) * 1000 + // (answered_at.tv_usec - cycle_started_at.tv_usec) / 1000) // ); buffer[n] = 0x00; ai = mrb_gc_arena_save(mrb); r_buffer = mrb_str_buf_new(mrb, n); mrb_str_buf_cat(mrb, r_buffer, buffer, n); // mrb_funcall(mrb, r_output, "tick", 0); mrb_funcall(mrb, r_output, "add", 1, r_buffer); check_exception("add", mrb); // pp(mrb, r_output, 0); mrb_gc_arena_restore(mrb, ai); } fds[i] = 0; } } } else if( n == 0 ) { printf("no responses received from %d plugins.\n", left); break; // timeout } else { perror("select"); } } int idx = mrb_gc_arena_save(mrb); mrb_funcall(mrb, r_output, "flush", 0); check_exception("flush", mrb); mrb_gc_arena_restore(mrb, idx); // and now sleep until the next cycle gettimeofday(&cycle_completed_at, NULL); #ifdef _MEM_PROFILER if( checkpoint_set ){ print_allocations(); } #endif // force a gc run at the end of each cycle mrb_full_gc(mrb); // printf("[main] capa: %d / %d\n", mrb->arena_idx, mrb->arena_capa); // for(i= 0; i< plugins_count; i++){ // printf("[%s] capa: %d / %d\n", plugins[i].name, plugins[i].mrb->arena_idx, plugins[i].mrb->arena_capa); // } #ifdef _MEM_PROFILER checkpoint_set = 1; // and set starting point profiler_set_checkpoint(); #endif #ifdef _MEM_PROFILER_RUBY // dump VMS state dump_state(mrb); for(i= 0; i< plugins_count; i++){ dump_state(plugins[i].mrb); } #endif fflush(stdout); sleep_delay(&cycle_started_at, &cycle_completed_at, interval); } printf("Sending exit signal to all plugins...\n"); strcpy(buffer, "exit"); for(i= 0; i< plugins_count; i++){ C_CHECK("send", send(plugins[i].host_pipe, buffer, strlen(buffer), 0) ); } printf("Giving some time for threads to exit...\n\n"); really_sleep(2000); for(i= 0; i< plugins_count; i++){ int ret = pthread_kill(plugins[i].thread, 0); // if a success is returned then the thread is still alive // which means the thread did not acknoledged the exit message // kill it. if( ret == 0 ){ printf(" - plugin \"%s\" failed to exit properly, killing it...\n", (const char *) plugins[i].mrb->ud); pthread_cancel(plugins[i].thread); } else { printf(" - plugin \"%s\" exited properly.\n", (const char *) plugins[i].mrb->allocf_ud); } if( pthread_join(plugins[i].thread, NULL) < 0){ fprintf(stderr, "join failed\n"); } mrb_close(plugins[i].mrb); } mrb_close(mrb); printf("Exited !\n"); return 0; }
static void fini_profiler(ClipMachine * ClipMachineMemory) { Coll coll; int r, i; FILE *out; char path[256]; struct timeval total; unsigned long ms, us; init_profiler(ClipMachineMemory); /* generate report here */ init_Coll(&coll, 0, cmp_profile_out); snprintf(path, sizeof(path), "%s.pro", _clip_progname); out = fopen(path, "w"); if (!out) out = stderr; for (r = HashTable_first(ClipMachineMemory->profiler); r; r = HashTable_next(ClipMachineMemory->profiler)) { ProfileBucket *bp = (ProfileBucket *) HashTable_current(ClipMachineMemory->profiler); insert_Coll(&coll, bp); } total.tv_sec = 0; total.tv_usec = 0; for (i = 0; i < coll.count_of_Coll; i++) { ProfileBucket *bp = (ProfileBucket *) coll.items_of_Coll[i]; struct timeval tv; if (!bp->procname_of_ProfileBucket[0] && !bp->filename_of_ProfileBucket[0]) continue; ms = bp->timeval_self_of_ProfileBucket.tv_sec * 1000 + bp->timeval_self_of_ProfileBucket.tv_usec / 1000; us = bp->timeval_self_of_ProfileBucket.tv_usec % 1000; tv = total; timer_add(&tv, &bp->timeval_self_of_ProfileBucket, &total); fprintf(out, "%18s %-13s %8ld calls %8lu.%03lu ms\n", bp->procname_of_ProfileBucket, bp->filename_of_ProfileBucket, bp->callno_of_ProfileBucket, ms, us); } ms = total.tv_sec * 1000 + total.tv_usec / 1000; us = total.tv_usec % 1000; fprintf(out, "---------------------------------\n"); fprintf(out, "total registered %8lu.%03lu ms\n", ms, us); destroy_Coll(&coll); if (out != stderr) fclose(out); }