diff --git a/src/Makefile.am b/src/Makefile.am
index 3a436f3a4ed2728fa3cab977057474ade60f0a05..6dc507a5bfb846fc19cd6d879e1c7721ca23fda9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,8 +26,8 @@ AM_LDFLAGS = $(LAPACK_LIBS) $(BLAS_LIBS) -version-info 0:0:0
 
 # Build the libgadgetsmp library
 lib_LTLIBRARIES = libgadgetsmp.la
-libgadgetsmp_la_SOURCES = space.c runner.c
+libgadgetsmp_la_SOURCES = space.c runner.c queue.c task.c cell.c
 
 # List required headers
-include_HEADERS = space.h runner.h lock.h
+include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h gadgetsmp.h
 
diff --git a/src/cell.c b/src/cell.c
new file mode 100644
index 0000000000000000000000000000000000000000..0092644a5a905e268b977ad9dedb4bc701a9f55f
--- /dev/null
+++ b/src/cell.c
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+/* Some standard headers. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+
+/* Local headers. */
+#include "cycle.h"
+#include "lock.h"
+#include "task.h"
+#include "part.h"
+#include "cell.h"
+
+
+/* Error macro. */
+#define error(s) { printf( "%s:%s:%i: %s\n" , __FILE__ , __FUNCTION__ , __LINE__ , s ); abort(); }
+
+
+/* The timers. */
+ticks cell_timer[ cell_timer_count ];
+
+
+/* Define the timer macros. */
+#ifdef TIMER_VERBOSE
+    #define TIMER
+#endif
+#ifdef TIMER
+    #define TIMER_TIC ticks tic = getticks();
+    #define TIMER_TOC(t) timer_toc( t , tic )
+    #define TIMER_TIC2 ticks tic2 = getticks();
+    #define TIMER_TOC2(t) timer_toc( t , tic2 )
+    #ifndef INLINE
+    # if __GNUC__ && !__GNUC_STDC_INLINE__
+    #  define INLINE extern inline
+    # else
+    #  define INLINE inline
+    # endif
+    #endif
+    INLINE ticks timer_toc ( int t , ticks tic ) {
+        ticks d = (getticks() - tic);
+        __sync_add_and_fetch( &cell_timer[t] , d );
+        return d;
+        }
+#else
+    #define TIMER_TIC
+    #define TIMER_TOC(t)
+#endif
+
+/**
+ * @brief Lock a cell and hold its parents.
+ *
+ * @param c The #cell.
+ */
+ 
+int cell_locktree( struct cell *c ) {
+
+    struct cell *finger, *finger2;
+    TIMER_TIC
+
+    /* First of all, try to lock this cell. */
+    if ( lock_trylock( &c->lock ) != 0 ) {
+        TIMER_TOC(cell_timer_tree);
+        return 1;
+        }
+        
+    /* Did somebody hold this cell in the meantime? */
+    if ( c->hold ) {
+        
+        /* Unlock this cell. */
+        if ( lock_unlock( &c->lock ) != 0 )
+            error( "Failed to unlock cell." );
+            
+        /* Admit defeat. */
+        TIMER_TOC(cell_timer_tree);
+        return 1;
+    
+        }
+        
+    /* Climb up the tree and lock/hold/unlock. */
+    for ( finger = c->parent ; finger != NULL ; finger = finger->parent ) {
+    
+        /* Lock this cell. */
+        if ( lock_trylock( &finger->lock ) != 0 )
+            break;
+            
+        /* Increment the hold. */
+        __sync_fetch_and_add( &finger->hold , 1 );
+        
+        /* Unlock the cell. */
+        if ( lock_unlock( &finger->lock ) != 0 )
+            error( "Failed to unlock cell." );
+    
+        }
+        
+    /* If we reached the top of the tree, we're done. */
+    if ( finger == NULL ) {
+        TIMER_TOC(cell_timer_tree);
+        return 0;
+        }
+        
+    /* Otherwise, we hit a snag. */
+    else {
+    
+        /* Undo the holds up to finger. */
+        for ( finger2 = c->parent ; finger2 != finger ; finger2 = finger2->parent )
+            __sync_fetch_and_sub( &finger2->hold , 1 );
+            
+        /* Unlock this cell. */
+        if ( lock_unlock( &c->lock ) != 0 )
+            error( "Failed to unlock cell." );
+            
+        /* Admit defeat. */
+        TIMER_TOC(cell_timer_tree);
+        return 1;
+    
+        }
+
+    }
+    
+    
+/**
+ * @brief Unock a cell's parents.
+ *
+ * @param c The #cell.
+ */
+ 
+void cell_unlocktree( struct cell *c ) {
+
+    struct cell *finger;
+    TIMER_TIC
+
+    /* First of all, try to unlock this cell. */
+    if ( lock_unlock( &c->lock ) != 0 )
+        error( "Failed to unlock cell." );
+        
+    /* Climb up the tree and unhold the parents. */
+    for ( finger = c->parent ; finger != NULL ; finger = finger->parent )
+        __sync_fetch_and_sub( &finger->hold , 1 );
+        
+    TIMER_TOC(cell_timer_tree);
+        
+    }
+    
+    
+/**
+ * @brief Sort the parts into eight bins along the given pivots.
+ *
+ * @param c The #cell array to be sorted.
+ */
+ 
+void cell_split ( struct cell *c  ) {
+
+    int i, j, k, kk;
+    struct part temp, *parts = c->parts;
+    int left[8], right[8];
+    double pivot[3];
+    
+    /* Init the pivot. */
+    for ( k = 0 ; k < 3 ; k++ )
+        pivot[k] = c->loc[k] + c->h[k]/2;
+    
+    /* Split along the x-axis. */
+    i = 0; j = c->count - 1;
+    while ( i <= j ) {
+        while ( i <= c->count-1 && parts[i].x[0] <= pivot[0] )
+            i += 1;
+        while ( j >= 0 && parts[j].x[0] > pivot[0] )
+            j -= 1;
+        if ( i < j ) {
+            temp = parts[i]; parts[i] = parts[j]; parts[j] = temp;
+            }
+        }
+    for ( k = 0 ; k <= j ; k++ )
+        if ( parts[k].x[0] > pivot[0] )
+            error( "cell_split: sorting failed." );
+    for ( k = i ; k < c->count ; k++ )
+        if ( parts[k].x[0] < pivot[0] )
+            error( "cell_split: sorting failed." );
+    left[1] = i; right[1] = c->count - 1;
+    left[0] = 0; right[0] = j;
+    
+    /* Split along the y axis, twice. */
+    for ( k = 1 ; k >= 0 ; k-- ) {
+        i = left[k]; j = right[k];
+        while ( i <= j ) {
+            while ( i <= right[k] && parts[i].x[1] <= pivot[1] )
+                i += 1;
+            while ( j >= left[k] && parts[j].x[1] > pivot[1] )
+                j -= 1;
+            if ( i < j ) {
+                temp = parts[i]; parts[i] = parts[j]; parts[j] = temp;
+                }
+            }
+        for ( kk = left[k] ; kk <= j ; kk++ )
+            if ( parts[kk].x[1] > pivot[1] ) {
+                printf( "cell_split: ival=[%i,%i], i=%i, j=%i.\n" , left[k] , right[k] , i , j );
+                error( "sorting failed (left)." );
+                }
+        for ( kk = i ; kk <= right[k] ; kk++ )
+            if ( parts[kk].x[1] < pivot[1] )
+                error( "sorting failed (right)." );
+        left[2*k+1] = i; right[2*k+1] = right[k];
+        left[2*k] = left[k]; right[2*k] = j;
+        }
+
+    /* Split along the z axis, four times. */
+    for ( k = 3 ; k >= 0 ; k-- ) {
+        i = left[k]; j = right[k];
+        while ( i <= j ) {
+            while ( i <= right[k] && parts[i].x[2] <= pivot[2] )
+                i += 1;
+            while ( j >= left[k] && parts[j].x[2] > pivot[2] )
+                j -= 1;
+            if ( i < j ) {
+                temp = parts[i]; parts[i] = parts[j]; parts[j] = temp;
+                }
+            }
+        for ( kk = left[k] ; kk <= j ; kk++ )
+            if ( parts[kk].x[2] > pivot[2] ) {
+                printf( "cell_split: ival=[%i,%i], i=%i, j=%i.\n" , left[k] , right[k] , i , j );
+                error( "sorting failed (left)." );
+                }
+        for ( kk = i ; kk <= right[k] ; kk++ )
+            if ( parts[kk].x[2] < pivot[2] ) {
+                printf( "cell_split: ival=[%i,%i], i=%i, j=%i.\n" , left[k] , right[k] , i , j );
+                error( "sorting failed (right)." );
+                }
+        left[2*k+1] = i; right[2*k+1] = right[k];
+        left[2*k] = left[k]; right[2*k] = j;
+        }
+        
+    /* Store the counts and offsets. */
+    for ( k = 0 ; k < 8 ; k++ ) {
+        c->progeny[k]->count = right[k] - left[k] + 1;
+        if ( c->progeny[k]->count < 0 )
+            abort();
+        c->progeny[k]->parts = &c->parts[ left[k] ];
+        }
+        
+    /* Verify a few sub-cells. */
+    /* for ( k = 0 ; k < c->progeny[0]->count ; k++ )
+        if ( c->progeny[0]->parts[k].x[0] > pivot[0] ||
+             c->progeny[0]->parts[k].x[1] > pivot[1] ||
+             c->progeny[0]->parts[k].x[2] > pivot[2] )
+            error( "Sorting failed (progeny=0)." );
+    for ( k = 0 ; k < c->progeny[1]->count ; k++ )
+        if ( c->progeny[1]->parts[k].x[0] > pivot[0] ||
+             c->progeny[1]->parts[k].x[1] > pivot[1] ||
+             c->progeny[1]->parts[k].x[2] <= pivot[2] )
+            error( "Sorting failed (progeny=1)." );
+    for ( k = 0 ; k < c->progeny[2]->count ; k++ )
+        if ( c->progeny[2]->parts[k].x[0] > pivot[0] ||
+             c->progeny[2]->parts[k].x[1] <= pivot[1] ||
+             c->progeny[2]->parts[k].x[2] > pivot[2] )
+            error( "Sorting failed (progeny=2)." ); */
+
+    }
+
+
diff --git a/src/cell.h b/src/cell.h
new file mode 100644
index 0000000000000000000000000000000000000000..0577d3c71c678ce56ca013915d3df18c87e50e2d
--- /dev/null
+++ b/src/cell.h
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+
+
+/* The queue timers. */
+enum {
+    cell_timer_none = 0,
+    cell_timer_tree,
+    cell_timer_count,
+    };
+extern ticks cell_timer[ cell_timer_count ];
+
+
+/* Structure to store the data of a single cell. */
+struct cell {
+
+    /* The cell location on the grid. */
+    double loc[3];
+    
+    /* The cell dimensions. */
+    double h[3];
+    
+    /* Max radii in this cell. */
+    double r_max;
+    
+    /* The depth of this cell in the tree. */
+    int depth, split;
+    
+    /* Nr of parts. */
+    int count;
+    
+    /* Pointers to the particle data. */
+    struct part *parts;
+    
+    /* Pointers for the sorted indices. */
+    struct entry *sort;
+    
+    /* Number of pairs associated with this cell. */
+    int nr_pairs;
+    
+    /* Pointers to the next level of cells. */
+    struct cell *progeny[8];
+    
+    /* Parent cell. */
+    struct cell *parent;
+    
+    /* The tasks computing this cell's sorts. */
+    struct task *sorts[14];
+    
+    /* Number of tasks this cell is waiting for and whether it is in use. */
+    int wait;
+    
+    /* Is the data of this cell being used in a sub-cell? */
+    int hold;
+    
+    /* Spin lock for various uses. */
+    lock_type lock;
+    
+    /* Linking pointer for "memory management". */
+    struct cell *next;
+
+    } __attribute__((aligned (64)));
+
+
+/* Function prototypes. */
+void cell_split ( struct cell *c  );
+int cell_locktree( struct cell *c );
+void cell_unlocktree( struct cell *c );
diff --git a/src/part.h b/src/part.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a95bf05992b8837dda93da5910e568360bc4499
--- /dev/null
+++ b/src/part.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+
+/* Some constants. */
+#define part_maxwait                    3
+#define part_maxunlock                  39
+
+
+/* Data of a single particle. */
+struct part {
+
+    /* Particle position. */
+    double x[3];
+    
+    /* Particle cutoff radius. */
+    float r;
+    
+    /* Particle time-step. */
+    float dt;
+    
+    /* Particle ID. */
+    int id;
+    
+    /* Number of pairwise interactions. */
+    double count, count_dh;
+    int icount;
+    
+    } __attribute__((aligned (32)));
+    
+
diff --git a/src/queue.c b/src/queue.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b6744c8b8083276001c2cea6ab636184649ef9c
--- /dev/null
+++ b/src/queue.c
@@ -0,0 +1,352 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+/* Some standard headers. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+#include <omp.h>
+#include <sched.h>
+
+/* Local headers. */
+#include "cycle.h"
+#include "lock.h"
+#include "task.h"
+#include "cell.h"
+#include "queue.h"
+
+/* Error macro. */
+#define error(s) { printf( "%s:%s:%i: %s\n" , __FILE__ , __FUNCTION__ , __LINE__ , s ); abort(); }
+
+/* Define the timer macros. */
+#ifdef TIMER_VERBOSE
+    #define TIMER
+#endif
+#ifdef TIMER
+    #define TIMER_TIC ticks tic = getticks();
+    #define TIMER_TOC(t) timer_toc( t , tic )
+    #define TIMER_TIC2 ticks tic2 = getticks();
+    #define TIMER_TOC2(t) timer_toc( t , tic2 )
+    #ifndef INLINE
+    # if __GNUC__ && !__GNUC_STDC_INLINE__
+    #  define INLINE extern inline
+    # else
+    #  define INLINE inline
+    # endif
+    #endif
+    INLINE ticks timer_toc ( int t , ticks tic ) {
+        ticks d = (getticks() - tic);
+        __sync_add_and_fetch( &queue_timer[t] , d );
+        return d;
+        }
+#else
+    #define TIMER_TIC
+    #define TIMER_TOC(t)
+#endif
+
+
+/* Counter macros. */
+#ifdef COUNTER
+    #define COUNT(c) ( __sync_add_and_fetch( &queue_counter[ c ] , 1 ) )
+#else
+    #define COUNT(c)
+#endif
+
+
+/* The timers. */
+ticks queue_timer[ queue_timer_count ];
+
+/* The counters. */
+int queue_counter[ queue_counter_count ];
+
+        
+
+/** 
+ * @brief Initialize the given queue.
+ *
+ * @param q The #queue.
+ * @param size The maximum size of the queue.
+ * @param tasks List of tasks to which the queue indices refer to.
+ */
+ 
+void queue_init ( struct queue *q , int size , struct task *tasks ) {
+    
+    /* Allocate the task list. */
+    q->size = size;
+    if ( ( q->tid = (int *)malloc( sizeof(int) * size ) ) == NULL )
+        error( "Failed to allocate queue tids." );
+    q->tasks = tasks;
+        
+    /* Init counters. */
+    q->count = 0;
+    q->next = 0;
+    
+    /* Init the queue lock. */
+    if ( lock_init( &q->lock ) != 0 )
+        error( "Failed to init queue lock." );
+
+    }
+
+
+/**
+ * @brief Get a task free of dependencies and conflicts.
+ *
+ * @param q The task #queue.
+ * @param blocking Block until access to the queue is granted.
+ * @param keep Remove the returned task from this queue.
+ */
+ 
+struct task *queue_gettask ( struct queue *q , int blocking , int keep ) {
+
+    int k, tid = -1, qcount, *qtid = q->tid;
+    lock_type *qlock = &q->lock;
+    struct task *qtasks = q->tasks, *res = NULL;
+    TIMER_TIC
+    
+    /* If there are no tasks, leave immediately. */
+    if ( q->next >= q->count ) {
+        TIMER_TOC(queue_timer_gettask);
+        return NULL;
+        }
+
+    /* Main loop, while there are tasks... */
+    while ( q->next < q->count ) {
+    
+        /* Grab the task lock. */
+        // if ( blocking ) {
+            if ( lock_lock( qlock ) != 0 )
+                error( "Locking the task_lock failed.\n" );
+        //     }
+        // else {
+        //     if ( lock_trylock( qlock ) != 0 )
+        //         break;
+        //     }
+            
+        /* Loop over the remaining task IDs. */
+        qcount = q->count;
+        for ( k = q->next ; k < qcount ; k++ ) {
+        
+            /* Put a finger on the task. */
+            res = &qtasks[ qtid[k] ];
+            
+            /* Is this task blocked? */
+            if ( res->wait )
+                continue;
+            
+            /* Different criteria for different types. */
+            if ( res->type == tid_self || (res->type == tid_sub && res->cj == NULL) ) {
+                if ( res->ci->hold || cell_locktree( res->ci ) != 0 )
+                    continue;
+                }
+            else if ( res->type == tid_pair || (res->type == tid_sub && res->cj != NULL) ) {
+                if ( res->ci->hold || res->cj->hold || res->ci->wait || res->cj->wait )
+                    continue;
+                if ( cell_locktree( res->ci ) != 0 )
+                    continue;
+                if ( cell_locktree( res->cj ) != 0 ) {
+                    cell_unlocktree( res->ci );
+                    continue;
+                    }
+                }
+            
+            /* If we made it this far, we're safe. */
+            break;
+        
+            } /* loop over the task IDs. */
+            
+        /* Did we get a task? */
+        if ( k < qcount ) {
+        
+            /* Do we need to swap? */
+            if ( k != q->next )
+                COUNT(queue_counter_swap);
+        
+            /* get the task ID. */
+            tid = qtid[k];
+        
+            /* Remove the task? */
+            if ( keep ) {
+            
+                /* Bubble-up. */
+                q->count = qcount - 1;
+                for ( ; k < qcount - 1 ; k++ )
+                    qtid[k] = qtid[k+1];
+            
+                }
+                
+            /* No, leave it in the queue. */
+            else {
+            
+                TIMER_TIC2
+
+                /* Bubble-down the task. */
+                while ( k > q->next ) {
+                    qtid[ k ] = qtid[ k-1 ];
+                    k -= 1;
+                    }
+                qtid[ q->next ] = tid;
+                
+                /* up the counter. */
+                q->next += 1;
+                
+                TIMER_TOC2(queue_timer_bubble);
+            
+                }
+            
+            }
+    
+        /* Release the task lock. */
+        if ( lock_unlock( qlock ) != 0 )
+            error( "Unlocking the task_lock failed.\n" );
+            
+        /* Leave? */
+        if ( tid >= 0 ) {
+            TIMER_TOC(queue_timer_gettask);
+            return &qtasks[tid];
+            }
+        else if ( !blocking )
+            break;
+    
+        } /* while there are tasks. */
+        
+    /* No beef. */
+    TIMER_TOC(queue_timer_gettask);
+    return NULL;
+
+    }
+
+
+/**
+ * @brief Sort the tasks IDs according to their weight and constraints.
+ *
+ * @param q The #queue.
+ */
+ 
+void queue_sort ( struct queue *q ) {
+
+    struct {
+        short int lo, hi;
+        } qstack[20];
+    int qpos, i, j, k, lo, hi, imin, temp;
+    int pivot_weight, pivot_wait;
+    int *weight, *wait;
+    int *data = q->tid;
+    struct task *t;
+        
+    /* Allocate and pre-compute each task's weight. */
+    if ( ( weight = (int *)alloca( sizeof(int) * q->count ) ) == NULL ||
+         ( wait = (int *)alloca( sizeof(int) * q->count ) ) == NULL )
+        error( "Failed to allocate weight buffer." );
+    for ( k = 0 ; k < q->count ; k++ ) {
+        t = &q->tasks[ q->tid[k] ];
+        switch ( t->type ) {
+            case tid_self:
+                wait[k] = t->rank;
+                weight[k] = 0; // t->ci->count * t->ci->count;
+                break;
+            case tid_pair:
+                wait[k] = t->rank;
+                weight[k] = 0; // t->ci->count * t->cj->count;
+                break;
+            case tid_sub:
+                wait[k] = t->rank;
+                weight[k] = 0; // (t->cj == NULL) ? t->ci->count * t->ci->count : t->ci->count * t->cj->count;
+                break;
+            case tid_sort:
+                wait[k] = t->rank;
+                weight[k] = 0; // t->ci->count;
+                break;
+            }
+        }
+        
+    /* Sort tasks. */
+    qstack[0].lo = 0; qstack[0].hi = q->count - 1; qpos = 0;
+    while ( qpos >= 0 ) {
+        lo = qstack[qpos].lo; hi = qstack[qpos].hi;
+        qpos -= 1;
+        if ( hi - lo < 15 ) {
+            for ( i = lo ; i < hi ; i++ ) {
+                imin = i;
+                for ( j = i+1 ; j <= hi ; j++ )
+                    if ( ( wait[ j ] < wait[ imin ] ) ||
+                         ( wait[ j ] == wait[ imin ] && weight[ j ] > weight[ imin ] ) )
+                if ( imin != i ) {
+                    temp = data[imin]; data[imin] = data[i]; data[i] = temp;
+                    temp = wait[imin]; wait[imin] = wait[i]; wait[i] = temp;
+                    temp = weight[imin]; weight[imin] = weight[i]; weight[i] = temp;
+                    }
+                }
+            }
+        else {
+            pivot_weight = weight[ ( lo + hi ) / 2 ];
+            pivot_wait = wait[ ( lo + hi ) / 2 ];
+            i = lo; j = hi;
+            while ( i <= j ) {
+                while ( ( wait[ i ] < pivot_wait ) ||
+                        ( wait[ i ] == pivot_wait && weight[ i ] > pivot_weight ) )
+                    i++;
+                while ( ( wait[ j ] > pivot_wait ) ||
+                        ( wait[ j ] == pivot_wait && weight[ j ] < pivot_weight ) )
+                    j--;
+                if ( i <= j ) {
+                    if ( i < j ) {
+                        temp = data[i]; data[i] = data[j]; data[j] = temp;
+                        temp = wait[i]; wait[i] = wait[j]; wait[j] = temp;
+                        temp = weight[i]; weight[i] = weight[j]; weight[j] = temp;
+                        }
+                    i += 1; j -= 1;
+                    }
+                }
+            if ( j > ( lo + hi ) / 2 ) {
+                if ( lo < j ) {
+                    qpos += 1;
+                    qstack[qpos].lo = lo;
+                    qstack[qpos].hi = j;
+                    }
+                if ( i < hi ) {
+                    qpos += 1;
+                    qstack[qpos].lo = i;
+                    qstack[qpos].hi = hi;
+                    }
+                }
+            else {
+                if ( i < hi ) {
+                    qpos += 1;
+                    qstack[qpos].lo = i;
+                    qstack[qpos].hi = hi;
+                    }
+                if ( lo < j ) {
+                    qpos += 1;
+                    qstack[qpos].lo = lo;
+                    qstack[qpos].hi = j;
+                    }
+                }
+            }
+        }
+                
+    }
+    
+    
diff --git a/src/queue.h b/src/queue.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f4b2670ada03cdc3fc97c3b645a744f26e56f2a
--- /dev/null
+++ b/src/queue.h
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+
+/* The queue timers themselves. */
+enum {
+    queue_timer_none = 0,
+    queue_timer_gettask,
+    queue_timer_bubble,
+    queue_timer_count,
+    };
+extern ticks queue_timer[ queue_timer_count ];
+
+
+/* Counters. */
+enum {
+    queue_counter_swap = 0,
+    queue_counter_count,
+    };
+extern int queue_counter[ queue_counter_count ];
+
+
+/** The queue struct. */
+struct queue {
+
+    /* The lock to access this queue. */
+    lock_type lock;
+
+    /* Size, count and next element. */
+    int size, count, next;
+    
+    /* The actual tasks to which the indices refer. */
+    struct task *tasks;
+    
+    /* The task indices. */
+    int *tid;
+
+    } __attribute__((aligned (64)));
+    
+
+/* Function prototypes. */
+struct task *queue_gettask ( struct queue *q , int blocking , int keep );
+void queue_init ( struct queue *q , int size , struct task *tasks );
+void queue_sort ( struct queue *q );
diff --git a/src/runner.c b/src/runner.c
index 53caf5f41d5e08780e28ea966ae25dbd785df754..644cbed88444d4963cb52207377911d6fb827ddf 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -34,7 +34,11 @@
 /* Local headers. */
 #include "cycle.h"
 #include "lock.h"
+#include "task.h"
+#include "part.h"
+#include "cell.h"
 #include "space.h"
+#include "queue.h"
 #include "runner.h"
 
 /* Error macro. */
@@ -70,117 +74,6 @@ const char runner_flip[27] = { 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1
                                0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; 
 
 
-/**
- * @brief Sort the tasks IDs according to their weight and constraints.
- *
- * @param q The #queue.
- */
- 
-void queue_sort ( struct queue *q ) {
-
-    struct {
-        short int lo, hi;
-        } qstack[20];
-    int qpos, i, j, k, lo, hi, imin, temp;
-    int pivot_weight, pivot_wait;
-    int *weight, *wait;
-    int *data = q->tid;
-    struct task *t;
-        
-    /* Allocate and pre-compute each task's weight. */
-    if ( ( weight = (int *)alloca( sizeof(int) * q->count ) ) == NULL ||
-         ( wait = (int *)alloca( sizeof(int) * q->count ) ) == NULL )
-        error( "Failed to allocate weight buffer." );
-    for ( k = 0 ; k < q->count ; k++ ) {
-        t = &q->tasks[ q->tid[k] ];
-        switch ( t->type ) {
-            case tid_self:
-                wait[k] = t->rank;
-                weight[k] = 0; // t->ci->count * t->ci->count;
-                break;
-            case tid_pair:
-                wait[k] = t->rank;
-                weight[k] = 0; // t->ci->count * t->cj->count;
-                break;
-            case tid_sub:
-                wait[k] = t->rank;
-                weight[k] = 0; // (t->cj == NULL) ? t->ci->count * t->ci->count : t->ci->count * t->cj->count;
-                break;
-            case tid_sort:
-                wait[k] = t->rank;
-                weight[k] = 0; // t->ci->count;
-                break;
-            }
-        }
-        
-    /* Sort tasks. */
-    qstack[0].lo = 0; qstack[0].hi = q->count - 1; qpos = 0;
-    while ( qpos >= 0 ) {
-        lo = qstack[qpos].lo; hi = qstack[qpos].hi;
-        qpos -= 1;
-        if ( hi - lo < 15 ) {
-            for ( i = lo ; i < hi ; i++ ) {
-                imin = i;
-                for ( j = i+1 ; j <= hi ; j++ )
-                    if ( ( wait[ j ] < wait[ imin ] ) ||
-                         ( wait[ j ] == wait[ imin ] && weight[ j ] > weight[ imin ] ) )
-                if ( imin != i ) {
-                    temp = data[imin]; data[imin] = data[i]; data[i] = temp;
-                    temp = wait[imin]; wait[imin] = wait[i]; wait[i] = temp;
-                    temp = weight[imin]; weight[imin] = weight[i]; weight[i] = temp;
-                    }
-                }
-            }
-        else {
-            pivot_weight = weight[ ( lo + hi ) / 2 ];
-            pivot_wait = wait[ ( lo + hi ) / 2 ];
-            i = lo; j = hi;
-            while ( i <= j ) {
-                while ( ( wait[ i ] < pivot_wait ) ||
-                        ( wait[ i ] == pivot_wait && weight[ i ] > pivot_weight ) )
-                    i++;
-                while ( ( wait[ j ] > pivot_wait ) ||
-                        ( wait[ j ] == pivot_wait && weight[ j ] < pivot_weight ) )
-                    j--;
-                if ( i <= j ) {
-                    if ( i < j ) {
-                        temp = data[i]; data[i] = data[j]; data[j] = temp;
-                        temp = wait[i]; wait[i] = wait[j]; wait[j] = temp;
-                        temp = weight[i]; weight[i] = weight[j]; weight[j] = temp;
-                        }
-                    i += 1; j -= 1;
-                    }
-                }
-            if ( j > ( lo + hi ) / 2 ) {
-                if ( lo < j ) {
-                    qpos += 1;
-                    qstack[qpos].lo = lo;
-                    qstack[qpos].hi = j;
-                    }
-                if ( i < hi ) {
-                    qpos += 1;
-                    qstack[qpos].lo = i;
-                    qstack[qpos].hi = hi;
-                    }
-                }
-            else {
-                if ( i < hi ) {
-                    qpos += 1;
-                    qstack[qpos].lo = i;
-                    qstack[qpos].hi = hi;
-                    }
-                if ( lo < j ) {
-                    qpos += 1;
-                    qstack[qpos].lo = lo;
-                    qstack[qpos].hi = j;
-                    }
-                }
-            }
-        }
-                
-    }
-    
-    
 /** 
  * @brief Sort the tasks in topological order over all queues.
  *
@@ -1083,102 +976,6 @@ void runner_dosort ( struct runner_thread *rt , struct cell *c , int flags ) {
     }
 
 
-/**
- * @brief Lock a cell and hold its parents.
- *
- * @param c The #cell.
- */
- 
-int cell_locktree( struct cell *c ) {
-
-    struct cell *finger, *finger2;
-    TIMER_TIC
-
-    /* First of all, try to lock this cell. */
-    if ( lock_trylock( &c->lock ) != 0 ) {
-        TIMER_TOC(runner_timer_tree);
-        return 1;
-        }
-        
-    /* Did somebody hold this cell in the meantime? */
-    if ( c->hold ) {
-        
-        /* Unlock this cell. */
-        if ( lock_unlock( &c->lock ) != 0 )
-            error( "Failed to unlock cell." );
-            
-        /* Admit defeat. */
-        TIMER_TOC(runner_timer_tree);
-        return 1;
-    
-        }
-        
-    /* Climb up the tree and lock/hold/unlock. */
-    for ( finger = c->parent ; finger != NULL ; finger = finger->parent ) {
-    
-        /* Lock this cell. */
-        if ( lock_trylock( &finger->lock ) != 0 )
-            break;
-            
-        /* Increment the hold. */
-        __sync_fetch_and_add( &finger->hold , 1 );
-        
-        /* Unlock the cell. */
-        if ( lock_unlock( &finger->lock ) != 0 )
-            error( "Failed to unlock cell." );
-    
-        }
-        
-    /* If we reached the top of the tree, we're done. */
-    if ( finger == NULL ) {
-        TIMER_TOC(runner_timer_tree);
-        return 0;
-        }
-        
-    /* Otherwise, we hit a snag. */
-    else {
-    
-        /* Undo the holds up to finger. */
-        for ( finger2 = c->parent ; finger2 != finger ; finger2 = finger2->parent )
-            __sync_fetch_and_sub( &finger2->hold , 1 );
-            
-        /* Unlock this cell. */
-        if ( lock_unlock( &c->lock ) != 0 )
-            error( "Failed to unlock cell." );
-            
-        /* Admit defeat. */
-        TIMER_TOC(runner_timer_tree);
-        return 1;
-    
-        }
-
-    }
-    
-    
-/**
- * @brief Unock a cell's parents.
- *
- * @param c The #cell.
- */
- 
-void cell_unlocktree( struct cell *c ) {
-
-    struct cell *finger;
-    TIMER_TIC
-
-    /* First of all, try to unlock this cell. */
-    if ( lock_unlock( &c->lock ) != 0 )
-        error( "Failed to unlock cell." );
-        
-    /* Climb up the tree and unhold the parents. */
-    for ( finger = c->parent ; finger != NULL ; finger = finger->parent )
-        __sync_fetch_and_sub( &finger->hold , 1 );
-        
-    TIMER_TOC(runner_timer_tree);
-        
-    }
-    
-    
 /**
  * @brief Implements a barrier for the #runner threads.
  *
@@ -1446,134 +1243,6 @@ void runner_run ( struct runner *r , int sort_queues ) {
     }
     
     
-/**
- * @brief Get a task free of dependencies and conflicts.
- *
- * @param q The task #queue.
- * @param blocking Block until access to the queue is granted.
- * @param keep Remove the returned task from this queue.
- */
- 
-struct task *queue_gettask ( struct queue *q , int blocking , int keep ) {
-
-    int k, tid = -1, qcount, *qtid = q->tid;
-    lock_type *qlock = &q->lock;
-    struct task *qtasks = q->tasks, *res = NULL;
-    TIMER_TIC
-    
-    /* If there are no tasks, leave immediately. */
-    if ( q->next >= q->count ) {
-        TIMER_TOC(runner_timer_queue);
-        return NULL;
-        }
-
-    /* Main loop, while there are tasks... */
-    while ( q->next < q->count ) {
-    
-        /* Grab the task lock. */
-        // if ( blocking ) {
-            if ( lock_lock( qlock ) != 0 )
-                error( "Locking the task_lock failed.\n" );
-        //     }
-        // else {
-        //     if ( lock_trylock( qlock ) != 0 )
-        //         break;
-        //     }
-            
-        /* Loop over the remaining task IDs. */
-        qcount = q->count;
-        for ( k = q->next ; k < qcount ; k++ ) {
-        
-            /* Put a finger on the task. */
-            res = &qtasks[ qtid[k] ];
-            
-            /* Is this task blocked? */
-            if ( res->wait )
-                continue;
-            
-            /* Different criteria for different types. */
-            if ( res->type == tid_self || (res->type == tid_sub && res->cj == NULL) ) {
-                if ( res->ci->hold || cell_locktree( res->ci ) != 0 )
-                    continue;
-                }
-            else if ( res->type == tid_pair || (res->type == tid_sub && res->cj != NULL) ) {
-                if ( res->ci->hold || res->cj->hold || res->ci->wait || res->cj->wait )
-                    continue;
-                if ( cell_locktree( res->ci ) != 0 )
-                    continue;
-                if ( cell_locktree( res->cj ) != 0 ) {
-                    cell_unlocktree( res->ci );
-                    continue;
-                    }
-                }
-            
-            /* If we made it this far, we're safe. */
-            break;
-        
-            } /* loop over the task IDs. */
-            
-        /* Did we get a task? */
-        if ( k < qcount ) {
-        
-            /* Do we need to swap? */
-            if ( k != q->next )
-                COUNT(runner_counter_swap);
-        
-            /* get the task ID. */
-            tid = qtid[k];
-        
-            /* Remove the task? */
-            if ( keep ) {
-            
-                /* Bubble-up. */
-                q->count = qcount - 1;
-                for ( ; k < qcount - 1 ; k++ )
-                    qtid[k] = qtid[k+1];
-            
-                }
-                
-            /* No, leave it in the queue. */
-            else {
-            
-                TIMER_TIC2
-
-                /* Bubble-down the task. */
-                while ( k > q->next ) {
-                    qtid[ k ] = qtid[ k-1 ];
-                    k -= 1;
-                    }
-                qtid[ q->next ] = tid;
-                
-                /* up the counter. */
-                q->next += 1;
-                
-                TIMER_TOC2(runner_timer_bubble);
-            
-                }
-            
-            }
-    
-        /* Release the task lock. */
-        if ( lock_unlock( qlock ) != 0 )
-            error( "Unlocking the task_lock failed.\n" );
-            
-        /* Leave? */
-        if ( tid >= 0 ) {
-            TIMER_TOC(runner_timer_queue);
-            return &qtasks[tid];
-            }
-        else if ( !blocking )
-            break;
-    
-        } /* while there are tasks. */
-        
-    /* No beef. */
-    TIMER_TOC(runner_timer_queue);
-    return NULL;
-
-    }
-
-
 /**
  * @brief init a runner with the given number of threads, queues, and
  *      the given policy.
@@ -1613,17 +1282,8 @@ void runner_init ( struct runner *r , struct space *s , int nr_threads , int nr_
     bzero( r->queues , nr_queues * sizeof(struct queue) );
         
     /* Init the queues. */
-    for ( k = 0 ; k < nr_queues ; k++ ) {
-        r->queues[k].size = s->nr_tasks;
-        if ( ( r->queues[k].tid = (int *)malloc( sizeof(int) * r->queues[k].size ) ) == NULL )
-            error( "Failed to allocate queue tids." );
-        r->queues[k].count = 0;
-        r->queues[k].next = 0;
-        if ( lock_init( &r->queues[k].lock ) != 0 )
-            error( "Failed to init queue lock." );
-        r->queues[k].tasks = s->tasks;
-        r->queues[k].r = r;
-        }
+    for ( k = 0 ; k < nr_queues ; k++ )
+        queue_init( &r->queues[k] , s->nr_tasks , s->tasks );
         
     /* Rank the tasks in topological order. */
     runner_ranktasks( r );
diff --git a/src/runner.h b/src/runner.h
index 07655fab5cc670212cb4d7286152fe06b3fcf521..1549fe7e16c642e8111311388b0a0d9e0ffae52d 100644
--- a/src/runner.h
+++ b/src/runner.h
@@ -237,27 +237,6 @@ __attribute__ ((always_inline)) INLINE void iact ( float r2 , float hi , float h
     
 
 
-/* A task queue. */
-struct queue {
-
-    /* The lock to access this queue. */
-    lock_type lock;
-
-    /* Size, count and next element. */
-    int size, count, next;
-    
-    /* The runner in which this queue lives. */
-    struct runner *r;
-    
-    /* The actual tasks to which the indices refer. */
-    struct task *tasks;
-    
-    /* The task indices. */
-    int *tid;
-
-    } __attribute__((aligned (64)));
-    
-
 /* A struct representing a runner's thread and its data. */
 struct runner_thread {
 
@@ -308,4 +287,3 @@ void runner_dopair ( struct runner_thread *rt , struct cell *ci , struct cell *c
 void runner_doself ( struct runner_thread *rt , struct cell *c );
 void runner_dosort ( struct runner_thread *rt , struct cell *c , int flag );
 void runner_init ( struct runner *r , struct space *s , int nr_threads , int nr_queues , int policy );
-struct task *queue_gettask ( struct queue *q , int blocking , int keep );
diff --git a/src/space.c b/src/space.c
index 90d6f44631c19433c9b8ec7132807a57e68d439c..c8795a0b9961f231fe9a2a96468f3a77d2222a95 100644
--- a/src/space.c
+++ b/src/space.c
@@ -32,6 +32,9 @@
 /* Local headers. */
 #include "cycle.h"
 #include "lock.h"
+#include "task.h"
+#include "part.h"
+#include "cell.h"
 #include "space.h"
 #include "runner.h"
 
@@ -44,9 +47,6 @@
 /* Split size. */
 int space_splitsize = space_splitsize_default;
 
-/* Task type names. */
-const char *taskID_names[tid_count] = { "none" , "sort" , "self" , "pair" , "sub" };
-
 /* Map shift vector to sortlist. */
 const int sortlistID[27] = {
     /* ( -1 , -1 , -1 ) */   0 ,
@@ -288,57 +288,6 @@ struct task *space_addtask ( struct space *s , int type , int flags , int wait ,
 
 
 
-/**
- * @brief Remove an unlock_task from the given task.
- *
- * @param ta The unlocking #task.
- * @param tb The #task that will be unlocked.
- */
- 
-void task_rmunlock( struct task *ta , struct task *tb ) {
-
-    int k;
-    
-    for ( k = 0 ; k < ta->nr_unlock_tasks ; k++ )
-        if ( ta->unlock_tasks[k] == tb ) {
-            ta->nr_unlock_tasks -= 1;
-            ta->unlock_tasks[k] = ta->unlock_tasks[ ta->nr_unlock_tasks ];
-            return;
-            }
-    error( "Task not found." );
-
-    }
-    
-
-/**
- * @brief Add an unlock_task to the given task.
- *
- * @param ta The unlocking #task.
- * @param tb The #task that will be unlocked.
- */
- 
-void task_addunlock( struct task *ta , struct task *tb ) {
-
-    int k;
-    
-    /* Bogus? */
-    if ( ta == NULL || tb == NULL )
-        return;
-    
-    /* Check if ta already unlocks tb. */
-    for ( k = 0 ; k < ta->nr_unlock_tasks ; k++ )
-        if ( ta->unlock_tasks[k] == tb )
-            return;
-
-    if ( ta->nr_unlock_tasks == task_maxunlock )
-        error( "Too many unlock_tasks in task." );
-        
-    ta->unlock_tasks[ ta->nr_unlock_tasks] = tb;
-    ta->nr_unlock_tasks += 1;
-
-    }
-    
-
 /**
  * @brief Split tasks that may be too large.
  *
@@ -1006,120 +955,6 @@ void space_maketasks ( struct space *s , int do_sort ) {
     }
     
     
-/**
- * @brief Sort the parts into eight bins along the given pivots.
- *
- * @param c The #cell array to be sorted.
- */
- 
-void cell_split ( struct cell *c  ) {
-
-    int i, j, k, kk;
-    struct part temp, *parts = c->parts;
-    int left[8], right[8];
-    double pivot[3];
-    
-    /* Init the pivot. */
-    for ( k = 0 ; k < 3 ; k++ )
-        pivot[k] = c->loc[k] + c->h[k]/2;
-    
-    /* Split along the x-axis. */
-    i = 0; j = c->count - 1;
-    while ( i <= j ) {
-        while ( i <= c->count-1 && parts[i].x[0] <= pivot[0] )
-            i += 1;
-        while ( j >= 0 && parts[j].x[0] > pivot[0] )
-            j -= 1;
-        if ( i < j ) {
-            temp = parts[i]; parts[i] = parts[j]; parts[j] = temp;
-            }
-        }
-    for ( k = 0 ; k <= j ; k++ )
-        if ( parts[k].x[0] > pivot[0] )
-            error( "cell_split: sorting failed." );
-    for ( k = i ; k < c->count ; k++ )
-        if ( parts[k].x[0] < pivot[0] )
-            error( "cell_split: sorting failed." );
-    left[1] = i; right[1] = c->count - 1;
-    left[0] = 0; right[0] = j;
-    
-    /* Split along the y axis, twice. */
-    for ( k = 1 ; k >= 0 ; k-- ) {
-        i = left[k]; j = right[k];
-        while ( i <= j ) {
-            while ( i <= right[k] && parts[i].x[1] <= pivot[1] )
-                i += 1;
-            while ( j >= left[k] && parts[j].x[1] > pivot[1] )
-                j -= 1;
-            if ( i < j ) {
-                temp = parts[i]; parts[i] = parts[j]; parts[j] = temp;
-                }
-            }
-        for ( kk = left[k] ; kk <= j ; kk++ )
-            if ( parts[kk].x[1] > pivot[1] ) {
-                printf( "cell_split: ival=[%i,%i], i=%i, j=%i.\n" , left[k] , right[k] , i , j );
-                error( "sorting failed (left)." );
-                }
-        for ( kk = i ; kk <= right[k] ; kk++ )
-            if ( parts[kk].x[1] < pivot[1] )
-                error( "sorting failed (right)." );
-        left[2*k+1] = i; right[2*k+1] = right[k];
-        left[2*k] = left[k]; right[2*k] = j;
-        }
-
-    /* Split along the z axis, four times. */
-    for ( k = 3 ; k >= 0 ; k-- ) {
-        i = left[k]; j = right[k];
-        while ( i <= j ) {
-            while ( i <= right[k] && parts[i].x[2] <= pivot[2] )
-                i += 1;
-            while ( j >= left[k] && parts[j].x[2] > pivot[2] )
-                j -= 1;
-            if ( i < j ) {
-                temp = parts[i]; parts[i] = parts[j]; parts[j] = temp;
-                }
-            }
-        for ( kk = left[k] ; kk <= j ; kk++ )
-            if ( parts[kk].x[2] > pivot[2] ) {
-                printf( "cell_split: ival=[%i,%i], i=%i, j=%i.\n" , left[k] , right[k] , i , j );
-                error( "sorting failed (left)." );
-                }
-        for ( kk = i ; kk <= right[k] ; kk++ )
-            if ( parts[kk].x[2] < pivot[2] ) {
-                printf( "cell_split: ival=[%i,%i], i=%i, j=%i.\n" , left[k] , right[k] , i , j );
-                error( "sorting failed (right)." );
-                }
-        left[2*k+1] = i; right[2*k+1] = right[k];
-        left[2*k] = left[k]; right[2*k] = j;
-        }
-        
-    /* Store the counts and offsets. */
-    for ( k = 0 ; k < 8 ; k++ ) {
-        c->progeny[k]->count = right[k] - left[k] + 1;
-        if ( c->progeny[k]->count < 0 )
-            abort();
-        c->progeny[k]->parts = &c->parts[ left[k] ];
-        }
-        
-    /* Verify a few sub-cells. */
-    /* for ( k = 0 ; k < c->progeny[0]->count ; k++ )
-        if ( c->progeny[0]->parts[k].x[0] > pivot[0] ||
-             c->progeny[0]->parts[k].x[1] > pivot[1] ||
-             c->progeny[0]->parts[k].x[2] > pivot[2] )
-            error( "Sorting failed (progeny=0)." );
-    for ( k = 0 ; k < c->progeny[1]->count ; k++ )
-        if ( c->progeny[1]->parts[k].x[0] > pivot[0] ||
-             c->progeny[1]->parts[k].x[1] > pivot[1] ||
-             c->progeny[1]->parts[k].x[2] <= pivot[2] )
-            error( "Sorting failed (progeny=1)." );
-    for ( k = 0 ; k < c->progeny[2]->count ; k++ )
-        if ( c->progeny[2]->parts[k].x[0] > pivot[0] ||
-             c->progeny[2]->parts[k].x[1] <= pivot[1] ||
-             c->progeny[2]->parts[k].x[2] > pivot[2] )
-            error( "Sorting failed (progeny=2)." ); */
-
-    }
-
 
 /**
  * @brief Split cells that contain too many particles.
diff --git a/src/space.h b/src/space.h
index ebe228d28e30780d1b041efaa4a1a1711827889c..61bf2e5503f52f0a21fc23eb5b533e897a224c0e 100644
--- a/src/space.h
+++ b/src/space.h
@@ -26,8 +26,6 @@
 #define space_splitratio                0.875
 #define space_splitsize_default         800
 #define space_dosub                     1
-#define task_maxwait                    3
-#define task_maxunlock                  39
 
 
 /* Split size. */
@@ -37,32 +35,6 @@ extern int space_splitsize;
 extern const int sortlistID[27];
     
     
-/* The different task IDs. */
-enum taskIDs {
-    tid_none = 0,
-    tid_sort,
-    tid_self,
-    tid_pair,
-    tid_sub,
-    tid_count
-    };
-extern const char *taskID_names[];
-    
-    
-/* Data of a task. */
-struct task {
-
-    int type, flags, wait, rank, done;
-    
-    int nr_unlock_tasks;
-    struct task *unlock_tasks[ task_maxunlock ];
-
-    int nr_unlock_cells;
-    struct cell *ci, *cj, *unlock_cells[2];
-    
-    } __attribute__((aligned (64)));
-
-
 /* Entry in a list of sorted indices. */
 struct entry {
     float d;
@@ -70,79 +42,6 @@ struct entry {
     };
     
     
-/* Data of a single particle. */
-struct part {
-
-    /* Particle position. */
-    double x[3];
-    
-    /* Particle cutoff radius. */
-    float r;
-    
-    /* Particle time-step. */
-    float dt;
-    
-    /* Particle ID. */
-    int id;
-    
-    /* Number of pairwise interactions. */
-    double count, count_dh;
-    int icount;
-    
-    } __attribute__((aligned (32)));
-    
-
-/* Structure to store the data of a single cell. */
-struct cell {
-
-    /* The cell location on the grid. */
-    double loc[3];
-    
-    /* The cell dimensions. */
-    double h[3];
-    
-    /* Max radii in this cell. */
-    double r_max;
-    
-    /* The depth of this cell in the tree. */
-    int depth, split;
-    
-    /* Nr of parts. */
-    int count;
-    
-    /* Pointers to the particle data. */
-    struct part *parts;
-    
-    /* Pointers for the sorted indices. */
-    struct entry *sort;
-    
-    /* Number of pairs associated with this cell. */
-    int nr_pairs;
-    
-    /* Pointers to the next level of cells. */
-    struct cell *progeny[8];
-    
-    /* Parent cell. */
-    struct cell *parent;
-    
-    /* The tasks computing this cell's sorts. */
-    struct task *sorts[14];
-    
-    /* Number of tasks this cell is waiting for and whether it is in use. */
-    int wait;
-    
-    /* Is the data of this cell being used in a sub-cell? */
-    int hold;
-    
-    /* Spin lock for various uses. */
-    lock_type lock;
-    
-    /* Linking pointer for "memory management". */
-    struct cell *next;
-
-    } __attribute__((aligned (64)));
-
-
 /* The space in which the cells reside. */
 struct space {
 
diff --git a/src/task.c b/src/task.c
new file mode 100644
index 0000000000000000000000000000000000000000..4e1a7db6f716c2ce0ee9ebd10264adcff56b865c
--- /dev/null
+++ b/src/task.c
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+/* Some standard headers. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+#include <omp.h>
+#include <sched.h>
+
+/* Local headers. */
+#include "cycle.h"
+#include "lock.h"
+#include "task.h"
+
+
+/* Task type names. */
+const char *taskID_names[tid_count] = { "none" , "sort" , "self" , "pair" , "sub" };
+
+
+/* Error macro. */
+#define error(s) { printf( "%s:%s:%i: %s\n" , __FILE__ , __FUNCTION__ , __LINE__ , s ); abort(); }
+
+
+/**
+ * @brief Remove an unlock_task from the given task.
+ *
+ * @param ta The unlocking #task.
+ * @param tb The #task that will be unlocked.
+ */
+ 
+void task_rmunlock( struct task *ta , struct task *tb ) {
+
+    int k;
+    
+    for ( k = 0 ; k < ta->nr_unlock_tasks ; k++ )
+        if ( ta->unlock_tasks[k] == tb ) {
+            ta->nr_unlock_tasks -= 1;
+            ta->unlock_tasks[k] = ta->unlock_tasks[ ta->nr_unlock_tasks ];
+            return;
+            }
+    error( "Task not found." );
+
+    }
+    
+
+/**
+ * @brief Add an unlock_task to the given task.
+ *
+ * @param ta The unlocking #task.
+ * @param tb The #task that will be unlocked.
+ */
+ 
+void task_addunlock( struct task *ta , struct task *tb ) {
+
+    int k;
+    
+    /* Bogus? */
+    if ( ta == NULL || tb == NULL )
+        return;
+    
+    /* Check if ta already unlocks tb. */
+    for ( k = 0 ; k < ta->nr_unlock_tasks ; k++ )
+        if ( ta->unlock_tasks[k] == tb )
+            return;
+
+    if ( ta->nr_unlock_tasks == task_maxunlock )
+        error( "Too many unlock_tasks in task." );
+        
+    ta->unlock_tasks[ ta->nr_unlock_tasks] = tb;
+    ta->nr_unlock_tasks += 1;
+
+    }
+    
+
diff --git a/src/task.h b/src/task.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d5d3422b0c91c3eaee2becc04078cbc76dd1d5c
--- /dev/null
+++ b/src/task.h
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * This file is part of GadgetSMP.
+ * Coypright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ ******************************************************************************/
+
+
+/* Some constants. */
+#define task_maxwait                    3
+#define task_maxunlock                  39
+
+
+/* The different task IDs. */
+enum taskIDs {
+    tid_none = 0,
+    tid_sort,
+    tid_self,
+    tid_pair,
+    tid_sub,
+    tid_count
+    };
+    
+extern const char *taskID_names[];
+    
+    
+/* Data of a task. */
+struct task {
+
+    int type, flags, wait, rank, done;
+    
+    int nr_unlock_tasks;
+    struct task *unlock_tasks[ task_maxunlock ];
+
+    int nr_unlock_cells;
+    struct cell *ci, *cj, *unlock_cells[2];
+    
+    } __attribute__((aligned (64)));
+
+
+/* Function prototypes. */
+void task_rmunlock( struct task *ta , struct task *tb );
+void task_addunlock( struct task *ta , struct task *tb );