Replace spins with proper pthread conditions.
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 7248ecc..2a5f65d 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -130,14 +130,10 @@
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);
}
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index 67ab434..37ec14b 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -37,16 +37,8 @@
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 @@
mPut += ((sizeInBytes + 3) & ~3) + 4;
//dumpState("commit 2");
+ mSignalToWorker.set();
}
void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes)
@@ -118,7 +111,7 @@
{
//dumpState("flush 1");
while(mPut != mGet) {
- usleep(1);
+ mSignalToControl.wait();
}
//dumpState("flush 2");
}
@@ -126,8 +119,10 @@
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 @@
{
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 @@
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);
+ }
+}
diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h
index ddef382..2f4d5c5 100644
--- a/libs/rs/rsLocklessFifo.h
+++ b/libs/rs/rsLocklessFifo.h
@@ -41,14 +41,32 @@
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);
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 23c808a..5641581 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -34,16 +34,17 @@
{
}
-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);
diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h
index ae2ffc0..973ee05 100644
--- a/libs/rs/rsThreadIO.h
+++ b/libs/rs/rsThreadIO.h
@@ -37,7 +37,7 @@
// 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;