/// Note that this function is quite sketchy. In particular, it drains threads, not requests, /// meaning that it may leave requests on the queue. This is the desired behavior (it may be called /// before fork, and we don't want to bother servicing requests before we fork), but in the test /// suite we depend on it draining all requests. In practice, this works, because a thread in /// practice won't exit while there is outstanding requests. /// /// At the moment, this function is only used in the test suite and in a /// drain-all-threads-before-fork compatibility mode that no architecture requires, so it's OK that /// it's terrible. void iothread_drain_all(void) { ASSERT_IS_MAIN_THREAD(); ASSERT_IS_NOT_FORKED_CHILD(); scoped_lock locker(s_spawn_queue_lock); #define TIME_DRAIN 0 #if TIME_DRAIN int thread_count = s_active_thread_count; double now = timef(); #endif // Nasty polling via select(). while (s_active_thread_count > 0) { locker.unlock(); if (iothread_wait_for_pending_completions(1000)) { iothread_service_completion(); } locker.lock(); } #if TIME_DRAIN double after = timef(); printf("(Waited %.02f msec for %d thread(s) to drain)\n", 1000 * (after - now), thread_count); #endif }
static double output_elapsed_time(double prev_tstamp, bool first_char_seen) { // How much time has passed since the previous char was received in microseconds. double now = timef(); long long int delta_tstamp_us = 1000000 * (now - prev_tstamp); if (delta_tstamp_us >= 200000 && first_char_seen) putchar('\n'); if (delta_tstamp_us >= 1000000) { printf(" "); } else { printf("(%3lld.%03lld ms) ", delta_tstamp_us / 1000, delta_tstamp_us % 1000); } return now; }
/// Note that this function is quite sketchy. In particular, it drains threads, not requests, /// meaning that it may leave requests on the queue. This is the desired behavior (it may be called /// before fork, and we don't want to bother servicing requests before we fork), but in the test /// suite we depend on it draining all requests. In practice, this works, because a thread in /// practice won't exit while there is outstanding requests. /// /// At the moment, this function is only used in the test suite and in a /// drain-all-threads-before-fork compatibility mode that no architecture requires, so it's OK that /// it's terrible. void iothread_drain_all(void) { ASSERT_IS_MAIN_THREAD(); ASSERT_IS_NOT_FORKED_CHILD(); #define TIME_DRAIN 0 #if TIME_DRAIN int thread_count = s_spawn_requests.acquire().value.thread_count; double now = timef(); #endif // Nasty polling via select(). while (s_spawn_requests.acquire().value.thread_count > 0) { if (iothread_wait_for_pending_completions(1000)) { iothread_service_completion(); } } #if TIME_DRAIN double after = timef(); fwprintf(stdout, L"(Waited %.02f msec for %d thread(s) to drain)\n", 1000 * (after - now), thread_count); #endif }
~time_profiler_t() { if (LOG_TIMES) { double end = timef(); printf("(LOG_TIMES %s: %02f msec)\n", what, (end - start) * 1000); } }
time_profiler_t(const char *w) { if (LOG_TIMES) { what = w; start = timef(); } }