int server_start() { thread_state_t *state = NULL; struct sockaddr_in cli_addr; int cli_fd; socklen_t clilen = sizeof (cli_addr); /* Allocate new configuration */ if ((server_config = config_new()) == NULL) { ERROR_MSG("Internal error: Can not allocate configuration\n"); return 1; } /* Creating socket */ if ((server_config->socket_fd = create_server_socket(get_port())) < 0) { ERROR_MSG("Error: Can not create socket\n"); config_free(&server_config); return 1; } while (1) { cli_fd = accept(server_config->socket_fd, (struct sockaddr *)&cli_addr, &clilen); if (cli_fd < 0) { ERROR_MSG("ERROR on accept\n"); continue; } if (check_overload() < 0) { ERROR_MSG("ERROR close\n"); close(cli_fd); continue; } state = thread_state_new(); state->cli_fd = cli_fd; INCR_SERVER_LOAD; pthread_create(&(state->thread), NULL, compile_file, state); } config_free(&server_config); return 0; }
/** * Main scheduling loop **/ static void* do_scheduler(void *arg) { static cpu_tick_t next_poll=0, next_overload_check=0, next_info_dump=0, next_graph_stats=0, now=0; static int pollcount=1000; static int init_done = 0; (void) arg; // suppress GCC "unused parameter" warning in_scheduler = 1; // make sure we start out by saving edge stats for a while if( !init_done ) { init_done = 1; if (conf_no_statcollect) bg_save_stats = 0; else bg_save_stats = 1; GET_REAL_CPU_TICKS( now ); next_graph_stats = now + 1 * ticks_per_second; start_timer(&scheduler_timer); } while( 1 ) { //current_thread = scheduler_thread; sanity_check_threadcounts(); sanity_check_io_stats(); // wake up threads that have timeouts sleepq_check(0); sanity_check_threadcounts(); // break out if there are only daemon threads if(unlikely (num_suspended_threads == 0 && num_runnable_threads == num_daemon_threads)) { // dump the blocking graph if( exit_func_done && conf_dump_blocking_graph ) { tdebug("dumping blocking graph from do_scheduler()\n"); dump_blocking_graph(); } // go back to mainthread, which should now be in exit_func() current_thread = main_thread; in_scheduler = 0; co_call(main_thread->coro, NULL); in_scheduler = 1; if( unlikely(current_thread_exited) ) { // free memory from deleted threads current_thread_exited=0; if (current_thread != main_thread) // main_thread is needed for whole program exit free_thread( current_thread ); } return NULL; } // cheesy way of handling things with timing requirements { GET_REAL_CPU_TICKS( now ); // toggle stats collection if( conf_no_statcollect == 0 && next_graph_stats < now ) { bg_save_stats = 1 - bg_save_stats; if( bg_save_stats ) { // record stats for 100 ms next_graph_stats = now + 100 * ticks_per_millisecond; // update the stats epoch, to allow proper handling of the first data items bg_stats_epoch++; } else { // avoid stats for 2000 ms next_graph_stats = now + 2000 * ticks_per_millisecond; } //output(" *********************** graph stats %s\n", bg_save_stats ? "ON" : "OFF" ); } // resource utalization if( unlikely (next_overload_check < now) ) { check_overload( now ); next_overload_check = now + OVERLOAD_CHECK_INTERVAL; } // poll if( likely( (int)io_polling_func) ) { if( num_runnable_threads==0 || --pollcount <= 0 || next_poll < now ) { //if( num_runnable_threads==0 ) { // poll long long timeout = 0; if( num_runnable_threads==0 ) { if (first_wake_usecs == 0) { timeout = -1; } else { // there are threads in the sleep queue // so poll for i/o till at most that time unsigned long long now; now = current_usecs(); tdebug ("first_wake: %lld, now: %lld\n", first_wake_usecs, now); if (first_wake_usecs > now) timeout = first_wake_usecs - now; } } stop_timer(&scheduler_timer); //if( timeout != -1 ) output("timeout is not zero\n"); io_polling_func( timeout ); // allow blocking start_timer(&scheduler_timer); sanity_check_threadcounts(); #ifndef USE_NIO // sleep for a bit, if there was nothing to do // FIXME: let the IO functions block instead?? if( num_runnable_threads == 0 ) { syscall(SYS_sched_yield); } #endif // vary the poll rate depending on the workload #if 0 if( num_runnable_threads < 5 ) { next_poll = now + (10*ticks_per_millisecond); pollcount = 1000; } else if( num_runnable_threads < 10 ) { next_poll = now + (50*ticks_per_millisecond); pollcount = 2000; } else { next_poll = now + (100*ticks_per_millisecond); pollcount = 3000; } #else next_poll = now + (ticks_per_millisecond << 13); pollcount = 10000; #endif } } // debug stats if( 0 && next_info_dump < now ) { dump_debug_info(); next_info_dump = now + 5 * ticks_per_second; } } // get the head of the run list current_thread = sched_next_thread(); // scheduler gave an invlid even though there are runnable // threads. This indicates that every runnable thead is likely to // require use of an overloaded resource. if( !valid_thread(current_thread) ) { pollcount = 0; continue; } // barf, if the returned thread is still on the sleep queue assert( current_thread->sleep == -1 ); tdebug("running TID %d (%s)\n", current_thread->tid, current_thread->name ? current_thread->name : "no name"); sanity_check_threadcounts(); // call thread stop_timer(&scheduler_timer); start_timer(&app_timer); in_scheduler = 0; co_call(current_thread->coro, NULL); in_scheduler = 1; stop_timer(&app_timer); start_timer(&scheduler_timer); if( unlikely(current_thread_exited) ) { // free memory from deleted threads current_thread_exited=0; if (current_thread != main_thread) // main_thread is needed for whole program exit free_thread( current_thread ); } #ifdef NO_SCHEDULER_THREAD return NULL; #endif } return NULL; }