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, "
"in seconds, for which a task that voluntarily yields should "
"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", 1.0,
PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
@ -396,13 +401,22 @@ remove_thread(ThreadSimpleImpl *thread) {
void ThreadSimpleManager::
system_sleep(double seconds) {
#ifdef WIN32
Sleep((int)(seconds * 1000));
Sleep((int)(seconds * 1000 + 0.5));
#else
/*
struct timespec rqtp;
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);
*/
// 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
}
@ -468,26 +482,24 @@ write_status(ostream &out) const {
////////////////////////////////////////////////////////////////////
void ThreadSimpleManager::
system_yield() {
if (!_pointers_initialized) {
// Ignore this call before we construct the global ThreadSimpleManager.
return;
}
if (thread_cat->is_debug()) {
thread_cat.debug()
<< "system_yield\n";
}
#ifdef WIN32
// 1 ms is the smallest effective time we can request on Windows;
// Sleep(0) doesn't seem to actually yield? Or at least it doesn't
// yield enough.
Sleep(1);
#else
// 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 = 0;
tv.tv_usec = 1;
select(0, NULL, NULL, NULL, &tv);
#endif // WIN32
// There seem to be some issues with modern operating systems not
// wanting to actually yield the timeslice in response to sleep(0).
// In particular, Windows and OSX both seemed to do nothing in that
// call. Whatever. We'll force the point by explicitly sleeping
// 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
// have).
system_sleep(_global_ptr->_simple_thread_yield_sleep);
}
////////////////////////////////////////////////////////////////////
@ -628,7 +640,7 @@ choose_next_context() {
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
// unintentional deadlock.
if (!_blocked.empty()) {

View File

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