Index: trunk/psLib/src/sys/psThread.c
===================================================================
--- trunk/psLib/src/sys/psThread.c	(revision 28138)
+++ trunk/psLib/src/sys/psThread.c	(revision 28140)
@@ -21,5 +21,10 @@
 #define TASK_BUCKETS 8                  // Number of hash buckets for task list
 
+// Mutex covers:
+// * pending queue
+// * done queue
+// * thread->busy states
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // Mutex for locking threads
+
 static psList *pending = NULL;          // queue of pending jobs
 static psList *done = NULL;             // queue of done jobs
@@ -28,5 +33,4 @@
 static psArray *tsd = NULL;             // Thread-specific data
 
-
 /***** basic thread functions *****/
 
@@ -121,7 +125,5 @@
     }
 
-    psThreadLock();
     psThreadJob *job = psListGetAndRemove(pending, PS_LIST_HEAD);
-    psThreadUnlock();
     return job;
 }
@@ -134,7 +136,5 @@
     }
 
-    psThreadLock();
     psThreadJob *job = psListGetAndRemove(done, PS_LIST_HEAD);
-    psThreadUnlock();
     return job;
 }
@@ -198,8 +198,13 @@
         // we have to lock here so the job queue cannot be empty yet no threads busy
         psThreadJob *job = NULL;        // Job to process
+        psThreadLock();
         while ((job = psThreadJobGetPending()) == NULL) {
+            // Unlock while sleeping, then lock to read the pending queue again
+            psThreadUnlock();
             usleep(THREAD_WAIT);
+            psThreadLock();
         }
         self->busy = true;
+        psThreadUnlock();
 
         psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
@@ -215,5 +220,4 @@
         psListAdd(done, PS_LIST_TAIL, job);
         psFree(job);
-        psThreadUnlock();
 
         if (!status) {
@@ -221,4 +225,5 @@
         }
         self->busy = false;
+        psThreadUnlock();
     }
 }
@@ -253,5 +258,5 @@
 }
 
-// Harvest jobs from the
+// Harvest jobs from the done list
 static void psThreadJobHarvest(void)
 {
@@ -270,4 +275,5 @@
         // Ensure everything is harvested, if requested
         if (harvest) {
+            // No threads, no no need to lock
             psThreadJobHarvest();
         }
@@ -284,4 +290,6 @@
         }
 
+        psThreadLock();
+
         // Harvest jobs in the background, if requested
         if (harvest) {
@@ -289,5 +297,4 @@
         }
 
-#if 0 // Thread state doesn't matter, only the pending job queue
         // are all threads idle?
         for (int i = 0; i < pool->n; i++) {
@@ -298,19 +305,17 @@
             }
         }
-#endif
-
-        psThreadLock();
-        bool more = (pending && pending->head) ? true : false; // More to process?
-        psThreadUnlock();
-
-        if (!more) {
-            // Nothing in the queue
+
+        if (!pending || !pending->head) {
+            // Nothing in the queue and nothing more to add
             // Ensure everything is harvested, if requested
             if (harvest) {
                 psThreadJobHarvest();
             }
+            psThreadUnlock();
             return true;
         }
 
+    SLEEP:
+        psThreadUnlock();
         usleep(THREAD_WAIT);
     }
