Index: trunk/kernel/kern/dqdt.c
===================================================================
--- trunk/kernel/kern/dqdt.c	(revision 582)
+++ trunk/kernel/kern/dqdt.c	(revision 583)
@@ -28,4 +28,5 @@
 #include <hal_atomic.h>
 #include <hal_remote.h>
+#include <thread.h>
 #include <printk.h>
 #include <chdev.h>
@@ -54,6 +55,6 @@
 
     // display node content
-	nolock_printk("- level %d in cluster %x (node %x) : threads = %x / pages = %x\n",
-    node.level, GET_CXY( node_xp ), GET_PTR( node_xp ), node.threads, node.pages );
+	nolock_printk("- level %d / cluster %x : threads = %x / pages = %x / clusters %d / cores %d\n",
+    node.level, GET_CXY( node_xp ), node.threads, node.pages, node.clusters, node.cores );
 
     // recursive call on children if node is not terminal
@@ -102,9 +103,8 @@
 // This static function initializes recursively, from top to bottom, the quad-tree
 // infrastructure. The DQDT nodes are allocated as global variables in each local
-//  cluster manager. At each level in the quad-tree, this function initializes the
-// parent DQDT node in the cluster identified by the <cxy> and <level> arguments.
-// A each level, it selects in each child macro-cluster the precise cluster where 
-// will be placed the the subtree root node, and call recursively itself to
-// initialize the child node in this cluster.
+// cluster manager. At each level in the quad-tree, this function initializes the
+// node identified by the <cxy> and <level> arguments, selects in each child 
+// macro-cluster the precise cluster where will be placed the subtree root node, 
+// and call recursively itself to initialize the child node in the selected cluster.
 ///////////////////////////////////////////////////////////////////////////////////////
 // @ node cxy  : cluster containing the node to initialize
@@ -124,6 +124,8 @@
     uint32_t node_base_y;    // associated macro_cluster y coordinate
     uint32_t half;           // associated macro-cluster half size
-
-    // get remote node cluster coordinates
+    uint32_t cores;          // number of cores in macro cluster
+    uint32_t clusters;       // number of clusters in macro cluster
+
+    // get node cluster coordinates
     node_x = HAL_X_FROM_CXY( node_cxy );
     node_y = HAL_Y_FROM_CXY( node_cxy );
@@ -140,32 +142,42 @@
     cluster_t * cluster = LOCAL_CLUSTER;
 
-    // get local pointer on remote node to be initialized
-    dqdt_node_t * node  = &cluster->dqdt_tbl[level];
+    // build local and extended pointer on node to be initialized
+    dqdt_node_t * node_ptr = &cluster->dqdt_tbl[level];
+    xptr_t        node_xp  = XPTR( node_cxy , node_ptr );
 
 #if DEBUG_DQDT_INIT
 printk("\n[DBG] %s : cxy(%d,%d) / level %d / mask %x / half %d / ptr %x\n",
-__FUNCTION__, node_x, node_y, level, mask, half, node );
+__FUNCTION__, node_x, node_y, level, mask, half, node_ptr );
 #endif
   
     // make remote node default initialisation
-    hal_remote_memset( XPTR( node_cxy , node ) , 0 , sizeof( dqdt_node_t ) );
+    hal_remote_memset( node_xp , 0 , sizeof( dqdt_node_t ) );
+
+    // initialize <parent> field
+    hal_remote_s64( XPTR( node_cxy , &node_ptr->parent ) , parent_xp );
+
+    // initialize <level> field
+    hal_remote_s32( XPTR( node_cxy , &node_ptr->level ) , level );
 
     // recursive initialisation 
-    if( level == 0 )                      // terminal case
+    if( level == 0 )                      // terminal case : cluster
     {
-        // update parent field
-        hal_remote_s64( XPTR( node_cxy , &node->parent ) , parent_xp );
+        // initialize <clusters> field in node
+        hal_remote_s32( XPTR( node_cxy , &node_ptr->clusters ) , 1 );
+
+        // initialize <cores> field in node
+        cores = hal_remote_l32( XPTR ( node_cxy , &cluster->cores_nr ) );
+        hal_remote_s32( XPTR( node_cxy , &node_ptr->cores ) , cores );
     }
-    else                                  // non terminal
+    else                                  // non terminal : macro-cluster
     {
-        uint32_t x;
-        uint32_t y;
-        cxy_t    cxy;
-        bool_t   found;
-
-        // update <level> in remote node
-        hal_remote_s32( XPTR( node_cxy , &node->level ) , level );
-
-        // try to find a valid cluster in child[0][0] macro-cluster
+        bool_t        found;
+        uint32_t      x;
+        uint32_t      y;
+        cxy_t         child_cxy;
+        xptr_t        child_xp;
+        dqdt_node_t * child_ptr =  &cluster->dqdt_tbl[level-1];
+
+        // search an active cluster in child[0][0] macro-cluster
         found = false; 
         for( x = node_base_x ; 
@@ -175,16 +187,27 @@
             (y < (node_base_y + half)) && (found == false) ; y++ )
             {
-                cxy = HAL_CXY_FROM_XY( x , y );
-                if( cluster_is_active( cxy ) )
+                child_cxy = HAL_CXY_FROM_XY( x , y );
+
+                if( cluster_is_active( child_cxy ) )
                 {
-                    // update <child[0][0]> in remote inode
-                    hal_remote_s64( XPTR( node_cxy , &node->children[0][0] ), 
-                                    XPTR( cxy , &cluster->dqdt_tbl[level - 1] ) );
-
-                    // udate <arity> in remote node
-                    hal_remote_atomic_add( XPTR( node_cxy , &node->arity ) , 1 );
-
-                    // initialize recursively child[0][0] node
-                    dqdt_recursive_build( cxy , level-1 , XPTR( node_cxy , node ) );
+                    // initialize recursively selected child[0][0] node
+                    dqdt_recursive_build( child_cxy , level-1 , node_xp );
+
+                    // build extended pointer on child[0][0] node
+                    child_xp = XPTR( child_cxy , child_ptr );
+
+                    // update <cores> field in node
+                    cores = hal_remote_l32( XPTR ( child_cxy , &child_ptr->cores ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->cores ) , cores );
+
+                    // update <clusters> field in node
+                    clusters = hal_remote_l32( XPTR ( child_cxy , &child_ptr->clusters ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->clusters ) , clusters );
+
+                    // update <child[0][0]> field in node
+                    hal_remote_s64( XPTR( node_cxy , &node_ptr->children[0][0] ), child_xp );
+
+                    // udate <arity> field in node
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->arity ) , 1 );
    
                     // exit loops
@@ -194,5 +217,5 @@
         }
 
-        // try to find a valid cluster in child[0][1] macro-cluster
+        // search an active cluster in child[0][1] macro-cluster
         found = false; 
         for( x = node_base_x ; 
@@ -200,18 +223,29 @@
         {
             for( y = (node_base_y + half) ; 
-            (y < (node_base_y + (half<<2))) && (found == false) ; y++ )
+            (y < (node_base_y + (half<<1))) && (found == false) ; y++ )
             {
-                cxy = HAL_CXY_FROM_XY( x , y );
-                if( cluster_is_active( cxy ) )
+                child_cxy = HAL_CXY_FROM_XY( x , y );
+
+                if( cluster_is_active( child_cxy ) )
                 {
-                    // update <child[0][1]> in remote inode
-                    hal_remote_s64( XPTR( node_cxy , &node->children[0][1] ), 
-                                    XPTR( cxy , &cluster->dqdt_tbl[level - 1] ) );
-
-                    // udate <arity> in remote node
-                    hal_remote_atomic_add( XPTR( node_cxy , &node->arity ) , 1 );
-
-                    // initialize recursively child[0][1] node
-                    dqdt_recursive_build( cxy , level-1 , XPTR( node_cxy , node ) );
+                    // initialize recursively selected child[0][1] node
+                    dqdt_recursive_build( child_cxy , level-1 , node_xp );
+
+                    // build extended pointer on child[0][1] node
+                    child_xp = XPTR( child_cxy , child_ptr );
+
+                    // update <cores> field in node
+                    cores = hal_remote_l32( XPTR ( child_cxy , &child_ptr->cores ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->cores ) , cores );
+
+                    // update <clusters> field in node
+                    clusters = hal_remote_l32( XPTR ( child_cxy , &child_ptr->clusters ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->clusters ) , clusters );
+
+                    // update <child[0][1]> field in node
+                    hal_remote_s64( XPTR( node_cxy , &node_ptr->children[0][1] ), child_xp );
+
+                    // udate <arity> field in node
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->arity ) , 1 );
    
                     // exit loops
@@ -220,8 +254,8 @@
             }
         }
-            
-        // try to find a valid cluster in child[1][0] macro-cluster
+
+        // search an active cluster in child[1][0] macro-cluster
         found = false; 
-        for( x = (node_base_x + half) ; 
+        for( x = (node_base_x +half) ; 
         (x < (node_base_x + (half<<1))) && (found == false) ; x++ )
         {
@@ -229,16 +263,27 @@
             (y < (node_base_y + half)) && (found == false) ; y++ )
             {
-                cxy = HAL_CXY_FROM_XY( x , y );
-                if( cluster_is_active( cxy ) )
+                child_cxy = HAL_CXY_FROM_XY( x , y );
+
+                if( cluster_is_active( child_cxy ) )
                 {
-                    // update <child[1][0]> in remote inode
-                    hal_remote_s64( XPTR( node_cxy , &node->children[1][0] ), 
-                                    XPTR( cxy , &cluster->dqdt_tbl[level - 1] ) );
-
-                    // udate <arity> in remote node
-                    hal_remote_atomic_add( XPTR( node_cxy , &node->arity ) , 1 );
-
-                    // initialize recursively child[1][0] node
-                    dqdt_recursive_build( cxy , level-1 , XPTR( node_cxy , node ) );
+                    // initialize recursively selected child[1][0] node
+                    dqdt_recursive_build( child_cxy , level-1 , node_xp );
+
+                    // build extended pointer on child[1][0] node
+                    child_xp = XPTR( child_cxy , child_ptr );
+
+                    // update <cores> field in node
+                    cores = hal_remote_l32( XPTR ( child_cxy , &child_ptr->cores ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->cores ) , cores );
+
+                    // update <clusters> field in node
+                    clusters = hal_remote_l32( XPTR ( child_cxy , &child_ptr->clusters ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->clusters ) , clusters );
+
+                    // update <child[1][0]> field in node
+                    hal_remote_s64( XPTR( node_cxy , &node_ptr->children[1][0] ), child_xp );
+
+                    // udate <arity> field in node
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->arity ) , 1 );
    
                     // exit loops
@@ -248,5 +293,5 @@
         }
 
-        // try to find a valid cluster in child[1][1] macro-cluster
+        // search an active cluster in child[1][1] macro-cluster
         found = false; 
         for( x = (node_base_x + half) ; 
@@ -254,18 +299,29 @@
         {
             for( y = (node_base_y + half) ; 
-            (y < (node_base_y + (half<<2))) && (found == false) ; y++ )
+            (y < (node_base_y + (half<<1))) && (found == false) ; y++ )
             {
-                cxy = HAL_CXY_FROM_XY( x , y );
-                if( cluster_is_active( cxy ) )
+                child_cxy = HAL_CXY_FROM_XY( x , y );
+
+                if( cluster_is_active( child_cxy ) )
                 {
-                    // update <child[1][1]> in remote inode
-                    hal_remote_s64( XPTR( node_cxy , &node->children[1][1] ), 
-                                    XPTR( cxy , &cluster->dqdt_tbl[level - 1] ) );
-
-                    // udate <arity> in remote node
-                    hal_remote_atomic_add( XPTR( node_cxy , &node->arity ) , 1 );
-
-                    // initialize recursively child[1][1] node
-                    dqdt_recursive_build( cxy , level-1 , XPTR( node_cxy , node ) );
+                    // initialize recursively selected child[1][1] node
+                    dqdt_recursive_build( child_cxy , level-1 , node_xp );
+
+                    // build extended pointer on child[1][1] node
+                    child_xp = XPTR( child_cxy , child_ptr );
+
+                    // update <cores> field in node
+                    cores = hal_remote_l32( XPTR ( child_cxy , &child_ptr->cores ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->cores ) , cores );
+
+                    // update <clusters> field in node
+                    clusters = hal_remote_l32( XPTR ( child_cxy , &child_ptr->clusters ) );
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->clusters ) , clusters );
+
+                    // update <child[1][1]> field in node
+                    hal_remote_s64( XPTR( node_cxy , &node_ptr->children[1][1] ), child_xp );
+
+                    // udate <arity> field in node
+                    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->arity ) , 1 );
    
                     // exit loops
@@ -311,30 +367,8 @@
 }  // end dqdt_init()
 
+
 ///////////////////////////////////////////////////////////////////////////
-// This recursive function is called by the dqdt_update_threads() function.
-// It traverses the quad tree from clusters to root.
-///////////////////////////////////////////////////////////////////////////
-// @ node       : extended pointer on current node
-// @ increment  : number of threads variation
-///////////////////////////////////////////////////////////////////////////
-static void dqdt_propagate_threads( xptr_t  node,
-                                    int32_t increment )
-{
-    // get current node cluster identifier and local pointer
-    cxy_t         cxy = GET_CXY( node );
-    dqdt_node_t * ptr = GET_PTR( node );
-
-    // update current node threads number
-    hal_remote_atomic_add( XPTR( cxy , &ptr->threads ) , increment );
-
-    // get extended pointer on parent node
-    xptr_t parent = (xptr_t)hal_remote_l64( XPTR( cxy , &ptr->parent ) );
-
-    // propagate if required
-    if ( parent != XPTR_NULL ) dqdt_propagate_threads( parent, increment );
-}
-
-///////////////////////////////////////////////////////////////////////////
-// This recursive function is called by the dqdt_update_pages() function.
+// This recursive function is called by both the dqdt_increment_pages()
+// and by the dqdt_decrement_pages() functions.
 // It traverses the quad tree from clusters to root.
 ///////////////////////////////////////////////////////////////////////////
@@ -349,5 +383,5 @@
     dqdt_node_t * ptr = GET_PTR( node );
 
-    // update current node threads number
+    // update current node pages number
     hal_remote_atomic_add( XPTR( cxy , &ptr->pages ) , increment );
 
@@ -359,6 +393,6 @@
 }
 
-/////////////////////////////////////////////
-void dqdt_update_threads( int32_t increment )
+///////////////////////////////////////////
+void dqdt_increment_pages( uint32_t order )
 {
 	cluster_t   * cluster = LOCAL_CLUSTER;
@@ -366,12 +400,20 @@
 
     // update DQDT node level 0
-    hal_atomic_add( &node->threads , increment );
+    hal_atomic_add( &node->pages , (1 << order) );
 
     // propagate to DQDT upper levels
-    if( node->parent != XPTR_NULL ) dqdt_propagate_threads( node->parent , increment );
+    if( node->parent != XPTR_NULL ) dqdt_propagate_pages( node->parent , (1 << order) );
+
+#if DEBUG_DQDT_UPDATE_PAGES
+uint32_t cycle = hal_get_cycles();
+if( cycle > DEBUG_DQDT_UPDATE_PAGES )
+printk("\n[DBG] %s : thread %x in process %x / %x pages in cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->pages, local_cxy, cycle );
+#endif
+
 }
 
 ///////////////////////////////////////////
-void dqdt_update_pages( int32_t increment )
+void dqdt_decrement_pages( uint32_t order )
 {
 	cluster_t   * cluster = LOCAL_CLUSTER;
@@ -379,16 +421,94 @@
 
     // update DQDT node level 0
-    hal_atomic_add( &node->pages , increment );
+    hal_atomic_add( &node->pages , -(1 << order) );
 
     // propagate to DQDT upper levels
-    if( node->parent != XPTR_NULL ) dqdt_propagate_pages( node->parent , increment );
-}
-
-////////////////////////////////////////////////////////////////////////////////
+    if( node->parent != XPTR_NULL ) dqdt_propagate_pages( node->parent , -(1 << order) );
+
+#if DEBUG_DQDT_UPDATE_PAGES
+uint32_t cycle = hal_get_cycles();
+if( cycle > DEBUG_DQDT_UPDATE_PAGES )
+printk("\n[DBG] %s : thread %x in process %x / %x pages in cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->pages, local_cxy, cycle );
+#endif
+
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+// This recursive function is called by both the dqdt_increment_threads() 
+// and by the dqdt_decrement_threads functions.
+// It traverses the quad tree from clusters to root.
+///////////////////////////////////////////////////////////////////////////
+// @ node       : extended pointer on current node
+// @ increment  : number of pages variation
+///////////////////////////////////////////////////////////////////////////
+static void dqdt_propagate_threads( xptr_t  node,
+                                    int32_t increment )
+{
+    // get current node cluster identifier and local pointer
+    cxy_t         cxy = GET_CXY( node );
+    dqdt_node_t * ptr = GET_PTR( node );
+
+    // update current node threads number
+    hal_remote_atomic_add( XPTR( cxy , &ptr->threads ) , increment );
+
+    // get extended pointer on parent node
+    xptr_t parent = (xptr_t)hal_remote_l64( XPTR( cxy , &ptr->parent ) );
+
+    // propagate if required
+    if ( parent != XPTR_NULL ) dqdt_propagate_threads( parent, increment );
+}
+
+///////////////////////////////////
+void dqdt_increment_threads( void )
+{
+	cluster_t   * cluster = LOCAL_CLUSTER;
+    dqdt_node_t * node    = &cluster->dqdt_tbl[0];
+
+    // update DQDT node level 0
+    hal_atomic_add( &node->threads , 1 );
+
+    // propagate to DQDT upper levels
+    if( node->parent != XPTR_NULL ) dqdt_propagate_threads( node->parent , 1 );
+
+#if DEBUG_DQDT_UPDATE_THREADS
+uint32_t cycle = hal_get_cycles();
+if( cycle > DEBUG_DQDT_UPDATE_THREADS )
+printk("\n[DBG] %s : thread %x in process %x / %d threads in cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->threads, local_cxy, cycle );
+#endif
+
+}
+
+///////////////////////////////////
+void dqdt_decrement_threads( void )
+{
+	cluster_t   * cluster = LOCAL_CLUSTER;
+    dqdt_node_t * node    = &cluster->dqdt_tbl[0];
+
+    // update DQDT node level 0
+    hal_atomic_add( &node->threads , -1 );
+
+    // propagate to DQDT upper levels
+    if( node->parent != XPTR_NULL ) dqdt_propagate_threads( node->parent , -1 );
+
+#if DEBUG_DQDT_UPDATE_THREADS
+uint32_t cycle = hal_get_cycles();
+if( cycle > DEBUG_DQDT_UPDATE_THREADS )
+printk("\n[DBG] %s : thread %x in process %x / %d threads in cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->threads, local_cxy, cycle );
+#endif
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
 // This recursive function is called by both the dqdt_get_cluster_for_process()
-// and by the dqdt_get_cluster_for_memory() functions to select the cluster
-// with smallest number of thread, or smallest number of allocated pages.
+// and by the dqdt_get_cluster_for_memory() functions to select the cluster with the 
+// smallest number of threads per core, or the smallest number of pages per cluster.
 // It traverses the quad tree from root to clusters.
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
 static cxy_t dqdt_select_cluster( xptr_t node,
                                   bool_t for_memory )
@@ -422,7 +542,19 @@
                 cxy_t         cxy  = GET_CXY( child_xp );
                 dqdt_node_t * ptr  = GET_PTR( child_xp );
-                if( for_memory ) load = hal_remote_l32( XPTR( cxy , &ptr->pages ) );
-                else             load = hal_remote_l32( XPTR( cxy , &ptr->threads ) );
-                if( load < load_min )
+
+                // compute average load  for each child
+                if( for_memory )
+                {
+                    load = hal_remote_l32( XPTR( cxy , &ptr->pages ) ) /
+                           hal_remote_l32( XPTR( cxy , &ptr->clusters ) );
+                }
+                else
+                {
+                    load = hal_remote_l32( XPTR( cxy , &ptr->threads ) ) /
+                           hal_remote_l32( XPTR( cxy , &ptr->cores ) );
+                }
+
+                // select children with smallest load
+                if( load <= load_min )
                 {
                     load_min = load;
@@ -436,5 +568,7 @@
     // select the child with the lowest load
     return dqdt_select_cluster( node_copy.children[select_x][select_y], for_memory );
-}
+
+}  // end dqdt_select_cluster()
+
 
 //////////////////////////////////////////
@@ -442,5 +576,14 @@
 {
     // call recursive function
-    return dqdt_select_cluster( LOCAL_CLUSTER->dqdt_root_xp , false );
+    cxy_t cxy = dqdt_select_cluster( LOCAL_CLUSTER->dqdt_root_xp , false );
+
+#if DEBUG_DQDT_SELECT_FOR_PROCESS
+uint32_t cycle = hal_get_cycles();
+if( cycle > DEBUG_DQDT_SELECT_FOR_PROCESS )
+printk("\n[DBG] %s : thread %x in process %x select cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cxy, cycle );
+#endif
+
+    return cxy;
 }
 
@@ -449,5 +592,14 @@
 {
     // call recursive function
-    return dqdt_select_cluster( LOCAL_CLUSTER->dqdt_root_xp , true );
-}
-
+    cxy_t cxy = dqdt_select_cluster( LOCAL_CLUSTER->dqdt_root_xp , true );
+
+#if DEBUG_DQDT_SELECT_FOR_MEMORY
+uint32_t cycle = hal_get_cycles();
+if( cycle > DEBUG_DQDT_SELECT_FOR_MEMORY )
+printk("\n[DBG] %s : thread %x in process %x select cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cxy, cycle );
+#endif
+
+    return cxy;
+}
+
