Set thread names to help debugging.

Have our worker threads call pthread_setname_np() on Linux and Android,
so that they can be easily identified in the thread listing of a
debugger.

BUG=2167

Change-Id: If04b1fa630e82da6f40c9c730eb62cf386fc5a0f
diff --git a/aom_util/aom_thread.c b/aom_util/aom_thread.c
index cae9f5e..c5a1fab 100644
--- a/aom_util/aom_thread.c
+++ b/aom_util/aom_thread.c
@@ -14,6 +14,10 @@
 // Original source:
 //  https://chromium.googlesource.com/webm/libwebp
 
+// Enable GNU extensions in glibc so that we can call pthread_setname_np().
+// This must be before any #include statements.
+#define _GNU_SOURCE
+
 #include <assert.h>
 #include <string.h>  // for memset()
 
@@ -34,6 +38,18 @@
 
 static THREADFN thread_loop(void *ptr) {
   AVxWorker *const worker = (AVxWorker *)ptr;
+#if defined(__GLIBC__) || defined(__BIONIC__)
+  if (worker->thread_name) {
+    // Android and recent versions of glibc on Linux have a form of
+    // pthread_setname_np().
+    // Linux requires names (with nul) fit in 16 chars, otherwise
+    // pthread_setname_np() fails with ERANGE (34).
+    char thread_name[16];
+    strncpy(thread_name, worker->thread_name, sizeof(thread_name));
+    thread_name[sizeof(thread_name) - 1] = '\0';
+    pthread_setname_np(pthread_self(), thread_name);
+  }
+#endif
   int done = 0;
   while (!done) {
     pthread_mutex_lock(&worker->impl_->mutex_);
diff --git a/aom_util/aom_thread.h b/aom_util/aom_thread.h
index f14c1ac..5660a5d 100644
--- a/aom_util/aom_thread.h
+++ b/aom_util/aom_thread.h
@@ -380,6 +380,10 @@
 typedef struct {
   AVxWorkerImpl *impl_;
   AVxWorkerStatus status_;
+  // Thread name for the debugger. If not NULL, must point to a string that
+  // outlives the worker thread. For portability, use a name <= 15 characters
+  // long (not including the terminating NUL character).
+  const char *thread_name;
   AVxWorkerHook hook;  // hook to call
   void *data1;         // first argument passed to 'hook'
   void *data2;         // second argument passed to 'hook'
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index 4a66310..69e0e86 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -402,6 +402,7 @@
     AVxWorker *const worker = &ctx->frame_workers[i];
     FrameWorkerData *frame_worker_data = NULL;
     winterface->init(worker);
+    worker->thread_name = "aom frame worker";
     worker->data1 = aom_memalign(32, sizeof(FrameWorkerData));
     if (worker->data1 == NULL) {
       set_error_detail(ctx, "Failed to allocate frame_worker_data");
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 6556a9e..ba0f7f2 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -3766,6 +3766,7 @@
       ++pbi->num_workers;
 
       winterface->init(worker);
+      worker->thread_name = "aom tile worker";
       if (worker_idx < num_threads - 1 && !winterface->reset(worker)) {
         aom_internal_error(&cm->error, AOM_CODEC_ERROR,
                            "Tile decoder thread creation failed");
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index a5f4fd6..6646ac8 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -126,6 +126,7 @@
   cm->error.setjmp = 0;
 
   aom_get_worker_interface()->init(&pbi->lf_worker);
+  pbi->lf_worker.thread_name = "aom lf worker";
 
   return pbi;
 }
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index e8ac30b..4aae868 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -64,6 +64,7 @@
 
     ++cpi->num_workers;
     winterface->init(worker);
+    worker->thread_name = "aom enc worker";
 
     thread_data->cpi = cpi;