drm_hwcomposer: add optional timeout for WaitForSignalOrExitLocked

Change-Id: I5beef0833cc0a384aa76e821694183e024a8850c
diff --git a/worker.cpp b/worker.cpp
index e169911..1cebedc 100644
--- a/worker.cpp
+++ b/worker.cpp
@@ -23,11 +23,14 @@
 #include <stdlib.h>
 #include <sys/resource.h>
 #include <sys/signal.h>
+#include <time.h>
 
 #include <cutils/log.h>
 
 namespace android {
 
+static const int64_t kBillion = 1000000000LL;
+
 Worker::Worker(const char *name, int priority)
     : name_(name), priority_(priority), exit_(false), initialized_(false) {
 }
@@ -42,7 +45,10 @@
 }
 
 int Worker::InitWorker() {
-  int ret = pthread_cond_init(&cond_, NULL);
+  pthread_condattr_t cond_attr;
+  pthread_condattr_init(&cond_attr);
+  pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
+  int ret = pthread_cond_init(&cond_, &cond_attr);
   if (ret) {
     ALOGE("Failed to int thread %s condition %d", name_.c_str(), ret);
     return ret;
@@ -128,11 +134,25 @@
   return exit_ret;
 }
 
-int Worker::WaitForSignalOrExitLocked() {
+int Worker::WaitForSignalOrExitLocked(int64_t max_nanoseconds) {
   if (exit_)
     return -EINTR;
 
-  int ret = pthread_cond_wait(&cond_, &lock_);
+  int ret = 0;
+  if (max_nanoseconds < 0) {
+    ret = pthread_cond_wait(&cond_, &lock_);
+  } else {
+    struct timespec abs_deadline;
+    ret = clock_gettime(CLOCK_MONOTONIC, &abs_deadline);
+    if (ret)
+      return ret;
+    int64_t nanos = (int64_t)abs_deadline.tv_nsec + max_nanoseconds;
+    abs_deadline.tv_sec += nanos / kBillion;
+    abs_deadline.tv_nsec = nanos % kBillion;
+    ret = pthread_cond_timedwait(&cond_, &lock_, &abs_deadline);
+    if (ret == ETIMEDOUT)
+      ret = -ETIMEDOUT;
+  }
 
   if (exit_)
     return -EINTR;
diff --git a/worker.h b/worker.h
index 492693c..7015178 100644
--- a/worker.h
+++ b/worker.h
@@ -18,6 +18,7 @@
 #define ANDROID_WORKER_H_
 
 #include <pthread.h>
+#include <stdint.h>
 #include <string>
 
 namespace android {
@@ -46,10 +47,12 @@
   virtual void Routine() = 0;
 
   /*
-   * Must be called with the lock acquired.
-   * Returns -EINTR if interrupted by exit request
+   * Must be called with the lock acquired. max_nanoseconds may be negative to
+   * indicate infinite timeout, otherwise it indicates the maximum time span to
+   * wait for a signal before returning.
+   * Returns -EINTR if interrupted by exit request, or -ETIMEDOUT if timed out
    */
-  int WaitForSignalOrExitLocked();
+  int WaitForSignalOrExitLocked(int64_t max_nanoseconds = -1);
 
  private:
   static void *InternalRoutine(void *worker);