@@ -28,7 +28,7 @@ int getLogicalCoreCount(); | |||
/** Sets a name of the current thread for debuggers and OS-specific process viewers. */ | |||
void setThreadName(const std::string &name); | |||
/** Sets the current thread to be high-priority. */ | |||
void setThreadRealTime(); | |||
void setThreadRealTime(bool realTime); | |||
/** Returns the caller's human-readable stack trace with "\n"-separated lines. */ | |||
std::string getStackTrace(); | |||
/** Opens a URL, also happens to work with PDFs and folders. | |||
@@ -211,7 +211,7 @@ static int rtCallback(void *outputBuffer, void *inputBuffer, unsigned int nFrame | |||
// Exploit the stream time to run code on startup of the audio thread | |||
if (streamTime == 0.0) { | |||
system::setThreadName("Audio"); | |||
system::setThreadRealTime(); | |||
// system::setThreadRealTime(); | |||
} | |||
port->processStream((const float *) inputBuffer, (float *) outputBuffer, nFrames); | |||
return 0; | |||
@@ -116,15 +116,7 @@ struct EngineWorker { | |||
thread.join(); | |||
} | |||
void run() { | |||
system::setThreadName("Engine worker"); | |||
// system::setThreadRealTime(); | |||
disableDenormals(); | |||
while (running) { | |||
step(); | |||
} | |||
} | |||
void run(); | |||
void step(); | |||
}; | |||
@@ -168,6 +160,8 @@ Engine::Engine() { | |||
internal->sampleRate = 44100.f; | |||
internal->sampleTime = 1 / internal->sampleRate; | |||
system::setThreadRealTime(false); | |||
} | |||
Engine::~Engine() { | |||
@@ -300,22 +294,31 @@ static void Engine_relaunchWorkers(Engine *that) { | |||
assert(1 <= internal->threadCount); | |||
// Stop all workers | |||
DEBUG("1"); | |||
for (EngineWorker &worker : internal->workers) { | |||
worker.stop(); | |||
} | |||
DEBUG("2"); | |||
internal->engineBarrier.wait(); | |||
// Destroy all workers | |||
DEBUG("3"); | |||
for (EngineWorker &worker : internal->workers) { | |||
worker.join(); | |||
} | |||
DEBUG("4"); | |||
internal->workers.resize(0); | |||
DEBUG("5"); | |||
// Configure main thread | |||
system::setThreadRealTime(internal->realTime); | |||
// Set barrier counts | |||
internal->engineBarrier.total = internal->threadCount; | |||
internal->workerBarrier.total = internal->threadCount; | |||
// Create workers | |||
DEBUG("6"); | |||
internal->workers.resize(internal->threadCount - 1); | |||
for (int id = 1; id < internal->threadCount; id++) { | |||
EngineWorker &worker = internal->workers[id - 1]; | |||
@@ -323,6 +326,7 @@ static void Engine_relaunchWorkers(Engine *that) { | |||
worker.engine = that; | |||
worker.start(); | |||
} | |||
DEBUG("7"); | |||
} | |||
static void Engine_run(Engine *that) { | |||
@@ -351,8 +355,9 @@ static void Engine_run(Engine *that) { | |||
} | |||
// Launch workers | |||
if (internal->threadCount != settings::threadCount) { | |||
if (internal->threadCount != settings::threadCount || internal->realTime != settings::realTime) { | |||
internal->threadCount = settings::threadCount; | |||
internal->realTime = settings::realTime; | |||
Engine_relaunchWorkers(that); | |||
} | |||
@@ -696,6 +701,15 @@ void Engine::updateParamHandle(ParamHandle *paramHandle, int moduleId, int param | |||
} | |||
void EngineWorker::run() { | |||
system::setThreadName("Engine worker"); | |||
system::setThreadRealTime(engine->internal->realTime); | |||
disableDenormals(); | |||
while (running) { | |||
step(); | |||
} | |||
} | |||
void EngineWorker::step() { | |||
engine->internal->engineBarrier.wait(); | |||
if (!running) | |||
@@ -105,17 +105,37 @@ void setThreadName(const std::string &name) { | |||
#endif | |||
} | |||
void setThreadRealTime() { | |||
void setThreadRealTime(bool realTime) { | |||
#if defined ARCH_LIN || defined ARCH_MAC | |||
// Round-robin scheduler policy | |||
int policy = SCHED_RR; | |||
int err; | |||
int policy; | |||
struct sched_param param; | |||
param.sched_priority = sched_get_priority_max(policy); | |||
pthread_setschedparam(pthread_self(), policy, ¶m); | |||
if (realTime) { | |||
// Round-robin scheduler policy | |||
policy = SCHED_RR; | |||
param.sched_priority = sched_get_priority_max(policy); | |||
} | |||
else { | |||
// Default scheduler policy | |||
policy = 0; | |||
param.sched_priority = 0; | |||
} | |||
err = pthread_setschedparam(pthread_self(), policy, ¶m); | |||
assert(!err); | |||
// pthread_getschedparam(pthread_self(), &policy, ¶m); | |||
// DEBUG("policy %d priority %d", policy, param.sched_priority); | |||
#elif defined ARCH_WIN | |||
// Set process class first | |||
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | |||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); | |||
if (realTime) { | |||
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | |||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); | |||
} | |||
else { | |||
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); | |||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); | |||
} | |||
#endif | |||
} | |||