Fix the RS frame timeout.

Previous a slow app would block from receiving new
commands until the timer expired.  This change will
expire the timer immediatly.

Change-Id: I42b949d21f98ee0f1d3156763cd723c3e9cabb67
This commit is contained in:
Jason Sams
2011-08-12 15:05:15 -07:00
parent 6e97ed2127
commit bfc7891bdd
7 changed files with 67 additions and 29 deletions

View File

@@ -245,20 +245,32 @@ void * Context::threadProc(void *vrsc) {
rsc->mRunning = true;
bool mDraw = true;
bool doWait = true;
uint64_t targetTime = rsc->getTime();
while (!rsc->mExit) {
mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
uint64_t waitTime = 0;
uint64_t now = rsc->getTime();
if (now < targetTime) {
waitTime = targetTime - now;
} else {
doWait = false;
}
mDraw |= rsc->mIO.playCoreCommands(rsc, doWait, waitTime);
mDraw &= (rsc->mRootScript.get() != NULL);
mDraw &= rsc->mHasSurface;
uint32_t targetTime = 0;
if (mDraw && rsc->mIsGraphicsContext) {
targetTime = rsc->runRootScript();
uint64_t delay = rsc->runRootScript() * 1000000;
targetTime = rsc->getTime() + delay;
doWait = delay != 0;
if (rsc->props.mLogVisual) {
rsc->displayDebugStats();
}
mDraw = targetTime && !rsc->mPaused;
mDraw = !rsc->mPaused;
rsc->timerSet(RS_TIMER_CLEAR_SWAP);
rsc->mHal.funcs.swap(rsc);
rsc->timerFrame();
@@ -266,12 +278,6 @@ void * Context::threadProc(void *vrsc) {
rsc->timerPrint();
rsc->timerReset();
}
if (targetTime > 1) {
int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
if (t > 0) {
usleep(t);
}
}
}
LOGV("%p, RS Thread exiting", rsc);

View File

@@ -129,21 +129,23 @@ void LocklessCommandFifo::flush() {
//dumpState("flush 2");
}
void LocklessCommandFifo::wait() {
bool LocklessCommandFifo::wait(uint64_t timeout) {
while (isEmpty() && !mInShutdown) {
mSignalToControl.set();
mSignalToWorker.wait();
return mSignalToWorker.wait(timeout);
}
return true;
}
const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData) {
const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData, uint64_t timeout) {
while (1) {
//dumpState("get");
wait();
if (mInShutdown) {
wait(timeout);
if (isEmpty() || mInShutdown) {
*command = 0;
*bytesData = 0;
return 0;
return NULL;
}
*command = reinterpret_cast<const uint16_t *>(mGet)[0];

View File

@@ -57,9 +57,9 @@ public:
void commitSync(uint32_t command, uint32_t bytes);
void flush();
void wait();
bool wait(uint64_t timeout = 0);
const void * get(uint32_t *command, uint32_t *bytesData);
const void * get(uint32_t *command, uint32_t *bytesData, uint64_t timeout = 0);
void next();
void makeSpace(uint32_t bytes);

View File

@@ -68,26 +68,43 @@ void Signal::set() {
}
}
void Signal::wait() {
bool Signal::wait(uint64_t timeout) {
int status;
bool ret = false;
status = pthread_mutex_lock(&mMutex);
if (status) {
LOGE("LocklessCommandFifo: error %i locking for condition.", status);
return;
return false;
}
if (!mSet) {
status = pthread_cond_wait(&mCondition, &mMutex);
if (status) {
LOGE("LocklessCommandFifo: error %i waiting on condition.", status);
if (!timeout) {
status = pthread_cond_wait(&mCondition, &mMutex);
} else {
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
status = pthread_cond_timeout_np(&mCondition, &mMutex, timeout / 1000000);
#else
// This is safe it will just make things less reponsive
status = pthread_cond_wait(&mCondition, &mMutex);
#endif
}
}
if (!status) {
mSet = false;
ret = true;
} else {
if (status != ETIMEDOUT) {
LOGE("LocklessCommandFifo: error %i waiting for condition.", status);
}
}
mSet = false;
status = pthread_mutex_unlock(&mMutex);
if (status) {
LOGE("LocklessCommandFifo: error %i unlocking for condition.", status);
}
return ret;
}

View File

@@ -31,7 +31,10 @@ public:
bool init();
void set();
void wait();
// returns true if the signal occured
// false for timeout
bool wait(uint64_t timeout = 0);
protected:
bool mSet;

View File

@@ -113,8 +113,10 @@ void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
}
bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait) {
bool ret = false;
uint64_t startTime = con->getTime();
while (!mToCore.isEmpty() || waitForCommand) {
uint32_t cmdID = 0;
uint32_t cmdSize = 0;
@@ -122,9 +124,17 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
if (con->props.mLogTimes) {
con->timerSet(Context::RS_TIMER_IDLE);
}
const void * data = mToCore.get(&cmdID, &cmdSize);
uint64_t delay = 0;
if (waitForCommand) {
delay = timeToWait - (con->getTime() - startTime);
if (delay > timeToWait) {
delay = 0;
}
}
const void * data = mToCore.get(&cmdID, &cmdSize, delay);
if (!cmdSize) {
// exception occured, probably shutdown.
// exception or timeout occurred.
return false;
}
if (con->props.mLogTimes) {

View File

@@ -37,7 +37,7 @@ public:
// Plays back commands from the client.
// Returns true if any commands were processed.
bool playCoreCommands(Context *con, bool waitForCommand);
bool playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait);
//LocklessCommandFifo mToCore;