/* zero all the stats structures */ void stats_zero(void) { int dir; unsigned i; char *fname; fname = format("%s/stats", cache_dir); x_unlink(fname); free(fname); for (dir = 0; dir <= 0xF; dir++) { struct counters *counters = counters_init(STATS_END); fname = format("%s/%1x/stats", cache_dir, dir); if (lockfile_acquire(fname, lock_staleness_limit)) { stats_read(fname, counters); for (i = 0; stats_info[i].message; i++) { if (!(stats_info[i].flags & FLAG_NOZERO)) { counters->data[stats_info[i].stat] = 0; } } stats_write(fname, counters); lockfile_release(fname); } counters_free(counters); free(fname); } }
static void init_counter_updates(void) { if (!counter_updates) { counter_updates = counters_init(STATS_END); } }
// Sum and display the total stats for all cache dirs. void stats_summary(void) { assert(conf); struct counters *counters = counters_init(STATS_END); time_t last_updated; stats_collect(counters, &last_updated); printf("cache directory %s\n", conf->cache_dir); printf("primary config %s\n", primary_config_path ? primary_config_path : ""); printf("secondary config (readonly) %s\n", secondary_config_path ? secondary_config_path : ""); if (last_updated > 0) { struct tm *tm = localtime(&last_updated); char timestamp[100]; strftime(timestamp, sizeof(timestamp), "%c", tm); printf("stats updated %s\n", timestamp); } // ...and display them. for (int i = 0; stats_info[i].message; i++) { enum stats stat = stats_info[i].stat; if (stats_info[i].flags & FLAG_NEVER) { continue; } if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) { continue; } char *value; if (stats_info[i].format_fn) { value = stats_info[i].format_fn(counters->data[stat]); } else { value = format("%8u", counters->data[stat]); } if (value) { printf("%-31s %s\n", stats_info[i].message, value); free(value); } if (stat == STATS_TOCACHE) { double percent = stats_hit_rate(counters); printf("cache hit rate %6.2f %%\n", percent); } } if (conf->max_files != 0) { printf("max files %8u\n", conf->max_files); } if (conf->max_size != 0) { char *value = format_size(conf->max_size); printf("max cache size %s\n", value); free(value); } counters_free(counters); }
// Zero all the stats structures. void stats_zero(void) { assert(conf); char *fname = format("%s/stats", conf->cache_dir); x_unlink(fname); free(fname); time_t timestamp = time(NULL); for (int dir = 0; dir <= 0xF; dir++) { struct counters *counters = counters_init(STATS_END); struct stat st; fname = format("%s/%1x/stats", conf->cache_dir, dir); if (stat(fname, &st) != 0) { // No point in trying to reset the stats file if it doesn't exist. free(fname); continue; } if (lockfile_acquire(fname, lock_staleness_limit)) { stats_read(fname, counters); for (unsigned i = 0; stats_info[i].message; i++) { if (!(stats_info[i].flags & FLAG_NOZERO)) { counters->data[stats_info[i].stat] = 0; } } counters->data[STATS_ZEROTIMESTAMP] = timestamp; stats_write(fname, counters); lockfile_release(fname); } counters_free(counters); free(fname); } }
/* sum and display the total stats for all cache dirs */ void stats_summary(struct conf *conf) { int dir, i; struct counters *counters = counters_init(STATS_END); assert(conf); /* add up the stats in each directory */ for (dir = -1; dir <= 0xF; dir++) { char *fname; if (dir == -1) { fname = format("%s/stats", conf->cache_dir); } else { fname = format("%s/%1x/stats", conf->cache_dir, dir); } stats_read(fname, counters); free(fname); } printf("cache directory %s\n", conf->cache_dir); printf("primary config %s\n", primary_config_path ? primary_config_path : ""); printf("secondary config (readonly) %s\n", secondary_config_path ? secondary_config_path : ""); /* and display them */ for (i = 0; stats_info[i].message; i++) { enum stats stat = stats_info[i].stat; if (stats_info[i].flags & FLAG_NEVER) { continue; } if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) { continue; } printf("%s ", stats_info[i].message); if (stats_info[i].fn) { stats_info[i].fn(counters->data[stat]); printf("\n"); } else { printf("%8u\n", counters->data[stat]); } } if (conf->max_files != 0) { printf("max files %8u\n", conf->max_files); } if (conf->max_size != 0) { printf("max cache size "); display_size(conf->max_size); printf("\n"); } counters_free(counters); }
/* Get the per directory limits */ void stats_get_limits(const char *dir, unsigned *maxfiles, unsigned *maxsize) { struct counters *counters = counters_init(STATS_END); char *sname = format("%s/stats", dir); stats_read(sname, counters); *maxfiles = counters->data[STATS_MAXFILES]; *maxsize = counters->data[STATS_MAXSIZE]; free(sname); counters_free(counters); }
/* Get the per directory limits */ void stats_get_obsolete_limits(const char *dir, unsigned *maxfiles, uint64_t *maxsize) { struct counters *counters = counters_init(STATS_END); char *sname = format("%s/stats", dir); stats_read(sname, counters); *maxfiles = counters->data[STATS_OBSOLETE_MAXFILES]; *maxsize = (uint64_t)counters->data[STATS_OBSOLETE_MAXSIZE] * 1024; free(sname); counters_free(counters); }
// Count directory cleanup run. void stats_add_cleanup(const char *dir, unsigned count) { struct counters *counters = counters_init(STATS_END); char *statsfile = format("%s/stats", dir); if (lockfile_acquire(statsfile, lock_staleness_limit)) { stats_read(statsfile, counters); counters->data[STATS_NUMCLEANUPS] += count; stats_write(statsfile, counters); lockfile_release(statsfile); } free(statsfile); counters_free(counters); }
// Set the per-directory sizes. void stats_set_sizes(const char *dir, unsigned num_files, uint64_t total_size) { struct counters *counters = counters_init(STATS_END); char *statsfile = format("%s/stats", dir); if (lockfile_acquire(statsfile, lock_staleness_limit)) { stats_read(statsfile, counters); counters->data[STATS_NUMFILES] = num_files; counters->data[STATS_TOTALSIZE] = total_size / 1024; stats_write(statsfile, counters); lockfile_release(statsfile); } free(statsfile); counters_free(counters); }
/* sum and display the total stats for all cache dirs */ void stats_summary(void) { int dir, i; struct counters *counters = counters_init(STATS_END); /* add up the stats in each directory */ for (dir = -1; dir <= 0xF; dir++) { char *fname; if (dir == -1) { fname = format("%s/stats", cache_dir); } else { fname = format("%s/%1x/stats", cache_dir, dir); } stats_read(fname, counters); free(fname); /* oh what a nasty hack ... */ if (dir == -1) { counters->data[STATS_MAXSIZE] = 0; } } printf("cache directory %s\n", cache_dir); /* and display them */ for (i = 0; stats_info[i].message; i++) { enum stats stat = stats_info[i].stat; if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) { continue; } printf("%s ", stats_info[i].message); if (stats_info[i].fn) { stats_info[i].fn(counters->data[stat]); printf("\n"); } else { printf("%8u\n", counters->data[stat]); } } counters_free(counters); }
/* set the per directory limits */ int stats_set_limits(long maxfiles, long maxsize) { int dir; if (maxfiles != -1) { maxfiles /= 16; } if (maxsize != -1) { maxsize /= 16; } if (create_dir(cache_dir) != 0) { return 1; } /* set the limits in each directory */ for (dir = 0; dir <= 0xF; dir++) { char *fname, *cdir; cdir = format("%s/%1x", cache_dir, dir); if (create_dir(cdir) != 0) { free(cdir); return 1; } fname = format("%s/stats", cdir); free(cdir); if (lockfile_acquire(fname, lock_staleness_limit)) { struct counters *counters = counters_init(STATS_END); stats_read(fname, counters); if (maxfiles != -1) { counters->data[STATS_MAXFILES] = maxfiles; } if (maxsize != -1) { counters->data[STATS_MAXSIZE] = maxsize; } stats_write(fname, counters); lockfile_release(fname); counters_free(counters); } free(fname); } return 0; }
// Record that a number of bytes and files have been added to the cache. Size // is in bytes. void stats_update_size(const char *sfile, int64_t size, int files) { struct counters *updates; if (sfile == stats_file) { init_counter_updates(); updates = counter_updates; } else { updates = counters_init(STATS_END); } updates->data[STATS_NUMFILES] += files; updates->data[STATS_TOTALSIZE] += size / 1024; if (sfile != stats_file) { stats_flush_to_file(sfile, updates); counters_free(updates); } }
// Print machine-parsable (tab-separated) statistics counters. void stats_print(void) { assert(conf); struct counters *counters = counters_init(STATS_END); time_t last_updated; stats_collect(counters, &last_updated); printf("stats_updated_timestamp\t%llu\n", (unsigned long long)last_updated); for (int i = 0; stats_info[i].message; i++) { if (!(stats_info[i].flags & FLAG_NEVER)) { printf("%s\t%u\n", stats_info[i].id, counters->data[stats_info[i].stat]); } } counters_free(counters); }
/* * Write counter updates in counter_updates to disk. */ void stats_flush(void) { struct counters *counters; bool need_cleanup = false; bool should_flush = false; int i; assert(conf); if (!conf->stats) { return; } if (!counter_updates) { return; } for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[i] > 0) { should_flush = true; break; } } if (!should_flush) { return; } if (!stats_file) { char *stats_dir; /* * A NULL stats_file means that we didn't get past calculate_object_hash(), * so we just choose one of stats files in the 16 subdirectories. */ stats_dir = format("%s/%x", conf->cache_dir, hash_from_int(getpid()) % 16); stats_file = format("%s/stats", stats_dir); free(stats_dir); } if (!lockfile_acquire(stats_file, lock_staleness_limit)) { return; } counters = counters_init(STATS_END); stats_read(stats_file, counters); for (i = 0; i < STATS_END; ++i) { counters->data[i] += counter_updates->data[i]; } stats_write(stats_file, counters); lockfile_release(stats_file); if (!str_eq(conf->log_file, "")) { for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[stats_info[i].stat] != 0 && !(stats_info[i].flags & FLAG_NOZERO)) { cc_log("Result: %s", stats_info[i].message); } } } if (conf->max_files != 0 && counters->data[STATS_NUMFILES] > conf->max_files / 16) { need_cleanup = true; } if (conf->max_size != 0 && counters->data[STATS_TOTALSIZE] > conf->max_size / 1024 / 16) { need_cleanup = true; } if (need_cleanup) { char *p = dirname(stats_file); cleanup_dir(conf, p); free(p); } counters_free(counters); }
// Sum and display the total stats for all cache dirs. void stats_summary(struct conf *conf) { struct counters *counters = counters_init(STATS_END); assert(conf); // Add up the stats in each directory. for (int dir = -1; dir <= 0xF; dir++) { char *fname; if (dir == -1) { fname = format("%s/stats", conf->cache_dir); } else { fname = format("%s/%1x/stats", conf->cache_dir, dir); } stats_read(fname, counters); free(fname); } printf("cache directory %s\n", conf->cache_dir); printf("primary config %s\n", primary_config_path ? primary_config_path : ""); printf("secondary config (readonly) %s\n", secondary_config_path ? secondary_config_path : ""); // ...and display them. for (int i = 0; stats_info[i].message; i++) { enum stats stat = stats_info[i].stat; if (stats_info[i].flags & FLAG_NEVER) { continue; } if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) { continue; } printf("%s ", stats_info[i].message); if (stats_info[i].fn) { stats_info[i].fn(counters->data[stat]); printf("\n"); } else { printf("%8u\n", counters->data[stat]); } if (stat == STATS_TOCACHE) { unsigned direct = counters->data[STATS_CACHEHIT_DIR]; unsigned preprocessed = counters->data[STATS_CACHEHIT_CPP]; unsigned hit = direct + preprocessed; unsigned miss = counters->data[STATS_TOCACHE]; unsigned total = hit + miss; double percent = total > 0 ? (100.0f * hit) / total : 0.0f; printf("cache hit rate %6.2f %%\n", percent); } } if (conf->max_files != 0) { printf("max files %8u\n", conf->max_files); } if (conf->max_size != 0) { printf("max cache size "); display_size(conf->max_size); printf("\n"); } counters_free(counters); }
/* * Write counter updates in counter_updates to disk. */ void stats_flush(void) { struct counters *counters; bool need_cleanup = false; bool should_flush = false; int i; extern char *cache_logfile; if (getenv("CCACHE_NOSTATS")) return; init_counter_updates(); for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[i] > 0) { should_flush = true; break; } } if (!should_flush) return; if (!stats_file) { char *stats_dir; /* * A NULL stats_file means that we didn't get past calculate_object_hash(), * so we just choose one of stats files in the 16 subdirectories. */ if (!cache_dir) return; stats_dir = format("%s/%x", cache_dir, hash_from_int(getpid()) % 16); stats_file = format("%s/stats", stats_dir); create_dir(stats_dir); free(stats_dir); } if (!lockfile_acquire(stats_file, lock_staleness_limit)) { return; } counters = counters_init(STATS_END); stats_read(stats_file, counters); for (i = 0; i < STATS_END; ++i) { counters->data[i] += counter_updates->data[i]; } stats_write(stats_file, counters); lockfile_release(stats_file); if (cache_logfile) { for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[stats_info[i].stat] != 0 && !(stats_info[i].flags & FLAG_NOZERO)) { cc_log("Result: %s", stats_info[i].message); } } } if (counters->data[STATS_MAXFILES] != 0 && counters->data[STATS_NUMFILES] > counters->data[STATS_MAXFILES]) { need_cleanup = true; } if (counters->data[STATS_MAXSIZE] != 0 && counters->data[STATS_TOTALSIZE] > counters->data[STATS_MAXSIZE]) { need_cleanup = true; } if (need_cleanup) { char *p = dirname(stats_file); cleanup_dir(p, counters->data[STATS_MAXFILES], counters->data[STATS_MAXSIZE]); free(p); } }
// Write counter updates in counter_updates to disk. void stats_flush(void) { assert(conf); if (!conf->stats) { return; } if (!counter_updates) { return; } bool should_flush = false; for (int i = 0; i < STATS_END; ++i) { if (counter_updates->data[i] > 0) { should_flush = true; break; } } if (!should_flush) { return; } if (!stats_file) { char *stats_dir; // A NULL stats_file means that we didn't get past calculate_object_hash(), // so we just choose one of stats files in the 16 subdirectories. stats_dir = format("%s/%x", conf->cache_dir, hash_from_int(getpid()) % 16); stats_file = format("%s/stats", stats_dir); free(stats_dir); } if (!lockfile_acquire(stats_file, lock_staleness_limit)) { return; } struct counters *counters = counters_init(STATS_END); stats_read(stats_file, counters); for (int i = 0; i < STATS_END; ++i) { counters->data[i] += counter_updates->data[i]; } stats_write(stats_file, counters); lockfile_release(stats_file); if (!str_eq(conf->log_file, "") || conf->debug) { for (int i = 0; i < STATS_END; ++i) { if (counter_updates->data[stats_info[i].stat] != 0 && !(stats_info[i].flags & FLAG_NOZERO)) { cc_log("Result: %s", stats_info[i].message); } } } char *subdir = dirname(stats_file); bool need_cleanup = false; if (conf->max_files != 0 && counters->data[STATS_NUMFILES] > conf->max_files / 16) { cc_log("Need to clean up %s since it holds %u files (limit: %u files)", subdir, counters->data[STATS_NUMFILES], conf->max_files / 16); need_cleanup = true; } if (conf->max_size != 0 && counters->data[STATS_TOTALSIZE] > conf->max_size / 1024 / 16) { cc_log("Need to clean up %s since it holds %u KiB (limit: %lu KiB)", subdir, counters->data[STATS_TOTALSIZE], (unsigned long)conf->max_size / 1024 / 16); need_cleanup = true; } if (need_cleanup) { clean_up_dir(conf, subdir, conf->limit_multiple); } free(subdir); counters_free(counters); }
// 从汇编阶段,进入C语言的阶段,传承了Unix的典型思想 // 汇编只负责引导和必要的硬件打交道的阶段 void start_ling(start_info_t *si) { //-------- init phase 1 -------- // //start_info包含的是xen的初始化信息 //是xen在启动GuestOS的时候,放在特定的地方 memcpy(&start_info, si, sizeof(*si)); phys_to_machine_mapping = (unsigned long *)start_info.mfn_list; HYPERVISOR_update_va_mapping((unsigned long)&shared_info, __pte(start_info.shared_info | 7), UVMF_INVLPG); HYPERVISOR_shared_info = &shared_info; //进行时钟初始化 time_init(); // sets start_of_day_wall_clock // use the time value to seed PRNG mt_seed(start_of_day_wall_clock); #if defined(__x86_64__) HYPERVISOR_set_callbacks(0, 0, 0); #else /* __x86_64__ */ HYPERVISOR_set_callbacks(0, 0, 0, 0); #endif mm_init(start_info.nr_pages, start_info.pt_base, start_info.nr_pt_frames); nalloc_init(); events_init(); grants_init(); console_init(mfn_to_virt(start_info.console.domU.mfn), start_info.console.domU.evtchn); xenstore_init(mfn_to_virt(start_info.store_mfn), start_info.store_evtchn); xenstore_read("name", my_domain_name, sizeof(my_domain_name)); //print_xenstore_values(); if (disk_vbd_is_present()) disk_init(); lwip_init(); netfe_init(); //-------- init phase 2 -------- // if (nalloc_no_memory()) fatal_error("init phase 2: no memory"); sys_stats_init(); atoms_init(); embed_init(); code_base_init(); scheduler_init(); ets_init(); pcre_init(); counters_init(); //print_start_info(); //print_xenmem_info(); //run_alloc_tests(); //run_mm_tests(); //print_xenstore_values(); //run_bignum_tests(); //printk("\r\nLing %s is here\r\n", quote_and_expand(LING_VER)); proc_main(0); // preliminary run spawn_init_start(start_info.cmd_line); //while (1) // HYPERVISOR_sched_op(SCHEDOP_block, 0); /* UNREACHABLE */ }