simple_thread_yield_sleep

This commit is contained in:
David Rose 2009-12-16 17:27:03 +00:00
parent 92ac3b6ee8
commit 5755ae390c
2 changed files with 31 additions and 18 deletions

View File

@ -45,6 +45,11 @@ ThreadSimpleManager() :
PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, " PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
"in seconds, for which a task that voluntarily yields should " "in seconds, for which a task that voluntarily yields should "
"be delayed.")), "be delayed.")),
_simple_thread_yield_sleep
("simple-thread-yield-sleep", 0.001,
PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
"in seconds, for which the process should be put to sleep when "
"yielding the timeslice to the system.")),
_simple_thread_window _simple_thread_window
("simple-thread-window", 1.0, ("simple-thread-window", 1.0,
PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, " PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
@ -396,13 +401,22 @@ remove_thread(ThreadSimpleImpl *thread) {
void ThreadSimpleManager:: void ThreadSimpleManager::
system_sleep(double seconds) { system_sleep(double seconds) {
#ifdef WIN32 #ifdef WIN32
Sleep((int)(seconds * 1000)); Sleep((int)(seconds * 1000 + 0.5));
#else #else
/*
struct timespec rqtp; struct timespec rqtp;
rqtp.tv_sec = time_t(seconds); rqtp.tv_sec = time_t(seconds);
rqtp.tv_nsec = long((seconds - (double)rqtp.tv_sec) * 1000000000.0); rqtp.tv_nsec = long((seconds - (double)rqtp.tv_sec) * 1000000000.0 + 0.5);
nanosleep(&rqtp, NULL); nanosleep(&rqtp, NULL);
*/
// We use select() as the only way that seems to actually yield the
// timeslice. sleep() and nanosleep() don't appear to do the trick.
struct timeval tv;
tv.tv_sec = time_t(seconds);
tv.tv_usec = long((seconds - (double)tv.tv_sec) * 1000000.0 + 0.5);
select(0, NULL, NULL, NULL, &tv);
#endif // WIN32 #endif // WIN32
} }
@ -468,26 +482,24 @@ write_status(ostream &out) const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void ThreadSimpleManager:: void ThreadSimpleManager::
system_yield() { system_yield() {
if (!_pointers_initialized) {
// Ignore this call before we construct the global ThreadSimpleManager.
return;
}
if (thread_cat->is_debug()) { if (thread_cat->is_debug()) {
thread_cat.debug() thread_cat.debug()
<< "system_yield\n"; << "system_yield\n";
} }
#ifdef WIN32 // There seem to be some issues with modern operating systems not
// 1 ms is the smallest effective time we can request on Windows; // wanting to actually yield the timeslice in response to sleep(0).
// Sleep(0) doesn't seem to actually yield? Or at least it doesn't // In particular, Windows and OSX both seemed to do nothing in that
// yield enough. // call. Whatever. We'll force the point by explicitly sleeping
Sleep(1); // for 1 ms in both cases. This is user-configurable in case 1 ms
// is too much (though on Windows that's all the resolution you
#else // have).
// We use select() as the only way that seems to actually yield the system_sleep(_global_ptr->_simple_thread_yield_sleep);
// timeslice. sleep() and nanosleep() don't appear to do the trick.
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1;
select(0, NULL, NULL, NULL, &tv);
#endif // WIN32
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -628,7 +640,7 @@ choose_next_context() {
break; break;
} }
// No threads are ready to rull, but we're not explicitly // No threads are ready to run, but we're not explicitly
// shutting down. This is an error condition, an // shutting down. This is an error condition, an
// unintentional deadlock. // unintentional deadlock.
if (!_blocked.empty()) { if (!_blocked.empty()) {

View File

@ -107,6 +107,7 @@ public:
// Defined within the class to avoid static-init ordering problems. // Defined within the class to avoid static-init ordering problems.
ConfigVariableDouble _simple_thread_epoch_timeslice; ConfigVariableDouble _simple_thread_epoch_timeslice;
ConfigVariableDouble _simple_thread_volunteer_delay; ConfigVariableDouble _simple_thread_volunteer_delay;
ConfigVariableDouble _simple_thread_yield_sleep;
ConfigVariableDouble _simple_thread_window; ConfigVariableDouble _simple_thread_window;
ConfigVariableDouble _simple_thread_low_weight; ConfigVariableDouble _simple_thread_low_weight;
ConfigVariableDouble _simple_thread_normal_weight; ConfigVariableDouble _simple_thread_normal_weight;