From 26dc003b9ca80ca56ce203bfda23a5d01ff4b404 Mon Sep 17 00:00:00 2001
From: Pedro Gonnet <pedro.gonnet@durham.ac.uk>
Date: Mon, 3 Dec 2012 20:19:51 +0000
Subject: [PATCH] better task selection in queues.

Former-commit-id: 23fa519ca82863e510757674d30856106b9b62fa
---
 src/cell.c  |  2 +-
 src/queue.c | 24 +++++++++++++++---------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/cell.c b/src/cell.c
index c8fb2901cb..bfcecc94d9 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -83,7 +83,7 @@ int cell_locktree( struct cell *c ) {
     TIMER_TIC
 
     /* First of all, try to lock this cell. */
-    if ( lock_trylock( &c->lock ) != 0 ) {
+    if ( c->hold || lock_trylock( &c->lock ) != 0 ) {
         TIMER_TOC(cell_timer_tree);
         return 1;
         }
diff --git a/src/queue.c b/src/queue.c
index 79edee4d28..320d604a94 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -272,6 +272,7 @@ struct task *queue_gettask ( struct queue *q , int rid , int blocking , int keep
     int k, tid = -1, qcount, *qtid = q->tid;
     lock_type *qlock = &q->lock;
     struct task *qtasks = q->tasks, *res = NULL;
+    struct cell *ci_best = NULL, *cj_best = NULL;
     int ind_best, score_best = -1, score;
     TIMER_TIC
     
@@ -312,34 +313,39 @@ struct task *queue_gettask ( struct queue *q , int rid , int blocking , int keep
                 score = ( res->ci->owner == rid ) + ( res->cj->owner == rid );
             if ( score <= score_best )
                 continue;
-            
-            /* Different criteria for different types. */
+                
+            /* Try to lock ci. */
             if ( res->type == task_type_self || (res->type == task_type_sub && res->cj == NULL) ) {
-                if ( res->ci->hold || cell_locktree( res->ci ) != 0 )
+                if ( res->ci != ci_best && res->ci != cj_best && cell_locktree( res->ci ) != 0 )
                     continue;
                 }
             else if ( res->type == task_type_pair || (res->type == task_type_sub && res->cj != NULL) ) {
                 if ( res->ci->hold || res->cj->hold || res->ci->wait || res->cj->wait )
                     continue;
-                if ( cell_locktree( res->ci ) != 0 )
+                if ( res->ci != ci_best && res->ci != cj_best && cell_locktree( res->ci ) != 0 )
                     continue;
-                if ( cell_locktree( res->cj ) != 0 ) {
-                    cell_unlocktree( res->ci );
+                if ( res->cj != ci_best && res->cj != cj_best && cell_locktree( res->cj ) != 0 ) {
+                    if ( res->ci != ci_best && res->ci != cj_best )
+                        cell_unlocktree( res->ci );
                     continue;
                     }
                 }
-                
+            
             /* If we owned a previous task, unlock it. */
             if ( ind_best >= 0 ) {
                 res = &qtasks[ qtid[ ind_best ] ];
                 if ( res->type == task_type_self || res->type == task_type_pair || res->type == task_type_sub )
-                    cell_unlocktree( res->ci );
+                    if ( res->ci != ci_best && res->ci != cj_best )
+                        cell_unlocktree( res->ci );
                 if ( res->type == task_type_pair || (res->type == task_type_sub && res->cj != NULL) )
-                    cell_unlocktree( res->cj );
+                    if ( res->cj != ci_best && res->cj != cj_best )
+                        cell_unlocktree( res->cj );
                 }
             
             /* If we made it this far, we're safe. */
             ind_best = k;
+            ci_best = qtasks[ qtid[ k ] ].ci;
+            cj_best = qtasks[ qtid[ k ] ].cj;
             score_best = score;
             
             /* Should we bother looking any farther? */
-- 
GitLab