Replace spins with proper pthread conditions.
This commit is contained in:
@@ -130,14 +130,10 @@ void * Context::threadProc(void *vrsc)
|
||||
rsc->mRunning = true;
|
||||
bool mDraw = true;
|
||||
while (!rsc->mExit) {
|
||||
mDraw |= gIO->playCoreCommands(rsc);
|
||||
mDraw |= gIO->playCoreCommands(rsc, !mDraw);
|
||||
mDraw &= (rsc->mRootScript.get() != NULL);
|
||||
|
||||
if (!mDraw || !rsc->mRootScript.get()) {
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rsc->mRootScript.get()) {
|
||||
if (mDraw) {
|
||||
mDraw = rsc->runRootScript();
|
||||
eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
|
||||
}
|
||||
|
||||
@@ -37,16 +37,8 @@ bool LocklessCommandFifo::init(uint32_t sizeInBytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
int status = pthread_mutex_init(&mMutex, NULL);
|
||||
if (status) {
|
||||
LOGE("LocklessFifo mutex init failure");
|
||||
free(mBuffer);
|
||||
return false;
|
||||
}
|
||||
status = pthread_cond_init(&mCondition, NULL);
|
||||
if (status) {
|
||||
LOGE("LocklessFifo condition init failure");
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
if (!mSignalToControl.init() || !mSignalToWorker.init()) {
|
||||
LOGE("Signal setup failed");
|
||||
free(mBuffer);
|
||||
return false;
|
||||
}
|
||||
@@ -106,6 +98,7 @@ void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes)
|
||||
mPut += ((sizeInBytes + 3) & ~3) + 4;
|
||||
//dumpState("commit 2");
|
||||
|
||||
mSignalToWorker.set();
|
||||
}
|
||||
|
||||
void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes)
|
||||
@@ -118,7 +111,7 @@ void LocklessCommandFifo::flush()
|
||||
{
|
||||
//dumpState("flush 1");
|
||||
while(mPut != mGet) {
|
||||
usleep(1);
|
||||
mSignalToControl.wait();
|
||||
}
|
||||
//dumpState("flush 2");
|
||||
}
|
||||
@@ -126,8 +119,10 @@ void LocklessCommandFifo::flush()
|
||||
const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData)
|
||||
{
|
||||
while(1) {
|
||||
//dumpState("get");
|
||||
while(isEmpty()) {
|
||||
usleep(10);
|
||||
mSignalToControl.set();
|
||||
mSignalToWorker.wait();
|
||||
}
|
||||
//dumpState("get 3");
|
||||
|
||||
@@ -149,6 +144,9 @@ void LocklessCommandFifo::next()
|
||||
{
|
||||
uint32_t bytes = reinterpret_cast<const uint16_t *>(mGet)[1];
|
||||
mGet += ((bytes + 3) & ~3) + 4;
|
||||
if (isEmpty()) {
|
||||
mSignalToControl.set();
|
||||
}
|
||||
//dumpState("next");
|
||||
}
|
||||
|
||||
@@ -179,4 +177,79 @@ void LocklessCommandFifo::dumpState(const char *s) const
|
||||
LOGE("%s put %p, get %p, buf %p, end %p", s, mPut, mGet, mBuffer, mEnd);
|
||||
}
|
||||
|
||||
LocklessCommandFifo::Signal::Signal()
|
||||
{
|
||||
mSet = true;
|
||||
}
|
||||
|
||||
LocklessCommandFifo::Signal::~Signal()
|
||||
{
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
pthread_cond_destroy(&mCondition);
|
||||
}
|
||||
|
||||
bool LocklessCommandFifo::Signal::init()
|
||||
{
|
||||
int status = pthread_mutex_init(&mMutex, NULL);
|
||||
if (status) {
|
||||
LOGE("LocklessFifo mutex init failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
status = pthread_cond_init(&mCondition, NULL);
|
||||
if (status) {
|
||||
LOGE("LocklessFifo condition init failure");
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocklessCommandFifo::Signal::set()
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_lock(&mMutex);
|
||||
if (status) {
|
||||
LOGE("LocklessCommandFifo: error %i locking for set condition.", status);
|
||||
return;
|
||||
}
|
||||
|
||||
mSet = true;
|
||||
|
||||
status = pthread_cond_signal(&mCondition);
|
||||
if (status) {
|
||||
LOGE("LocklessCommandFifo: error %i on set condition.", status);
|
||||
}
|
||||
|
||||
status = pthread_mutex_unlock(&mMutex);
|
||||
if (status) {
|
||||
LOGE("LocklessCommandFifo: error %i unlocking for set condition.", status);
|
||||
}
|
||||
}
|
||||
|
||||
void LocklessCommandFifo::Signal::wait()
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_lock(&mMutex);
|
||||
if (status) {
|
||||
LOGE("LocklessCommandFifo: error %i locking for condition.", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mSet) {
|
||||
status = pthread_cond_wait(&mCondition, &mMutex);
|
||||
if (status) {
|
||||
LOGE("LocklessCommandFifo: error %i waiting on condition.", status);
|
||||
}
|
||||
}
|
||||
mSet = false;
|
||||
|
||||
status = pthread_mutex_unlock(&mMutex);
|
||||
if (status) {
|
||||
LOGE("LocklessCommandFifo: error %i unlocking for condition.", status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,14 +41,32 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
class Signal {
|
||||
public:
|
||||
Signal();
|
||||
~Signal();
|
||||
|
||||
bool init();
|
||||
|
||||
void set();
|
||||
void wait();
|
||||
|
||||
protected:
|
||||
bool mSet;
|
||||
pthread_mutex_t mMutex;
|
||||
pthread_cond_t mCondition;
|
||||
};
|
||||
|
||||
uint8_t * volatile mPut;
|
||||
uint8_t * volatile mGet;
|
||||
uint8_t * mBuffer;
|
||||
uint8_t * mEnd;
|
||||
uint8_t mSize;
|
||||
|
||||
pthread_mutex_t mMutex;
|
||||
pthread_cond_t mCondition;
|
||||
Signal mSignalToWorker;
|
||||
Signal mSignalToControl;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
void * reserve(uint32_t bytes);
|
||||
|
||||
@@ -34,16 +34,17 @@ ThreadIO::~ThreadIO()
|
||||
{
|
||||
}
|
||||
|
||||
bool ThreadIO::playCoreCommands(Context *con)
|
||||
bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand)
|
||||
{
|
||||
//LOGE("playCoreCommands 1");
|
||||
uint32_t cmdID = 0;
|
||||
uint32_t cmdSize = 0;
|
||||
bool ret = false;
|
||||
while(!mToCore.isEmpty()) {
|
||||
while(!mToCore.isEmpty() || waitForCommand) {
|
||||
ret = true;
|
||||
//LOGE("playCoreCommands 2");
|
||||
const void * data = mToCore.get(&cmdID, &cmdSize);
|
||||
waitForCommand = false;
|
||||
//LOGE("playCoreCommands 3 %i %i", cmdID, cmdSize);
|
||||
|
||||
gPlaybackFuncs[cmdID](con, data);
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
|
||||
// Plays back commands from the client.
|
||||
// Returns true if any commands were processed.
|
||||
bool playCoreCommands(Context *con);
|
||||
bool playCoreCommands(Context *con, bool waitForCommand);
|
||||
|
||||
|
||||
LocklessCommandFifo mToCore;
|
||||
|
||||
Reference in New Issue
Block a user