diff --git a/Src/GroupTree/StarPUUtils/FStarPUHeteoprio.hpp b/Src/GroupTree/StarPUUtils/FStarPUHeteoprio.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7b5f691fbbf66c14a44ae1579d0d9ebb040f2abd
--- /dev/null
+++ b/Src/GroupTree/StarPUUtils/FStarPUHeteoprio.hpp
@@ -0,0 +1,523 @@
+// @SCALFMM_PRIVATE
+#ifndef FSTARPUHETEOPRIO_HPP
+#define FSTARPUHETEOPRIO_HPP
+
+#include "../../Utils/FGlobal.hpp"
+#include "FStarPUUtils.hpp"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <starpu_scheduler.h>
+#include <starpu_bitmap.h>
+
+#include <assert.h>
+
+
+/* Out of starpu build, cannot access : #include <sched_policies/fifo_queues.h> */
+struct _starpu_fifo_taskq_node{
+    struct _starpu_fifo_taskq_node* next;
+    struct starpu_task* task;
+};
+
+struct _starpu_fifo_taskq{
+    struct _starpu_fifo_taskq_node* head;
+    struct _starpu_fifo_taskq_node* tail;
+    unsigned ntasks;
+};
+
+struct _starpu_fifo_taskq* _starpu_create_fifo(){
+    struct _starpu_fifo_taskq* fifo = (struct _starpu_fifo_taskq*)malloc(sizeof(struct _starpu_fifo_taskq));
+    memset(fifo, 0, sizeof(struct _starpu_fifo_taskq));
+    return fifo;
+}
+
+void _starpu_destroy_fifo(struct _starpu_fifo_taskq* fifo){
+    assert(fifo);
+    assert(fifo->head == NULL && fifo->tail == NULL && fifo->ntasks == 0);
+    free(fifo);
+}
+
+int _starpu_fifo_empty(struct _starpu_fifo_taskq *fifo){
+    return fifo->ntasks == 0;
+}
+
+struct starpu_task* _starpu_fifo_pop_local_task(struct _starpu_fifo_taskq *fifo){
+    assert(fifo);
+    assert(fifo->ntasks);
+    assert(fifo->head);
+    struct starpu_task* task = fifo->head->task;
+    struct _starpu_fifo_taskq_node* to_remove = fifo->head;
+    if(fifo->tail == fifo->head){
+        fifo->tail = NULL;
+    }
+    fifo->head = fifo->head->next;
+    free(to_remove);
+    fifo->ntasks -= 1;
+    return task;
+}
+
+void _starpu_task_list_push_back(struct _starpu_fifo_taskq *fifo, struct starpu_task* task){
+    assert(fifo);
+    struct _starpu_fifo_taskq_node* new_node = (struct _starpu_fifo_taskq_node*)malloc(sizeof(struct _starpu_fifo_taskq_node));
+    new_node->task = task;
+    new_node->next = NULL;
+    if(fifo->tail != NULL){
+        fifo->tail->next = new_node;
+        fifo->tail = new_node;
+    }
+    else{
+        fifo->head = new_node;
+        fifo->tail = new_node;
+    }
+    fifo->ntasks += 1;
+}
+
+/* Cannot find a function that give the nb of task in a fifo so provide it */
+int _starpu_fifo_size(struct _starpu_fifo_taskq *fifo){
+    return fifo->ntasks;
+}
+
+/* A bucket corresponds to a Pair of priorities
+ * When a task is pushed with a priority X, it will be stored
+ * into the bucket X.
+ * All the tasks stored in the fifo should be computable by the arch
+ * in valide_archs.
+ * For example if valide_archs = (STARPU_CPU|STARPU_CUDA)
+ * Then task->task->cl->where should be at least (STARPU_CPU|STARPU_CUDA)
+ */
+struct _starpu_heteroprio_bucket{
+    /* The task of the current bucket */
+    struct _starpu_fifo_taskq* tasks_queue;
+    /* The correct arch for the current bucket */
+    unsigned valide_archs;
+    /* The slow factors for any archs */
+    float slow_factors_per_index[FSTARPU_NB_TYPES];
+    /* The base arch for the slow factor (the fatest arch for the current task in the bucket */
+    unsigned factor_base_arch_index;
+};
+
+/* Init a bucket */
+static void _starpu_heteroprio_bucket_init(struct _starpu_heteroprio_bucket* bucket){
+    memset(bucket, 0, sizeof(*bucket));
+    bucket->tasks_queue =  _starpu_create_fifo();
+}
+
+/* Release a bucket */
+static void _starpu_heteroprio_bucket_release(struct _starpu_heteroprio_bucket* bucket){
+    assert(_starpu_fifo_empty(bucket->tasks_queue) != 0);
+    _starpu_destroy_fifo(bucket->tasks_queue);
+}
+
+/* HETEROPRIO_MAX_PREFETCH Represent the number of task stored in each worker queue if possible */
+#define HETEROPRIO_MAX_PREFETCH 2
+#if HETEROPRIO_MAX_PREFETCH <= 0
+#error HETEROPRIO_MAX_PREFETCH == 1 means no prefetch so HETEROPRIO_MAX_PREFETCH must >= 1
+#endif
+
+/* A worker is mainly composed of a fifo for the tasks
+ * and some direct access to worker properties.
+ * The fifo is implemented with any array,
+ * to read a task, access tasks_queue[tasks_queue_index]
+ * to write a task, access tasks_queue[(tasks_queue_index+tasks_queue_size)%HETEROPRIO_MAX_PREFETCH]
+ */
+struct _starpu_heteroprio_worker{
+    unsigned arch_type;
+    unsigned arch_index;
+    struct starpu_task* tasks_queue[HETEROPRIO_MAX_PREFETCH];
+    unsigned tasks_queue_size;
+    unsigned tasks_queue_index;
+};
+
+/* Init a worker by setting every thing to zero */
+static void _starpu_heteroprio_worker_init(struct _starpu_heteroprio_worker* worker){
+    memset(worker, 0, sizeof(*worker));
+    worker->tasks_queue_index = 0;
+}
+
+/* Release a worker */
+static void _starpu_heteroprio_worker_release(struct _starpu_heteroprio_worker* worker){
+    assert(worker->tasks_queue_size == 0);
+}
+
+/* HETEROPRIO_MAX_PRIO is the maximum prio/buckets available */
+#define HETEROPRIO_MAX_PRIO 100
+
+/* This is the core part of the scheduler.
+ * It contains the buckets, the worker information
+ * and several counters to avoid useless iteration
+ * Also it contains the mapping for each arch to the correct buckets.
+ * For example a worker of type CUDA has index FSTARPU_CUDA_IDX
+ * It has nb_prio_per_arch_index[FSTARPU_CUDA_IDX] buckets to check (<= HETEROPRIO_MAX_PRIO).
+ * It will access the correct bucket using the mapping prio_mapping_per_arch_index[FSTARPU_CUDA_IDX][idx].
+ */
+struct _starpu_heteroprio_center_policy_heteroprio
+{
+    starpu_pthread_mutex_t policy_mutex;
+    struct starpu_bitmap *waiters;
+    /* The bucket to store the tasks */
+    struct _starpu_heteroprio_bucket buckets[HETEROPRIO_MAX_PRIO];
+    /* The number of buckets for each arch */
+    unsigned nb_prio_per_arch_index[FSTARPU_NB_TYPES];
+    /* The mapping to the corresponding buckets */
+    unsigned prio_mapping_per_arch_index[FSTARPU_NB_TYPES][HETEROPRIO_MAX_PRIO];
+    /* The number of available tasks for a given arch (not prefetched) */
+    unsigned nb_remaining_tasks_per_arch_index[FSTARPU_NB_TYPES];
+    /* The total number of tasks in the bucket (not prefetched) */
+    unsigned total_tasks_in_buckets;
+    /* The total number of prefetched tasks for a given arch */
+    unsigned nb_prefetched_tasks_per_arch_index[FSTARPU_NB_TYPES];
+    /* The information for all the workers */
+    struct _starpu_heteroprio_worker workers_heteroprio[STARPU_NMAXWORKERS];
+    /* The number of workers */
+    unsigned nb_workers;
+    /* The number of workers for a given arch */
+    unsigned nb_workers_per_arch_index[FSTARPU_NB_TYPES];
+};
+
+/* This is the callback that must init the scheduler buckets */
+/*extern*/ void (*initialize_heteroprio_center_policy_callback)(unsigned sched_ctx_id,
+                struct _starpu_heteroprio_center_policy_heteroprio *heteroprio) = NULL;
+
+/* Init the scheduler - This will call the init callback! */
+static void initialize_heteroprio_center_policy(unsigned sched_ctx_id)
+{
+    /* Copy of eager */
+#ifdef STARPU_HAVE_HWLOC
+    starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_TREE);
+#else
+    starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
+#endif
+    /* Alloc the scheduler data  */
+    struct _starpu_heteroprio_center_policy_heteroprio* heteroprio = (struct _starpu_heteroprio_center_policy_heteroprio*)malloc(sizeof(struct _starpu_heteroprio_center_policy_heteroprio));
+    heteroprio->waiters = starpu_bitmap_create();
+    starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)heteroprio);
+    STARPU_PTHREAD_MUTEX_INIT(&heteroprio->policy_mutex, NULL);
+    /* End copy of eager */
+
+    /* Init the buckets */
+    for(unsigned idx_prio = 0 ; idx_prio < HETEROPRIO_MAX_PRIO ; ++idx_prio){
+        _starpu_heteroprio_bucket_init(&heteroprio->buckets[idx_prio]);
+    }
+
+    /* Init the worker information */
+    heteroprio->nb_workers = starpu_worker_get_count();
+    for(unsigned idx_worker = 0 ; idx_worker < starpu_worker_get_count() ; ++idx_worker){
+        _starpu_heteroprio_worker_init(&heteroprio->workers_heteroprio[idx_worker]);
+        switch(starpu_worker_get_type(idx_worker)){
+#ifdef STARPU_USE_CPU
+            case STARPU_CPU_WORKER:
+                heteroprio->workers_heteroprio[idx_worker].arch_type = STARPU_CPU;
+                heteroprio->workers_heteroprio[idx_worker].arch_index = FSTARPU_CPU_IDX;
+                break;
+#endif
+#ifdef STARPU_USE_CUDA
+            case STARPU_CUDA_WORKER:
+                heteroprio->workers_heteroprio[idx_worker].arch_type = STARPU_CUDA;
+                heteroprio->workers_heteroprio[idx_worker].arch_index = FSTARPU_CUDA_IDX;
+                break;
+#endif
+#ifdef STARPU_USE_OPENCL
+            case STARPU_OPENCL_WORKER:
+                heteroprio->workers_heteroprio[idx_worker].arch_type = STARPU_OPENCL;
+                heteroprio->workers_heteroprio[idx_worker].arch_index = FSTARPU_OPENCL_IDX;
+                break;
+#endif
+        default:
+            assert(0);
+        }
+        heteroprio->nb_workers_per_arch_index[heteroprio->workers_heteroprio[idx_worker].arch_index] += 1;
+    }
+
+    /* Ask the user to fill the bucket information */
+    assert(initialize_heteroprio_center_policy_callback != NULL);
+    (*initialize_heteroprio_center_policy_callback)(sched_ctx_id, heteroprio);
+
+    /* Ensure that information have been correctly filled */
+    unsigned check_all_archs[HETEROPRIO_MAX_PRIO];
+    memset(check_all_archs, 0, sizeof(unsigned)*HETEROPRIO_MAX_PRIO);
+    for(unsigned arch_index = 0 ; arch_index < FSTARPU_NB_TYPES ; ++arch_index){
+        assert(heteroprio->nb_prio_per_arch_index[arch_index] <= HETEROPRIO_MAX_PRIO);
+        unsigned check_archs[HETEROPRIO_MAX_PRIO];
+        memset(check_archs, 0, sizeof(unsigned)*HETEROPRIO_MAX_PRIO);
+
+        for(unsigned idx_prio = 0 ; idx_prio < heteroprio->nb_prio_per_arch_index[arch_index] ; ++idx_prio){
+            const unsigned mapped_prio = heteroprio->prio_mapping_per_arch_index[arch_index][idx_prio];
+            assert(mapped_prio <= HETEROPRIO_MAX_PRIO);
+            assert(heteroprio->buckets[mapped_prio].slow_factors_per_index[arch_index] >= 0.0);
+            assert(heteroprio->buckets[mapped_prio].valide_archs & FStarPUTypesToArch[arch_index]);
+            check_archs[mapped_prio]      = 1;
+            check_all_archs[mapped_prio] += 1;
+        }
+        for(unsigned idx_prio = 0 ; idx_prio < HETEROPRIO_MAX_PRIO ; ++idx_prio){
+            /* Ensure the current arch use a bucket or someone else can use it */
+            assert(check_archs[idx_prio] == 1 || heteroprio->buckets[idx_prio].valide_archs == 0
+                   || (heteroprio->buckets[idx_prio].valide_archs & ~FStarPUTypesToArch[arch_index]) != 0);
+        }
+    }
+    /* Ensure that if a valide_archs = (STARPU_CPU|STARPU_CUDA) then check_all_archs[] = 2 for example */
+    for(unsigned idx_prio = 0 ; idx_prio < HETEROPRIO_MAX_PRIO ; ++idx_prio){
+        unsigned nb_arch_on_bucket = 0;
+        for(unsigned arch_index = 0 ; arch_index < FSTARPU_NB_TYPES ; ++arch_index){
+            if(heteroprio->buckets[idx_prio].valide_archs & FStarPUTypesToArch[arch_index]){
+                nb_arch_on_bucket += 1;
+            }
+        }
+        assert(check_all_archs[idx_prio] == nb_arch_on_bucket);
+    }
+}
+
+/* Release a scheduler */
+static void deinitialize_heteroprio_center_policy(unsigned sched_ctx_id)
+{
+    struct _starpu_heteroprio_center_policy_heteroprio *heteroprio = (struct _starpu_heteroprio_center_policy_heteroprio*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
+
+    /* Ensure there are no more tasks */
+    assert(heteroprio->total_tasks_in_buckets == 0);
+    for(unsigned arch_index = 0 ; arch_index < FSTARPU_NB_TYPES ; ++arch_index){
+        assert(heteroprio->nb_remaining_tasks_per_arch_index[arch_index] == 0);
+        assert(heteroprio->nb_prefetched_tasks_per_arch_index[arch_index] == 0);
+    }
+
+    for(unsigned idx_prio = 0 ; idx_prio < HETEROPRIO_MAX_PRIO ; ++idx_prio){
+        _starpu_heteroprio_bucket_release(&heteroprio->buckets[idx_prio]);
+    }
+
+    for(unsigned idx_worker = 0 ; idx_worker < heteroprio->nb_workers ; ++idx_worker){
+        _starpu_heteroprio_worker_release(&heteroprio->workers_heteroprio[idx_worker]);
+    }
+
+    /* Copy of eager */
+    starpu_bitmap_destroy(heteroprio->waiters);
+
+    starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
+    STARPU_PTHREAD_MUTEX_DESTROY(&heteroprio->policy_mutex);
+    free(heteroprio);
+    /* End copy of eager */
+}
+
+/* Push a new task (simply store it and update counters) */
+static int push_task_heteroprio_policy(struct starpu_task *task)
+{
+    unsigned sched_ctx_id = task->sched_ctx;
+    struct _starpu_heteroprio_center_policy_heteroprio *heteroprio = (struct _starpu_heteroprio_center_policy_heteroprio*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
+
+    /* One worker at a time use heteroprio */
+    STARPU_PTHREAD_MUTEX_LOCK(&heteroprio->policy_mutex);
+
+    /* Retrieve the correct bucket */
+    assert(task->priority < HETEROPRIO_MAX_PRIO);
+    struct _starpu_heteroprio_bucket* bucket = &heteroprio->buckets[task->priority];
+    /* Ensure that any worker that check that list can compute the task */
+    assert(bucket->valide_archs
+           && ((bucket->valide_archs ^ task->cl->where) & bucket->valide_archs) == 0);
+    /* save the task */
+    _starpu_task_list_push_back(bucket->tasks_queue,task);
+
+    /* Inc counters */
+    for(unsigned arch_index = 0 ; arch_index < FSTARPU_NB_TYPES ; ++arch_index){
+        /* We test the archs on the bucket and not on task->cl->where since it is restrictive */
+        if(bucket->valide_archs & FStarPUTypesToArch[arch_index]){
+            heteroprio->nb_remaining_tasks_per_arch_index[arch_index] += 1;
+        }
+    }
+    heteroprio->total_tasks_in_buckets += 1;
+
+    starpu_push_task_end(task);
+
+    /* Copy of eager */
+    /*if there are no tasks_queue block */
+    /* wake people waiting for a task */
+    unsigned worker = 0;
+    struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx_id);
+
+    struct starpu_sched_ctx_iterator it;
+#ifndef STARPU_NON_BLOCKING_DRIVERS
+    char dowake[STARPU_NMAXWORKERS] = { 0 };
+#endif
+
+    workers->init_iterator(workers, &it);
+    while(workers->has_next_master(workers, &it))
+    {
+        worker = workers->get_next_master(workers, &it);
+
+#ifdef STARPU_NON_BLOCKING_DRIVERS
+        if (!starpu_bitmap_get(heteroprio->waiters, worker))
+            /* This worker is not waiting for a task */
+            continue;
+#endif
+
+        if (starpu_worker_can_execute_task_first_impl(worker, task, NULL))
+        {
+            /* It can execute this one, tell him! */
+#ifdef STARPU_NON_BLOCKING_DRIVERS
+            starpu_bitmap_unset(heteroprio->waiters, worker);
+            /* We really woke at least somebody, no need to wake somebody else */
+            break;
+#else
+            dowake[worker] = 1;
+#endif
+        }
+    }
+    /* Let the task free */
+    STARPU_PTHREAD_MUTEX_UNLOCK(&heteroprio->policy_mutex);
+
+#ifndef STARPU_NON_BLOCKING_DRIVERS
+    /* Now that we have a list of potential workers, try to wake one */
+
+    workers->init_iterator(workers, &it);
+    while(workers->has_next(workers, &it))
+    {
+        worker = workers->get_next(workers, &it);
+        if (dowake[worker])
+            if (starpu_wake_worker(worker))
+                break; // wake up a single worker
+    }
+#endif
+    /* End copy of eager */
+
+    return 0;
+}
+
+
+static struct starpu_task *pop_task_heteroprio_policy(unsigned sched_ctx_id)
+{
+    unsigned workerid = starpu_worker_get_id();
+    struct _starpu_heteroprio_center_policy_heteroprio *heteroprio = (struct _starpu_heteroprio_center_policy_heteroprio*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
+    struct _starpu_heteroprio_worker* worker = &heteroprio->workers_heteroprio[workerid];
+
+    /* If not tasks available, not tasks in worker queue or some arch worker queue just return NULL */
+    if ((heteroprio->total_tasks_in_buckets == 0 || heteroprio->nb_remaining_tasks_per_arch_index[worker->arch_index] == 0)
+            && worker->tasks_queue_size == 0 && heteroprio->nb_prefetched_tasks_per_arch_index[worker->arch_index] == 0){
+        return NULL;
+    }
+
+#ifdef STARPU_NON_BLOCKING_DRIVERS
+    if (starpu_bitmap_get(heteroprio->waiters, workerid)){
+        /* Nobody woke us, avoid bothering the mutex */
+        return NULL;
+    }
+#endif
+
+    STARPU_PTHREAD_MUTEX_LOCK(&heteroprio->policy_mutex);
+
+    /* Check that some tasks are available for the current worker arch */
+    if( heteroprio->nb_remaining_tasks_per_arch_index[worker->arch_index] != 0 ){
+        /* Ideally we would like to fill the prefetch array */
+        unsigned nb_tasks_to_prefetch = (HETEROPRIO_MAX_PREFETCH-worker->tasks_queue_size);
+        /* But in case there are less tasks than worker we take the minimum */
+        if(heteroprio->nb_remaining_tasks_per_arch_index[worker->arch_index] < heteroprio->nb_workers){
+            if(worker->tasks_queue_size == 0) nb_tasks_to_prefetch = 1;
+            else nb_tasks_to_prefetch = 0;
+        }
+
+        /* We iterate until we found all the tasks we need */
+        for(unsigned idx_prio = 0 ; nb_tasks_to_prefetch && idx_prio < heteroprio->nb_prio_per_arch_index[worker->arch_index] ; ++idx_prio){
+            /* Retrieve the bucket using the mapping */
+            struct _starpu_heteroprio_bucket* bucket = &heteroprio->buckets[heteroprio->prio_mapping_per_arch_index[worker->arch_index][idx_prio]];
+            /* Ensure we can compute task from this bucket */
+            assert(bucket->valide_archs & worker->arch_type);
+            /* Take nb_tasks_to_prefetch tasks if possible */
+            while(_starpu_fifo_empty(bucket->tasks_queue) == 0 && nb_tasks_to_prefetch
+                 && (worker->arch_index == bucket->factor_base_arch_index
+                  || (float(_starpu_fifo_size(bucket->tasks_queue))/float(heteroprio->nb_workers_per_arch_index[bucket->factor_base_arch_index])
+                        >= bucket->slow_factors_per_index[worker->arch_index]))){
+                struct starpu_task* task = _starpu_fifo_pop_local_task(bucket->tasks_queue);
+                assert(starpu_worker_can_execute_task(workerid, task, 0));
+                /* Save the task */
+                worker->tasks_queue[(worker->tasks_queue_index+worker->tasks_queue_size)%HETEROPRIO_MAX_PREFETCH] = task;
+                worker->tasks_queue_size += 1;
+                /* Update general counter */
+                heteroprio->nb_prefetched_tasks_per_arch_index[worker->arch_index] += 1;
+                heteroprio->total_tasks_in_buckets    -= 1;
+                for(unsigned arch_index = 0 ; arch_index < FSTARPU_NB_TYPES ; ++arch_index){
+                    /* We test the archs on the bucket and not on task->cl->where since it is restrictive */
+                    if(bucket->valide_archs & FStarPUTypesToArch[arch_index]){
+                        heteroprio->nb_remaining_tasks_per_arch_index[arch_index] -= 1;
+                    }
+                }
+                /* Decrease the number of tasks to found */
+                nb_tasks_to_prefetch -= 1;
+                // TODO starpu_prefetch_task_input_on_node(task, workerid);
+            }
+        }
+        assert(nb_tasks_to_prefetch == 0);
+    }
+
+    struct starpu_task* task = NULL;
+
+    /* The worker has some tasks in its queue */
+    if(worker->tasks_queue_size){
+        task = worker->tasks_queue[worker->tasks_queue_index];
+        worker->tasks_queue_index = (worker->tasks_queue_index+1)%HETEROPRIO_MAX_PREFETCH;
+        worker->tasks_queue_size -= 1;
+        heteroprio->nb_prefetched_tasks_per_arch_index[worker->arch_index] -= 1;
+    }
+    /* Otherwise look if we can steal some work */
+    else if(heteroprio->nb_prefetched_tasks_per_arch_index[worker->arch_index]){
+        /* If HETEROPRIO_MAX_PREFETCH==1 it should not be possible to steal work */
+        assert(HETEROPRIO_MAX_PREFETCH != 1);
+        /* Each worker starts from its own index and do a turn */
+        for(unsigned idx_worker_it = 1 ; idx_worker_it < heteroprio->nb_workers ; ++idx_worker_it){
+            const unsigned idx_worker = ((workerid+idx_worker_it)%heteroprio->nb_workers);
+            /* If it is the same arch and there is a task to steal */
+            if(heteroprio->workers_heteroprio[idx_worker].arch_index == worker->arch_index
+                    && heteroprio->workers_heteroprio[idx_worker].tasks_queue_size){
+                task = heteroprio->workers_heteroprio[idx_worker].tasks_queue[heteroprio->workers_heteroprio[idx_worker].tasks_queue_index];
+                heteroprio->workers_heteroprio[idx_worker].tasks_queue_index = (heteroprio->workers_heteroprio[idx_worker].tasks_queue_index+1)%HETEROPRIO_MAX_PREFETCH;
+                heteroprio->workers_heteroprio[idx_worker].tasks_queue_size -= 1;
+                heteroprio->nb_prefetched_tasks_per_arch_index[heteroprio->workers_heteroprio[idx_worker].arch_index] -= 1;
+                break;
+            }
+        }
+    }
+
+    /* Copy of eager */
+    if (!task){
+        /* Tell pushers that we are waiting for tasks_queue for us */
+        starpu_bitmap_set(heteroprio->waiters, workerid);
+    }
+    STARPU_PTHREAD_MUTEX_UNLOCK(&heteroprio->policy_mutex);
+
+    if(task){
+        unsigned child_sched_ctx = starpu_sched_ctx_worker_is_master_for_child_ctx(workerid, sched_ctx_id);
+        if(child_sched_ctx != STARPU_NMAX_SCHED_CTXS){
+            starpu_sched_ctx_revert_task_counters(sched_ctx_id, task->flops);
+            starpu_sched_ctx_move_task_to_ctx(task, child_sched_ctx);
+            return NULL;
+        }
+    }
+    /* End copy of eager */
+
+    return task;
+}
+
+
+struct starpu_sched_policy _starpu_sched_heteroprio_policy_build(){
+    struct starpu_sched_policy policy;
+    memset(&policy, 0, sizeof(policy));
+    policy.init_sched         = initialize_heteroprio_center_policy;
+    policy.deinit_sched       = deinitialize_heteroprio_center_policy;
+    policy.add_workers        = NULL;
+    policy.remove_workers     = NULL;
+    policy.push_task          = push_task_heteroprio_policy;
+    policy.pop_task           = pop_task_heteroprio_policy;
+    policy.pre_exec_hook      = NULL;
+    policy.post_exec_hook     = NULL;
+    policy.pop_every_task     = NULL;
+    policy.policy_name        = "heteroprio";
+    policy.policy_description = "heteroprio policy from scalfmm";
+    return policy;
+}
+
+struct starpu_sched_policy _starpu_sched_heteroprio_policy = _starpu_sched_heteroprio_policy_build();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FSTARPUHETEOPRIO_HPP
+