/// 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 }
/// 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 }