/* * Open connection to xenstore. * * @pollfds defines of signal-handling descriptors to be watched * if has to wait. * * Will not touch pollfds[NPFD_XS]. */ static void open_xs_connection(struct pollfd *pollfds) { struct timespec ts0; int64_t wsec; bool displayed_msg = false; int k; /* * If we are running as a daemon during system startup, there * can be a race condition with continuing Xen initialization * (/proc/xen including /proc/xen/privcmd may be unavailable yet, * still to be created even though Xen service startup completion * has already been signalled), so wait for a while if necessary. */ for (ts0 = getnow();;) { if (!xs) xs = xs_open(0); if (xs) break; /* time since the start */ wsec = timespec_diff_ms(getnow(), ts0) / MSEC_PER_SEC; if (run_as_daemon && wsec < max_xen_init_retries) { if (wsec >= xen_init_retry_msg && !displayed_msg) { notice_msg("waiting for Xen to initialize"); displayed_msg = true; } if (pollfds != NULL) { int npollfds = NPFD_COUNT - 1; for (k = 0; k < npollfds; k++) pollfds[k].revents = 0; if (poll(pollfds, npollfds, 1 * MSEC_PER_SEC) < 0) fatal_perror("poll"); handle_signals(pollfds, NULL); } else { sleep(1); } } else { fatal_perror("unable to open connection to xenstore"); } } }
int dfs(int w) { int now,x,y,k; if (w==cnt) return 1; now=getnow(); if (now==-1) { printf("now==-1\n"); return 0;} x=order[now].x; y=order[now].y; for (k=1;k<=9;k++) if (order[now].candidate[k]) //如果k这个数字是可以填 { row[x][k]=1; col[y][k]=1; block[x/3*3+y/3][k]=1; table[x][y]=k; updata(); if (dfs(w+1)==1) return 1; row[x][k]=0; col[y][k]=0; block[x/3*3+y/3][k]=0; table[x][y]=0; updata(); } return 0; //一个好使的解都没有找到,直接返回0 }
/* * Read memory statistics data */ static void get_paging_data(struct paging_data *pd) { static const char *key_pgpgin = "pgpgin"; static const char *key_nr_free_pages = "nr_free_pages"; static const char parse_error_msg[] = "error parsing /proc/vmstat"; char *cp, *xp; bool found_pgpgin = false; bool found_nr_free_pages = false; int nfound = 0; const int need_found = 2; pd->ts = getnow(); pd->mem_pages = sysconf(_SC_PHYS_PAGES); if (pd->mem_pages <= 0) fatal_msg("unable to get system memory size"); read_whole_file("/proc/vmstat", &vmstat, &vmstat_size, 4096); for (cp = vmstat; *cp != '\0';) { if (is_key(&cp, key_pgpgin)) { if (!consume_umax(&cp, &pd->pgpgin)) fatal_msg(parse_error_msg); if (!found_pgpgin) { found_pgpgin = true; if (need_found == ++nfound) break; } } else if (is_key(&cp, key_nr_free_pages)) { if (!consume_umax(&cp, &pd->nr_free_pages)) fatal_msg(parse_error_msg); if (!found_nr_free_pages) { found_nr_free_pages = true; if (need_found == ++nfound) break; } } else { xp = strchr(cp, '\n'); if (!xp) break; cp = xp + 1; } } if (need_found != nfound) fatal_msg(parse_error_msg); }
int rpl_nanosleep (const struct timespec *requested_delay, struct timespec *remaining_delay) { /* nanosleep mishandles large sleeps due to internal overflow problems, so check that the proper amount of time has actually elapsed. */ struct timespec delay = *requested_delay; struct timespec t0; getnow (&t0); for (;;) { int r = nanosleep (&delay, remaining_delay); if (r == 0) { time_t secs_sofar; struct timespec now; getnow (&now); secs_sofar = now.tv_sec - t0.tv_sec; if (requested_delay->tv_sec < secs_sofar) return 0; delay.tv_sec = requested_delay->tv_sec - secs_sofar; delay.tv_nsec = requested_delay->tv_nsec - (now.tv_nsec - t0.tv_nsec); if (delay.tv_nsec < 0) { if (delay.tv_sec == 0) return 0; delay.tv_nsec += BILLION; delay.tv_sec--; } else if (BILLION <= delay.tv_nsec) { delay.tv_nsec -= BILLION; delay.tv_sec++; } } } }
void execute(const struct command *commands, size_t mlen, const uint8_t *cores, size_t rlen) { uint64_t *times = alloca(mlen * sizeof(uint64_t)); uint64_t start = getnow(), now, next; struct timespec ts; msrval_t *values; msradr_t *addresses; values = alloca(mlen * rlen * sizeof (msrval_t)); addresses = alloca(mlen * rlen * sizeof (msradr_t)); print_header(commands, mlen, cores, rlen); signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); signal(SIGQUIT, handle_signal); setup_start_data(addresses, commands, mlen, rlen); setup_next_data(values, commands, mlen, rlen); setup_start_times(times, commands, mlen, start); while (!stopped) { now = getnow(); apply_commands(values, addresses, times, commands, mlen, cores, rlen, now); print_data(times, values, commands, mlen, rlen, start, now); next = setup_next_times(times, commands, mlen, now); if (next == ~(0ul)) break; setup_next_data(values, commands, mlen, rlen); ts.tv_sec = (next - now) / 1000; ts.tv_nsec = ((next - now) - ts.tv_sec * 1000) * 1000000; nanosleep(&ts, NULL); } }
void *sh_timeradd(unsigned long msec,int flags,void (*action)(void*),void *handle) { register Timer_t *tp; double t; Handler_t fn; t = ((double)msec)/1000.; if(t<=0 || !action) return((void*)0); if(tp=tpfree) tpfree = tp->next; else if(!(tp=(Timer_t*)malloc(sizeof(Timer_t)))) return((void*)0); tp->wakeup = getnow() + t; tp->incr = (flags?t:0); tp->action = action; tp->handle = handle; time_state |= IN_ADDTIMEOUT; tp->next = tptop; tptop = tp; if(!tpmin || tp->wakeup < tpmin->wakeup) { tpmin = tp; fn = (Handler_t)signal(SIGALRM,sigalrm); if((t= setalarm(t))>0 && fn && fn!=(Handler_t)sigalrm) { Handler_t *hp = (Handler_t*)malloc(sizeof(Handler_t)); if(hp) { *hp = fn; sh_timeradd((long)(1000*t), 0, oldalrm, (void*)hp); } } tp = tptop; } else if(tpmin && !tpmin->action) time_state |= DEFER_SIGALRM; time_state &= ~IN_ADDTIMEOUT; if(time_state&DEFER_SIGALRM) { time_state=SIGALRM_CALL; sigalrm(SIGALRM); if(tp!=tptop) tp=0; } return((void*)tp); }
/* signal handler for alarm call */ static void sigalrm(int sig) { register Timer_t *tp, *tplast, *tpold, *tpnext; double now; static double left; NOT_USED(sig); left = 0; if(time_state&SIGALRM_CALL) time_state &= ~SIGALRM_CALL; else if(alarm(0)) sh_fault(SIGALRM|SH_TRAP); if(time_state) { if(time_state&IN_ADDTIMEOUT) time_state |= DEFER_SIGALRM; errno = EINTR; return; } time_state |= IN_SIGALRM; sigrelease(SIGALRM); while(1) { now = getnow(); tpold = tpmin = 0; for(tplast=0,tp=tptop; tp; tp=tpnext) { tpnext = tp->next; if(tp->action) { if(tp->wakeup <=now) { if(!tpold || tpold->wakeup>tp->wakeup) tpold = tp; } else { if(!tpmin || tpmin->wakeup>tp->wakeup) tpmin=tp; } tplast = tp; } else { if(tplast) tplast->next = tp->next; else tptop = tp->next; tp->next = tpfree; tpfree = tp; } } if((tp=tpold) && tp->incr) { while((tp->wakeup += tp->incr) <= now); if(!tpmin || tpmin->wakeup>tp->wakeup) tpmin=tp; } if(tpmin && (left==0 || (tp && tpmin->wakeup < (now+left)))) { if(left==0) signal(SIGALRM,sigalrm); left = setalarm(tpmin->wakeup-now); if(left && (now+left) < tpmin->wakeup) setalarm(left); else left=tpmin->wakeup-now; } if(tp) { void (*action)(void*); action = tp->action; if(!tp->incr) tp->action = 0; errno = EINTR; time_state &= ~IN_SIGALRM; (*action)(tp->handle); time_state |= IN_SIGALRM; } else break; } if(!tpmin) signal(SIGALRM,(sh.sigflag[SIGALRM]&SH_SIGFAULT)?sh_fault:SIG_DFL); time_state &= ~IN_SIGALRM; errno = EINTR; }
size_t get_worker(void) { // get a worker // off, so we don't check worker 0 a million times static size_t off = -1; static int tries = 0; ++off; int which; for(which=0;which<numworkers;++which) { size_t derp = (which+off)%numworkers; switch(workers[derp].status) { case IDLE: workers[derp].status = BUSY; PFD(derp).events = POLLIN; tries = 0; return derp; }; } if(tries < 3) { ++tries; // if we timeout 3 times, stop waiting for idle workers. return -1; } /* no idle found, try starting some workers */ if(numworkers < MAXWORKERS) { // add a worker to the end if(start_worker()) { tries = 0; return numworkers-1; } } else { reap_workers(); for(which=0;which<numworkers;++which) { if(workers[which].status == DOOMED) { /* if 995 ns left (expiration - now) and doom delay is 1000ns 1000 - 995 < 50, so wait a teensy bit longer please */ Time diff = timediff(DOOM_DELAY, timediff(workers[which].expiration, getnow())); if(diff.tv_nsec > 50) { // waited too long, kill the thing. kill_worker(which); if(start_worker()) { tries = 0; return numworkers-1; } } } } } if(wait_for_accept()) { if(accept_workers()) { return get_worker(); } } // have to wait until the new worker connects errno = EAGAIN; // eh return -1; }
void stop_worker(int which) { workers[which].status = DOOMED; workers[which].expiration = timeadd(getnow(),DOOM_DELAY); kill(workers[which].pid,SIGTERM); reap_workers(); }
int main(int argc, char **argv) { sigset_t sigmask; struct pollfd pollfds[NPFD_COUNT]; int npollfds; int k; int64_t wait_ms; struct paging_data pd0; struct paging_data pd1; bool recheck_time; int init_pass = 0; /* * if running interactively, output initially to the terminal, * otherwise to syslog right away */ if (isatty(fileno(stderr))) { log_fp = stderr; log_syslog = false; } else { log_fp = NULL; log_syslog = true; } if (log_syslog) openlog(progname, LOG_CONS | LOG_PID, LOG_DAEMON); /* parse arguments */ handle_cmdline(argc, argv); if (run_as_daemon) daemonize(); debug_msg(1, "debug level set to %d", debug_level); // page_size = sysconf(_SC_PAGESIZE); // if (page_size <= 0) // fatal_msg("unable to get system page size"); /* * Block signals so that they aren't handled according to their * default dispositions */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGHUP); sigaddset(&sigmask, SIGTERM); if (sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0) fatal_perror("sigprocmask"); /* * Receive signals on file descriptors */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGHUP); fd_sighup = signalfd(-1, &sigmask, 0); if (fd_sighup < 0) fatal_perror("signalfd(SIGHUP)"); sigemptyset(&sigmask); sigaddset(&sigmask, SIGTERM); fd_sigterm = signalfd(-1, &sigmask, 0); if (fd_sigterm < 0) fatal_perror("signalfd(SIGTERM)"); /* select clock to use */ select_clk_id(); /* verify we are running under a hypervisor */ verify_hypervisor(); pollfds[NPFD_SIGTERM].fd = fd_sigterm; pollfds[NPFD_SIGTERM].events = POLLIN|POLLPRI; pollfds[NPFD_SIGHUP].fd = fd_sighup; pollfds[NPFD_SIGHUP].events = POLLIN|POLLPRI; /* keep xs poll fd last in the array */ pollfds[NPFD_XS].fd = -1; pollfds[NPFD_XS].events = POLLIN|POLLPRI; /* initialize xenstore structure */ initialize_xs(pollfds); pollfds[NPFD_XS].fd = xs_fileno(xs); get_paging_data(&pd0); for (;;) { try_subscribe_membalance_settings(); /* calculate sleep time till next sample point */ if (initialized_xs) { wait_ms = timespec_diff_ms(pd0.ts, getnow()) + interval * MSEC_PER_SEC; } else { /* if xs not initialzied, keep retrying */ wait_ms = interval * MSEC_PER_SEC; if (++init_pass > 30) wait_ms *= 2; } if (wait_ms >= tolerance_ms) { for (k = 0; k < countof(pollfds); k++) pollfds[k].revents = 0; /* if settings need to be updated, retry in 1 sec or sooner */ if (need_update_membalance_settings) wait_ms = min(wait_ms, MSEC_PER_SEC); /* include xs in the poll only if has initialized xs */ npollfds = countof(pollfds); if (!initialized_xs) npollfds--; if (poll(pollfds, npollfds, wait_ms) < 0) { if (errno == EINTR) continue; fatal_perror("poll"); } recheck_time = false; handle_signals(pollfds, &recheck_time); if (!initialized_xs) { /* try to initialzie xs */ initialize_xs(NULL); /* if successful, start monitoring page map-in rate */ if (initialized_xs) get_paging_data(&pd0); continue; } if (pollfds[NPFD_XS].revents & (POLLIN|POLLPRI)) { /* a watched value in xenstore has been changed */ handle_xs_watch(); recheck_time = true; } if (need_update_membalance_settings) update_membalance_settings(); if (recheck_time) { /* go sleep again if wait interval has not expired yet */ if (timespec_diff_ms(getnow(), pd0.ts) < interval * MSEC_PER_SEC - tolerance_ms) continue; } } if (!initialized_xs) { /* try to initialzie xs */ initialize_xs(NULL); /* if successful, start monitoring page map-in rate */ if (initialized_xs) get_paging_data(&pd0); continue; } /* process sample and set it as the new "previous" one */ get_paging_data(&pd1); process_sample(&pd1, &pd0); pd0 = pd1; } /* close connection to xenstore */ shutdown_xs(); return EXIT_SUCCESS; }