Prechádzať zdrojové kódy

reintegrate branch synchro intro trunk

Olivier Aumage 8 rokov pred
rodič
commit
2e06af2c9a
64 zmenil súbory, kde vykonal 2121 pridanie a 1256 odobranie
  1. 2 0
      examples/mandelbrot/mandelbrot.c
  2. 4 1
      examples/sched_ctx/nested_sched_ctxs.c
  3. 14 10
      examples/sched_ctx/parallel_tasks_reuse_handle.c
  4. 18 10
      examples/sched_ctx/sched_ctx.c
  5. 15 0
      include/starpu_sched_component.h
  6. 6 2
      include/starpu_sched_ctx.h
  7. 2 5
      include/starpu_scheduler.h
  8. 1 1
      include/starpu_worker.h
  9. 9 0
      socl/examples/matmul/matmul.c
  10. 11 0
      src/common/graph.c
  11. 2 19
      src/common/thread.c
  12. 1 1
      src/core/combined_workers.c
  13. 1 3
      src/core/errorcheck.h
  14. 2 2
      src/core/jobs.c
  15. 0 1
      src/core/perfmodel/multiple_regression.c
  16. 20 7
      src/core/perfmodel/perfmodel.c
  17. 157 3
      src/core/perfmodel/perfmodel_history.c
  18. 583 380
      src/core/sched_ctx.c
  19. 62 45
      src/core/sched_ctx.h
  20. 2 1
      src/core/sched_ctx_list.c
  21. 17 9
      src/core/sched_policy.c
  22. 1 0
      src/core/task.c
  23. 148 57
      src/core/workers.c
  24. 452 20
      src/core/workers.h
  25. 24 26
      src/datawizard/copy_driver.c
  26. 4 4
      src/datawizard/memory_nodes.c
  27. 6 6
      src/datawizard/memory_nodes.h
  28. 9 2
      src/drivers/cpu/driver_cpu.c
  29. 29 1
      src/drivers/cuda/driver_cuda.c
  30. 72 81
      src/drivers/driver_common/driver_common.c
  31. 10 3
      src/drivers/opencl/driver_opencl.c
  32. 9 10
      src/sched_policies/component_fifo.c
  33. 8 8
      src/sched_policies/component_heft.c
  34. 4 4
      src/sched_policies/component_mct.c
  35. 33 14
      src/sched_policies/component_prio.c
  36. 12 10
      src/sched_policies/component_sched.c
  37. 18 18
      src/sched_policies/component_work_stealing.c
  38. 67 193
      src/sched_policies/component_worker.c
  39. 32 49
      src/sched_policies/deque_modeling_policy_data_aware.c
  40. 27 11
      src/sched_policies/eager_central_policy.c
  41. 29 24
      src/sched_policies/eager_central_priority_policy.c
  42. 35 6
      src/sched_policies/graph_test_policy.c
  43. 3 2
      src/sched_policies/helper_mct.c
  44. 18 19
      src/sched_policies/heteroprio.c
  45. 1 1
      src/sched_policies/modular_eager.c
  46. 1 1
      src/sched_policies/modular_eager_prefetching.c
  47. 1 1
      src/sched_policies/modular_heft.c
  48. 1 1
      src/sched_policies/modular_heft2.c
  49. 1 1
      src/sched_policies/modular_heft_prio.c
  50. 1 1
      src/sched_policies/modular_prio.c
  51. 1 1
      src/sched_policies/modular_prio_prefetching.c
  52. 2 2
      src/sched_policies/modular_random.c
  53. 2 2
      src/sched_policies/modular_random_prefetching.c
  54. 1 1
      src/sched_policies/modular_ws.c
  55. 21 16
      src/sched_policies/parallel_eager.c
  56. 41 54
      src/sched_policies/parallel_heft.c
  57. 2 8
      src/sched_policies/sched_component.h
  58. 1 1
      src/sched_policies/scheduler_maker.c
  59. 44 46
      src/sched_policies/work_stealing_policy.c
  60. 1 1
      src/worker_collection/worker_list.c
  61. 2 2
      src/worker_collection/worker_tree.c
  62. 16 9
      tests/sched_ctx/sched_ctx_hierarchy.c
  63. 2 2
      tests/sched_policies/simple_cpu_gpu_sched.c
  64. 0 37
      tools/valgrind/starpu.suppr

+ 2 - 0
examples/mandelbrot/mandelbrot.c

@@ -497,7 +497,9 @@ int main(int argc, char **argv)
 	conf.ncuda = 0;
 
 	if (use_spmd_p)
+	{
 		conf.sched_policy_name = "peager";
+	}
 
 	ret = starpu_init(&conf);
 	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");

+ 4 - 1
examples/sched_ctx/nested_sched_ctxs.c

@@ -53,7 +53,10 @@ static void sched_ctx_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg)
 	unsigned sched_ctx = (uintptr_t)arg;
 	int t = parallel_code(sched_ctx);
 	if (sched_ctx > 0 && sched_ctx < 3)
-		tasks_executed[sched_ctx-1] += t;
+	{
+		STARPU_ATOMIC_ADD(&tasks_executed[sched_ctx-1], t);
+	}
+
 	//printf("w %d executed %d it \n", w, n);
 }
 

+ 14 - 10
examples/sched_ctx/parallel_tasks_reuse_handle.c

@@ -17,6 +17,7 @@
 
 #include <starpu.h>
 #include <omp.h>
+#include <pthread.h>
 
 #ifdef STARPU_QUICK_CHECK
 #define NTASKS 64
@@ -28,6 +29,8 @@
 #define LOOPS  10
 #endif
 
+#define N_NESTED_CTXS 2
+
 struct context
 {
 	int ncpus;
@@ -38,6 +41,7 @@ struct context
 /* Helper for the task that will initiate everything */
 void parallel_task_prologue_init_once_and_for_all(void * sched_ctx_)
 {
+	fprintf(stderr, "%p: %s -->\n", (void*)pthread_self(), __func__);
 	int sched_ctx = *(int *)sched_ctx_;
 	int *cpuids = NULL;
 	int ncpuids = 0;
@@ -50,6 +54,7 @@ void parallel_task_prologue_init_once_and_for_all(void * sched_ctx_)
 
 	omp_set_num_threads(ncpuids);
 	free(cpuids);
+	fprintf(stderr, "%p: %s <--\n", (void*)pthread_self(), __func__);
 	return;
 }
 
@@ -101,25 +106,24 @@ void parallel_task_init()
 						  0);
 
 	/* Initialize nested contexts */
-	/* WARNING : the number of contexts must be a divisor of the number of available cpus*/
-
-	contexts = malloc(sizeof(struct context)*2);
-	int cpus_per_context = main_context.ncpus/2;
+	contexts = malloc(sizeof(struct context)*N_NESTED_CTXS);
+	int cpus_per_context = main_context.ncpus/N_NESTED_CTXS;
 	int i;
-	for(i = 0; i < 2; i++)
+	for(i = 0; i < N_NESTED_CTXS; i++)
 	{
-		fprintf(stderr, "ncpus %d for context %d \n",cpus_per_context, i);
 		contexts[i].ncpus = cpus_per_context;
+		if (i == N_NESTED_CTXS-1)
+			contexts[i].ncpus += main_context.ncpus%N_NESTED_CTXS;
 		contexts[i].cpus = main_context.cpus+i*cpus_per_context;
 	}
 
-	for(i = 0; i < 2; i++)
+	for(i = 0; i < N_NESTED_CTXS; i++)
 		contexts[i].id = starpu_sched_ctx_create(contexts[i].cpus,
 							 contexts[i].ncpus,"nested_ctx",
 							 STARPU_SCHED_CTX_NESTED,main_context.id,
 							 0);
 
-	for (i = 0; i < 2; i++)
+	for (i = 0; i < N_NESTED_CTXS; i++)
 	{
 		parallel_task_init_one_context(&contexts[i].id);
 	}
@@ -131,7 +135,7 @@ void parallel_task_init()
 void parallel_task_deinit()
 {
 	int i;
-	for (i=0; i<2;i++)
+	for (i=0; i<N_NESTED_CTXS;i++)
 		starpu_sched_ctx_delete(contexts[i].id);
 	free(contexts);
 	free(main_context.cpus);
@@ -174,7 +178,7 @@ int main(int argc, char **argv)
 		return 77;
 	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
 
-	if (starpu_cpu_worker_get_count() < 2)
+	if (starpu_cpu_worker_get_count() < N_NESTED_CTXS)
 	{
 		starpu_shutdown();
 		return 77;

+ 18 - 10
examples/sched_ctx/sched_ctx.c

@@ -25,17 +25,25 @@
 #endif
 
 int tasks_executed = 0;
-starpu_pthread_mutex_t mut;
+int ctx1_tasks_executed = 0;
+int ctx2_tasks_executed = 0;
 
 static void sched_ctx_cpu_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg STARPU_ATTRIBUTE_UNUSED)
 {
-	STARPU_PTHREAD_MUTEX_LOCK(&mut);
-	tasks_executed++;
-	STARPU_PTHREAD_MUTEX_UNLOCK(&mut);
+	(void)STARPU_ATOMIC_ADD(&tasks_executed,1);
+	(void)STARPU_ATOMIC_ADD(&ctx1_tasks_executed,1);
 }
 
-static void sched_ctx_cuda_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg STARPU_ATTRIBUTE_UNUSED)
+static void sched_ctx2_cpu_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg STARPU_ATTRIBUTE_UNUSED)
 {
+	(void)STARPU_ATOMIC_ADD(&tasks_executed,1);
+	(void)STARPU_ATOMIC_ADD(&ctx2_tasks_executed,1);
+}
+
+static void sched_ctx2_cuda_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg STARPU_ATTRIBUTE_UNUSED)
+{
+	(void)STARPU_ATOMIC_ADD(&tasks_executed,1);
+	(void)STARPU_ATOMIC_ADD(&ctx2_tasks_executed,1);
 }
 
 static struct starpu_codelet sched_ctx_codelet1 =
@@ -48,8 +56,8 @@ static struct starpu_codelet sched_ctx_codelet1 =
 
 static struct starpu_codelet sched_ctx_codelet2 =
 {
-	.cpu_funcs = {sched_ctx_cpu_func},
-	.cuda_funcs = {sched_ctx_cuda_func},
+	.cpu_funcs = {sched_ctx2_cpu_func},
+	.cuda_funcs = {sched_ctx2_cuda_func},
 	.model = NULL,
 	.nbuffers = 0,
 	.name = "sched_ctx"
@@ -71,8 +79,6 @@ int main(int argc, char **argv)
 		return 77;
 	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
 
-	STARPU_PTHREAD_MUTEX_INIT(&mut, NULL);
-
 #ifdef STARPU_USE_CPU
 	nprocs1 = starpu_cpu_worker_get_count();
 	starpu_worker_get_ids_by_type(STARPU_CPU_WORKER, procs1, nprocs1);
@@ -155,7 +161,9 @@ int main(int argc, char **argv)
 	starpu_sched_ctx_add_workers(procs1, nprocs1, sched_ctx2);
 	starpu_sched_ctx_delete(sched_ctx1);
 	starpu_sched_ctx_delete(sched_ctx2);
-	printf("tasks executed %d out of %d\n", tasks_executed, ntasks/2);
+	printf("tasks executed %d out of %d\n", tasks_executed, ntasks+1);
+	printf("tasks executed on ctx1: %d\n", ctx1_tasks_executed);
+	printf("tasks executed on ctx2: %d\n", ctx2_tasks_executed);
 
 enodev:
 	starpu_shutdown();

+ 15 - 0
include/starpu_sched_component.h

@@ -110,6 +110,7 @@ void starpu_sched_component_prefetch_on_node(struct starpu_sched_component *comp
 void starpu_sched_component_connect(struct starpu_sched_component *parent, struct starpu_sched_component *child);
 
 struct starpu_sched_component *starpu_sched_component_worker_get(unsigned sched_ctx, int workerid);
+struct starpu_sched_component *starpu_sched_component_worker_new(unsigned sched_ctx, int workerid);
 int starpu_sched_component_worker_get_workerid(struct starpu_sched_component *worker_component);
 int starpu_sched_component_is_worker(struct starpu_sched_component *component);
 int starpu_sched_component_is_simple_worker(struct starpu_sched_component *component);
@@ -199,6 +200,20 @@ struct starpu_sched_component_specs
 struct starpu_sched_tree *starpu_sched_component_make_scheduler(unsigned sched_ctx_id, struct starpu_sched_component_specs s);
 #endif /* STARPU_HAVE_HWLOC */
 
+#define STARPU_COMPONENT_MUTEX_LOCK(m) \
+do \
+{ \
+	const int _relaxed_state = _starpu_worker_get_relax_state(); \
+	if (!_relaxed_state) \
+		_starpu_worker_relax_on(); \
+	STARPU_PTHREAD_MUTEX_LOCK((m)); \
+	if (!_relaxed_state) \
+		_starpu_worker_relax_off(); \
+} \
+while(0)
+
+#define STARPU_COMPONENT_MUTEX_UNLOCK(m) STARPU_PTHREAD_MUTEX_UNLOCK((m))
+
 #ifdef __cplusplus
 }
 #endif

+ 6 - 2
include/starpu_sched_ctx.h

@@ -43,9 +43,9 @@ unsigned starpu_sched_ctx_create_inside_interval(const char *policy_name, const
 
 void starpu_sched_ctx_register_close_callback(unsigned sched_ctx_id, void (*close_callback)(unsigned sched_ctx_id, void* args), void *args);
 
-void starpu_sched_ctx_add_workers(int *workerids_ctx, int nworkers_ctx, unsigned sched_ctx_id);
+void starpu_sched_ctx_add_workers(int *workerids_ctx, unsigned nworkers_ctx, unsigned sched_ctx_id);
 
-void starpu_sched_ctx_remove_workers(int *workerids_ctx, int nworkers_ctx, unsigned sched_ctx_id);
+void starpu_sched_ctx_remove_workers(int *workerids_ctx, unsigned nworkers_ctx, unsigned sched_ctx_id);
 
 void starpu_sched_ctx_display_workers(unsigned sched_ctx_id, FILE *f);
 
@@ -134,8 +134,10 @@ void starpu_sched_ctx_list_task_counters_decrement(unsigned sched_ctx_id, int wo
 void starpu_sched_ctx_list_task_counters_reset(unsigned sched_ctx_id, int workerid);
 
 void starpu_sched_ctx_list_task_counters_increment_all(struct starpu_task *task, unsigned sched_ctx_id);
+void starpu_sched_ctx_list_task_counters_increment_all_ctx_locked(struct starpu_task *task, unsigned sched_ctx_id);
 
 void starpu_sched_ctx_list_task_counters_decrement_all(struct starpu_task *task, unsigned sched_ctx_id);
+void starpu_sched_ctx_list_task_counters_decrement_all_ctx_locked(struct starpu_task *task, unsigned sched_ctx_id);
 
 void starpu_sched_ctx_list_task_counters_reset_all(struct starpu_task *task, unsigned sched_ctx_id);
 
@@ -161,8 +163,10 @@ unsigned starpu_sched_ctx_worker_is_master_for_child_ctx(int workerid, unsigned
 unsigned starpu_sched_ctx_master_get_context(int masterid);
 
 void starpu_sched_ctx_revert_task_counters(unsigned sched_ctx_id, double flops);
+void starpu_sched_ctx_revert_task_counters_ctx_locked(unsigned sched_ctx_id, double flops);
 
 void starpu_sched_ctx_move_task_to_ctx(struct starpu_task *task, unsigned sched_ctx, unsigned manage_mutex, unsigned with_repush);
+void starpu_sched_ctx_move_task_to_ctx_locked(struct starpu_task *task, unsigned sched_ctx, unsigned with_repush);
 
 int starpu_sched_ctx_get_worker_rank(unsigned sched_ctx_id);
 

+ 2 - 5
include/starpu_scheduler.h

@@ -60,13 +60,10 @@ void starpu_worker_get_sched_condition(int workerid, starpu_pthread_mutex_t **sc
 unsigned long starpu_task_get_job_id(struct starpu_task *task);
 
 /* This function must be called to wake up a worker that is sleeping on the cond. 
- * It returns 0 whenever the worker is not in a sleeping state */
-int starpu_wake_worker(int workerid);
-int starpu_wakeup_worker(int workerid, starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex);
+ * It returns 0 whenever the worker is not in a sleeping state or has the state_keep_awake flag on */
+int starpu_wake_worker_no_relax(int workerid);
 /* This is a version of starpu_wake_worker which assumes that the sched mutex is locked */
 int starpu_wake_worker_locked(int workerid);
-/* This is a version of starpu_wakeup_worker which assumes that the sched mutex is locked */
-int starpu_wakeup_worker_locked(int workerid, starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex);
 
 int starpu_worker_can_execute_task(unsigned workerid, struct starpu_task *task, unsigned nimpl);
 int starpu_worker_can_execute_task_impl(unsigned workerid, struct starpu_task *task, unsigned *impl_mask);

+ 1 - 1
include/starpu_worker.h

@@ -127,7 +127,7 @@ struct starpu_tree* starpu_workers_get_tree(void);
 
 unsigned starpu_worker_get_sched_ctx_list(int worker, unsigned **sched_ctx);
 
-unsigned starpu_worker_is_blocked(int workerid);
+unsigned starpu_worker_is_blocked_in_parallel(int workerid);
 
 unsigned starpu_worker_is_slave_somewhere(int workerid);
 

+ 9 - 0
socl/examples/matmul/matmul.c

@@ -13,6 +13,14 @@
  *
  * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  */
+#ifndef STARPU_NON_BLOCKING_DRIVERS
+int main(int argc, const char** argv) {
+	(void) argv;
+	(void) argv;
+	/* testcase does not seem to support blocking drivers */
+	return 77;
+}
+#else
 
 #ifdef __APPLE_CC__
 #include <OpenCL/opencl.h>
@@ -512,3 +520,4 @@ void computeReference(TYPE* C, const TYPE* A, const TYPE* B, unsigned int hA, un
 			C[i * wB + j] = (TYPE)sum;
 		}
 }
+#endif /* STARPU_NON_BLOCKING_DRIVERS */

+ 11 - 0
src/common/graph.c

@@ -28,6 +28,7 @@
 #include <starpu.h>
 #include <core/jobs.h>
 #include <common/graph.h>
+#include <core/workers.h>
 
 /* Protects the whole task graph except the dropped list */
 static starpu_pthread_rwlock_t graph_lock;
@@ -60,7 +61,9 @@ void _starpu_graph_init(void)
 /* LockWR the graph lock */
 void _starpu_graph_wrlock(void)
 {
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_RWLOCK_WRLOCK(&graph_lock);
+	_starpu_worker_relax_off();
 }
 
 void _starpu_graph_drop_node(struct _starpu_graph_node *node);
@@ -94,14 +97,18 @@ void _starpu_graph_drop_dropped_nodes(void)
 /* UnlockWR the graph lock */
 void _starpu_graph_wrunlock(void)
 {
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&dropped_lock);
+	_starpu_worker_relax_off();
 	_starpu_graph_drop_dropped_nodes();
 }
 
 /* LockRD the graph lock */
 void _starpu_graph_rdlock(void)
 {
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_RWLOCK_RDLOCK(&graph_lock);
+	_starpu_worker_relax_off();
 }
 
 /* UnlockRD the graph lock */
@@ -247,12 +254,16 @@ void _starpu_graph_drop_job(struct _starpu_job *job)
 	if (!node)
 		return;
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&node->mutex);
+	_starpu_worker_relax_off();
 	/* Will not be able to use the job any more */
 	node->job = NULL;
 	STARPU_PTHREAD_MUTEX_UNLOCK(&node->mutex);
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&dropped_lock);
+	_starpu_worker_relax_off();
 	/* Queue for removal when lock becomes available */
 	_starpu_graph_node_multilist_push_back_dropped(&dropped, node);
 	if (STARPU_PTHREAD_RWLOCK_TRYWRLOCK(&graph_lock) == 0)

+ 2 - 19
src/common/thread.c

@@ -720,34 +720,17 @@ int starpu_pthread_barrier_wait(starpu_pthread_barrier_t *barrier)
  * macros of course) which record when the mutex is held or not */
 int starpu_pthread_mutex_lock_sched(starpu_pthread_mutex_t *mutex)
 {
-	int p_ret = starpu_pthread_mutex_lock(mutex);
-	int workerid = starpu_worker_get_id();
-	if(workerid != -1 && _starpu_worker_mutex_is_sched_mutex(workerid, mutex))
-		_starpu_worker_set_flag_sched_mutex_locked(workerid, 1);
-	return p_ret;
+	return starpu_pthread_mutex_lock(mutex);
 }
 
 int starpu_pthread_mutex_unlock_sched(starpu_pthread_mutex_t *mutex)
 {
-	int workerid = starpu_worker_get_id();
-	if(workerid != -1 && _starpu_worker_mutex_is_sched_mutex(workerid, mutex))
-		_starpu_worker_set_flag_sched_mutex_locked(workerid, 0);
-
 	return starpu_pthread_mutex_unlock(mutex);
 }
 
 int starpu_pthread_mutex_trylock_sched(starpu_pthread_mutex_t *mutex)
 {
-	int ret = starpu_pthread_mutex_trylock(mutex);
-
-	if (!ret)
-	{
-		int workerid = starpu_worker_get_id();
-		if(workerid != -1 && _starpu_worker_mutex_is_sched_mutex(workerid, mutex))
-			_starpu_worker_set_flag_sched_mutex_locked(workerid, 1);
-	}
-
-	return ret;
+	return starpu_pthread_mutex_trylock(mutex);
 }
 
 #ifdef STARPU_DEBUG

+ 1 - 1
src/core/combined_workers.c

@@ -160,7 +160,7 @@ int starpu_combined_worker_assign_workerid(int nworkers, int workerid_array[])
 #endif
 	}
 
-	starpu_sched_ctx_add_workers(&combined_worker_id, 1, STARPU_GLOBAL_SCHED_CTX);
+	starpu_sched_ctx_add_combined_workers(&combined_worker_id, 1, STARPU_GLOBAL_SCHED_CTX);
 
 	return new_workerid;
 }

+ 1 - 3
src/core/errorcheck.h

@@ -37,9 +37,7 @@ enum _starpu_worker_status
 	/* while executing the scheduler code */
 	STATUS_SCHEDULING,
 	/* while sleeping because there is nothing to do */
-	STATUS_SLEEPING,
-	/* while a sleeping worker is about to wake up (to avoid waking twice for the same worker) */
-	STATUS_WAKING_UP
+	STATUS_SLEEPING
 };
 
 struct _starpu_worker;

+ 2 - 2
src/core/jobs.c

@@ -714,7 +714,7 @@ int _starpu_push_local_task(struct _starpu_worker *worker, struct starpu_task *t
 	if (STARPU_UNLIKELY(!(worker->worker_mask & task->cl->where)))
 		return -ENODEV;
 
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+	_starpu_worker_lock(worker->workerid);
 
 	if (task->execute_on_a_specific_worker && task->workerorder)
 	{
@@ -758,7 +758,7 @@ int _starpu_push_local_task(struct _starpu_worker *worker, struct starpu_task *t
 
 	starpu_wake_worker_locked(worker->workerid);
 	starpu_push_task_end(task);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+	_starpu_worker_unlock(worker->workerid);
 
 	return 0;
 }

+ 0 - 1
src/core/perfmodel/multiple_regression.c

@@ -265,7 +265,6 @@ int _starpu_multiple_regression(struct starpu_perfmodel_history_list *ptr, doubl
 
 	/* Computing number of rows */
 	long n=find_long_list_size(ptr);
-	STARPU_ASSERT(n);
 
         /* Reading old calibrations if necessary */
 	FILE *f=NULL;

+ 20 - 7
src/core/perfmodel/perfmodel.c

@@ -181,6 +181,7 @@ void _starpu_init_and_load_perfmodel(struct starpu_perfmodel *model)
 
 static double starpu_model_expected_perf(struct starpu_task *task, struct starpu_perfmodel *model, struct starpu_perfmodel_arch* arch,  unsigned nimpl)
 {
+	double exp_perf = 0.0;
 	if (model)
 	{
 		_starpu_init_and_load_perfmodel(model);
@@ -190,24 +191,36 @@ static double starpu_model_expected_perf(struct starpu_task *task, struct starpu
 		switch (model->type)
 		{
 			case STARPU_PER_ARCH:
-				return per_arch_task_expected_perf(model, arch, task, nimpl);
+				exp_perf = per_arch_task_expected_perf(model, arch, task, nimpl);
+				STARPU_ASSERT_MSG(isnan(exp_perf)||exp_perf>=0,"exp_perf=%lf\n",exp_perf);
+				break;
 			case STARPU_COMMON:
-				return common_task_expected_perf(model, arch, task, nimpl);
+				exp_perf = common_task_expected_perf(model, arch, task, nimpl);
+				STARPU_ASSERT_MSG(isnan(exp_perf)||exp_perf>=0,"exp_perf=%lf\n",exp_perf);
+				break;
 			case STARPU_HISTORY_BASED:
-				return _starpu_history_based_job_expected_perf(model, arch, j, nimpl);
+				exp_perf = _starpu_history_based_job_expected_perf(model, arch, j, nimpl);
+				STARPU_ASSERT_MSG(isnan(exp_perf)||exp_perf>=0,"exp_perf=%lf\n",exp_perf);
+				break;
 			case STARPU_REGRESSION_BASED:
-				return _starpu_regression_based_job_expected_perf(model, arch, j, nimpl);
+				exp_perf = _starpu_regression_based_job_expected_perf(model, arch, j, nimpl);
+				STARPU_ASSERT_MSG(isnan(exp_perf)||exp_perf>=0,"exp_perf=%lf\n",exp_perf);
+				break;
 			case STARPU_NL_REGRESSION_BASED:
-				return _starpu_non_linear_regression_based_job_expected_perf(model, arch, j,nimpl);
+				exp_perf = _starpu_non_linear_regression_based_job_expected_perf(model, arch, j,nimpl);
+				STARPU_ASSERT_MSG(isnan(exp_perf)||exp_perf>=0,"exp_perf=%lf\n",exp_perf);
+				break;
 			case STARPU_MULTIPLE_REGRESSION_BASED:
-				return _starpu_multiple_regression_based_job_expected_perf(model, arch, j, nimpl);
+				exp_perf = _starpu_multiple_regression_based_job_expected_perf(model, arch, j, nimpl);
+				STARPU_ASSERT_MSG(isnan(exp_perf)||exp_perf>=0,"exp_perf=%lf\n",exp_perf);
+				break;
 			default:
 				STARPU_ABORT();
 		}
 	}
 
 	/* no model was found */
-	return 0.0;
+	return exp_perf;
 }
 
 double starpu_task_expected_length(struct starpu_task *task, struct starpu_perfmodel_arch* arch, unsigned nimpl)

+ 157 - 3
src/core/perfmodel/perfmodel_history.c

@@ -242,6 +242,68 @@ static void insert_history_entry(struct starpu_perfmodel_history_entry *entry, s
 }
 
 #ifndef STARPU_SIMGRID
+static void check_reg_model(struct starpu_perfmodel *model, int comb, int impl)
+{
+	struct starpu_perfmodel_per_arch *per_arch_model;
+
+	per_arch_model = &model->state->per_arch[comb][impl];
+	struct starpu_perfmodel_regression_model *reg_model;
+	reg_model = &per_arch_model->regression;
+
+	/*
+	 * Linear Regression model
+	 */
+
+	/* Unless we have enough measurements, we put NaN in the file to indicate the model is invalid */
+	double alpha = nan(""), beta = nan("");
+	if (model->type == STARPU_REGRESSION_BASED || model->type == STARPU_NL_REGRESSION_BASED)
+	{
+		if (reg_model->nsample > 1)
+		{
+			alpha = reg_model->alpha;
+			beta = reg_model->beta;
+		}
+	}
+
+	/* TODO: check:
+	 * reg_model->sumlnx
+	 * reg_model->sumlnx2
+	 * reg_model->sumlny
+	 * reg_model->sumlnxlny
+	 * alpha
+	 * beta
+	 * reg_model->minx
+	 * reg_model->maxx
+	 */
+	STARPU_ASSERT(reg_model->nsample >= 0);
+	(void)alpha;
+	(void)beta;
+
+	/*
+	 * Non-Linear Regression model
+	 */
+
+	double a = nan(""), b = nan(""), c = nan("");
+
+	if (model->type == STARPU_NL_REGRESSION_BASED)
+		_starpu_regression_non_linear_power(per_arch_model->list, &a, &b, &c);
+
+	/* TODO: check:
+	 * a
+	 * b
+	 * c
+	 */
+
+	/*
+	 * Multiple Regression Model
+	 */
+
+	if (model->type == STARPU_MULTIPLE_REGRESSION_BASED)
+	{
+		/* TODO: check: */
+	}
+}
+
 static void dump_reg_model(FILE *f, struct starpu_perfmodel *model, int comb, int impl)
 {
 	struct starpu_perfmodel_per_arch *per_arch_model;
@@ -416,6 +478,15 @@ static void scan_reg_model(FILE *f, const char *path, struct starpu_perfmodel_re
 
 
 #ifndef STARPU_SIMGRID
+static void check_history_entry(struct starpu_perfmodel_history_entry *entry)
+{
+	STARPU_ASSERT_MSG(entry->deviation >= 0, "entry=%p, entry->deviation=%lf\n", entry, entry->deviation);
+	STARPU_ASSERT_MSG(entry->sum >= 0, "entry=%p, entry->sum=%lf\n", entry, entry->sum);
+	STARPU_ASSERT_MSG(entry->sum2 >= 0, "entry=%p, entry->sum2=%lf\n", entry, entry->sum2);
+	STARPU_ASSERT_MSG(entry->mean >= 0, "entry=%p, entry->mean=%lf\n", entry, entry->mean);
+	STARPU_ASSERT_MSG(isnan(entry->flops)||entry->flops >= 0, "entry=%p, entry->flops=%lf\n", entry, entry->flops);
+	STARPU_ASSERT_MSG(entry->duration >= 0, "entry=%p, entry->duration=%lf\n", entry, entry->duration);
+}
 static void dump_history_entry(FILE *f, struct starpu_perfmodel_history_entry *entry)
 {
 	fprintf(f, "%08x\t%-15lu\t%-15e\t%-15e\t%-15e\t%-15e\t%-15e\t%u\n", entry->footprint, (unsigned long) entry->size, entry->flops, entry->mean, entry->deviation, entry->sum, entry->sum2, entry->nsample);
@@ -458,6 +529,11 @@ static void scan_history_entry(FILE *f, const char *path, struct starpu_perfmode
 
 	if (entry)
 	{
+		STARPU_ASSERT_MSG(flops >=0, "Negative flops %lf in performance model file %s", flops, path);
+		STARPU_ASSERT_MSG(mean >=0, "Negative mean %lf in performance model file %s", mean, path);
+		STARPU_ASSERT_MSG(deviation >=0, "Negative deviation %lf in performance model file %s", deviation, path);
+		STARPU_ASSERT_MSG(sum >=0, "Negative sum %lf in performance model file %s", sum, path);
+		STARPU_ASSERT_MSG(sum2 >=0, "Negative sum2 %lf in performance model file %s", sum2, path);
 		entry->footprint = footprint;
 		entry->size = size;
 		entry->flops = flops;
@@ -487,7 +563,7 @@ static void parse_per_arch_model_file(FILE *f, const char *path, struct starpu_p
 		struct starpu_perfmodel_history_entry *entry = NULL;
 		if (scan_history)
 		{
-			_STARPU_MALLOC(entry, sizeof(struct starpu_perfmodel_history_entry));
+			_STARPU_CALLOC(entry, 1, sizeof(struct starpu_perfmodel_history_entry));
 
 			/* Tell  helgrind that we do not care about
 			 * racing access to the sampling, we only want a
@@ -660,6 +736,43 @@ static int parse_model_file(FILE *f, const char *path, struct starpu_perfmodel *
 }
 
 #ifndef STARPU_SIMGRID
+static void check_per_arch_model(struct starpu_perfmodel *model, int comb, unsigned impl)
+{
+	struct starpu_perfmodel_per_arch *per_arch_model;
+
+	per_arch_model = &model->state->per_arch[comb][impl];
+	/* count the number of elements in the lists */
+	struct starpu_perfmodel_history_list *ptr = NULL;
+	unsigned nentries = 0;
+
+	if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
+	{
+		/* Dump the list of all entries in the history */
+		ptr = per_arch_model->list;
+		while(ptr)
+		{
+			nentries++;
+			ptr = ptr->next;
+		}
+	}
+
+	/* header */
+	char archname[32];
+	starpu_perfmodel_get_arch_name(arch_combs[comb], archname,  32, impl);
+	STARPU_ASSERT(strlen(archname)>0);
+	check_reg_model(model, comb, impl);
+
+	/* Dump the history into the model file in case it is necessary */
+	if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
+	{
+		ptr = per_arch_model->list;
+		while (ptr)
+		{
+			check_history_entry(ptr->entry);
+			ptr = ptr->next;
+		}
+	}
+}
 static void dump_per_arch_model_file(FILE *f, struct starpu_perfmodel *model, int comb, unsigned impl)
 {
 	struct starpu_perfmodel_per_arch *per_arch_model;
@@ -704,6 +817,39 @@ static void dump_per_arch_model_file(FILE *f, struct starpu_perfmodel *model, in
 	fprintf(f, "\n");
 }
 
+static void check_model(struct starpu_perfmodel *model)
+{
+	int ncombs = model->state->ncombs;
+	STARPU_ASSERT(ncombs >= 0);
+
+	int i, impl, dev;
+	for(i = 0; i < ncombs; i++)
+	{
+		int comb = model->state->combs[i];
+		STARPU_ASSERT(comb >= 0);
+
+		int ndevices = arch_combs[comb]->ndevices;
+		STARPU_ASSERT(ndevices >= 1);
+
+		for(dev = 0; dev < ndevices; dev++)
+		{
+			STARPU_ASSERT(arch_combs[comb]->devices[dev].type >= 0);
+			STARPU_ASSERT(arch_combs[comb]->devices[dev].type <= 5);
+
+			STARPU_ASSERT(arch_combs[comb]->devices[dev].devid >= 0);
+
+			STARPU_ASSERT(arch_combs[comb]->devices[dev].ncores >= 0);
+		}
+
+		int nimpls = model->state->nimpls[comb];
+		STARPU_ASSERT(nimpls >= 1);
+		for (impl = 0; impl < nimpls; impl++)
+		{
+			check_per_arch_model(model, comb, impl);
+		}
+	}
+}
+
 static void dump_model_file(FILE *f, struct starpu_perfmodel *model)
 {
 	fprintf(f, "##################\n");
@@ -873,6 +1019,7 @@ static void save_history_based_model(struct starpu_perfmodel *model)
 	STARPU_ASSERT_MSG(f, "Could not save performance model %s\n", path);
 
 	locked = _starpu_fwrlock(f) == 0;
+	check_model(model);
 	_starpu_fftruncate(f, 0);
 	dump_model_file(f, model);
 	if (locked)
@@ -1423,6 +1570,7 @@ double _starpu_history_based_job_expected_perf(struct starpu_perfmodel *model, s
 	history = per_arch_model->history;
 	HASH_FIND_UINT32_T(history, &key, elt);
 	entry = (elt == NULL) ? NULL : elt->history_entry;
+	STARPU_ASSERT_MSG(!entry || entry->mean >= 0, "entry=%p, entry->mean=%lf\n", entry, entry?entry->mean:NAN);
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&model->state->model_rwlock);
 
 	/* Here helgrind would shout that this is unprotected access.
@@ -1430,10 +1578,13 @@ double _starpu_history_based_job_expected_perf(struct starpu_perfmodel *model, s
 	 * a good-enough estimation */
 
 	if (entry && entry->nsample >= _starpu_calibration_minimum)
+	{
+		STARPU_ASSERT_MSG(entry->mean >= 0, "entry->mean=%lf\n", entry->mean);
 		/* TODO: report differently if we've scheduled really enough
 		 * of that task and the scheduler should perhaps put it aside */
 		/* Calibrated enough */
 		exp = entry->mean;
+	}
 
 docal:
 	STARPU_HG_DISABLE_CHECKING(model->benchmarking);
@@ -1447,6 +1598,7 @@ docal:
 		model->benchmarking = 1;
 	}
 
+	STARPU_ASSERT_MSG(isnan(exp)||exp >= 0, "exp=%lf\n", exp);
 	return exp;
 }
 
@@ -1470,6 +1622,7 @@ int _starpu_perfmodel_create_comb_if_needed(struct starpu_perfmodel_arch* arch)
 
 void _starpu_update_perfmodel_history(struct _starpu_job *j, struct starpu_perfmodel *model, struct starpu_perfmodel_arch* arch, unsigned cpuid STARPU_ATTRIBUTE_UNUSED, double measured, unsigned impl)
 {
+	STARPU_ASSERT_MSG(measured >= 0, "measured=%lf\n", measured);
 	if (model)
 	{
 		int c;
@@ -1526,7 +1679,7 @@ void _starpu_update_perfmodel_history(struct _starpu_job *j, struct starpu_perfm
 			if (!entry)
 			{
 				/* this is the first entry with such a footprint */
-				_STARPU_MALLOC(entry, sizeof(struct starpu_perfmodel_history_entry));
+				_STARPU_CALLOC(entry, 1, sizeof(struct starpu_perfmodel_history_entry));
 
 				/* Tell  helgrind that we do not care about
 				 * racing access to the sampling, we only want a
@@ -1585,7 +1738,7 @@ void _starpu_update_perfmodel_history(struct _starpu_job *j, struct starpu_perfm
 
 					unsigned n = entry->nsample;
 					entry->mean = entry->sum / n;
-					entry->deviation = sqrt((entry->sum2 - (entry->sum*entry->sum)/n)/n);
+					entry->deviation = sqrt((fabs(entry->sum2 - (entry->sum*entry->sum))/n)/n);
 				}
 
 				if (j->task->flops != 0.)
@@ -1645,6 +1798,7 @@ void _starpu_update_perfmodel_history(struct _starpu_job *j, struct starpu_perfm
 			_STARPU_MALLOC(entry->parameters, model->nparameters*sizeof(double));
 			model->parameters(j->task, entry->parameters);
 			entry->tag = j->task->tag_id;
+			STARPU_ASSERT(measured >= 0);
 			entry->duration = measured;
 
 			struct starpu_perfmodel_history_list *link;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 583 - 380
src/core/sched_ctx.c


+ 62 - 45
src/core/sched_ctx.h

@@ -74,27 +74,12 @@ struct _starpu_sched_ctx
 	long iterations[2];
 	int iteration_level;
 
-	/* cond to block push when there are no workers in the ctx */
-	starpu_pthread_cond_t no_workers_cond;
-
-	/* mutex to block push when there are no workers in the ctx */
-	starpu_pthread_mutex_t no_workers_mutex;
-
 	/*ready tasks that couldn't be pushed because the ctx has no workers*/
 	struct starpu_task_list empty_ctx_tasks;
 
-	/* mutext protecting empty_ctx_tasks list */
-	starpu_pthread_mutex_t empty_ctx_mutex;
-
 	/*ready tasks that couldn't be pushed because the the window of tasks was already full*/
 	struct starpu_task_list waiting_tasks;
 
-	/* mutext protecting waiting_tasks list */
-	starpu_pthread_mutex_t waiting_tasks_mutex;
-
-	/* mutext protecting write to all worker's sched_ctx_list structure for this sched_ctx */
-	starpu_pthread_mutex_t sched_ctx_list_mutex;
-
 	/* min CPUs to execute*/
 	int min_ncpus;
 
@@ -143,27 +128,6 @@ struct _starpu_sched_ctx
 	   if not master is -1 */
 	int main_master;
 
-	/* conditions variables used when parallel sections are executed in contexts */
-	starpu_pthread_cond_t parallel_sect_cond[STARPU_NMAXWORKERS];
-	starpu_pthread_mutex_t parallel_sect_mutex[STARPU_NMAXWORKERS];
-	starpu_pthread_cond_t parallel_sect_cond_busy[STARPU_NMAXWORKERS];
-	int busy[STARPU_NMAXWORKERS];
-
-	/* boolean indicating that workers should block in order to allow
-	   parallel sections to be executed on their allocated resources */
-	unsigned parallel_sect[STARPU_NMAXWORKERS];
-
-	/* semaphore that block appl thread until starpu threads are
-	   all blocked and ready to exec the parallel code */
-	starpu_sem_t fall_asleep_sem[STARPU_NMAXWORKERS];
-
-	/* semaphore that block appl thread until starpu threads are 
-	   all woke up and ready continue appl */
-	starpu_sem_t wake_up_sem[STARPU_NMAXWORKERS];
-
-	/* bool indicating if the workers is sleeping in this ctx */
-	unsigned sleeping[STARPU_NMAXWORKERS];
-
 	/* ctx nesting the current ctx */
 	unsigned nesting_sched_ctx;
 
@@ -191,8 +155,21 @@ struct _starpu_sched_ctx
 	int sms_end_idx;
 
 	int stream_worker;
+
+	starpu_pthread_rwlock_t rwlock;
+	starpu_pthread_t lock_write_owner;
 };
 
+/* per-worker list of deferred ctx_change ops */
+LIST_TYPE(_starpu_ctx_change,
+	int sched_ctx_id;
+	int op;
+	int nworkers_to_notify;
+	int *workerids_to_notify;
+	int nworkers_to_change;
+	int *workerids_to_change;
+);
+
 struct _starpu_machine_config;
 
 /* init sched_ctx_id of all contextes*/
@@ -242,19 +219,10 @@ void _starpu_worker_gets_out_of_ctx(unsigned sched_ctx_id, struct _starpu_worker
 /* Check if the worker belongs to another sched_ctx */
 unsigned _starpu_worker_belongs_to_a_sched_ctx(int workerid, unsigned sched_ctx_id);
 
-/* mutex synchronising several simultaneous modifications of a context */
-starpu_pthread_rwlock_t* _starpu_sched_ctx_get_changing_ctx_mutex(unsigned sched_ctx_id);
-
 /* indicates wheather this worker should go to sleep or not 
    (if it is the last one awake in a context he should better keep awake) */
 unsigned _starpu_sched_ctx_last_worker_awake(struct _starpu_worker *worker);
 
-/* let the appl know that the worker blocked to execute parallel code */
-void _starpu_sched_ctx_signal_worker_blocked(unsigned sched_ctx_id, int workerid);
-
-/* let the appl know that the worker woke up */
-void _starpu_sched_ctx_signal_worker_woke_up(unsigned sched_ctx_id, int workerid);
-
 /* If starpu_sched_ctx_set_context() has been called, returns the context
  * id set by its last call, or the id of the initial context */
 unsigned _starpu_sched_ctx_get_current_context();
@@ -273,10 +241,59 @@ void _starpu_sched_ctx_post_exec_task_cb(int workerid, struct starpu_task *task,
 
 #endif //STARPU_USE_SC_HYPERVISOR
 
+void starpu_sched_ctx_add_combined_workers(int *combined_workers_to_add, unsigned n_combined_workers_to_add, unsigned sched_ctx_id);
+
 /* if the worker is the master of a parallel context, and the job is meant to be executed on this parallel context, return a pointer to the context */
 struct _starpu_sched_ctx *__starpu_sched_ctx_get_sched_ctx_for_worker_and_job(struct _starpu_worker *worker, struct _starpu_job *j);
 
 #define _starpu_sched_ctx_get_sched_ctx_for_worker_and_job(w,j) \
 	(_starpu_get_nsched_ctxs() <= 1 ? _starpu_get_sched_ctx_struct(0) : __starpu_sched_ctx_get_sched_ctx_for_worker_and_job((w),(j)))
 
+static inline struct _starpu_sched_ctx *_starpu_get_sched_ctx_struct(unsigned id);
+
+static inline int _starpu_sched_ctx_check_write_locked(unsigned sched_ctx_id)
+{
+	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(sched_ctx_id);
+	return starpu_pthread_equal(sched_ctx->lock_write_owner, starpu_pthread_self());
+}
+#define STARPU_SCHED_CTX_CHECK_LOCK(sched_ctx_id) STARPU_ASSERT(_starpu_sched_ctx_check_write_locked((sched_ctx_id)))
+
+static inline void _starpu_sched_ctx_lock_write(unsigned sched_ctx_id)
+{
+	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(sched_ctx_id);
+	STARPU_HG_DISABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_ASSERT(!starpu_pthread_equal(sched_ctx->lock_write_owner, starpu_pthread_self()));
+	STARPU_HG_ENABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_PTHREAD_RWLOCK_WRLOCK(&sched_ctx->rwlock);
+	sched_ctx->lock_write_owner = starpu_pthread_self();
+}
+
+static inline void _starpu_sched_ctx_unlock_write(unsigned sched_ctx_id)
+{
+	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(sched_ctx_id);
+	STARPU_HG_DISABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_ASSERT(starpu_pthread_equal(sched_ctx->lock_write_owner, starpu_pthread_self()));
+	memset(&sched_ctx->lock_write_owner, 0, sizeof(sched_ctx->lock_write_owner));
+	STARPU_HG_ENABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_PTHREAD_RWLOCK_UNLOCK(&sched_ctx->rwlock);
+}
+
+static inline void _starpu_sched_ctx_lock_read(unsigned sched_ctx_id)
+{
+	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(sched_ctx_id);
+	STARPU_HG_DISABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_ASSERT(!starpu_pthread_equal(sched_ctx->lock_write_owner, starpu_pthread_self()));
+	STARPU_HG_ENABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_PTHREAD_RWLOCK_RDLOCK(&sched_ctx->rwlock);
+}
+
+static inline void _starpu_sched_ctx_unlock_read(unsigned sched_ctx_id)
+{
+	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(sched_ctx_id);
+	STARPU_HG_DISABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_ASSERT(!starpu_pthread_equal(sched_ctx->lock_write_owner, starpu_pthread_self()));
+	STARPU_HG_ENABLE_CHECKING(sched_ctx->lock_write_owner);
+	STARPU_PTHREAD_RWLOCK_UNLOCK(&sched_ctx->rwlock);
+}
+
 #endif // __SCHED_CONTEXT_H__

+ 2 - 1
src/core/sched_ctx_list.c

@@ -253,7 +253,8 @@ void _starpu_sched_ctx_list_remove_elt(struct _starpu_sched_ctx_list **list,
 		if (parent->prev == NULL)
 		{
 			*list = parent->next;
-			parent->next->prev = NULL;
+			if (parent->next != NULL)
+				parent->next->prev = NULL;
 		}
 		else
 		{

+ 17 - 9
src/core/sched_policy.c

@@ -433,9 +433,9 @@ int _starpu_repush_task(struct _starpu_job *j)
 
 		if(nworkers == 0)
 		{
-			STARPU_PTHREAD_MUTEX_LOCK(&sched_ctx->empty_ctx_mutex);
+			_starpu_sched_ctx_lock_write(sched_ctx->id);
 			starpu_task_list_push_front(&sched_ctx->empty_ctx_tasks, task);
-			STARPU_PTHREAD_MUTEX_UNLOCK(&sched_ctx->empty_ctx_mutex);
+			_starpu_sched_ctx_unlock_write(sched_ctx->id);
 #ifdef STARPU_USE_SC_HYPERVISOR
 			if(sched_ctx->id != 0 && sched_ctx->perf_counters != NULL
 			   && sched_ctx->perf_counters->notify_empty_ctx)
@@ -499,9 +499,9 @@ int _starpu_push_task_to_workers(struct starpu_task *task)
 
 		if (nworkers == 0)
 		{
-			STARPU_PTHREAD_MUTEX_LOCK(&sched_ctx->empty_ctx_mutex);
+			_starpu_sched_ctx_lock_write(sched_ctx->id);
 			starpu_task_list_push_back(&sched_ctx->empty_ctx_tasks, task);
-			STARPU_PTHREAD_MUTEX_UNLOCK(&sched_ctx->empty_ctx_mutex);
+			_starpu_sched_ctx_unlock_write(sched_ctx->id);
 #ifdef STARPU_USE_SC_HYPERVISOR
 			if(sched_ctx->id != 0 && sched_ctx->perf_counters != NULL
 			   && sched_ctx->perf_counters->notify_empty_ctx)
@@ -591,19 +591,29 @@ int _starpu_push_task_to_workers(struct starpu_task *task)
 		{
 			STARPU_ASSERT(sched_ctx->sched_policy->push_task);
 			/* check out if there are any workers in the context */
-			starpu_pthread_rwlock_t *changing_ctx_mutex = _starpu_sched_ctx_get_changing_ctx_mutex(sched_ctx->id);
-			STARPU_PTHREAD_RWLOCK_RDLOCK(changing_ctx_mutex);
 			nworkers = starpu_sched_ctx_get_nworkers(sched_ctx->id);
 			if (nworkers == 0)
 				ret = -1;
 			else
 			{
+				struct _starpu_worker *worker = _starpu_get_local_worker_key();
+				if (worker)
+				{
+					STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+					_starpu_worker_enter_sched_op(worker);
+					STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+				}
 				_STARPU_TASK_BREAK_ON(task, push);
 				_STARPU_SCHED_BEGIN;
 				ret = sched_ctx->sched_policy->push_task(task);
 				_STARPU_SCHED_END;
+				if (worker)
+				{
+					STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+					_starpu_worker_leave_sched_op(worker);
+					STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+				}
 			}
-			STARPU_PTHREAD_RWLOCK_UNLOCK(changing_ctx_mutex);
 		}
 
 		if(ret == -1)
@@ -954,7 +964,6 @@ pick:
 	 * We do have a task that uses multiformat handles. Let's create the
 	 * required conversion tasks.
 	 */
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
 	unsigned i;
 	unsigned nbuffers = STARPU_TASK_GET_NBUFFERS(task);
 	for (i = 0; i < nbuffers; i++)
@@ -978,7 +987,6 @@ pick:
 
 	task->mf_skip = 1;
 	starpu_task_list_push_back(&worker->local_tasks, task);
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
 	goto pick;
 
 profiling:

+ 1 - 0
src/core/task.c

@@ -801,6 +801,7 @@ int _starpu_task_submit_conversion_task(struct starpu_task *task,
 	struct _starpu_worker *worker;
 	worker = _starpu_get_worker_struct(workerid);
 	starpu_task_list_push_back(&worker->local_tasks, task);
+	starpu_wake_worker_locked(worker->workerid);
 
 	_starpu_profiling_set_task_push_end_time(task);
 

+ 148 - 57
src/core/workers.c

@@ -309,12 +309,15 @@ static inline int _starpu_can_use_nth_implementation(enum starpu_worker_archtype
 	return 0;
 }
 
+/* must be called with sched_mutex locked to protect state_blocked_in_parallel */
 int starpu_worker_can_execute_task(unsigned workerid, struct starpu_task *task, unsigned nimpl)
 {
-	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(task->sched_ctx);
-
 	/* if the worker is blocked in a parallel ctx don't submit tasks on it */
-	if(sched_ctx->parallel_sect[workerid] ) return 0;
+#ifdef STARPU_DEVEL
+#warning FIXME: this is very expensive, while can_execute is supposed to be not very costly so schedulers can call it a lot
+#endif
+	if(starpu_worker_is_blocked_in_parallel(workerid))
+		return 0;
 
 	/* TODO: check that the task operand sizes will fit on that device */
 	return (task->cl->where & _starpu_config.workers[workerid].worker_mask) &&
@@ -322,12 +325,12 @@ int starpu_worker_can_execute_task(unsigned workerid, struct starpu_task *task,
 		(!task->cl->can_execute || task->cl->can_execute(workerid, task, nimpl));
 }
 
+/* must be called with sched_mutex locked to protect state_blocked_in_parallel */
 int starpu_worker_can_execute_task_impl(unsigned workerid, struct starpu_task *task, unsigned *impl_mask)
 {
-	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(task->sched_ctx);
-
 	/* if the worker is blocked in a parallel ctx don't submit tasks on it */
-	if(sched_ctx->parallel_sect[workerid]) return 0;
+	if(starpu_worker_is_blocked_in_parallel(workerid))
+		return 0;
 
 	unsigned mask;
 	int i;
@@ -365,13 +368,15 @@ int starpu_worker_can_execute_task_impl(unsigned workerid, struct starpu_task *t
 	return mask != 0;
 }
 
+/* must be called with sched_mutex locked to protect state_blocked */
 int starpu_worker_can_execute_task_first_impl(unsigned workerid, struct starpu_task *task, unsigned *nimpl)
 {
-	struct _starpu_sched_ctx *sched_ctx = _starpu_get_sched_ctx_struct(task->sched_ctx);
+	/* if the worker is blocked in a parallel ctx don't submit tasks on it */
+	if(starpu_worker_is_blocked_in_parallel(workerid))
+		return 0;
 	int i;
 	enum starpu_worker_archtype arch;
 	struct starpu_codelet *cl;
-	if(sched_ctx->parallel_sect[workerid]) return 0;
 	/* TODO: check that the task operand sizes will fit on that device */
 	cl = task->cl;
 	if (!(cl->where & _starpu_config.workers[workerid].worker_mask)) return 0;
@@ -451,14 +456,9 @@ int starpu_combined_worker_can_execute_task(unsigned workerid, struct starpu_tas
  * Runtime initialization methods
  */
 
-static void _starpu_init_worker_queue(struct _starpu_worker *workerarg)
+static void _starpu_init_worker_queue(struct _starpu_worker *worker)
 {
-	starpu_pthread_cond_t *cond = &workerarg->sched_cond;
-	starpu_pthread_mutex_t *mutex = &workerarg->sched_mutex;
-
-	unsigned memory_node = workerarg->memory_node;
-
-	_starpu_memory_node_register_condition(cond, mutex, memory_node);
+	_starpu_memory_node_register_condition(worker, &worker->sched_cond, worker->memory_node);
 }
 
 /*
@@ -527,6 +527,7 @@ static void _starpu_worker_init(struct _starpu_worker *workerarg, struct _starpu
 	STARPU_PTHREAD_COND_INIT(&workerarg->sched_cond, NULL);
 	STARPU_PTHREAD_MUTEX_INIT(&workerarg->sched_mutex, NULL);
 	starpu_task_list_init(&workerarg->local_tasks);
+	_starpu_ctx_change_list_init(&workerarg->ctx_change_list);
 	workerarg->local_ordered_tasks = NULL;
 	workerarg->local_ordered_tasks_size = 0;
 	workerarg->current_ordered_task = 0;
@@ -548,6 +549,7 @@ static void _starpu_worker_init(struct _starpu_worker *workerarg, struct _starpu
 	workerarg->worker_is_running = 0;
 	workerarg->worker_is_initialized = 0;
 	workerarg->status = STATUS_INITIALIZING;
+	workerarg->state_keep_awake = 0;
 	/* name initialized by driver */
 	/* short_name initialized by driver */
 	workerarg->run_by_starpu = 1;
@@ -575,10 +577,28 @@ static void _starpu_worker_init(struct _starpu_worker *workerarg, struct _starpu
 	workerarg->reverse_phase[0] = 0;
 	workerarg->reverse_phase[1] = 0;
 	workerarg->pop_ctx_priority = 1;
-	workerarg->sched_mutex_locked = 0;
-	workerarg->blocked = 0;
 	workerarg->is_slave_somewhere = 0;
 
+	workerarg->state_relax_refcnt = 1;
+#ifdef STARPU_SPINLOCK_CHECK
+	workerarg->relax_on_file = __FILE__;
+	workerarg->relax_on_line = __LINE__;
+	workerarg->relax_on_func = __starpu_func__;
+	workerarg->relax_off_file = NULL;
+	workerarg->relax_off_line = 0;
+	workerarg->relax_off_func = NULL;
+#endif
+	workerarg->state_sched_op_pending = 0;
+	workerarg->state_changing_ctx_waiting = 0;
+	workerarg->state_changing_ctx_notice = 0;
+	workerarg->state_blocked_in_parallel_observed = 0;
+	workerarg->state_blocked_in_parallel = 0;
+	workerarg->state_block_in_parallel_req = 0;
+	workerarg->state_block_in_parallel_ack = 0;
+	workerarg->state_unblock_in_parallel_req = 0;
+	workerarg->state_unblock_in_parallel_ack = 0;
+	workerarg->block_in_parallel_ref_count = 0;
+
 	/* cpu_set/hwloc_cpu_set initialized in topology.c */
 }
 
@@ -1448,6 +1468,7 @@ out:
 			STARPU_ASSERT(worker->local_ordered_tasks[n] == NULL);
 		_starpu_sched_ctx_list_delete(&worker->sched_ctx_list);
 		free(worker->local_ordered_tasks);
+		STARPU_ASSERT(_starpu_ctx_change_list_empty(&worker->ctx_change_list));
 	}
 }
 
@@ -1680,14 +1701,72 @@ unsigned starpu_worker_get_count(void)
 	return _starpu_config.topology.nworkers;
 }
 
-unsigned starpu_worker_is_blocked(int workerid)
+unsigned starpu_worker_is_blocked_in_parallel(int workerid)
 {
-	return _starpu_config.workers[workerid].blocked;
+	int relax_own_observation_state = 0;
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+	struct _starpu_worker *cur_worker = NULL;
+	int cur_workerid = starpu_worker_get_id();
+	if (workerid != cur_workerid)
+	{
+		/* in order to observe the 'blocked' state of a worker from
+		 * another worker, we must avoid race conditions between
+		 * 'blocked' state changes and state observations. This is the
+		 * purpose of this 'if' block. */
+		cur_worker = cur_workerid<starpu_worker_get_count()?_starpu_get_worker_struct(cur_workerid):NULL;
+
+		relax_own_observation_state = (cur_worker != NULL) && (cur_worker->state_relax_refcnt == 0);
+		if (relax_own_observation_state && !worker->state_relax_refcnt)
+		{
+			/* moreover, when a worker (cur_worker != NULL)
+			 * observes another worker, we need to take special
+			 * care to avoid live locks, thus the observing worker
+			 * must enter the relaxed state (if not relaxed
+			 * already) before doing the observation in mutual
+			 * exclusion */
+			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+
+			STARPU_PTHREAD_MUTEX_LOCK_SCHED(&cur_worker->sched_mutex);
+			cur_worker->state_relax_refcnt = 1;
+			STARPU_PTHREAD_COND_BROADCAST(&cur_worker->sched_cond);
+			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&cur_worker->sched_mutex);
+
+			STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+		}
+		/* the observer waits for a safe window to observe the state,
+		 * and also waits for any pending blocking state change
+		 * requests to be processed, in order to not obtain an
+		 * ephemeral information */
+		while (!worker->state_relax_refcnt
+				|| worker->state_block_in_parallel_req
+				|| worker->state_unblock_in_parallel_req)
+		{
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+		}
+	}
+	unsigned ret = _starpu_config.workers[workerid].state_blocked_in_parallel;
+	/* once a worker state has been observed, the worker is 'tainted' for the next one full sched_op,
+	 * to avoid changing the observed worker state - on which the observer
+	 * made a scheduling decision - after the fact. */
+	worker->state_blocked_in_parallel_observed = 1;
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+	if (relax_own_observation_state)
+	{
+		STARPU_PTHREAD_MUTEX_LOCK_SCHED(&cur_worker->sched_mutex);
+		cur_worker->state_relax_refcnt = 0;
+		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&cur_worker->sched_mutex);
+	}
+	return ret;
 }
 
 unsigned starpu_worker_is_slave_somewhere(int workerid)
 {
-	return _starpu_config.workers[workerid].is_slave_somewhere;
+	_starpu_worker_lock(workerid);
+	unsigned ret = _starpu_config.workers[workerid].is_slave_somewhere;
+	_starpu_worker_unlock(workerid);
+	return ret;
 }
 
 int starpu_worker_get_count_by_type(enum starpu_worker_archtype type)
@@ -2042,26 +2121,33 @@ void starpu_worker_get_sched_condition(int workerid, starpu_pthread_mutex_t **sc
 	*sched_mutex = &_starpu_config.workers[workerid].sched_mutex;
 }
 
-int starpu_wakeup_worker_locked(int workerid, starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex STARPU_ATTRIBUTE_UNUSED)
+static int starpu_wakeup_worker_locked(int workerid, starpu_pthread_cond_t *sched_cond, starpu_pthread_mutex_t *mutex STARPU_ATTRIBUTE_UNUSED)
 {
 #ifdef STARPU_SIMGRID
 	starpu_pthread_queue_broadcast(&_starpu_simgrid_task_queue[workerid]);
 #endif
-	if (_starpu_config.workers[workerid].status == STATUS_SLEEPING)
+	if (_starpu_config.workers[workerid].status == STATUS_SCHEDULING)
+	{
+		_starpu_config.workers[workerid].state_keep_awake = 1;
+		return 1;
+	}
+	else if (_starpu_config.workers[workerid].status == STATUS_SLEEPING)
 	{
-		_starpu_config.workers[workerid].status = STATUS_WAKING_UP;
-		STARPU_PTHREAD_COND_SIGNAL(cond);
+		_starpu_config.workers[workerid].state_keep_awake = 1;
+		/* cond_broadcast is required over cond_signal since
+		 * the condition is share for multiple purpose */
+		STARPU_PTHREAD_COND_BROADCAST(sched_cond);
 		return 1;
 	}
 	return 0;
 }
 
-int starpu_wakeup_worker(int workerid, starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex)
+static int starpu_wakeup_worker_no_relax(int workerid, starpu_pthread_cond_t *sched_cond, starpu_pthread_mutex_t *sched_mutex)
 {
 	int success;
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(mutex);
-	success = starpu_wakeup_worker_locked(workerid, cond, mutex);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(mutex);
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	success = starpu_wakeup_worker_locked(workerid, sched_cond, sched_mutex);
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
 	return success;
 }
 
@@ -2073,12 +2159,12 @@ int starpu_wake_worker_locked(int workerid)
 	return starpu_wakeup_worker_locked(workerid, sched_cond, sched_mutex);
 }
 
-int starpu_wake_worker(int workerid)
+int starpu_wake_worker_no_relax(int workerid)
 {
 	starpu_pthread_mutex_t *sched_mutex;
 	starpu_pthread_cond_t *sched_cond;
 	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	return starpu_wakeup_worker(workerid, sched_cond, sched_mutex);
+	return starpu_wakeup_worker_no_relax(workerid, sched_cond, sched_mutex);
 }
 
 int starpu_worker_get_nids_by_type(enum starpu_worker_archtype type, int *workerids, int maxsize)
@@ -2154,33 +2240,6 @@ void starpu_get_version(int *major, int *minor, int *release)
 	*release = STARPU_RELEASE_VERSION;
 }
 
-void _starpu_unlock_mutex_if_prev_locked()
-{
-	int workerid = starpu_worker_get_id();
-	if(workerid != -1)
-	{
-		struct _starpu_worker *w = _starpu_get_worker_struct(workerid);
-		if(w->sched_mutex_locked)
-		{
-			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&w->sched_mutex);
-			_starpu_worker_set_flag_sched_mutex_locked(workerid, 1);
-		}
-	}
-	return;
-}
-
-void _starpu_relock_mutex_if_prev_locked()
-{
-	int workerid = starpu_worker_get_id();
-	if(workerid != -1)
-	{
-		struct _starpu_worker *w = _starpu_get_worker_struct(workerid);
-		if(w->sched_mutex_locked)
-			STARPU_PTHREAD_MUTEX_LOCK_SCHED(&w->sched_mutex);
-	}
-	return;
-}
-
 unsigned starpu_worker_get_sched_ctx_list(int workerid, unsigned **sched_ctxs)
 {
 	unsigned s = 0;
@@ -2254,3 +2313,35 @@ void starpu_worker_display_names(FILE *output, enum starpu_worker_archtype type)
 		}
 	}
 }
+
+void _starpu_worker_refuse_task(struct _starpu_worker *worker, struct starpu_task *task)
+{
+	if (worker->pipeline_length || worker->arch == STARPU_OPENCL_WORKER)
+	{
+		int j;
+		for (j = 0; j < worker->ntasks; j++)
+		{
+			const int j_mod = (j+worker->first_task)%STARPU_MAX_PIPELINE;
+			if (task == worker->current_tasks[j_mod])
+			{
+				worker->current_tasks[j_mod] = NULL;
+				if (j == 0)
+				{
+					worker->first_task = (worker->first_task + 1) % STARPU_MAX_PIPELINE;
+					worker->current_task = NULL;
+					_starpu_set_current_task(NULL);
+				}
+				break;
+			}
+		}
+		STARPU_ASSERT(j<worker->ntasks);
+	}
+	else
+	{
+		worker->current_task = NULL;
+		_starpu_set_current_task(NULL);
+	}
+	worker->ntasks--;
+	int res = _starpu_push_task_to_workers(task);
+	STARPU_ASSERT_MSG(res == 0, "_starpu_push_task_to_workers() unexpectedly returned = %d\n", res);
+}

+ 452 - 20
src/core/workers.h

@@ -64,6 +64,8 @@
 
 enum initialization { UNINITIALIZED = 0, CHANGING, INITIALIZED };
 
+struct _starpu_ctx_change_list;
+
 /* This is initialized from in _starpu_worker_init */
 LIST_TYPE(_starpu_worker,
 	struct _starpu_machine_config *config;
@@ -82,8 +84,37 @@ LIST_TYPE(_starpu_worker,
 	starpu_pthread_cond_t started_cond; /* indicate when the worker is ready */
 	starpu_pthread_cond_t ready_cond; /* indicate when the worker is ready */
 	unsigned memory_node; /* which memory node is the worker associated with ? */
-	starpu_pthread_cond_t sched_cond; /* condition variable used when the worker waits for tasks. */
+	/* condition variable used for passive waiting operations on worker
+	 * STARPU_PTHREAD_COND_BROADCAST must be used instead of STARPU_PTHREAD_COND_SIGNAL,
+	 * since the condition is shared for multiple purpose */
+	starpu_pthread_cond_t sched_cond;
         starpu_pthread_mutex_t sched_mutex; /* mutex protecting sched_cond */
+	unsigned state_relax_refcnt; /* mark scheduling sections where other workers can safely access the worker state */
+#ifdef STARPU_SPINLOCK_CHECK
+	const char *relax_on_file;
+	int relax_on_line;
+	const char *relax_on_func;
+	const char *relax_off_file;
+	int relax_off_line;
+	const char *relax_off_func;
+#endif
+	unsigned state_sched_op_pending; /* a task pop is ongoing even though sched_mutex may temporarily be unlocked */
+	unsigned state_changing_ctx_waiting; /* a thread is waiting for operations such as pop to complete before acquiring sched_mutex and modifying the worker ctx*/
+	unsigned state_changing_ctx_notice; /* the worker ctx is about to change or being changed, wait for flag to be cleared before starting new scheduling operations */
+	unsigned state_blocked_in_parallel; /* worker is currently blocked on a parallel section */
+	unsigned state_blocked_in_parallel_observed; /* the blocked state of the worker has been observed by another worker during a relaxed section */
+	unsigned state_block_in_parallel_req; /* a request for state transition from unblocked to blocked is pending */
+	unsigned state_block_in_parallel_ack; /* a block request has been honored */
+	unsigned state_unblock_in_parallel_req; /* a request for state transition from blocked to unblocked is pending */
+	unsigned state_unblock_in_parallel_ack; /* an unblock request has been honored */
+	 /* cumulative blocking depth
+	  * - =0  worker unblocked
+	  * - >0  worker blocked
+	  * - transition from 0 to 1 triggers a block_req
+	  * - transition from 1 to 0 triggers a unblock_req
+	  */
+	unsigned block_in_parallel_ref_count;
+	struct _starpu_ctx_change_list ctx_change_list;
 	struct starpu_task_list local_tasks; /* this queue contains tasks that have been explicitely submitted to that queue */
 	struct starpu_task **local_ordered_tasks; /* this queue contains tasks that have been explicitely submitted to that queue with an explicit order */
 	unsigned local_ordered_tasks_size; /* this records the size of local_ordered_tasks */
@@ -103,6 +134,7 @@ LIST_TYPE(_starpu_worker,
 	unsigned worker_is_running;
 	unsigned worker_is_initialized;
 	enum _starpu_worker_status status; /* what is the worker doing now ? (eg. CALLBACK) */
+	unsigned state_keep_awake; /* !0 if a task has been pushed to the worker and the task has not yet been seen by the worker, the worker should no go to sleep before processing this task*/
 	char name[64];
 	char short_name[10];
 	unsigned run_by_starpu; /* Is this run by StarPU or directly by the application ? */
@@ -137,12 +169,6 @@ LIST_TYPE(_starpu_worker,
 	/* indicate which priority of ctx is currently active: the values are 0 or 1*/
 	unsigned pop_ctx_priority;
 
-	/* flag to know if sched_mutex is locked or not */
-	unsigned sched_mutex_locked;
-
-	/* bool to indicate if the worker is blocked in a ctx */
-	unsigned blocked;
-
 	/* bool to indicate if the worker is slave in a ctx */
 	unsigned is_slave_somewhere;
 
@@ -508,7 +534,7 @@ static inline struct _starpu_worker *_starpu_get_worker_struct(unsigned id)
 	return &_starpu_config.workers[id];
 }
 
-/* Returns the starpu_sched_ctx structure that descriebes the state of the 
+/* Returns the starpu_sched_ctx structure that describes the state of the 
  * specified ctx */
 static inline struct _starpu_sched_ctx *_starpu_get_sched_ctx_struct(unsigned id)
 {
@@ -558,18 +584,6 @@ int starpu_worker_get_nids_by_type(enum starpu_worker_archtype type, int *worker
    the list might not be updated */
 int starpu_worker_get_nids_ctx_free_by_type(enum starpu_worker_archtype type, int *workerids, int maxsize);
 
-/* if the current worker has the lock release it */
-void _starpu_unlock_mutex_if_prev_locked();
-
-/* if we prev released the lock relock it */
-void _starpu_relock_mutex_if_prev_locked();
-
-static inline void _starpu_worker_set_flag_sched_mutex_locked(int workerid, unsigned flag)
-{
-	struct _starpu_worker *w = _starpu_get_worker_struct(workerid);
-	w->sched_mutex_locked = flag;
-}
-
 static inline unsigned _starpu_worker_mutex_is_sched_mutex(int workerid, starpu_pthread_mutex_t *mutex)
 {
 	struct _starpu_worker *w = _starpu_get_worker_struct(workerid);
@@ -584,6 +598,8 @@ static inline int _starpu_worker_get_nsched_ctxs(int workerid)
 /* Get the total number of sched_ctxs created till now */
 static inline unsigned _starpu_get_nsched_ctxs(void)
 {
+	/* topology.nsched_ctxs may be increased asynchronously in sched_ctx_create */
+	STARPU_RMB();
 	return _starpu_config.topology.nsched_ctxs;
 }
 
@@ -622,4 +638,420 @@ void _starpu_worker_set_stream_ctx(unsigned workerid, struct _starpu_sched_ctx *
 
 struct _starpu_sched_ctx* _starpu_worker_get_ctx_stream(unsigned stream_workerid);
 
+/* Must be called with worker's sched_mutex held.
+ */
+static inline void _starpu_worker_request_blocking_in_parallel(struct _starpu_worker * const worker)
+{
+	/* flush pending requests to start on a fresh transaction epoch */
+	while (worker->state_unblock_in_parallel_req)
+		STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+	/* announce blocking intent */
+	STARPU_ASSERT(worker->block_in_parallel_ref_count < UINT_MAX);
+	worker->block_in_parallel_ref_count++;
+
+	if (worker->block_in_parallel_ref_count == 1)
+	{
+		/* only the transition from 0 to 1 triggers the block_in_parallel_req */
+
+		STARPU_ASSERT(!worker->state_blocked_in_parallel);
+		STARPU_ASSERT(!worker->state_block_in_parallel_req);
+		STARPU_ASSERT(!worker->state_block_in_parallel_ack);
+		STARPU_ASSERT(!worker->state_unblock_in_parallel_req);
+		STARPU_ASSERT(!worker->state_unblock_in_parallel_ack);
+
+		/* trigger the block_in_parallel_req */
+		worker->state_block_in_parallel_req = 1;
+		STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+
+		/* wait for block_in_parallel_req to be processed */
+		while (!worker->state_block_in_parallel_ack)
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+		STARPU_ASSERT(worker->block_in_parallel_ref_count >= 1);
+		STARPU_ASSERT(worker->state_block_in_parallel_req);
+		STARPU_ASSERT(worker->state_blocked_in_parallel);
+
+		/* reset block_in_parallel_req state flags */
+		worker->state_block_in_parallel_req = 0;
+		worker->state_block_in_parallel_ack = 0;
+
+		/* broadcast block_in_parallel_req state flags reset */
+		STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+	}
+}
+
+/* Must be called with worker's sched_mutex held.
+ */
+static inline void _starpu_worker_request_unblocking_in_parallel(struct _starpu_worker * const worker)
+{
+	/* flush pending requests to start on a fresh transaction epoch */
+	while (worker->state_block_in_parallel_req)
+		STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+	/* unblocking may be requested unconditionnally
+	 * thus, check is unblocking is really needed */
+	if (worker->state_blocked_in_parallel)
+	{
+		if (worker->block_in_parallel_ref_count == 1)
+		{
+			/* only the transition from 1 to 0 triggers the unblock_in_parallel_req */
+
+			STARPU_ASSERT(!worker->state_block_in_parallel_req);
+			STARPU_ASSERT(!worker->state_block_in_parallel_ack);
+			STARPU_ASSERT(!worker->state_unblock_in_parallel_req);
+			STARPU_ASSERT(!worker->state_unblock_in_parallel_ack);
+
+			/* trigger the unblock_in_parallel_req */
+			worker->state_unblock_in_parallel_req = 1;
+			STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+
+			/* wait for the unblock_in_parallel_req to be processed */
+			while (!worker->state_unblock_in_parallel_ack)
+				STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+			STARPU_ASSERT(worker->state_unblock_in_parallel_req);
+			STARPU_ASSERT(!worker->state_blocked_in_parallel);
+
+			/* reset unblock_in_parallel_req state flags */
+			worker->state_unblock_in_parallel_req = 0;
+			worker->state_unblock_in_parallel_ack = 0;
+
+			/* broadcast unblock_in_parallel_req state flags reset */
+			STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+		}
+
+		/* announce unblocking complete */
+		STARPU_ASSERT(worker->block_in_parallel_ref_count > 0);
+		worker->block_in_parallel_ref_count--;
+	}
+}
+
+/* Must be called with worker's sched_mutex held.
+ */
+static inline void _starpu_worker_process_block_in_parallel_requests(struct _starpu_worker * const worker)
+{
+	while (worker->state_block_in_parallel_req)
+	{
+		STARPU_ASSERT(!worker->state_blocked_in_parallel);
+		STARPU_ASSERT(!worker->state_block_in_parallel_ack);
+		STARPU_ASSERT(!worker->state_unblock_in_parallel_req);
+		STARPU_ASSERT(!worker->state_unblock_in_parallel_ack);
+		STARPU_ASSERT(worker->block_in_parallel_ref_count > 0);
+		
+		/* enter effective blocked state */
+		worker->state_blocked_in_parallel = 1;
+
+		/* notify block_in_parallel_req processing */
+		worker->state_block_in_parallel_ack = 1;
+		STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+
+		/* block */
+		while (!worker->state_unblock_in_parallel_req)
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+		STARPU_ASSERT(worker->state_blocked_in_parallel);
+		STARPU_ASSERT(!worker->state_block_in_parallel_req);
+		STARPU_ASSERT(!worker->state_block_in_parallel_ack);
+		STARPU_ASSERT(!worker->state_unblock_in_parallel_ack);
+		STARPU_ASSERT(worker->block_in_parallel_ref_count > 0);
+
+		/* leave effective blocked state */
+		worker->state_blocked_in_parallel = 0;
+
+		/* notify unblock_in_parallel_req processing */
+		worker->state_unblock_in_parallel_ack = 1;
+		STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+	}
+}
+
+/* Must be called with worker's sched_mutex held.
+ * Mark the beginning of a scheduling operation during which the sched_mutex
+ * lock may be temporarily released, but the scheduling context of the worker
+ * should not be modified */
+#ifdef STARPU_SPINLOCK_CHECK
+static inline void __starpu_worker_enter_sched_op(struct _starpu_worker * const worker, const char*file, int line, const char* func)
+#else
+static inline void _starpu_worker_enter_sched_op(struct _starpu_worker * const worker)
+#endif
+{
+	STARPU_ASSERT(!worker->state_sched_op_pending);
+	if (!worker->state_blocked_in_parallel_observed)
+	{
+		/* process pending block requests before entering a sched_op region */
+		_starpu_worker_process_block_in_parallel_requests(worker);
+		while (worker->state_changing_ctx_notice)
+		{
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+			/* new block requests may have been triggered during the wait,
+			 * need to check again */
+			_starpu_worker_process_block_in_parallel_requests(worker);
+		}
+	}
+	else
+	{
+		/* if someone observed the worker state since the last call, postpone block request
+		 * processing for one sched_op turn more, because the observer will not have seen
+		 * new block requests between its observation and now.
+		 *
+		 * however, the worker still has to wait for context change operations to complete
+		 * before entering sched_op again*/
+		while (worker->state_changing_ctx_notice)
+		{
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+		}
+	}
+
+	/* no block request and no ctx change ahead,
+	 * enter sched_op */
+	worker->state_sched_op_pending = 1;
+	worker->state_blocked_in_parallel_observed = 0;
+	worker->state_relax_refcnt = 0;
+#ifdef STARPU_SPINLOCK_CHECK
+	worker->relax_on_file = file;
+	worker->relax_on_line = line;
+	worker->relax_on_func = func;
+#endif
+}
+#ifdef STARPU_SPINLOCK_CHECK
+#define _starpu_worker_enter_sched_op(worker) __starpu_worker_enter_sched_op((worker), __FILE__, __LINE__, __starpu_func__)
+#endif
+
+/* Must be called with worker's sched_mutex held.
+ * Mark the end of a scheduling operation, and notify potential waiters that
+ * scheduling context changes can safely be performed again.
+ */
+void _starpu_worker_apply_deferred_ctx_changes(void);
+#ifdef STARPU_SPINLOCK_CHECK
+static inline void __starpu_worker_leave_sched_op(struct _starpu_worker * const worker, const char*file, int line, const char* func)
+#else
+static inline void _starpu_worker_leave_sched_op(struct _starpu_worker * const worker)
+#endif
+{
+	STARPU_ASSERT(worker->state_sched_op_pending);
+	worker->state_relax_refcnt = 1;
+#ifdef STARPU_SPINLOCK_CHECK
+	worker->relax_off_file = file;
+	worker->relax_off_line = line;
+	worker->relax_off_func = func;
+#endif
+	worker->state_sched_op_pending = 0;
+	STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+	_starpu_worker_apply_deferred_ctx_changes();
+}
+#ifdef STARPU_SPINLOCK_CHECK
+#define _starpu_worker_leave_sched_op(worker) __starpu_worker_leave_sched_op((worker), __FILE__, __LINE__, __starpu_func__)
+#endif
+
+static inline int _starpu_worker_sched_op_pending(void)
+{
+	int workerid = starpu_worker_get_id();
+	if (workerid == -1)
+		return 0;
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	return worker->state_sched_op_pending;
+}
+
+/* Must be called with worker's sched_mutex held.
+ */
+static inline void _starpu_worker_enter_changing_ctx_op(struct _starpu_worker * const worker)
+{
+	/* flush pending requests to start on a fresh transaction epoch */
+	while (worker->state_changing_ctx_notice)
+		STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+
+	/* announce changing_ctx intent
+	 *
+	 * - an already started sched_op is allowed to complete
+	 * - no new sched_op may be started
+	 */
+	worker->state_changing_ctx_notice = 1;
+
+	/* allow for an already started sched_op to complete */
+	if (worker->state_sched_op_pending)
+	{
+		/* request sched_op to broadcast when way is cleared */
+		worker->state_changing_ctx_waiting = 1;
+
+		/* wait for sched_op completion */
+		STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+		do
+		{
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+		}
+		while (worker->state_sched_op_pending);
+
+		/* reset flag so other sched_ops wont have to broadcast state */
+		worker->state_changing_ctx_waiting = 0;
+	}
+}
+
+/* Must be called with worker's sched_mutex held.
+ */
+static inline void _starpu_worker_leave_changing_ctx_op(struct _starpu_worker * const worker)
+{
+	worker->state_changing_ctx_notice = 0;
+	STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+}
+
+/* Temporarily allow other worker to access current worker state, when still scheduling,
+ * but the scheduling has not yet been made or is already done */
+#ifdef STARPU_SPINLOCK_CHECK
+static inline void __starpu_worker_relax_on(const char*file, int line, const char* func)
+#else
+static inline void _starpu_worker_relax_on(void)
+#endif
+{
+	int workerid = starpu_worker_get_id();
+	if (workerid == -1)
+		return;
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	if (!worker->state_sched_op_pending)
+		return;
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+#ifdef STARPU_SPINLOCK_CHECK
+	STARPU_ASSERT_MSG(worker->state_relax_refcnt<UINT_MAX, "relax last turn on in %s (%s:%d)\n", worker->relax_on_func, worker->relax_on_file, worker->relax_on_line);
+#else
+	STARPU_ASSERT(worker->state_relax_refcnt<UINT_MAX);
+#endif
+	worker->state_relax_refcnt++;
+#ifdef STARPU_SPINLOCK_CHECK
+	worker->relax_on_file = file;
+	worker->relax_on_line = line;
+	worker->relax_on_func = func;
+#endif
+	STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+}
+#ifdef STARPU_SPINLOCK_CHECK
+#define _starpu_worker_relax_on() __starpu_worker_relax_on(__FILE__, __LINE__, __starpu_func__)
+#endif
+
+#ifdef STARPU_SPINLOCK_CHECK
+static inline void __starpu_worker_relax_off(const char*file, int line, const char* func)
+#else
+static inline void _starpu_worker_relax_off(void)
+#endif
+{
+	int workerid = starpu_worker_get_id();
+	if (workerid == -1)
+		return;
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	if (!worker->state_sched_op_pending)
+		return;
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+#ifdef STARPU_SPINLOCK_CHECK
+	STARPU_ASSERT_MSG(worker->state_relax_refcnt>0, "relax last turn off in %s (%s:%d)\n", worker->relax_on_func, worker->relax_on_file, worker->relax_on_line);
+#else
+	STARPU_ASSERT(worker->state_relax_refcnt>0);
+#endif
+	worker->state_relax_refcnt--;
+#ifdef STARPU_SPINLOCK_CHECK
+	worker->relax_off_file = file;
+	worker->relax_off_line = line;
+	worker->relax_off_func = func;
+#endif
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+}
+#ifdef STARPU_SPINLOCK_CHECK
+#define _starpu_worker_relax_off() __starpu_worker_relax_off(__FILE__, __LINE__, __starpu_func__)
+#endif
+
+static inline int _starpu_worker_get_relax_state(void)
+{
+	int workerid = starpu_worker_get_id();
+	if (workerid < 0)
+		return 1;
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	return worker->state_relax_refcnt != 0;
+}
+
+/* lock a worker for observing contents 
+ *
+ * notes:
+ * - if the observed worker is not in state_relax_refcnt, the function block until the state is reached */
+static inline void _starpu_worker_lock(int workerid)
+{
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	int cur_workerid = starpu_worker_get_id();
+	if (workerid != cur_workerid)
+	{
+		_starpu_worker_relax_on();
+
+		STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+		while (!worker->state_relax_refcnt)
+		{
+			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+		}
+	}
+	else
+	{
+		STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+	}
+}
+
+static inline int _starpu_worker_trylock(int workerid)
+{
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	int ret = STARPU_PTHREAD_MUTEX_TRYLOCK_SCHED(&worker->sched_mutex);
+	if (!ret)
+	{
+		int cur_workerid = starpu_worker_get_id();
+		if (workerid != cur_workerid) {
+			ret = !worker->state_relax_refcnt;
+			if (ret)
+				STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+		}
+	}
+	if (!ret)
+	{
+		_starpu_worker_relax_on();
+	}
+	return ret;
+}
+
+static inline void _starpu_worker_unlock(int workerid)
+{
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+	int cur_workerid = starpu_worker_get_id();
+	if (workerid != cur_workerid)
+	{
+		_starpu_worker_relax_off();
+	}
+}
+
+static inline void _starpu_worker_lock_self(void)
+{
+	int workerid = starpu_worker_get_id_check();
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+}
+
+static inline void _starpu_worker_unlock_self(void)
+{
+	int workerid = starpu_worker_get_id_check();
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
+	STARPU_ASSERT(worker != NULL);
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
+}
+
+static inline int _starpu_wake_worker_relax(int workerid)
+{
+	_starpu_worker_lock(workerid);
+	int ret = starpu_wake_worker_locked(workerid);
+	_starpu_worker_unlock(workerid);
+	return ret;
+}
+
+void _starpu_worker_refuse_task(struct _starpu_worker *worker, struct starpu_task *task);
 #endif // __WORKERS_H__

+ 24 - 26
src/datawizard/copy_driver.c

@@ -41,34 +41,33 @@
 void _starpu_wake_all_blocked_workers_on_node(unsigned nodeid)
 {
 	/* wake up all workers on that memory node */
-	unsigned cond_id;
-
 	struct _starpu_memory_node_descr * const descr = _starpu_memory_node_get_description();
-
-	starpu_pthread_mutex_t *mymutex = NULL;
-	starpu_pthread_cond_t *mycond = NULL;
-	const int myworkerid = starpu_worker_get_id();
-	if (myworkerid >= 0)
-		starpu_worker_get_sched_condition(myworkerid, &mymutex, &mycond);
+	const int cur_workerid = starpu_worker_get_id();
+	struct _starpu_worker *cur_worker = cur_workerid>=0?_starpu_get_worker_struct(cur_workerid):NULL;
 
 	STARPU_PTHREAD_RWLOCK_RDLOCK(&descr->conditions_rwlock);
 
 	unsigned nconds = descr->condition_count[nodeid];
+	unsigned cond_id;
 	for (cond_id = 0; cond_id < nconds; cond_id++)
 	{
-		struct _starpu_cond_and_mutex *condition;
-		condition  = &descr->conditions_attached_to_node[nodeid][cond_id];
+		struct _starpu_cond_and_worker *condition;
+		condition = &descr->conditions_attached_to_node[nodeid][cond_id];
 
-		if (condition->mutex == mymutex)
+		if (condition->worker == cur_worker)
 			/* No need to wake myself, and I might be called from
 			 * the scheduler with mutex locked, through
 			 * starpu_prefetch_task_input_on_node */
 			continue;
 
 		/* wake anybody waiting on that condition */
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(condition->mutex);
+		STARPU_PTHREAD_MUTEX_LOCK_SCHED(&condition->worker->sched_mutex);
+		if (condition->cond == &condition->worker->sched_cond)
+		{
+			condition->worker->state_keep_awake = 1;
+		} 
 		STARPU_PTHREAD_COND_BROADCAST(condition->cond);
-		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(condition->mutex);
+		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&condition->worker->sched_mutex);
 	}
 
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&descr->conditions_rwlock);
@@ -81,34 +80,33 @@ void _starpu_wake_all_blocked_workers_on_node(unsigned nodeid)
 void starpu_wake_all_blocked_workers(void)
 {
 	/* workers may be blocked on the various queues' conditions */
-	unsigned cond_id;
-
 	struct _starpu_memory_node_descr * const descr = _starpu_memory_node_get_description();
-
-	starpu_pthread_mutex_t *mymutex = NULL;
-	starpu_pthread_cond_t *mycond = NULL;
-	const int myworkerid = starpu_worker_get_id();
-	if (myworkerid >= 0)
-		starpu_worker_get_sched_condition(myworkerid, &mymutex, &mycond);
+	const int cur_workerid = starpu_worker_get_id();
+	struct _starpu_worker *cur_worker = cur_workerid>=0?_starpu_get_worker_struct(cur_workerid):NULL;
 
 	STARPU_PTHREAD_RWLOCK_RDLOCK(&descr->conditions_rwlock);
 
 	unsigned nconds = descr->total_condition_count;
+	unsigned cond_id;
 	for (cond_id = 0; cond_id < nconds; cond_id++)
 	{
-		struct _starpu_cond_and_mutex *condition;
-		condition  = &descr->conditions_all[cond_id];
+		struct _starpu_cond_and_worker *condition;
+		condition = &descr->conditions_all[cond_id];
 
-		if (condition->mutex == mymutex)
+		if (condition->worker == cur_worker)
 			/* No need to wake myself, and I might be called from
 			 * the scheduler with mutex locked, through
 			 * starpu_prefetch_task_input_on_node */
 			continue;
 
 		/* wake anybody waiting on that condition */
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(condition->mutex);
+		STARPU_PTHREAD_MUTEX_LOCK_SCHED(&condition->worker->sched_mutex);
+		if (condition->cond == &condition->worker->sched_cond)
+		{
+			condition->worker->state_keep_awake = 1;
+		}
 		STARPU_PTHREAD_COND_BROADCAST(condition->cond);
-		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(condition->mutex);
+		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&condition->worker->sched_mutex);
 	}
 
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&descr->conditions_rwlock);

+ 4 - 4
src/datawizard/memory_nodes.c

@@ -130,7 +130,7 @@ unsigned _starpu_memory_node_register(enum starpu_node_kind kind, int devid)
 /* TODO move in a more appropriate file  !! */
 /* Register a condition variable associated to worker which is associated to a
  * memory node itself. */
-void _starpu_memory_node_register_condition(starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex, unsigned nodeid)
+void _starpu_memory_node_register_condition(struct _starpu_worker *worker, starpu_pthread_cond_t *cond, unsigned nodeid)
 {
 	unsigned cond_id;
 	unsigned nconds_total, nconds;
@@ -143,7 +143,7 @@ void _starpu_memory_node_register_condition(starpu_pthread_cond_t *cond, starpu_
 	{
 		if (_starpu_descr.conditions_attached_to_node[nodeid][cond_id].cond == cond)
 		{
-			STARPU_ASSERT(_starpu_descr.conditions_attached_to_node[nodeid][cond_id].mutex == mutex);
+			STARPU_ASSERT(_starpu_descr.conditions_attached_to_node[nodeid][cond_id].worker == worker);
 
 			/* the condition is already in the list */
 			STARPU_PTHREAD_RWLOCK_UNLOCK(&_starpu_descr.conditions_rwlock);
@@ -153,7 +153,7 @@ void _starpu_memory_node_register_condition(starpu_pthread_cond_t *cond, starpu_
 
 	/* it was not found locally */
 	_starpu_descr.conditions_attached_to_node[nodeid][cond_id].cond = cond;
-	_starpu_descr.conditions_attached_to_node[nodeid][cond_id].mutex = mutex;
+	_starpu_descr.conditions_attached_to_node[nodeid][cond_id].worker = worker;
 	_starpu_descr.condition_count[nodeid]++;
 
 	/* do we have to add it in the global list as well ? */
@@ -170,7 +170,7 @@ void _starpu_memory_node_register_condition(starpu_pthread_cond_t *cond, starpu_
 
 	/* it was not in the global list either */
 	_starpu_descr.conditions_all[nconds_total].cond = cond;
-	_starpu_descr.conditions_all[nconds_total].mutex = mutex;
+	_starpu_descr.conditions_all[nconds_total].worker = worker;
 	_starpu_descr.total_condition_count++;
 
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&_starpu_descr.conditions_rwlock);

+ 6 - 6
src/datawizard/memory_nodes.h

@@ -35,10 +35,10 @@
 
 extern char _starpu_worker_drives_memory[STARPU_NMAXWORKERS][STARPU_MAXNODES];
 
-struct _starpu_cond_and_mutex
+struct _starpu_cond_and_worker
 {
-        starpu_pthread_cond_t *cond;
-        starpu_pthread_mutex_t *mutex;
+	starpu_pthread_cond_t *cond;
+	struct _starpu_worker *worker;
 };
 
 struct _starpu_memory_node_descr
@@ -62,8 +62,8 @@ struct _starpu_memory_node_descr
 	 * list of all these condition variables so that we can wake up all
 	 * worker attached to a memory node that are waiting on a task. */
 	starpu_pthread_rwlock_t conditions_rwlock;
-	struct _starpu_cond_and_mutex conditions_attached_to_node[STARPU_MAXNODES][STARPU_NMAXWORKERS];
-	struct _starpu_cond_and_mutex conditions_all[STARPU_MAXNODES*STARPU_NMAXWORKERS];
+	struct _starpu_cond_and_worker conditions_attached_to_node[STARPU_MAXNODES][STARPU_NMAXWORKERS];
+	struct _starpu_cond_and_worker conditions_all[STARPU_MAXNODES*STARPU_NMAXWORKERS];
 	/* the number of queues attached to each node */
 	unsigned total_condition_count;
 	unsigned condition_count[STARPU_MAXNODES];
@@ -109,7 +109,7 @@ static inline msg_host_t _starpu_simgrid_memory_node_get_host(unsigned node)
 #endif
 unsigned _starpu_memory_node_register(enum starpu_node_kind kind, int devid);
 //void _starpu_memory_node_attach_queue(struct starpu_jobq_s *q, unsigned nodeid);
-void _starpu_memory_node_register_condition(starpu_pthread_cond_t *cond, starpu_pthread_mutex_t *mutex, unsigned memory_node);
+void _starpu_memory_node_register_condition(struct _starpu_worker *worker, starpu_pthread_cond_t *cond, unsigned nodeid);
 
 static inline int _starpu_memory_node_get_devid(unsigned node)
 {

+ 9 - 2
src/drivers/cpu/driver_cpu.c

@@ -55,7 +55,11 @@ static int execute_job_on_cpu(struct _starpu_job *j, struct starpu_task *worker_
 {
 	int is_parallel_task = (j->task_size > 1);
 	int profiling = starpu_profiling_status_get();
-	struct timespec codelet_start, codelet_end;
+	/* start/end timestamp are only conditionnally measured in
+	 * _starpu_driver_start_job/_end_job, thus make sure that they are
+	 * always initialized */
+	struct timespec codelet_start = {0,0};
+	struct timespec codelet_end = {0,0};
 
 	struct starpu_task *task = j->task;
 	struct starpu_codelet *cl = task->cl;
@@ -210,9 +214,12 @@ int _starpu_cpu_driver_init(struct _starpu_worker *cpu_worker)
 
 	_STARPU_TRACE_WORKER_INIT_END(cpu_worker->workerid);
 
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&cpu_worker->sched_mutex);
+	cpu_worker->status = STATUS_UNKNOWN;
+	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&cpu_worker->sched_mutex);
+
 	/* tell the main thread that we are ready */
 	STARPU_PTHREAD_MUTEX_LOCK(&cpu_worker->mutex);
-	cpu_worker->status = STATUS_UNKNOWN;
 	cpu_worker->worker_is_initialized = 1;
 	STARPU_PTHREAD_COND_SIGNAL(&cpu_worker->ready_cond);
 	STARPU_PTHREAD_MUTEX_UNLOCK(&cpu_worker->mutex);

+ 29 - 1
src/drivers/cuda/driver_cuda.c

@@ -900,8 +900,36 @@ int _starpu_cuda_driver_run_once(struct _starpu_worker_set *worker_set)
 		if (!_STARPU_CUDA_MAY_PERFORM(j))
 		{
 			/* this is neither a cuda or a cublas task */
+			_starpu_worker_refuse_task(worker, task);
+#if 0
+			if (worker->pipeline_length)
+			{
+				int j;
+				for (j = 0; j < worker->ntasks; j++)
+				{
+					const int j_mod = (j+worker->first_task)%STARPU_MAX_PIPELINE;
+					if (task == worker->current_tasks[j_mod])
+					{
+						worker->current_tasks[j_mod] = NULL;
+						if (j == 0)
+						{
+							worker->first_task = (worker->first_task + 1) % STARPU_MAX_PIPELINE;
+							_starpu_set_current_task(NULL);
+						}
+						break;
+					}
+				}
+				STARPU_ASSERT(j<worker->ntasks);
+			}
+			else
+			{
+				worker->current_task = NULL;
+				_starpu_set_current_task(NULL);
+			}
 			worker->ntasks--;
-			_starpu_push_task_to_workers(task);
+			int res = _starpu_push_task_to_workers(task);
+			STARPU_ASSERT_MSG(res == 0, "_starpu_push_task_to_workers() unexpectedly returned = %d\n", res);
+#endif
 			continue;
 		}
 

+ 72 - 81
src/drivers/driver_common/driver_common.c

@@ -76,6 +76,7 @@ void _starpu_driver_start_job(struct _starpu_worker *worker, struct _starpu_job
 	struct _starpu_sched_ctx *sched_ctx = _starpu_sched_ctx_get_sched_ctx_for_worker_and_job(worker, j);
 	if(!sched_ctx)
 		sched_ctx = _starpu_get_sched_ctx_struct(j->task->sched_ctx);
+	_starpu_sched_ctx_lock_read(sched_ctx->id);
 	if(!sched_ctx->sched_policy)
 	{
 		if(!sched_ctx->awake_workers && sched_ctx->main_master == worker->workerid)
@@ -101,6 +102,7 @@ void _starpu_driver_start_job(struct _starpu_worker *worker, struct _starpu_job
 	}
 	else
 		_STARPU_TRACE_START_CODELET_BODY(j, j->nimpl, perf_arch, workerid);
+	_starpu_sched_ctx_unlock_read(sched_ctx->id);
 	_STARPU_TASK_BREAK_ON(task, exec);
 }
 
@@ -193,6 +195,7 @@ void _starpu_driver_update_job_feedback(struct _starpu_job *j, struct _starpu_wo
 
 		starpu_timespec_sub(codelet_end, codelet_start, &measured_ts);
 		measured = starpu_timing_timespec_to_us(&measured_ts);
+		STARPU_ASSERT_MSG(measured >= 0, "measured=%lf\n", measured);
 
 		if (profiling && profiling_info)
 		{
@@ -300,9 +303,7 @@ static void _starpu_worker_set_status_scheduling_done(int workerid)
 
 static void _starpu_worker_set_status_sleeping(int workerid)
 {
-	if ( _starpu_worker_get_status(workerid) == STATUS_WAKING_UP)
-		_starpu_worker_set_status(workerid, STATUS_SLEEPING);
-	else if (_starpu_worker_get_status(workerid) != STATUS_SLEEPING)
+	if (_starpu_worker_get_status(workerid) != STATUS_SLEEPING)
 	{
 		_STARPU_TRACE_WORKER_SLEEP_START;
 		_starpu_worker_restart_sleeping(workerid);
@@ -313,7 +314,7 @@ static void _starpu_worker_set_status_sleeping(int workerid)
 
 static void _starpu_worker_set_status_wakeup(int workerid)
 {
-	if (_starpu_worker_get_status(workerid) == STATUS_SLEEPING || _starpu_worker_get_status(workerid) == STATUS_WAKING_UP)
+	if (_starpu_worker_get_status(workerid) == STATUS_SLEEPING)
 	{
 		_STARPU_TRACE_WORKER_SLEEP_END;
 		_starpu_worker_stop_sleeping(workerid);
@@ -340,74 +341,13 @@ static void _starpu_exponential_backoff(struct _starpu_worker *worker)
 /* Workers may block when there is no work to do at all. */
 struct starpu_task *_starpu_get_worker_task(struct _starpu_worker *worker, int workerid, unsigned memnode STARPU_ATTRIBUTE_UNUSED)
 {
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
 	struct starpu_task *task;
-	unsigned needed = 1;
 	unsigned executing STARPU_ATTRIBUTE_UNUSED = 0;
+	unsigned keep_awake = 0;
 
+	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+	_starpu_worker_enter_sched_op(worker);
 	_starpu_worker_set_status_scheduling(workerid);
-	while(needed)
-	{
-		struct _starpu_sched_ctx *sched_ctx = NULL;
-		struct _starpu_sched_ctx_elt *e = NULL;
-		struct _starpu_sched_ctx_list_iterator list_it;
-
-		_starpu_sched_ctx_list_iterator_init(worker->sched_ctx_list, &list_it);
-		while (_starpu_sched_ctx_list_iterator_has_next(&list_it))
-		{
-			e = _starpu_sched_ctx_list_iterator_get_next(&list_it);
-			sched_ctx = _starpu_get_sched_ctx_struct(e->sched_ctx);
-			if(sched_ctx && sched_ctx->id > 0 && sched_ctx->id < STARPU_NMAX_SCHED_CTXS)
-			{
-				STARPU_PTHREAD_MUTEX_LOCK(&sched_ctx->parallel_sect_mutex[workerid]);
-				if(!sched_ctx->sched_policy)
-					worker->is_slave_somewhere = sched_ctx->main_master != workerid;
-
-				if(sched_ctx->parallel_sect[workerid])
-				{
-					/* don't let the worker sleep with the sched_mutex taken */
-					/* we need it until here bc of the list of ctxs of the workers
-					   that can change in another thread */
-					STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
-					needed = 0;
-					_starpu_sched_ctx_signal_worker_blocked(sched_ctx->id, workerid);
-					sched_ctx->busy[workerid] = 1;
-					STARPU_PTHREAD_COND_WAIT(&sched_ctx->parallel_sect_cond[workerid], &sched_ctx->parallel_sect_mutex[workerid]);
-					sched_ctx->busy[workerid] = 0;
-					STARPU_PTHREAD_COND_SIGNAL(&sched_ctx->parallel_sect_cond_busy[workerid]);
-					_starpu_sched_ctx_signal_worker_woke_up(sched_ctx->id, workerid);
-					sched_ctx->parallel_sect[workerid] = 0;
-					STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
-				}
-				STARPU_PTHREAD_MUTEX_UNLOCK(&sched_ctx->parallel_sect_mutex[workerid]);
-			}
-			if(!needed)
-				break;
-		}
-		/* don't worry if the value is not correct (no lock) it will do it next time */
-		if(worker->tmp_sched_ctx != -1)
-		{
-			sched_ctx = _starpu_get_sched_ctx_struct(worker->tmp_sched_ctx);
-			STARPU_PTHREAD_MUTEX_LOCK(&sched_ctx->parallel_sect_mutex[workerid]);
-			if(sched_ctx->parallel_sect[workerid])
-			{
-//				needed = 0;
-				STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
-				_starpu_sched_ctx_signal_worker_blocked(sched_ctx->id, workerid);
-				sched_ctx->busy[workerid] = 1;
-				STARPU_PTHREAD_COND_WAIT(&sched_ctx->parallel_sect_cond[workerid], &sched_ctx->parallel_sect_mutex[workerid]);
-				sched_ctx->busy[workerid] = 0;
-				STARPU_PTHREAD_COND_SIGNAL(&sched_ctx->parallel_sect_cond_busy[workerid]);
-				_starpu_sched_ctx_signal_worker_woke_up(sched_ctx->id, workerid);
-				sched_ctx->parallel_sect[workerid] = 0;
-				STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
-			}
-			STARPU_PTHREAD_MUTEX_UNLOCK(&sched_ctx->parallel_sect_mutex[workerid]);
-		}
-
-		needed = !needed;
-	}
-
 	if ((worker->pipeline_length == 0 && worker->current_task)
 		|| (worker->pipeline_length != 0 && worker->ntasks))
 		/* This worker is executing something */
@@ -421,10 +361,19 @@ struct starpu_task *_starpu_get_worker_task(struct _starpu_worker *worker, int w
 		task = NULL;
 	/*else try to pop a task*/
 	else
+	{
+		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
 		task = _starpu_pop_task(worker);
+		STARPU_PTHREAD_MUTEX_LOCK_SCHED(&worker->sched_mutex);
+		if (worker->state_keep_awake)
+		{
+			keep_awake = worker->state_keep_awake;
+			worker->state_keep_awake = 0;
+		}
+	}
 
 #if !defined(STARPU_SIMGRID)
-	if (task == NULL && !executing)
+	if (task == NULL && !executing && !keep_awake)
 	{
 		/* Didn't get a task to run and none are running, go to sleep */
 
@@ -432,21 +381,30 @@ struct starpu_task *_starpu_get_worker_task(struct _starpu_worker *worker, int w
 		 * from popping a task from the scheduler to blocking. Otherwise the
 		 * driver may go block just after the scheduler got a new task to be
 		 * executed, and thus hanging. */
-
 		_starpu_worker_set_status_sleeping(workerid);
+		_starpu_worker_leave_sched_op(worker);
+		STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
 
 		if (_starpu_worker_can_block(memnode, worker)
-			&& !_starpu_sched_ctx_last_worker_awake(worker))
+			&& !_starpu_sched_ctx_last_worker_awake(worker)
+			&& !worker->state_block_in_parallel_req
+			&& !worker->state_unblock_in_parallel_req)
 		{
-			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+			do
+			{
+				STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+			}
+			/* do not check status != SLEEPING here since status is
+			 * not changed by other threads/workers */
+			while (!worker->state_keep_awake
+					&& !worker->state_block_in_parallel_req
+					&& !worker->state_unblock_in_parallel_req);
+			worker->state_keep_awake = 0;
 			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
-		}
-		else
-		{
+		} else {
 			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
 			if (_starpu_machine_is_running())
-				_starpu_exponential_backoff(worker);
-		}
+				_starpu_exponential_backoff(worker); }
 
 		return NULL;
 	}
@@ -463,6 +421,8 @@ struct starpu_task *_starpu_get_worker_task(struct _starpu_worker *worker, int w
 	}
 	worker->spinning_backoff = BACKOFF_MIN;
 
+	_starpu_worker_leave_sched_op(worker);
+	STARPU_PTHREAD_COND_BROADCAST(&worker->sched_cond);
 	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
 
 
@@ -483,10 +443,13 @@ int _starpu_get_multi_worker_task(struct _starpu_worker *workers, struct starpu_
 #ifndef STARPU_NON_BLOCKING_DRIVERS
 	/* This assumes only 1 worker */
 	STARPU_ASSERT_MSG(nworkers == 1, "Multiple workers is not yet possible in blocking drivers mode\n");
+	_starpu_set_local_worker_key(&workers[0]);
 	STARPU_PTHREAD_MUTEX_LOCK_SCHED(&workers[0].sched_mutex);
+	_starpu_worker_enter_sched_op(&workers[0]);
 #endif
 	for (i = 0; i < nworkers; i++)
 	{
+		unsigned keep_awake = 0;
 		if ((workers[i].pipeline_length == 0 && workers[i].current_task)
 			|| (workers[i].pipeline_length != 0 && workers[i].ntasks))
 			/* At least this worker is executing something */
@@ -508,20 +471,33 @@ int _starpu_get_multi_worker_task(struct _starpu_worker *workers, struct starpu_
 		else
 		{
 #ifdef STARPU_NON_BLOCKING_DRIVERS
+			_starpu_set_local_worker_key(&workers[i]);
 			STARPU_PTHREAD_MUTEX_LOCK_SCHED(&workers[i].sched_mutex);
+			_starpu_worker_enter_sched_op(&workers[i]);
 #endif
 			_starpu_worker_set_status_scheduling(workers[i].workerid);
-			_starpu_set_local_worker_key(&workers[i]);
+			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&workers[i].sched_mutex);
 			tasks[i] = _starpu_pop_task(&workers[i]);
-			if(tasks[i] != NULL)
+			STARPU_PTHREAD_MUTEX_LOCK_SCHED(&workers[i].sched_mutex);
+			if (workers[i].state_keep_awake)
+			{
+				keep_awake = workers[i].state_keep_awake;
+				workers[i].state_keep_awake = 0;
+			}
+			if(tasks[i] != NULL || keep_awake)
 			{
 				_starpu_worker_set_status_scheduling_done(workers[i].workerid);
 				_starpu_worker_set_status_wakeup(workers[i].workerid);
+				STARPU_PTHREAD_COND_BROADCAST(&workers[i].sched_cond);
 #ifdef STARPU_NON_BLOCKING_DRIVERS
+				_starpu_worker_leave_sched_op(&workers[i]);
 				STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&workers[i].sched_mutex);
 #endif
 
 				count ++;
+				if (tasks[i] == NULL)
+					/* no task, but keep_awake */
+					continue;
 				j = _starpu_get_job_associated_to_task(tasks[i]);
 				is_parallel_task = (j->task_size > 1);
 				if (workers[i].pipeline_length)
@@ -556,6 +532,10 @@ int _starpu_get_multi_worker_task(struct _starpu_worker *workers, struct starpu_
 			{
 				_starpu_worker_set_status_sleeping(workers[i].workerid);
 #ifdef STARPU_NON_BLOCKING_DRIVERS
+				_starpu_worker_leave_sched_op(&workers[i]);
+#endif
+				STARPU_PTHREAD_COND_BROADCAST(&workers[i].sched_cond);
+#ifdef STARPU_NON_BLOCKING_DRIVERS
 				STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&workers[i].sched_mutex);
 #endif
 			}
@@ -577,11 +557,21 @@ int _starpu_get_multi_worker_task(struct _starpu_worker *workers, struct starpu_
 		 * driver may go block just after the scheduler got a new task to be
 		 * executed, and thus hanging. */
 		_starpu_worker_set_status_sleeping(workerid);
+		_starpu_worker_leave_sched_op(worker);
 
 		if (_starpu_worker_can_block(memnode, worker)
-				&& !_starpu_sched_ctx_last_worker_awake(worker))
+				&& !_starpu_sched_ctx_last_worker_awake(worker)
+				&& !worker->state_block_in_parallel_req
+				&& !worker->state_unblock_in_parallel_req)
 		{
-			STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+			do
+			{
+				STARPU_PTHREAD_COND_WAIT(&worker->sched_cond, &worker->sched_mutex);
+			}
+			while (!worker->state_keep_awake
+					&& !worker->state_block_in_parallel_req
+					&& !worker->state_unblock_in_parallel_req);
+			worker->state_keep_awake = 0;
 			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&worker->sched_mutex);
 		}
 		else
@@ -597,6 +587,7 @@ int _starpu_get_multi_worker_task(struct _starpu_worker *workers, struct starpu_
 	worker->spinning_backoff = BACKOFF_MIN;
 #endif /* !STARPU_SIMGRID */
 
+	_starpu_worker_leave_sched_op(&workers[0]);
 	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(&workers[0].sched_mutex);
 #endif /* !STARPU_NON_BLOCKING_DRIVERS */
 

+ 10 - 3
src/drivers/opencl/driver_opencl.c

@@ -793,17 +793,24 @@ int _starpu_opencl_driver_run_once(struct _starpu_worker *worker)
 
 	j = _starpu_get_job_associated_to_task(task);
 
+	worker->current_tasks[(worker->first_task  + worker->ntasks)%STARPU_MAX_PIPELINE] = task;
+	worker->ntasks++;
+	if (worker->pipeline_length == 0)
+	/* _starpu_get_worker_task checks .current_task field if pipeline_length == 0
+	 *
+	 * TODO: update driver to not use current_tasks[] when pipeline_length == 0,
+	 * as for cuda driver */
+		worker->current_task = task;
+
 	/* can OpenCL do that task ? */
 	if (!_STARPU_OPENCL_MAY_PERFORM(j))
 	{
 		/* this is not a OpenCL task */
-		_starpu_push_task_to_workers(task);
+		_starpu_worker_refuse_task(worker, task);
 		return 0;
 	}
 
 	_STARPU_TRACE_END_PROGRESS(memnode);
-	worker->current_tasks[(worker->first_task  + worker->ntasks)%STARPU_MAX_PIPELINE] = task;
-	worker->ntasks++;
 
 	/* Fetch data asynchronously */
 	res = _starpu_fetch_task_input(task, j, 1);

+ 9 - 10
src/sched_policies/component_fifo.c

@@ -65,9 +65,9 @@ static double fifo_estimated_load(struct starpu_sched_component * component)
 	{
 		int first_worker = starpu_bitmap_first(component->workers_in_ctx);
 		relative_speedup = starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(first_worker, component->tree->sched_ctx_id));
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(mutex);
 		load += fifo->ntasks / relative_speedup;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 		return load;
 	}
 	else
@@ -79,9 +79,9 @@ static double fifo_estimated_load(struct starpu_sched_component * component)
 			relative_speedup += starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(i, component->tree->sched_ctx_id));
 		relative_speedup /= starpu_bitmap_cardinal(component->workers_in_ctx);
 		STARPU_ASSERT(!_STARPU_IS_ZERO(relative_speedup));
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(mutex);
 		load += fifo->ntasks / relative_speedup;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 	}
 	return load;
 }
@@ -94,8 +94,7 @@ static int fifo_push_local_task(struct starpu_sched_component * component, struc
 	struct _starpu_fifo_taskq * fifo = data->fifo;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	int ret = 0;
-
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(mutex);
 	double exp_len;
 	if(!isnan(task->predicted))
 		exp_len = fifo->exp_len + task->predicted;
@@ -113,7 +112,7 @@ static int fifo_push_local_task(struct starpu_sched_component * component, struc
 		}
 		STARPU_ASSERT(!is_pushback);
 		ret = 1;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 	}
 	else
 	{
@@ -136,7 +135,7 @@ static int fifo_push_local_task(struct starpu_sched_component * component, struc
 
 		if(!is_pushback)
 			component->can_pull(component);
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 	}
 
 	return ret;
@@ -153,7 +152,7 @@ static struct starpu_task * fifo_pull_task(struct starpu_sched_component * compo
 	struct _starpu_fifo_data * data = component->data;
 	struct _starpu_fifo_taskq * fifo = data->fifo;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(mutex);
 	struct starpu_task * task = _starpu_fifo_pop_task(fifo, starpu_worker_get_id_check());
 	if(task)
 	{
@@ -169,7 +168,7 @@ static struct starpu_task * fifo_pull_task(struct starpu_sched_component * compo
 	STARPU_ASSERT(!isnan(fifo->exp_end));
 	STARPU_ASSERT(!isnan(fifo->exp_len));
 	STARPU_ASSERT(!isnan(fifo->exp_start));
-	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 
 	// When a pop is called, a can_push is called for pushing tasks onto
 	// the empty place of the queue left by the popped task.

+ 8 - 8
src/sched_policies/component_heft.c

@@ -46,7 +46,7 @@ static int heft_progress_one(struct starpu_sched_component *component)
 	struct starpu_task * (tasks[NTASKS]);
 	unsigned ntasks;
 
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(mutex);
 	/* Try to look at NTASKS from the queue */
 	for (ntasks = 0; ntasks < NTASKS; ntasks++)
 	{
@@ -54,7 +54,7 @@ static int heft_progress_one(struct starpu_sched_component *component)
 		if (!tasks[ntasks])
 			break;
 	}
-	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 
 	if (!ntasks)
 	{
@@ -121,11 +121,11 @@ static int heft_progress_one(struct starpu_sched_component *component)
 		int best_icomponent = -1;
 
 		/* Push back the other tasks */
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(mutex);
 		for (n = ntasks - 1; n < ntasks; n--)
 			if ((int) n != best_task)
 				_starpu_prio_deque_push_back_task(prio, tasks[n]);
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 
 		/* And now find out which worker suits best for this task,
 		 * including data transfer */
@@ -166,9 +166,9 @@ static int heft_progress_one(struct starpu_sched_component *component)
 		if (ret)
 		{
 			/* Could not push to child actually, push that one back too */
-			STARPU_PTHREAD_MUTEX_LOCK(mutex);
+			STARPU_COMPONENT_MUTEX_LOCK(mutex);
 			_starpu_prio_deque_push_back_task(prio, tasks[best_task]);
-			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+			STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 			return 1;
 		}
 		else
@@ -191,9 +191,9 @@ static int heft_push_task(struct starpu_sched_component * component, struct star
 	struct _starpu_prio_deque * prio = &data->prio;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(mutex);
 	_starpu_prio_deque_push_task(prio,task);
-	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 
 	heft_progress(component);
 

+ 4 - 4
src/sched_policies/component_mct.c

@@ -66,7 +66,7 @@ static int mct_push_task(struct starpu_sched_component * component, struct starp
 
 	/* Entering critical section to make sure no two workers
 	   make scheduling decisions at the same time */
-	STARPU_PTHREAD_MUTEX_LOCK(&d->scheduling_mutex); 
+	STARPU_COMPONENT_MUTEX_LOCK(&d->scheduling_mutex); 
 
 
 	starpu_mct_compute_expected_times(component, task, estimated_lengths, estimated_transfer_length, 
@@ -99,7 +99,7 @@ static int mct_push_task(struct starpu_sched_component * component, struct starp
 	 * We should send a push_fail message to its parent so that it will
 	 * be able to reschedule the task properly. */
 	if(best_icomponent == -1) {
-		STARPU_PTHREAD_MUTEX_UNLOCK(&d->scheduling_mutex); 
+		STARPU_COMPONENT_MUTEX_UNLOCK(&d->scheduling_mutex); 
 		return 1;
 	}
 
@@ -111,7 +111,7 @@ static int mct_push_task(struct starpu_sched_component * component, struct starp
 	if(starpu_sched_component_is_worker(best_component))
 	{
 		best_component->can_pull(best_component);
-		STARPU_PTHREAD_MUTEX_UNLOCK(&d->scheduling_mutex); 
+		STARPU_COMPONENT_MUTEX_UNLOCK(&d->scheduling_mutex); 
 		
 		return 1;
 	}
@@ -121,7 +121,7 @@ static int mct_push_task(struct starpu_sched_component * component, struct starp
 	
 	/* I can now exit the critical section: Pushing the task below ensures that its execution 
 	   time will be taken into account for subsequent scheduling decisions */
-	STARPU_PTHREAD_MUTEX_UNLOCK(&d->scheduling_mutex); 
+	STARPU_COMPONENT_MUTEX_UNLOCK(&d->scheduling_mutex); 
 
 	return ret;
 }

+ 33 - 14
src/sched_policies/component_prio.c

@@ -17,6 +17,7 @@
 #include <starpu_sched_component.h>
 #include <starpu_scheduler.h>
 #include <common/fxt.h>
+#include <core/workers.h>
 
 #include "prio_deque.h"
 #include "sched_component.h"
@@ -83,9 +84,9 @@ static double prio_estimated_load(struct starpu_sched_component * component)
 	{
 		int first_worker = starpu_bitmap_first(component->workers_in_ctx);
 		relative_speedup = starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(first_worker, component->tree->sched_ctx_id));
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(mutex);
 		load += prio->ntasks / relative_speedup;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 		return load;
 	}
 	else
@@ -97,9 +98,9 @@ static double prio_estimated_load(struct starpu_sched_component * component)
 			relative_speedup += starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(i, component->tree->sched_ctx_id));
 		relative_speedup /= starpu_bitmap_cardinal(component->workers_in_ctx);
 		STARPU_ASSERT(!_STARPU_IS_ZERO(relative_speedup));
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(mutex);
 		load += prio->ntasks / relative_speedup;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 	}
 	return load;
 }
@@ -112,8 +113,7 @@ static int prio_push_local_task(struct starpu_sched_component * component, struc
 	struct _starpu_prio_deque * prio = &data->prio;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	int ret;
-	
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(mutex);
 	double exp_len;
 	if(!isnan(task->predicted))
 		exp_len = prio->exp_len + task->predicted;
@@ -130,7 +130,7 @@ static int prio_push_local_task(struct starpu_sched_component * component, struc
 			warned = 1;
 		}
 		ret = 1;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 	}
 	else
 	{
@@ -162,7 +162,7 @@ static int prio_push_local_task(struct starpu_sched_component * component, struc
 		STARPU_ASSERT(!isnan(prio->exp_len));
 		STARPU_ASSERT(!isnan(prio->exp_start));
 		
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 		if(!is_pushback)
 			component->can_pull(component);
 	}
@@ -182,18 +182,37 @@ static struct starpu_task * prio_pull_task(struct starpu_sched_component * compo
 	struct _starpu_prio_data * data = component->data;
 	struct _starpu_prio_deque * prio = &data->prio;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(mutex);
 	struct starpu_task * task = _starpu_prio_deque_pop_task(prio);
 	if(task)
 	{
 		if(!isnan(task->predicted))
 		{
-			prio->exp_start = starpu_timing_now() + task->predicted;
-			prio->exp_len -= task->predicted;
+			const double exp_len = prio->exp_len - task->predicted;
+			const double now = starpu_timing_now();
+			prio->exp_start = now + task->predicted;
+			if (exp_len >= 0.0)
+			{
+				prio->exp_len = exp_len;
+			}
+			else
+			{
+				/* exp_len can become negative due to rounding errors */
+				prio->exp_len = starpu_timing_now()-now;
+			}
 		}
+		STARPU_ASSERT_MSG(prio->exp_len>=0, "prio->exp_len=%lf\n",prio->exp_len);
 		if(!isnan(task->predicted_transfer)){
-			prio->exp_start += task->predicted_transfer; 
-			prio->exp_len -= task->predicted_transfer; 
+			if (prio->exp_len > task->predicted_transfer)
+			{
+				prio->exp_start += task->predicted_transfer;
+				prio->exp_len -= task->predicted_transfer;
+			}
+			else
+			{
+				prio->exp_start += prio->exp_len;
+				prio->exp_len = 0;
+			}
 		}
 
 		prio->exp_end = prio->exp_start + prio->exp_len;
@@ -205,7 +224,7 @@ static struct starpu_task * prio_pull_task(struct starpu_sched_component * compo
 	STARPU_ASSERT(!isnan(prio->exp_end));
 	STARPU_ASSERT(!isnan(prio->exp_len));
 	STARPU_ASSERT(!isnan(prio->exp_start));
-	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(mutex);
 
 	// When a pop is called, a can_push is called for pushing tasks onto
 	// the empty place of the queue left by the popped task.

+ 12 - 10
src/sched_policies/component_sched.c

@@ -73,6 +73,7 @@ int starpu_sched_component_execute_preds(struct starpu_sched_component * compone
 				{
 					continue;
 				}
+				STARPU_ASSERT_MSG(d >= 0, "workerid=%d, nimpl=%d, bundle=%p, d=%lf\n", workerid, nimpl, bundle, d);
 				if(d < len)
 				{
 					len = d;
@@ -271,16 +272,17 @@ void _starpu_sched_component_update_workers(struct starpu_sched_component * comp
 void _starpu_sched_component_update_workers_in_ctx(struct starpu_sched_component * component, unsigned sched_ctx_id)
 {
 	STARPU_ASSERT(component);
+	/* worker components are shared among sched_ctxs, thus we do not apply the sched_ctx worker mask to them.
+	 * per-ctx filtering is performed higher in the tree */
 	if(starpu_sched_component_is_worker(component))
 		return;
 	struct starpu_bitmap * workers_in_ctx = _starpu_get_worker_mask(sched_ctx_id);
 	starpu_bitmap_unset_and(component->workers_in_ctx,component->workers, workers_in_ctx);
-	int i,j;
+	int i;
 	for(i = 0; i < component->nchildren; i++)
 	{
 		struct starpu_sched_component * child = component->children[i];
 		_starpu_sched_component_update_workers_in_ctx(child, sched_ctx_id);
-		starpu_bitmap_or(component->workers_in_ctx, child->workers_in_ctx);
 	}
 	set_properties(component);
 	component->notify_change_workers(component);
@@ -399,8 +401,8 @@ void starpu_sched_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsign
 	STARPU_ASSERT(workerids);
 	struct starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
-	STARPU_PTHREAD_MUTEX_LOCK(&t->lock);
-	_starpu_sched_component_lock_all_workers(sched_ctx_id);
+	STARPU_COMPONENT_MUTEX_LOCK(&t->lock);
+	_starpu_sched_component_lock_all_workers();
 
 	unsigned i;
 	for(i = 0; i < nworkers; i++)
@@ -408,8 +410,8 @@ void starpu_sched_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsign
 
 	starpu_sched_tree_update_workers_in_ctx(t);
 
-	_starpu_sched_component_unlock_all_workers(sched_ctx_id);
-	STARPU_PTHREAD_MUTEX_UNLOCK(&t->lock);
+	_starpu_sched_component_unlock_all_workers();
+	STARPU_COMPONENT_MUTEX_UNLOCK(&t->lock);
 }
 
 void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers)
@@ -418,8 +420,8 @@ void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, uns
 	STARPU_ASSERT(workerids);
 	struct starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
-	STARPU_PTHREAD_MUTEX_LOCK(&t->lock);
-	_starpu_sched_component_lock_all_workers(sched_ctx_id);
+	STARPU_COMPONENT_MUTEX_LOCK(&t->lock);
+	_starpu_sched_component_lock_all_workers();
 
 	unsigned i;
 	for(i = 0; i < nworkers; i++)
@@ -427,8 +429,8 @@ void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, uns
 
 	starpu_sched_tree_update_workers_in_ctx(t);
 
-	_starpu_sched_component_unlock_all_workers(sched_ctx_id);
-	STARPU_PTHREAD_MUTEX_UNLOCK(&t->lock);
+	_starpu_sched_component_unlock_all_workers();
+	STARPU_COMPONENT_MUTEX_UNLOCK(&t->lock);
 }
 
 static struct starpu_sched_tree *trees[STARPU_NMAX_SCHED_CTXS];

+ 18 - 18
src/sched_policies/component_work_stealing.c

@@ -47,8 +47,10 @@ struct _starpu_work_stealing_data
 static struct starpu_task *  steal_task_round_robin(struct starpu_sched_component *component, int workerid)
 {
 	struct _starpu_work_stealing_data *wsd = component->data;
+	STARPU_HG_DISABLE_CHECKING(wsd->last_pop_child);
 	unsigned i = wsd->last_pop_child;
-	wsd->last_pop_child = (wsd->last_pop_child + 1) % component->nchildren;
+	wsd->last_pop_child = (i + 1) % component->nchildren;
+	STARPU_HG_ENABLE_CHECKING(wsd->last_pop_child);
 	/* If the worker's queue have no suitable tasks, let's try
 	 * the next ones */
 	struct starpu_task * task = NULL;
@@ -56,14 +58,14 @@ static struct starpu_task *  steal_task_round_robin(struct starpu_sched_componen
 	{
 		struct _starpu_prio_deque * fifo = wsd->fifos[i];
 
-		STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 		task = _starpu_prio_deque_deque_task_for_worker(fifo, workerid, NULL);
 		if(task && !isnan(task->predicted))
 		{
 			fifo->exp_len -= task->predicted;
 			fifo->nprocessed--;
 		}
-		STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 		if(task)
 		{
 			_STARPU_TASK_BREAK_ON(task, sched);
@@ -134,7 +136,7 @@ static struct starpu_task * pull_task(struct starpu_sched_component * component)
 	}
 	STARPU_ASSERT(i < component->nchildren);
 	struct _starpu_work_stealing_data * wsd = component->data;
-	STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+	STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 	struct starpu_task * task = _starpu_prio_deque_pop_task(wsd->fifos[i]);
 	if(task)
 	{
@@ -147,7 +149,7 @@ static struct starpu_task * pull_task(struct starpu_sched_component * component)
 	else
 		wsd->fifos[i]->exp_len = 0.0;
 
-	STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+	STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 	if(task)
 	{
 		return task;
@@ -156,9 +158,9 @@ static struct starpu_task * pull_task(struct starpu_sched_component * component)
 	task  = steal_task(component, workerid);
 	if(task)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 		wsd->fifos[i]->nprocessed++;
-		STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 
 		return task;
 	}
@@ -188,11 +190,11 @@ double _ws_estimated_end(struct starpu_sched_component * component)
 	int i;
 	for(i = 0; i < component->nchildren; i++)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 		sum_len += wsd->fifos[i]->exp_len;
 		wsd->fifos[i]->exp_start = STARPU_MAX(starpu_timing_now(), wsd->fifos[i]->exp_start);
 		sum_start += wsd->fifos[i]->exp_start;
-		STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 
 	}
 	int nb_workers = starpu_bitmap_cardinal(component->workers_in_ctx);
@@ -208,9 +210,9 @@ double _ws_estimated_load(struct starpu_sched_component * component)
 	int i;
 	for(i = 0; i < component->nchildren; i++)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 		ntasks += wsd->fifos[i]->ntasks;
-		STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+		STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 	}
 	double speedup = 0.0;
 	int workerid;
@@ -230,11 +232,10 @@ static int push_task(struct starpu_sched_component * component, struct starpu_ta
 	int ret;
 	int i = wsd->last_push_child;
 	i = (i+1)%component->nchildren;
-
-	STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+	STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 	_STARPU_TASK_BREAK_ON(task, sched);
 	ret = _starpu_prio_deque_push_task(wsd->fifos[i], task);
-	STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+	STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 
 	wsd->last_push_child = i;
 	component->can_pull(component);
@@ -251,7 +252,7 @@ int starpu_sched_tree_work_stealing_push_task(struct starpu_task *task)
 
 	unsigned sched_ctx_id = task->sched_ctx;
 	struct starpu_sched_component * component =starpu_sched_component_worker_get(sched_ctx_id, workerid);
-	while(component->parents[sched_ctx_id] != NULL)
+	while(sched_ctx_id < component->nparents && component->parents[sched_ctx_id] != NULL)
 	{
 		component = component->parents[sched_ctx_id];
 		if(starpu_sched_component_is_work_stealing(component))
@@ -266,11 +267,11 @@ int starpu_sched_tree_work_stealing_push_task(struct starpu_task *task)
 			STARPU_ASSERT(i < component->nchildren);
 
 			struct _starpu_work_stealing_data * wsd = component->data;
-			STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes[i]);
+			STARPU_COMPONENT_MUTEX_LOCK(wsd->mutexes[i]);
 			int ret = _starpu_prio_deque_push_task(wsd->fifos[i] , task);
 			if(ret == 0 && !isnan(task->predicted))
 				wsd->fifos[i]->exp_len += task->predicted;
-			STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes[i]);
+			STARPU_COMPONENT_MUTEX_UNLOCK(wsd->mutexes[i]);
 
 			//we need to wake all workers
 			component->can_pull(component);
@@ -278,7 +279,6 @@ int starpu_sched_tree_work_stealing_push_task(struct starpu_task *task)
 		}
 	}
 
-	/* this should not be reached */
 	return starpu_sched_tree_push_task(task);
 }
 

+ 67 - 193
src/sched_policies/component_worker.c

@@ -146,26 +146,14 @@ static void _starpu_worker_task_list_finished(struct _starpu_worker_task_list *l
 }
 
 
-enum _starpu_worker_component_status
-{
-	COMPONENT_STATUS_SLEEPING,
-	COMPONENT_STATUS_RESET,
-	COMPONENT_STATUS_CHANGED
-};
-
 struct _starpu_worker_component_data
 {
 	union
 	{
-		struct
-		{
-			struct _starpu_worker * worker;
-			starpu_pthread_mutex_t lock;
-		};
+		struct _starpu_worker * worker;
 		struct _starpu_combined_worker * combined_worker;
 	};
 	struct _starpu_worker_task_list * list;
-	enum _starpu_worker_component_status status;
 };
 
 /* this array store worker components */
@@ -372,93 +360,12 @@ struct _starpu_combined_worker * _starpu_sched_component_combined_worker_get_com
 	return data->combined_worker;
 }
 
-void _starpu_sched_component_lock_worker(unsigned sched_ctx_id, int workerid)
-{
-	STARPU_ASSERT(workerid >= 0 && workerid < (int) starpu_worker_get_count());
-	struct _starpu_worker_component_data * data = starpu_sched_component_worker_get(sched_ctx_id, workerid)->data;
-	STARPU_PTHREAD_MUTEX_LOCK(&data->lock);
-}
-void _starpu_sched_component_unlock_worker(unsigned sched_ctx_id, int workerid)
-{
-	STARPU_ASSERT(workerid >= 0  && workerid < (int)starpu_worker_get_count());
-	struct _starpu_worker_component_data * data = starpu_sched_component_worker_get(sched_ctx_id, workerid)->data;
-	STARPU_PTHREAD_MUTEX_UNLOCK(&data->lock);
-}
-
-
-
 /******************************************************************************
  *				Worker Components' Private Helper Functions			      	  *
  *****************************************************************************/
 
 
 
-/* Allows a worker to lock/unlock scheduling mutexes. Currently used in
- * self-defined can_push calls to allow can_pull calls to take those mutexes while the
- * current worker is pushing tasks on other workers (or itself).
- */
-static void _starpu_sched_component_worker_lock_scheduling(unsigned sched_ctx_id)
-{
-	unsigned workerid = starpu_worker_get_id_check();
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	_starpu_sched_component_lock_worker(sched_ctx_id, workerid);
-#ifdef STARPU_DEVEL
-#warning Reverses locking order between worker lock and worker component lock!
-#warning See helgrind suppression file for the details
-#endif
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
-}
-
-static void _starpu_sched_component_worker_unlock_scheduling(unsigned sched_ctx_id)
-{
-	unsigned workerid = starpu_worker_get_id_check();
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
-	_starpu_sched_component_unlock_worker(sched_ctx_id, workerid);
-}
-
-static void _starpu_sched_component_worker_set_sleep_status(struct starpu_sched_component * worker_component)
-{
-	STARPU_ASSERT(starpu_sched_component_is_worker(worker_component));
-	struct _starpu_worker_component_data * data = worker_component->data;
-	data->status = COMPONENT_STATUS_SLEEPING;
-}
-static void _starpu_sched_component_worker_set_changed_status(struct starpu_sched_component * worker_component)
-{
-	STARPU_ASSERT(starpu_sched_component_is_worker(worker_component));
-	struct _starpu_worker_component_data * data = worker_component->data;
-	data->status = COMPONENT_STATUS_CHANGED;
-}
-static void _starpu_sched_component_worker_reset_status(struct starpu_sched_component * worker_component)
-{
-	STARPU_ASSERT(starpu_sched_component_is_worker(worker_component));
-	struct _starpu_worker_component_data * data = worker_component->data;
-	data->status = COMPONENT_STATUS_RESET;
-}
-
-static int _starpu_sched_component_worker_is_reset_status(struct starpu_sched_component * worker_component)
-{
-	STARPU_ASSERT(starpu_sched_component_is_worker(worker_component));
-	struct _starpu_worker_component_data * data = worker_component->data;
-	return (data->status == COMPONENT_STATUS_RESET);
-}
-static int _starpu_sched_component_worker_is_changed_status(struct starpu_sched_component * worker_component)
-{
-	STARPU_ASSERT(starpu_sched_component_is_worker(worker_component));
-	struct _starpu_worker_component_data * data = worker_component->data;
-	return (data->status == COMPONENT_STATUS_CHANGED);
-}
-static int _starpu_sched_component_worker_is_sleeping_status(struct starpu_sched_component * worker_component)
-{
-	STARPU_ASSERT(starpu_sched_component_is_worker(worker_component));
-	struct _starpu_worker_component_data * data = worker_component->data;
-	return (data->status == COMPONENT_STATUS_SLEEPING);
-}
-
 #ifndef STARPU_NO_ASSERT
 static int _worker_consistant(struct starpu_sched_component * component)
 {
@@ -490,27 +397,9 @@ static int _worker_consistant(struct starpu_sched_component * component)
 
 static void simple_worker_can_pull(struct starpu_sched_component * worker_component)
 {
-	(void) worker_component;
-	struct _starpu_worker * w = _starpu_sched_component_worker_get_worker(worker_component);
-	_starpu_sched_component_lock_worker(worker_component->tree->sched_ctx_id, w->workerid);
-	if(_starpu_sched_component_worker_is_reset_status(worker_component))
-		_starpu_sched_component_worker_set_changed_status(worker_component);
-
-	if(w->workerid == _starpu_worker_get_id())
-	{
-		_starpu_sched_component_unlock_worker(worker_component->tree->sched_ctx_id, w->workerid);
-		return;
-	}
-	if(_starpu_sched_component_worker_is_sleeping_status(worker_component))
-	{
-		starpu_pthread_mutex_t *sched_mutex;
-		starpu_pthread_cond_t *sched_cond;
-		starpu_worker_get_sched_condition(w->workerid, &sched_mutex, &sched_cond);
-		_starpu_sched_component_unlock_worker(worker_component->tree->sched_ctx_id, w->workerid);
-		starpu_wakeup_worker(w->workerid, sched_cond, sched_mutex);
-	}
-	else
-		_starpu_sched_component_unlock_worker(worker_component->tree->sched_ctx_id, w->workerid);
+	struct _starpu_worker * worker = _starpu_sched_component_worker_get_worker(worker_component);
+	int workerid = worker->workerid;
+	_starpu_wake_worker_relax(workerid);
 }
 
 static int simple_worker_push_task(struct starpu_sched_component * component, struct starpu_task *task)
@@ -531,9 +420,9 @@ static int simple_worker_push_task(struct starpu_sched_component * component, st
 	}
 #endif
 	struct _starpu_worker_task_list * list = data->list;
-	STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
 	_starpu_worker_task_list_push(list, t);
-	STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
 	simple_worker_can_pull(component);
 	return 0;
 }
@@ -541,70 +430,71 @@ static int simple_worker_push_task(struct starpu_sched_component * component, st
 static struct starpu_task * simple_worker_pull_task(struct starpu_sched_component *component)
 {
 	unsigned workerid = starpu_worker_get_id_check();
+	struct _starpu_worker *worker = _starpu_get_worker_struct(workerid);
 	struct _starpu_worker_component_data * data = component->data;
 	struct _starpu_worker_task_list * list = data->list;
-	STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
-	/* Take the opportunity to update start time */
-	data->list->exp_start = STARPU_MAX(starpu_timing_now(), data->list->exp_start);
-	data->list->exp_end = data->list->exp_start + data->list->exp_len;
-	struct starpu_task * task =  _starpu_worker_task_list_pop(list);
-	if(task)
-	{
-		_starpu_worker_task_list_transfer_started(list, task);
-		STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
-		starpu_push_task_end(task);
-		return task;
-	}
-	STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
-	_starpu_sched_component_lock_worker(component->tree->sched_ctx_id, workerid);
+	struct starpu_task * task;
 	int i;
+	int n_tries = 0;
 	do
 	{
-		_starpu_sched_component_worker_reset_status(component);
+		/* do not reset state_keep_awake here has it may hide tasks in worker->local_tasks */
+		n_tries++;
+		STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
+		/* Take the opportunity to update start time */
+		data->list->exp_start = STARPU_MAX(starpu_timing_now(), data->list->exp_start);
+		data->list->exp_end = data->list->exp_start + data->list->exp_len;
+		task =  _starpu_worker_task_list_pop(list);
+		if(task)
+		{
+			_starpu_worker_task_list_transfer_started(list, task);
+			STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
+			starpu_push_task_end(task);
+			goto ret;
+		}
+		STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
 		for(i=0; i < component->nparents; i++)
 		{
 			if(component->parents[i] == NULL)
 				continue;
 			else
 			{
-				_starpu_sched_component_worker_unlock_scheduling(component->tree->sched_ctx_id);
 				task = starpu_sched_component_pull_task(component->parents[i],component);
-				_starpu_sched_component_worker_lock_scheduling(component->tree->sched_ctx_id);
 				if(task)
 					break;
 			}
 		}
 	}
-	while((!task) && _starpu_sched_component_worker_is_changed_status(component));
-	_starpu_sched_component_worker_set_sleep_status(component);
-	_starpu_sched_component_unlock_worker(component->tree->sched_ctx_id, workerid);
+	while((!task) && worker->state_keep_awake && n_tries < 2);
 	if(!task)
-		return NULL;
+		goto ret;
 	if(task->cl->type == STARPU_SPMD)
 	{
 		if(!starpu_worker_is_combined_worker(workerid))
 		{
-			STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+			STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
 			_starpu_worker_task_list_add(list, task);
 			_starpu_worker_task_list_transfer_started(list, task);
-			STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
+			STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
 			starpu_push_task_end(task);
-			return task;
+			goto ret;
 		}
 		struct starpu_sched_component * combined_worker_component = starpu_sched_component_worker_get(component->tree->sched_ctx_id, workerid);
 		starpu_sched_component_push_task(component, combined_worker_component, task);
 		/* we have pushed a task in queue, so can make a recursive call */
-		return simple_worker_pull_task(component);
+		task = simple_worker_pull_task(component);
+		goto ret;
 
 	}
 	if(task)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
 		_starpu_worker_task_list_add(list, task);
 		_starpu_worker_task_list_transfer_started(list, task);
-		STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
+		STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
 		starpu_push_task_end(task);
 	}
+ret:
 	return task;
 }
 
@@ -624,14 +514,14 @@ static double simple_worker_estimated_load(struct starpu_sched_component * compo
 {
 	struct _starpu_worker * worker = _starpu_sched_component_worker_get_worker(component);
 	int nb_task = 0;
-	STARPU_PTHREAD_MUTEX_LOCK(&worker->mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(&worker->mutex);
 	struct starpu_task_list list = worker->local_tasks;
 	struct starpu_task * task;
 	for(task = starpu_task_list_front(&list);
 	    task != starpu_task_list_end(&list);
 	    task = starpu_task_list_next(task))
 		nb_task++;
-	STARPU_PTHREAD_MUTEX_UNLOCK(&worker->mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(&worker->mutex);
 	struct _starpu_worker_component_data * d = component->data;
 	struct _starpu_worker_task_list * l = d->list;
 	int ntasks_in_fifo = l ? l->ntasks : 0;
@@ -644,8 +534,6 @@ static void _worker_component_deinit_data(struct starpu_sched_component * compon
 {
 	struct _starpu_worker_component_data * d = component->data;
 	_starpu_worker_task_list_destroy(d->list);
-	if(starpu_sched_component_is_simple_worker(component))
-		STARPU_PTHREAD_MUTEX_DESTROY(&d->lock);
 	int i, j;
 	for(j = 0; j < STARPU_NMAX_SCHED_CTXS; j++)
 	for(i = 0; i < STARPU_NMAXWORKERS; i++)
@@ -675,8 +563,6 @@ static struct starpu_sched_component * starpu_sched_component_worker_create(stru
 	memset(data, 0, sizeof(*data));
 
 	data->worker = worker;
-	STARPU_PTHREAD_MUTEX_INIT(&data->lock,NULL);
-	data->status = COMPONENT_STATUS_SLEEPING;
 	data->list = _starpu_worker_task_list_create();
 	component->data = data;
 
@@ -722,19 +608,7 @@ static void combined_worker_can_pull(struct starpu_sched_component * component)
 	{
 		if((unsigned) i == workerid)
 			continue;
-		int worker = data->combined_worker->combined_workerid[i];
-		_starpu_sched_component_lock_worker(component->tree->sched_ctx_id, worker);
-		if(_starpu_sched_component_worker_is_sleeping_status(component))
-		{
-			starpu_pthread_mutex_t *sched_mutex;
-			starpu_pthread_cond_t *sched_cond;
-			starpu_worker_get_sched_condition(worker, &sched_mutex, &sched_cond);
-			starpu_wakeup_worker(worker, sched_cond, sched_mutex);
-		}
-		if(_starpu_sched_component_worker_is_reset_status(component))
-			_starpu_sched_component_worker_set_changed_status(component);
-
-		_starpu_sched_component_unlock_worker(component->tree->sched_ctx_id, worker);
+		_starpu_wake_worker_relax(workerid);
 	}
 }
 
@@ -772,9 +646,9 @@ static int combined_worker_push_task(struct starpu_sched_component * component,
 		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(component->tree->sched_ctx_id, combined_worker->combined_workerid[i]);
 		struct _starpu_worker_component_data * worker_data = worker_component->data;
 		struct _starpu_worker_task_list * list = worker_data->list;
-		STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+		STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
 		if(mutex_to_unlock)
-			STARPU_PTHREAD_MUTEX_UNLOCK(mutex_to_unlock);
+			STARPU_COMPONENT_MUTEX_UNLOCK(mutex_to_unlock);
 		mutex_to_unlock = &list->mutex;
 
 		_starpu_worker_task_list_push(list, task_alias[i]);
@@ -782,7 +656,7 @@ static int combined_worker_push_task(struct starpu_sched_component * component,
 	}
 	while(i < combined_worker->worker_size);
 
-	STARPU_PTHREAD_MUTEX_UNLOCK(mutex_to_unlock);
+	STARPU_COMPONENT_MUTEX_UNLOCK(mutex_to_unlock);
 
 	int workerid = starpu_worker_get_id();
 	if(-1 == workerid)
@@ -791,11 +665,6 @@ static int combined_worker_push_task(struct starpu_sched_component * component,
 	}
 	else
 	{
-		starpu_pthread_mutex_t *worker_sched_mutex;
-		starpu_pthread_cond_t *worker_sched_cond;
-		starpu_worker_get_sched_condition(workerid, &worker_sched_mutex, &worker_sched_cond);
-		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(worker_sched_mutex);
-
 		/* wake up all other workers of combined worker */
 		for(i = 0; i < combined_worker->worker_size; i++)
 		{
@@ -804,8 +673,6 @@ static int combined_worker_push_task(struct starpu_sched_component * component,
 		}
 
 		combined_worker_can_pull(component);
-
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(worker_sched_mutex);
 	}
 
 	return 0;
@@ -856,7 +723,6 @@ static struct starpu_sched_component  * starpu_sched_component_combined_worker_c
 	_STARPU_MALLOC(data, sizeof(*data));
 	memset(data, 0, sizeof(*data));
 	data->combined_worker = combined_worker;
-	data->status = COMPONENT_STATUS_SLEEPING;
 
 	component->data = data;
 	component->push_task = combined_worker_push_task;
@@ -887,17 +753,17 @@ static struct starpu_sched_component  * starpu_sched_component_combined_worker_c
 
 
 
-void _starpu_sched_component_lock_all_workers(unsigned sched_ctx_id)
+void _starpu_sched_component_lock_all_workers(void)
 {
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count(); i++)
-		_starpu_sched_component_lock_worker(sched_ctx_id, i);
+		_starpu_worker_lock(i);
 }
-void _starpu_sched_component_unlock_all_workers(unsigned sched_ctx_id)
+void _starpu_sched_component_unlock_all_workers(void)
 {
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count(); i++)
-		_starpu_sched_component_unlock_worker(sched_ctx_id, i);
+		_starpu_worker_unlock(i);
 }
 
 void _starpu_sched_component_workers_destroy(void)
@@ -921,11 +787,11 @@ int starpu_sched_component_worker_get_workerid(struct starpu_sched_component * w
 void starpu_sched_component_worker_pre_exec_hook(struct starpu_task * task, unsigned sched_ctx_id STARPU_ATTRIBUTE_UNUSED)
 {
 	struct _starpu_worker_task_list * list = _worker_get_list(sched_ctx_id);
-	STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
 	_starpu_worker_task_list_started(list, task);
 	/* Take the opportunity to update start time */
 	list->exp_start = STARPU_MAX(starpu_timing_now() + list->pipeline_len, list->exp_start);
-	STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
 }
 
 void starpu_sched_component_worker_post_exec_hook(struct starpu_task * task, unsigned sched_ctx_id STARPU_ATTRIBUTE_UNUSED)
@@ -933,9 +799,9 @@ void starpu_sched_component_worker_post_exec_hook(struct starpu_task * task, uns
 	if(task->execute_on_a_specific_worker)
 		return;
 	struct _starpu_worker_task_list * list = _worker_get_list(sched_ctx_id);
-	STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+	STARPU_COMPONENT_MUTEX_LOCK(&list->mutex);
 	_starpu_worker_task_list_finished(list, task);
-	STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
+	STARPU_COMPONENT_MUTEX_UNLOCK(&list->mutex);
 }
 
 int starpu_sched_component_is_simple_worker(struct starpu_sched_component * component)
@@ -959,16 +825,24 @@ struct starpu_sched_component * starpu_sched_component_worker_get(unsigned sched
 {
 	STARPU_ASSERT(workerid >= 0 && workerid < STARPU_NMAXWORKERS);
 	/* we may need to take a mutex here */
-	if(_worker_components[sched_ctx][workerid])
-		return _worker_components[sched_ctx][workerid];
+	STARPU_ASSERT(_worker_components[sched_ctx][workerid]);
+	return _worker_components[sched_ctx][workerid];
+}
+
+struct starpu_sched_component * starpu_sched_component_worker_new(unsigned sched_ctx, int workerid)
+{
+	STARPU_ASSERT(workerid >= 0 && workerid < STARPU_NMAXWORKERS);
+	/* we may need to take a mutex here */
+	STARPU_ASSERT(!_worker_components[sched_ctx][workerid]);
+	struct starpu_sched_component * component;
+	if(workerid < (int) starpu_worker_get_count())
+		component = starpu_sched_component_worker_create(starpu_sched_tree_get(sched_ctx), workerid);
 	else
-	{
-		struct starpu_sched_component * component;
-		if(workerid < (int) starpu_worker_get_count())
-			component = starpu_sched_component_worker_create(starpu_sched_tree_get(sched_ctx), workerid);
-		else
-			component = starpu_sched_component_combined_worker_create(starpu_sched_tree_get(sched_ctx), workerid);
-		_worker_components[sched_ctx][workerid] = component;
-		return component;
-	}
+		component = starpu_sched_component_combined_worker_create(starpu_sched_tree_get(sched_ctx), workerid);
+	_worker_components[sched_ctx][workerid] = component;
+	return component;
 }
+
+
+
+

+ 32 - 49
src/sched_policies/deque_modeling_policy_data_aware.c

@@ -325,12 +325,9 @@ static struct starpu_task *dmda_pop_every_task(unsigned sched_ctx_id)
 	fifo->exp_start = STARPU_MAX(starpu_timing_now(), fifo->exp_start);
 	fifo->exp_end = fifo->exp_start + fifo->exp_len;
 
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock_self();
 	new_list = _starpu_fifo_pop_every_task(fifo, workerid);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock_self();
 
 	starpu_sched_ctx_list_task_counters_reset(sched_ctx_id, workerid);
 
@@ -368,7 +365,7 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 	starpu_sched_ctx_call_pushed_task_cb(best_workerid, sched_ctx_id);
 #endif //STARPU_USE_SC_HYPERVISOR
 
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock(best_workerid);
 
         /* Sometimes workers didn't take the tasks as early as we expected */
 	fifo->exp_start = isnan(fifo->exp_start) ? now + fifo->pipeline_len : STARPU_MAX(fifo->exp_start, now);
@@ -414,7 +411,7 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 	}
 	fifo->exp_end = fifo->exp_start + fifo->exp_len;
 
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock(best_workerid);
 
 	task->predicted = predicted;
 	task->predicted_transfer = predicted_transfer;
@@ -442,7 +439,7 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 	int ret = 0;
 	if (prio)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+		_starpu_worker_lock(best_workerid);
 		ret =_starpu_fifo_push_sorted_task(dt->queue_array[best_workerid], task);
 		if(dt->num_priorities != -1)
 		{
@@ -454,22 +451,22 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 
 
 #if !defined(STARPU_NON_BLOCKING_DRIVERS) || defined(STARPU_SIMGRID)
-		starpu_wakeup_worker_locked(best_workerid, sched_cond, sched_mutex);
+		starpu_wake_worker_locked(best_workerid);
 #endif
 		starpu_push_task_end(task);
-		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+		_starpu_worker_unlock(best_workerid);
 	}
 	else
 	{
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+		_starpu_worker_lock(best_workerid);
 		starpu_task_list_push_back (&dt->queue_array[best_workerid]->taskq, task);
 		dt->queue_array[best_workerid]->ntasks++;
 		dt->queue_array[best_workerid]->nprocessed++;
 #if !defined(STARPU_NON_BLOCKING_DRIVERS) || defined(STARPU_SIMGRID)
-		starpu_wakeup_worker_locked(best_workerid, sched_cond, sched_mutex);
+		starpu_wake_worker_locked(best_workerid);
 #endif
 		starpu_push_task_end(task);
-		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+		_starpu_worker_unlock(best_workerid);
 	}
 
 	starpu_sched_ctx_list_task_counters_increment(sched_ctx_id, best_workerid);
@@ -661,19 +658,19 @@ static void compute_all_performance_predictions(struct starpu_task *task,
 
 	struct starpu_sched_ctx_iterator it;
 	workers->init_iterator_for_parallel_tasks(workers, &it, task);
-	while(workers->has_next(workers, &it))
+	while(worker_ctx<nworkers && workers->has_next(workers, &it))
 	{
 		unsigned nimpl;
 		unsigned impl_mask;
-		unsigned worker = workers->get_next(workers, &it);
-		struct _starpu_fifo_taskq *fifo = dt->queue_array[worker];
-		struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(worker, sched_ctx_id);
-		unsigned memory_node = starpu_worker_get_memory_node(worker);
+		unsigned workerid = workers->get_next(workers, &it);
+		struct _starpu_fifo_taskq *fifo = dt->queue_array[workerid];
+		struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(workerid, sched_ctx_id);
+		unsigned memory_node = starpu_worker_get_memory_node(workerid);
 
 		/* Sometimes workers didn't take the tasks as early as we expected */
 		double exp_start = isnan(fifo->exp_start) ? now + fifo->pipeline_len : STARPU_MAX(fifo->exp_start, now);
 
-		if (!starpu_worker_can_execute_task_impl(worker, task, &impl_mask))
+		if (!starpu_worker_can_execute_task_impl(workerid, task, &impl_mask))
 			continue;
 
 		for (nimpl  = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
@@ -683,11 +680,11 @@ static void compute_all_performance_predictions(struct starpu_task *task,
 				/* no one on that queue may execute this task */
 				continue;
 			}
-			STARPU_ASSERT_MSG(fifo != NULL, "worker %u ctx %u\n", worker, sched_ctx_id);
+			STARPU_ASSERT_MSG(fifo != NULL, "workerid %u ctx %u\n", workerid, sched_ctx_id);
 
 			int fifo_ntasks = fifo->ntasks;
 			double prev_exp_len = fifo->exp_len;
-			/* consider the priority of the task when deciding on which worker to schedule,
+			/* consider the priority of the task when deciding on which workerid to schedule,
 			   compute the expected_end of the task if it is inserted before other tasks already scheduled */
 			if(sorted_decision)
 			{
@@ -698,12 +695,9 @@ static void compute_all_performance_predictions(struct starpu_task *task,
 				}
 				else
 				{
-					starpu_pthread_mutex_t *sched_mutex;
-					starpu_pthread_cond_t *sched_cond;
-					starpu_worker_get_sched_condition(worker, &sched_mutex, &sched_cond);
-					STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
-					prev_exp_len = _starpu_fifo_get_exp_len_prev_task_list(fifo, task, worker, nimpl, &fifo_ntasks);
-					STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+					_starpu_worker_lock(workerid);
+					prev_exp_len = _starpu_fifo_get_exp_len_prev_task_list(fifo, task, workerid, nimpl, &fifo_ntasks);
+					_starpu_worker_unlock(workerid);
 				}
 			}
 
@@ -711,7 +705,7 @@ static void compute_all_performance_predictions(struct starpu_task *task,
 			if (exp_end[worker_ctx][nimpl] > max_exp_end)
 				max_exp_end = exp_end[worker_ctx][nimpl];
 
-			//_STARPU_DEBUG("Scheduler dmda: task length (%lf) worker (%u) kernel (%u) \n", local_task_length[worker][nimpl],worker,nimpl);
+			//_STARPU_DEBUG("Scheduler dmda: task length (%lf) workerid (%u) kernel (%u) \n", local_task_length[workerid][nimpl],workerid,nimpl);
 
 			if (bundle)
 			{
@@ -752,18 +746,18 @@ static void compute_all_performance_predictions(struct starpu_task *task,
 			    || (!calibrating && ntasks_end < ntasks_best_end)
 
 			    /* The performance model of this task is not
-			     * calibrated on this worker, try to run it there
+			     * calibrated on this workerid, try to run it there
 			     * to calibrate it there. */
 			    || (!calibrating && isnan(local_task_length[worker_ctx][nimpl]))
 
 			    /* the performance model of this task is not
-			     * calibrated on this worker either, rather run it
+			     * calibrated on this workerid either, rather run it
 			     * there if this one is low on scheduled tasks. */
 			    || (calibrating && isnan(local_task_length[worker_ctx][nimpl]) && ntasks_end < ntasks_best_end)
 				)
 			{
 				ntasks_best_end = ntasks_end;
-				ntasks_best = worker;
+				ntasks_best = workerid;
 				nimpl_best = nimpl;
 			}
 
@@ -864,7 +858,7 @@ static double _dmda_push_task(struct starpu_task *task, unsigned prio, unsigned
 		unsigned worker_ctx = 0;
 		struct starpu_sched_ctx_iterator it;
 		workers->init_iterator_for_parallel_tasks(workers, &it, task);
-		while(workers->has_next(workers, &it))
+		while(worker_ctx < nworkers_ctx && workers->has_next(workers, &it))
 		{
 			unsigned worker = workers->get_next(workers, &it);
 			unsigned nimpl;
@@ -1125,13 +1119,9 @@ static void dmda_pre_exec_hook(struct starpu_task *task, unsigned sched_ctx_id)
 	struct _starpu_dmda_data *dt = (struct _starpu_dmda_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	struct _starpu_fifo_taskq *fifo = dt->queue_array[workerid];
 
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-
 	/* Once the task is executing, we can update the predicted amount
 	 * of work. */
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock_self();
 
 	_starpu_fifo_task_started(fifo, task, dt->num_priorities);
 
@@ -1139,7 +1129,7 @@ static void dmda_pre_exec_hook(struct starpu_task *task, unsigned sched_ctx_id)
 	fifo->exp_start = STARPU_MAX(starpu_timing_now() + fifo->pipeline_len, fifo->exp_start);
 	fifo->exp_end = fifo->exp_start + fifo->exp_len;
 
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock_self();
 }
 
 static void dmda_push_task_notify(struct starpu_task *task, int workerid, int perf_workerid, unsigned sched_ctx_id)
@@ -1155,13 +1145,9 @@ static void dmda_push_task_notify(struct starpu_task *task, int workerid, int pe
 
 	double predicted_transfer = starpu_task_expected_data_transfer_time(memory_node, task);
 	double now = starpu_timing_now();
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-
 
 	/* Update the predictions */
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock(workerid);
 	/* Sometimes workers didn't take the tasks as early as we expected */
 	fifo->exp_start = isnan(fifo->exp_start) ? now + fifo->pipeline_len : STARPU_MAX(fifo->exp_start, now);
 	fifo->exp_end = fifo->exp_start + fifo->exp_len;
@@ -1219,7 +1205,7 @@ static void dmda_push_task_notify(struct starpu_task *task, int workerid, int pe
 
 	fifo->ntasks++;
 
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock(workerid);
 }
 
 static void dmda_post_exec_hook(struct starpu_task * task, unsigned sched_ctx_id)
@@ -1227,12 +1213,9 @@ static void dmda_post_exec_hook(struct starpu_task * task, unsigned sched_ctx_id
 	struct _starpu_dmda_data *dt = (struct _starpu_dmda_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	unsigned workerid = starpu_worker_get_id_check();
 	struct _starpu_fifo_taskq *fifo = dt->queue_array[workerid];
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock_self();
 	_starpu_fifo_task_finished(fifo, task, dt->num_priorities);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock_self();
 }
 
 struct starpu_sched_policy _starpu_sched_dm_policy =

+ 27 - 11
src/sched_policies/eager_central_policy.c

@@ -75,7 +75,9 @@ static int push_task_eager_policy(struct starpu_task *task)
 	unsigned sched_ctx_id = task->sched_ctx;
 	struct _starpu_eager_center_policy_data *data = (struct _starpu_eager_center_policy_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+	_starpu_worker_relax_off();
 	starpu_task_list_push_back(&data->fifo->taskq,task);
 	data->fifo->ntasks++;
 	data->fifo->nprocessed++;
@@ -125,12 +127,19 @@ static int push_task_eager_policy(struct starpu_task *task)
 	{
 		unsigned worker = workers->get_next(workers, &it);
 		if (dowake[worker])
-			if (starpu_wake_worker(worker))
+			if (_starpu_wake_worker_relax(worker))
 				break; // wake up a single worker
 	}
 #endif
 
-	starpu_sched_ctx_list_task_counters_increment_all(task, sched_ctx_id);
+	if (_starpu_get_nsched_ctxs() > 1)
+	{
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
+		starpu_sched_ctx_list_task_counters_increment_all_ctx_locked(task, sched_ctx_id);
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
+	}
 
 	return 0;
 }
@@ -154,20 +163,25 @@ static struct starpu_task *pop_task_eager_policy(unsigned sched_ctx_id)
 	unsigned workerid = starpu_worker_get_id_check();
 	struct _starpu_eager_center_policy_data *data = (struct _starpu_eager_center_policy_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
-	/* block until some event happens */
 	/* Here helgrind would shout that this is unprotected, this is just an
 	 * integer access, and we hold the sched mutex, so we can not miss any
 	 * wake up. */
 	if (!STARPU_RUNNING_ON_VALGRIND && _starpu_fifo_empty(data->fifo))
+	{
 		return NULL;
+	}
 
 #ifdef STARPU_NON_BLOCKING_DRIVERS
 	if (!STARPU_RUNNING_ON_VALGRIND && starpu_bitmap_get(data->waiters, workerid))
 		/* Nobody woke us, avoid bothering the mutex */
+	{
 		return NULL;
+	}
 #endif
-
+	/* block until some event happens */
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+	_starpu_worker_relax_off();
 
 	chosen_task = _starpu_fifo_pop_task(data->fifo, workerid);
 	if (!chosen_task)
@@ -175,21 +189,23 @@ static struct starpu_task *pop_task_eager_policy(unsigned sched_ctx_id)
 		starpu_bitmap_set(data->waiters, workerid);
 
 	STARPU_PTHREAD_MUTEX_UNLOCK(&data->policy_mutex);
-
 	if(chosen_task)
 	{
-		starpu_sched_ctx_list_task_counters_decrement_all(chosen_task, sched_ctx_id);
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
+		starpu_sched_ctx_list_task_counters_decrement_all_ctx_locked(chosen_task, sched_ctx_id);
 
 		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_move_task_to_ctx(chosen_task, child_sched_ctx, 1, 1);
-			starpu_sched_ctx_revert_task_counters(sched_ctx_id, chosen_task->flops);
-			return NULL;
+			starpu_sched_ctx_move_task_to_ctx_locked(chosen_task, child_sched_ctx, 1);
+			starpu_sched_ctx_revert_task_counters_ctx_locked(sched_ctx_id, chosen_task->flops);
+			chosen_task = NULL;
 		}
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
 	}
 
-
 	return chosen_task;
 }
 
@@ -201,7 +217,7 @@ static void eager_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nw
 		int workerid = workerids[i];
 		int curr_workerid = _starpu_worker_get_id();
 		if(workerid != curr_workerid)
-			starpu_wake_worker(workerid);
+			starpu_wake_worker_locked(workerid);
 
 		starpu_sched_ctx_worker_shares_tasks_lists(workerid, sched_ctx_id);
 	}

+ 29 - 24
src/sched_policies/eager_central_priority_policy.c

@@ -79,8 +79,9 @@ static int _starpu_priority_push_task(struct starpu_task *task)
 	struct _starpu_eager_central_prio_data *data = (struct _starpu_eager_central_prio_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	struct _starpu_prio_deque *taskq = &data->taskq;
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
-
+	_starpu_worker_relax_off();
 	_starpu_prio_deque_push_back_task(taskq, task);
 	starpu_push_task_end(task);
 
@@ -127,12 +128,20 @@ static int _starpu_priority_push_task(struct starpu_task *task)
 	{
 		unsigned worker = workers->get_next(workers, &it);
 		if (dowake[worker])
-			if (starpu_wake_worker(worker))
+			if (_starpu_wake_worker_relax(worker))
 				break; // wake up a single worker
 	}
 #endif
 
-	starpu_sched_ctx_list_task_counters_increment_all(task, sched_ctx_id);
+	if (_starpu_get_nsched_ctxs() > 1)
+	{
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
+		starpu_sched_ctx_list_task_counters_increment_all_ctx_locked(task, sched_ctx_id);
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
+	}
+
 
 	return 0;
 }
@@ -147,28 +156,25 @@ static struct starpu_task *_starpu_priority_pop_task(unsigned sched_ctx_id)
 
 	struct _starpu_prio_deque *taskq = &data->taskq;
 
-	/* block until some event happens */
 	/* Here helgrind would shout that this is unprotected, this is just an
 	 * integer access, and we hold the sched mutex, so we can not miss any
 	 * wake up. */
 	if (!STARPU_RUNNING_ON_VALGRIND && _starpu_prio_deque_is_empty(taskq))
+	{
 		return NULL;
+	}
 
 #ifdef STARPU_NON_BLOCKING_DRIVERS
 	if (!STARPU_RUNNING_ON_VALGRIND && starpu_bitmap_get(data->waiters, workerid))
 		/* Nobody woke us, avoid bothering the mutex */
+	{
 		return NULL;
+	}
 #endif
-
-	/* release this mutex before trying to wake up other workers */
-	starpu_pthread_mutex_t *curr_sched_mutex;
-	starpu_pthread_cond_t *curr_sched_cond;
-	starpu_worker_get_sched_condition(workerid, &curr_sched_mutex, &curr_sched_cond);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(curr_sched_mutex);
-
-	/* all workers will block on this mutex anyway so
-	   there's no need for their own mutex to be locked */
+	/* block until some event happens */
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+	_starpu_worker_relax_off();
 
 	chosen_task = _starpu_prio_deque_pop_task_for_worker(taskq, workerid, &skipped);
 
@@ -188,7 +194,7 @@ static struct starpu_task *_starpu_priority_pop_task(unsigned sched_ctx_id)
 #ifdef STARPU_NON_BLOCKING_DRIVERS
 				starpu_bitmap_unset(data->waiters, worker);
 #else
-				starpu_wake_worker_locked(worker);
+				_starpu_wake_worker_relax(worker);
 #endif
 			}
 		}
@@ -200,24 +206,23 @@ static struct starpu_task *_starpu_priority_pop_task(unsigned sched_ctx_id)
 		starpu_bitmap_set(data->waiters, workerid);
 
 	STARPU_PTHREAD_MUTEX_UNLOCK(&data->policy_mutex);
-
-	/* leave the mutex how it was found before this */
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(curr_sched_mutex);
-
 	if(chosen_task)
 	{
-		starpu_sched_ctx_list_task_counters_decrement_all(chosen_task, sched_ctx_id);
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
+		starpu_sched_ctx_list_task_counters_decrement_all_ctx_locked(chosen_task, sched_ctx_id);
 
                 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_move_task_to_ctx(chosen_task, child_sched_ctx, 1, 1);
-			starpu_sched_ctx_revert_task_counters(sched_ctx_id, chosen_task->flops);
-			return NULL;
+			starpu_sched_ctx_move_task_to_ctx_locked(chosen_task, child_sched_ctx, 1);
+			starpu_sched_ctx_revert_task_counters_ctx_locked(sched_ctx_id, chosen_task->flops);
+			chosen_task = NULL;
 		}
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
 	}
 
-
 	return chosen_task;
 }
 
@@ -229,7 +234,7 @@ static void eager_center_priority_add_workers(unsigned sched_ctx_id, int *worker
 		int workerid = workerids[i];
 		int curr_workerid = _starpu_worker_get_id();
 		if(workerid != curr_workerid)
-			starpu_wake_worker(workerid);
+			starpu_wake_worker_locked(workerid);
 
                 starpu_sched_ctx_worker_shares_tasks_lists(workerid, sched_ctx_id);
         }

+ 35 - 6
src/sched_policies/graph_test_policy.c

@@ -84,6 +84,7 @@ static void deinitialize_graph_test_policy(unsigned sched_ctx_id)
 	 _starpu_prio_deque_destroy(&data->prio_gpu);
 	starpu_bitmap_destroy(data->waiters);
 
+	_starpu_graph_record = 0;
 	STARPU_PTHREAD_MUTEX_DESTROY(&data->policy_mutex);
 	free(data);
 }
@@ -123,8 +124,19 @@ static struct _starpu_prio_deque *select_prio(unsigned sched_ctx_id, struct _sta
 			length = 0.;
 		if (length == 0.)
 		{
-			_STARPU_DISP("Warning: graph_test needs performance models for all tasks, including %s\n",
-					starpu_task_get_name(task));
+			if (!task->cl || task->cl->model == NULL)
+			{
+				static unsigned _warned;
+				if (STARPU_ATOMIC_ADD(&_warned, 1) == 1)
+				{
+					_STARPU_DISP("Warning: graph_test needs performance models for all tasks, including %s\n",
+							starpu_task_get_name(task));
+				}
+				else
+				{
+					(void)STARPU_ATOMIC_ADD(&_warned, -1);
+				}
+			}
 			power = 0.;
 		}
 		else
@@ -148,7 +160,9 @@ static struct _starpu_prio_deque *select_prio(unsigned sched_ctx_id, struct _sta
 static void set_priority(void *_data, struct _starpu_graph_node *node)
 {
 	struct _starpu_graph_test_policy_data *data = _data;
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&node->mutex);
+	_starpu_worker_relax_off();
 	struct _starpu_job *job = node->job;
 	if (job)
 	{
@@ -164,13 +178,22 @@ static void do_schedule_graph_test_policy(unsigned sched_ctx_id)
 {
 	struct _starpu_graph_test_policy_data *data = (struct _starpu_graph_test_policy_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+	_starpu_worker_relax_off();
 	if (data->descendants)
 		_starpu_graph_compute_descendants();
 	else
 		_starpu_graph_compute_depths();
-	data->computed = 1;
-	_starpu_graph_foreach(set_priority, data);
+	if (data->computed == 0)
+	{
+		data->computed = 1;
+
+		/* FIXME: if data->computed already == 1, some tasks may already have been pushed to priority stage '0' in
+		 * push_task_graph_test_policy, then if we change the priority here, the stage lookup to remove the task
+		 * will get the wrong stage */
+		_starpu_graph_foreach(set_priority, data);
+	}
 
 	/* Now that we have priorities, move tasks from bag to priority queue */
 	while(!_starpu_fifo_empty(data->fifo))
@@ -200,7 +223,7 @@ static void do_schedule_graph_test_policy(unsigned sched_ctx_id)
 	{
 		/* Wake each worker */
 		unsigned worker = workers->get_next(workers, &it);
-		starpu_wake_worker(worker);
+		_starpu_wake_worker_relax(worker);
 	}
 #endif
 }
@@ -210,7 +233,9 @@ static int push_task_graph_test_policy(struct starpu_task *task)
 	unsigned sched_ctx_id = task->sched_ctx;
 	struct _starpu_graph_test_policy_data *data = (struct _starpu_graph_test_policy_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+	_starpu_worker_relax_off();
 	if (!data->computed)
 	{
 		/* Priorities are not computed, leave the task in the bag for now */
@@ -277,8 +302,10 @@ static int push_task_graph_test_policy(struct starpu_task *task)
 	{
 		unsigned worker = workers->get_next(workers, &it);
 		if (dowake[worker])
-			if (starpu_wake_worker(worker))
+		{
+			if (_starpu_wake_worker_relax(worker))
 				break; // wake up a single worker
+		}
 	}
 #endif
 
@@ -313,7 +340,9 @@ static struct starpu_task *pop_task_graph_test_policy(unsigned sched_ctx_id)
 		return NULL;
 #endif
 
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+	_starpu_worker_relax_off();
 	if (!data->computed)
 	{
 		STARPU_PTHREAD_MUTEX_UNLOCK(&data->policy_mutex);

+ 3 - 2
src/sched_policies/helper_mct.c

@@ -85,7 +85,7 @@ struct _starpu_mct_data *starpu_mct_init_parameters(struct starpu_sched_componen
 static double compute_expected_time(double now, double predicted_end, double predicted_length, double predicted_transfer)
 {
 	STARPU_ASSERT(!isnan(now + predicted_end + predicted_length + predicted_transfer));
-	STARPU_ASSERT(now >= 0.0 && predicted_end >= 0.0 && predicted_length >= 0.0 && predicted_transfer >= 0.0);
+	STARPU_ASSERT_MSG(now >= 0.0 && predicted_end >= 0.0 && predicted_length >= 0.0 && predicted_transfer >= 0.0, "now=%lf, predicted_end=%lf, predicted_length=%lf, predicted_transfer=%lf\n", now, predicted_end, predicted_length, predicted_transfer);
 
 	/* TODO: actually schedule transfers */
 	/* Compute the transfer time which will not be overlapped */
@@ -123,7 +123,6 @@ int starpu_mct_compute_execution_times(struct starpu_sched_component *component,
 				       double *estimated_lengths, double *estimated_transfer_length, int *suitable_components) 
 {
 	int nsuitable_components = 0;
-	double now = starpu_timing_now();
 
 	int i;
 	for(i = 0; i < component->nchildren; i++)
@@ -135,6 +134,8 @@ int starpu_mct_compute_execution_times(struct starpu_sched_component *component,
 				/* The perfmodel had been purged since the task was pushed
 				 * onto the mct component. */
 				continue;
+			STARPU_ASSERT_MSG(estimated_lengths[i]>=0, "component=%p, child[%d]=%p, estimated_lengths[%d]=%lf\n", component, i, c, i, estimated_lengths[i]);
+
 			estimated_transfer_length[i] = starpu_sched_component_transfer_length(c, task);
 			suitable_components[nsuitable_components++] = i;
 		}

+ 18 - 19
src/sched_policies/heteroprio.c

@@ -159,6 +159,8 @@ static inline void default_init_sched(unsigned sched_ctx_id)
 {
 	int min_prio = starpu_sched_ctx_get_min_priority(sched_ctx_id);
 	int max_prio = starpu_sched_ctx_get_max_priority(sched_ctx_id);
+	STARPU_ASSERT(min_prio >= 0);
+	STARPU_ASSERT(max_prio >= 0);
 	// By default each type of devices uses 1 bucket and no slow factor
 #ifdef STARPU_USE_CPU
 	starpu_heteroprio_set_nb_prios(sched_ctx_id, STARPU_CPU_IDX, max_prio-min_prio+1);
@@ -368,7 +370,9 @@ static int push_task_heteroprio_policy(struct starpu_task *task)
 	struct _starpu_heteroprio_data *hp = (struct _starpu_heteroprio_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
 	/* One worker at a time use heteroprio */
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&hp->policy_mutex);
+	_starpu_worker_relax_off();
 
 	/* Retrieve the correct bucket */
 	STARPU_ASSERT(task->priority < STARPU_HETEROPRIO_MAX_PRIO);
@@ -436,7 +440,7 @@ static int push_task_heteroprio_policy(struct starpu_task *task)
 	{
 		unsigned worker = workers->get_next(workers, &it);
 		if (dowake[worker])
-			if (starpu_wake_worker(worker))
+			if (_starpu_wake_worker_relax(worker))
 				break; // wake up a single worker
 	}
 #endif
@@ -465,14 +469,9 @@ static struct starpu_task *pop_task_heteroprio_policy(unsigned sched_ctx_id)
 		return NULL;
 	}
 #endif
-	starpu_pthread_mutex_t *worker_sched_mutex;
-	starpu_pthread_cond_t *worker_sched_cond;
-	starpu_worker_get_sched_condition(workerid, &worker_sched_mutex, &worker_sched_cond);
-
-	/* Note: Releasing this mutex before taking the victim mutex, to avoid interlock*/
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(worker_sched_mutex);
-
+	_starpu_worker_relax_on();
 	STARPU_PTHREAD_MUTEX_LOCK(&hp->policy_mutex);
+	_starpu_worker_relax_off();
 
 	/* keep track of the new added task to perfom real prefetch on node */
 	unsigned nb_added_tasks = 0;
@@ -585,12 +584,8 @@ static struct starpu_task *pop_task_heteroprio_policy(unsigned sched_ctx_id)
 				if(hp->workers_heteroprio[victim].arch_index == worker->arch_index
 				   && hp->workers_heteroprio[victim].tasks_queue->ntasks)
 				{
-					starpu_pthread_mutex_t *victim_sched_mutex;
-					starpu_pthread_cond_t *victim_sched_cond;
-					starpu_worker_get_sched_condition(victim, &victim_sched_mutex, &victim_sched_cond);
-
 					/* ensure the worker is not currently prefetching its data */
-					STARPU_PTHREAD_MUTEX_LOCK_SCHED(victim_sched_mutex);
+					_starpu_worker_lock(victim);
 
 					if(hp->workers_heteroprio[victim].arch_index == worker->arch_index
 					   && hp->workers_heteroprio[victim].tasks_queue->ntasks)
@@ -600,10 +595,10 @@ static struct starpu_task *pop_task_heteroprio_policy(unsigned sched_ctx_id)
 						/* we steal a task update global counter */
 						hp->nb_prefetched_tasks_per_arch_index[hp->workers_heteroprio[victim].arch_index] -= 1;
 
-						STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(victim_sched_mutex);
+						_starpu_worker_unlock(victim);
 						goto done;
 					}
-					STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(victim_sched_mutex);
+					_starpu_worker_unlock(victim);
 				}
 			}
 		}
@@ -617,16 +612,20 @@ done:		;
 	}
 	STARPU_PTHREAD_MUTEX_UNLOCK(&hp->policy_mutex);
 
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(worker_sched_mutex);
 	if(task)
 	{
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
 		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_move_task_to_ctx(task, child_sched_ctx, 1, 1);
-			starpu_sched_ctx_revert_task_counters(sched_ctx_id, task->flops);
-			return NULL;
+			starpu_sched_ctx_move_task_to_ctx_locked(task, child_sched_ctx, 1);
+			starpu_sched_ctx_revert_task_counters_ctx_locked(sched_ctx_id, task->flops);
+			task = NULL;
 		}
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
+		return task;
 	}
 
 	/* if we have task (task) me way have some in the queue (worker->tasks_queue_size) that was freshly addeed (nb_added_tasks) */

+ 1 - 1
src/sched_policies/modular_eager.c

@@ -33,7 +33,7 @@ static void initialize_eager_center_policy(unsigned sched_ctx_id)
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
-		starpu_sched_component_connect(eager_component, starpu_sched_component_worker_get(sched_ctx_id, i));
+		starpu_sched_component_connect(eager_component, starpu_sched_component_worker_new(sched_ctx_id, i));
 
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 1 - 1
src/sched_policies/modular_eager_prefetching.c

@@ -43,7 +43,7 @@ static void initialize_eager_prefetching_center_policy(unsigned sched_ctx_id)
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * fifo_component = starpu_sched_component_fifo_create(t, &fifo_data);
 
 		starpu_sched_component_connect(fifo_component, worker_component);

+ 1 - 1
src/sched_policies/modular_heft.c

@@ -98,7 +98,7 @@ static void initialize_heft_center_policy(unsigned sched_ctx_id)
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * prio_component = starpu_sched_component_prio_create(t, &prio_data);
 		struct starpu_sched_component * impl_component = starpu_sched_component_best_implementation_create(t, NULL);
 

+ 1 - 1
src/sched_policies/modular_heft2.c

@@ -98,7 +98,7 @@ static void initialize_heft2_center_policy(unsigned sched_ctx_id)
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * prio_component = starpu_sched_component_prio_create(t, &prio_data);
 		struct starpu_sched_component * impl_component = starpu_sched_component_best_implementation_create(t, NULL);
 

+ 1 - 1
src/sched_policies/modular_heft_prio.c

@@ -140,7 +140,7 @@ static void initialize_heft_prio_policy(unsigned sched_ctx_id)
 
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * impl_component = starpu_sched_component_best_implementation_create(t, NULL);
 
 		starpu_sched_component_connect(eagers[starpu_worker_get_memory_node(i)], impl_component);

+ 1 - 1
src/sched_policies/modular_prio.c

@@ -30,7 +30,7 @@ void starpu_initialize_prio_center_policy(unsigned sched_ctx_id)
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
-		starpu_sched_component_connect(eager_component, starpu_sched_component_worker_get(sched_ctx_id, i));
+		starpu_sched_component_connect(eager_component, starpu_sched_component_worker_new(sched_ctx_id, i));
 
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 1 - 1
src/sched_policies/modular_prio_prefetching.c

@@ -40,7 +40,7 @@ static void initialize_prio_prefetching_center_policy(unsigned sched_ctx_id)
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * prio_component = starpu_sched_component_prio_create(t, &prio_data);
 
 		starpu_sched_component_connect(prio_component, worker_component);

+ 2 - 2
src/sched_policies/modular_random.c

@@ -33,7 +33,7 @@ static void initialize_random_fifo_center_policy(unsigned sched_ctx_id)
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
-		starpu_sched_component_connect(random_component, starpu_sched_component_worker_get(sched_ctx_id, i));
+		starpu_sched_component_connect(random_component, starpu_sched_component_worker_new(sched_ctx_id, i));
 
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
@@ -76,7 +76,7 @@ static void initialize_random_prio_center_policy(unsigned sched_ctx_id)
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
-		starpu_sched_component_connect(random_component, starpu_sched_component_worker_get(sched_ctx_id, i));
+		starpu_sched_component_connect(random_component, starpu_sched_component_worker_new(sched_ctx_id, i));
 
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 2 - 2
src/sched_policies/modular_random_prefetching.c

@@ -43,7 +43,7 @@ static void initialize_random_fifo_prefetching_center_policy(unsigned sched_ctx_
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * fifo_component = starpu_sched_component_fifo_create(t, &fifo_data);
 
 		starpu_sched_component_connect(fifo_component, worker_component);
@@ -97,7 +97,7 @@ static void initialize_random_prio_prefetching_center_policy(unsigned sched_ctx_
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
-		struct starpu_sched_component * worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component * worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		struct starpu_sched_component * prio_component = starpu_sched_component_prio_create(t, &prio_data);
 
 		starpu_sched_component_connect(prio_component, worker_component);

+ 1 - 1
src/sched_policies/modular_ws.c

@@ -28,7 +28,7 @@ static void initialize_ws_center_policy(unsigned sched_ctx_id)
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
-		starpu_sched_component_connect(t->root, starpu_sched_component_worker_get(sched_ctx_id, i));
+		starpu_sched_component_connect(t->root, starpu_sched_component_worker_new(sched_ctx_id, i));
 
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 21 - 16
src/sched_policies/parallel_eager.c

@@ -170,7 +170,7 @@ static int push_task_peager_policy(struct starpu_task *task)
 		    starpu_worker_get_type(worker) != STARPU_MIC_WORKER &&
 		    starpu_worker_get_type(worker) != STARPU_CPU_WORKER)
 			|| (master == worker))
-			starpu_wake_worker(worker);
+			_starpu_wake_worker_relax(worker);
 	}
 #endif
 
@@ -187,7 +187,9 @@ static struct starpu_task *pop_task_peager_policy(unsigned sched_ctx_id)
 	if (starpu_worker_get_type(workerid) != STARPU_CPU_WORKER && starpu_worker_get_type(workerid) != STARPU_MIC_WORKER)
 	{
 		struct starpu_task *task = NULL;
+		_starpu_worker_relax_on();
 		STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+		_starpu_worker_relax_off();
 		task = _starpu_fifo_pop_task(data->fifo, workerid);
 		STARPU_PTHREAD_MUTEX_UNLOCK(&data->policy_mutex);
 
@@ -199,16 +201,18 @@ static struct starpu_task *pop_task_peager_policy(unsigned sched_ctx_id)
 	//_STARPU_DEBUG("workerid:%d, master:%d\n",workerid,master);
 
 
+	struct starpu_task *task = NULL;
 	if (master == workerid)
 	{
 		/* The worker is a master */
-		struct starpu_task *task = NULL;
+		_starpu_worker_relax_on();
 		STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+		_starpu_worker_relax_off();
 		task = _starpu_fifo_pop_task(data->fifo, workerid);
 		STARPU_PTHREAD_MUTEX_UNLOCK(&data->policy_mutex);
 
 		if (!task)
-			return NULL;
+			goto ret;
 
 		/* Find the largest compatible worker combination */
 		int best_size = -1;
@@ -231,7 +235,7 @@ static struct starpu_task *pop_task_peager_policy(unsigned sched_ctx_id)
 		 * worker take it anyway, so that it can discard it afterward.
 		 * */
 		if (best_workerid == -1)
-			return task;
+			goto ret;
 
 		/* Is this a basic worker or a combined worker ? */
 		int nbasic_workers = (int)starpu_worker_get_count();
@@ -240,7 +244,7 @@ static struct starpu_task *pop_task_peager_policy(unsigned sched_ctx_id)
 		{
 
 			/* The master is alone */
-			return task;
+			goto ret;
 		}
 		else
 		{
@@ -256,32 +260,33 @@ static struct starpu_task *pop_task_peager_policy(unsigned sched_ctx_id)
 				int local_worker = combined_workerid[i];
 
 				alias->destroy = 1;
-				starpu_pthread_mutex_t *sched_mutex;
-				starpu_pthread_cond_t *sched_cond;
-				starpu_worker_get_sched_condition(local_worker, &sched_mutex, &sched_cond);
-
-				STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
-
+				_starpu_worker_lock(local_worker);
 				_starpu_fifo_push_task(data->local_fifo[local_worker], alias);
 
 #if !defined(STARPU_NON_BLOCKING_DRIVERS) || defined(STARPU_SIMGRID)
-				starpu_wakeup_worker_locked(local_worker, sched_cond, sched_mutex);
+				starpu_wake_worker_locked(local_worker);
 #endif
-				STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
-
+				_starpu_worker_unlock(local_worker);
 			}
 
 			/* The master also manipulated an alias */
 			struct starpu_task *master_alias = starpu_task_dup(task);
 			master_alias->destroy = 1;
-			return master_alias;
+			task = master_alias;
+			goto ret;
 		}
 	}
 	else
 	{
 		/* The worker is a slave */
-		return _starpu_fifo_pop_task(data->local_fifo[workerid], workerid);
+		_starpu_worker_relax_on();
+		STARPU_PTHREAD_MUTEX_LOCK(&data->policy_mutex);
+		_starpu_worker_relax_off();
+		task = _starpu_fifo_pop_task(data->local_fifo[workerid], workerid);
+		STARPU_PTHREAD_MUTEX_UNLOCK(&data->policy_mutex);
 	}
+ret:
+	return task;
 }
 
 struct starpu_sched_policy _starpu_sched_peager_policy =

+ 41 - 54
src/sched_policies/parallel_heft.c

@@ -88,17 +88,14 @@ static void parallel_heft_pre_exec_hook(struct starpu_task *task, unsigned sched
 	if (isnan(transfer_model))
 		transfer_model = 0.0;
 
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
 	/* Once we have executed the task, we can update the predicted amount
 	 * of work. */
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock_self();
 	worker_exp_len[workerid] -= model + transfer_model;
 	worker_exp_start[workerid] = starpu_timing_now() + model;
 	worker_exp_end[workerid] = worker_exp_start[workerid] + worker_exp_len[workerid];
 	ntasks[workerid]--;
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock_self();
 }
 
 static int push_task_on_best_worker(struct starpu_task *task, int best_workerid, double exp_end_predicted, int prio, unsigned sched_ctx_id)
@@ -119,11 +116,7 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 
 	if (!starpu_worker_is_combined_worker(best_workerid))
 	{
-		starpu_pthread_mutex_t *sched_mutex;
-		starpu_pthread_cond_t *sched_cond;
-		starpu_worker_get_sched_condition(best_workerid, &sched_mutex, &sched_cond);
-
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+		_starpu_worker_lock(best_workerid);
 		task->predicted = exp_end_predicted - worker_exp_end[best_workerid];
 		/* TODO */
 		task->predicted_transfer = 0;
@@ -132,7 +125,7 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 		worker_exp_start[best_workerid] = exp_end_predicted - worker_exp_len[best_workerid];
 
 		ntasks[best_workerid]++;
-		STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+		_starpu_worker_unlock(best_workerid);
 
 		/* We don't want it to interlace its task with a combined
 		 * worker's one */
@@ -163,24 +156,21 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 		for (i = 0; i < worker_size; i++)
 		{
 			struct starpu_task *alias = starpu_task_dup(task);
-			int local_worker = combined_workerid[i];
+			int local_combined_workerid = combined_workerid[i];
 
-			alias->predicted = exp_end_predicted - worker_exp_end[local_worker];
+			alias->predicted = exp_end_predicted - worker_exp_end[local_combined_workerid];
 			/* TODO */
 			alias->predicted_transfer = 0;
 			alias->destroy = 1;
-			starpu_pthread_mutex_t *sched_mutex;
-			starpu_pthread_cond_t *sched_cond;
-			starpu_worker_get_sched_condition(local_worker, &sched_mutex, &sched_cond);
-			STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
-			worker_exp_len[local_worker] += alias->predicted;
-			worker_exp_end[local_worker] = exp_end_predicted;
-			worker_exp_start[local_worker] = exp_end_predicted - worker_exp_len[local_worker];
-
-			ntasks[local_worker]++;
-			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
-
-			ret |= starpu_push_local_task(local_worker, alias, prio);
+			_starpu_worker_lock(local_combined_workerid);
+			worker_exp_len[local_combined_workerid] += alias->predicted;
+			worker_exp_end[local_combined_workerid] = exp_end_predicted;
+			worker_exp_start[local_combined_workerid] = exp_end_predicted - worker_exp_len[local_combined_workerid];
+
+			ntasks[local_combined_workerid]++;
+			_starpu_worker_unlock(local_combined_workerid);
+
+			ret |= starpu_push_local_task(local_combined_workerid, alias, prio);
 		}
 
 		STARPU_PTHREAD_MUTEX_UNLOCK(&hd->global_push_mutex);
@@ -284,10 +274,10 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 	struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx_id);
 	unsigned nworkers_ctx = workers->nworkers;
 
-	unsigned worker, worker_ctx = 0;
+	unsigned workerid, worker_ctx = 0;
 	int best = -1, best_id_ctx = -1;
 
-	/* this flag is set if the corresponding worker is selected because
+	/* this flag is set if the corresponding workerid is selected because
 	   there is no performance prediction available yet */
 	int forced_best = -1, forced_best_ctx = -1, forced_nimpl = -1;
 
@@ -319,20 +309,17 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 	workers->init_iterator(workers, &it);
 	while(workers->has_next(workers, &it))
 	{
-		worker = workers->get_next(workers, &it);
+		workerid = workers->get_next(workers, &it);
 
-		if(!starpu_worker_is_combined_worker(worker))
+		if(!starpu_worker_is_combined_worker(workerid))
 		{
-			starpu_pthread_mutex_t *sched_mutex;
-			starpu_pthread_cond_t *sched_cond;
-			starpu_worker_get_sched_condition(worker, &sched_mutex, &sched_cond);
 			/* Sometimes workers didn't take the tasks as early as we expected */
-			STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
-			worker_exp_start[worker] = STARPU_MAX(worker_exp_start[worker], now);
-			worker_exp_end[worker] = worker_exp_start[worker] + worker_exp_len[worker];
-			if (worker_exp_end[worker] > max_exp_end)
-				max_exp_end = worker_exp_end[worker];
-			STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+			_starpu_worker_lock(workerid);
+			worker_exp_start[workerid] = STARPU_MAX(worker_exp_start[workerid], now);
+			worker_exp_end[workerid] = worker_exp_start[workerid] + worker_exp_len[workerid];
+			if (worker_exp_end[workerid] > max_exp_end)
+				max_exp_end = worker_exp_end[workerid];
+			_starpu_worker_unlock(workerid);
 		}
 	}
 
@@ -340,11 +327,11 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 	worker_ctx = 0;
 	while(workers->has_next(workers, &it))
 	{
-                worker = workers->get_next(workers, &it);
+                workerid = workers->get_next(workers, &it);
 
 		for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
 		{
-			if (!starpu_combined_worker_can_execute_task(worker, task, nimpl))
+			if (!starpu_combined_worker_can_execute_task(workerid, task, nimpl))
 			{
 				/* no one on that queue may execute this task */
 				skip_worker[worker_ctx][nimpl] = 1;
@@ -356,23 +343,23 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 			}
 
 
-			struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(worker, sched_ctx_id);
+			struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(workerid, sched_ctx_id);
 
 			local_task_length[worker_ctx][nimpl] = starpu_task_expected_length(task, perf_arch,nimpl);
 
-			unsigned memory_node = starpu_worker_get_memory_node(worker);
+			unsigned memory_node = starpu_worker_get_memory_node(workerid);
 			local_data_penalty[worker_ctx][nimpl] = starpu_task_expected_data_transfer_time(memory_node, task);
 
-			double ntasks_end = compute_ntasks_end(worker, sched_ctx_id);
+			double ntasks_end = compute_ntasks_end(workerid, sched_ctx_id);
 
 			if (ntasks_best == -1
 			    || (!calibrating && ntasks_end < ntasks_best_end) /* Not calibrating, take better task */
-			    || (!calibrating && isnan(local_task_length[worker_ctx][nimpl])) /* Not calibrating but this worker is being calibrated */
-			    || (calibrating && isnan(local_task_length[worker_ctx][nimpl]) && ntasks_end < ntasks_best_end) /* Calibrating, compete this worker with other non-calibrated */
+			    || (!calibrating && isnan(local_task_length[worker_ctx][nimpl])) /* Not calibrating but this workerid is being calibrated */
+			    || (calibrating && isnan(local_task_length[worker_ctx][nimpl]) && ntasks_end < ntasks_best_end) /* Calibrating, compete this workerid with other non-calibrated */
 					)
 			{
 				ntasks_best_end = ntasks_end;
-				ntasks_best = worker;
+				ntasks_best = workerid;
 				ntasks_best_ctx = worker_ctx;
 				nimpl_best = nimpl;
 			}
@@ -383,7 +370,7 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 				if (!warned)
 				{
 					warned = 1;
-					_STARPU_DISP("Warning: performance model for %s not finished calibrating on %u, using a dumb scheduling heuristic for now\n", starpu_task_get_name(task), worker);
+					_STARPU_DISP("Warning: performance model for %s not finished calibrating on %u, using a dumb scheduling heuristic for now\n", starpu_task_get_name(task), workerid);
 				}
 				/* we are calibrating, we want to speed-up calibration time
 				 * so we privilege non-calibrated tasks (but still
@@ -400,9 +387,9 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 			if (unknown)
 				continue;
 
-			local_exp_end[worker_ctx][nimpl] = compute_expected_end(worker, local_task_length[worker_ctx][nimpl]);
+			local_exp_end[worker_ctx][nimpl] = compute_expected_end(workerid, local_task_length[worker_ctx][nimpl]);
 
-			//fprintf(stderr, "WORKER %d -> length %e end %e\n", worker, local_task_length[worker_ctx][nimpl], local_exp_end[worker][nimpl]);
+			//fprintf(stderr, "WORKER %d -> length %e end %e\n", workerid, local_task_length[worker_ctx][nimpl], local_exp_end[workerid][nimpl]);
 
 			if (local_exp_end[worker_ctx][nimpl] < best_exp_end)
 			{
@@ -413,7 +400,7 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 
 
 			local_energy[worker_ctx][nimpl] = starpu_task_expected_energy(task, perf_arch,nimpl);
-			//_STARPU_DEBUG("Scheduler parallel heft: task length (%lf) local energy (%lf) worker (%u) kernel (%u) \n", local_task_length[worker],local_energy[worker],worker,nimpl);
+			//_STARPU_DEBUG("Scheduler parallel heft: task length (%lf) local energy (%lf) workerid (%u) kernel (%u) \n", local_task_length[workerid],local_energy[workerid],workerid,nimpl);
 
 			if (isnan(local_energy[worker_ctx][nimpl]))
 				local_energy[worker_ctx][nimpl] = 0.;
@@ -436,7 +423,7 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 		worker_ctx = 0;
 		while(workers->has_next(workers, &it))
 		{
-			worker = workers->get_next(workers, &it);
+			workerid = workers->get_next(workers, &it);
 
 			for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
 			{
@@ -460,12 +447,12 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 				{
 					/* we found a better solution */
 					best_fitness = fitness[worker_ctx][nimpl];
-					best = worker;
+					best = workerid;
 					best_id_ctx = worker_ctx;
 					nimpl_best = nimpl;
 				}
 
-			//	fprintf(stderr, "FITNESS worker %d -> %e local_exp_end %e - local_data_penalty %e\n", worker, fitness[worker][nimpl], local_exp_end[worker][nimpl] - best_exp_end, local_data_penalty[worker][nimpl]);
+			//	fprintf(stderr, "FITNESS workerid %d -> %e local_exp_end %e - local_data_penalty %e\n", workerid, fitness[workerid][nimpl], local_exp_end[workerid][nimpl] - best_exp_end, local_data_penalty[workerid][nimpl]);
 			}
 			worker_ctx++;
 		}
@@ -492,7 +479,7 @@ static int _parallel_heft_push_task(struct starpu_task *task, unsigned prio, uns
 
 	//_STARPU_DEBUG("Scheduler parallel heft: kernel (%u)\n", nimpl_best);
 	starpu_task_set_implementation(task, nimpl_best);
-	/* we should now have the best worker in variable "best" */
+	/* we should now have the best workerid in variable "best" */
 	_STARPU_TASK_BREAK_ON(task, sched);
 	return push_task_on_best_worker(task, best, best_exp_end, prio, sched_ctx_id);
 }

+ 2 - 8
src/sched_policies/sched_component.h

@@ -21,10 +21,8 @@
 
 
 /* lock and unlock drivers for modifying schedulers */
-void _starpu_sched_component_lock_all_workers(unsigned sched_ctx_id);
-void _starpu_sched_component_unlock_all_workers(unsigned sched_ctx_id);
-void _starpu_sched_component_lock_worker(unsigned sched_ctx_id, int workerid);
-void _starpu_sched_component_unlock_worker(unsigned sched_ctx_id, int workerid);
+void _starpu_sched_component_lock_all_workers(void);
+void _starpu_sched_component_unlock_all_workers(void);
 
 void _starpu_sched_component_workers_destroy(void);
 
@@ -33,8 +31,4 @@ struct _starpu_combined_worker * _starpu_sched_component_combined_worker_get_com
 
 struct starpu_bitmap * _starpu_get_worker_mask(unsigned sched_ctx_id);
 
-
-void _starpu_sched_component_lock_scheduling(void);
-void _starpu_sched_component_unlock_scheduling(void);
-
 #endif

+ 1 - 1
src/sched_policies/scheduler_maker.c

@@ -257,7 +257,7 @@ struct starpu_sched_tree * starpu_sched_component_make_scheduler(unsigned sched_
 	for(i = 0; i < starpu_worker_get_count(); i++)
 	{
 		struct _starpu_worker *worker = _starpu_get_worker_struct(i);
-		struct starpu_sched_component *worker_component = starpu_sched_component_worker_get(sched_ctx_id, i);
+		struct starpu_sched_component *worker_component = starpu_sched_component_worker_new(sched_ctx_id, i);
 		STARPU_ASSERT(worker);
 		set_worker_leaf(tree->root,worker_component, sched_ctx_id, specs);
 	}

+ 44 - 46
src/sched_policies/work_stealing_policy.c

@@ -74,7 +74,6 @@ struct _starpu_work_stealing_data_per_worker
 {
 	struct _starpu_fifo_taskq *queue_array;
 	int *proxlist;
-	starpu_pthread_mutex_t worker_mutex;
 	int busy;
 
 #ifdef USE_LOCALITY_TASKS
@@ -135,7 +134,7 @@ static int select_victim_round_robin(struct _starpu_work_stealing_data *ws, unsi
 		ntasks = ws->per_worker[workerids[worker]].queue_array->ntasks;
 
 		if (ntasks && (ws->per_worker[workerids[worker]].busy
-					   || starpu_worker_is_blocked(workerids[worker])))
+					   || starpu_worker_is_blocked_in_parallel(workerids[worker])))
 			break;
 
 		worker = (worker + 1) % nworkers;
@@ -172,7 +171,7 @@ static unsigned select_worker_round_robin(struct _starpu_work_stealing_data *ws,
 	worker = ws->last_push_worker;
 	do
 		worker = (worker + 1) % nworkers;
-	while (!starpu_worker_can_execute_task_first_impl(workerids[worker], task, NULL));
+	while (ws->per_worker[worker].queue_array && !starpu_worker_can_execute_task_first_impl(workerids[worker], task, NULL));
 
 	ws->last_push_worker = worker;
 
@@ -215,7 +214,7 @@ static unsigned select_worker_locality(struct _starpu_work_stealing_data *ws, st
 		while(workers->has_next(workers, &it))
 		{
 			int workerid = workers->get_next(workers, &it);
-			if (ndata[workerid] > best_ndata && ws->per_worker[workerid].busy)
+			if (ndata[workerid] > best_ndata && ws->per_worker[worker].queue_array && ws->per_worker[workerid].busy)
 			{
 				best_worker = workerid;
 				best_ndata = ndata[workerid];
@@ -435,7 +434,7 @@ static int select_victim_overload(struct _starpu_work_stealing_data *ws, unsigne
                 unsigned worker = workers->get_next(workers, &it);
 		float worker_ratio = overload_metric(ws, sched_ctx_id, worker);
 
-		if (worker_ratio > best_ratio && ws->per_worker[worker].busy)
+		if (worker_ratio > best_ratio && ws->per_worker[worker].queue_array && ws->per_worker[worker].busy)
 		{
 			best_worker = worker;
 			best_ratio = worker_ratio;
@@ -472,7 +471,7 @@ static unsigned select_worker_overload(struct _starpu_work_stealing_data *ws, st
 		unsigned worker = workers->get_next(workers, &it);
 		float worker_ratio = overload_metric(ws, sched_ctx_id, worker);
 
-		if (worker_ratio < best_ratio && starpu_worker_can_execute_task_first_impl(worker, task, NULL))
+		if (worker_ratio < best_ratio && ws->per_worker[worker].queue_array && starpu_worker_can_execute_task_first_impl(worker, task, NULL))
 		{
 			best_worker = worker;
 			best_ratio = worker_ratio;
@@ -529,47 +528,42 @@ static struct starpu_task *ws_pop_task(unsigned sched_ctx_id)
 	if (STARPU_RUNNING_ON_VALGRIND || !_starpu_fifo_empty(ws->per_worker[workerid].queue_array))
 #endif
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(&ws->per_worker[workerid].worker_mutex);
 		task = ws_pick_task(ws, workerid, workerid);
 		if (task)
 			locality_popped_task(ws, task, workerid, sched_ctx_id);
-		STARPU_PTHREAD_MUTEX_UNLOCK(&ws->per_worker[workerid].worker_mutex);
 	}
 
 	if (task)
 	{
 		/* there was a local task */
 		ws->per_worker[workerid].busy = 1;
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
 		starpu_sched_ctx_list_task_counters_decrement(sched_ctx_id, workerid);
 		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_move_task_to_ctx(task, child_sched_ctx, 1, 1);
-			starpu_sched_ctx_revert_task_counters(sched_ctx_id, task->flops);
-			return NULL;
+			starpu_sched_ctx_move_task_to_ctx_locked(task, child_sched_ctx, 1);
+			starpu_sched_ctx_revert_task_counters_ctx_locked(sched_ctx_id, task->flops);
+			task = NULL;
 		}
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
 		return task;
 	}
 
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	/* While stealing, relieve mutex used to synchronize with pushers */
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
-
-
 	/* we need to steal someone's job */
+	_starpu_worker_relax_on();
 	int victim = ws->select_victim(ws, sched_ctx_id, workerid);
+	_starpu_worker_relax_off();
 	if (victim == -1)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
 		return NULL;
 	}
 
-	if (STARPU_PTHREAD_MUTEX_TRYLOCK(&ws->per_worker[victim].worker_mutex))
+	if (_starpu_worker_trylock(victim))
 	{
 		/* victim is busy, don't bother it, come back later */
-		STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
 		return NULL;
 	}
 	if (ws->per_worker[victim].queue_array != NULL && ws->per_worker[victim].queue_array->ntasks > 0)
@@ -586,33 +580,40 @@ static struct starpu_task *ws_pop_task(unsigned sched_ctx_id)
 		record_worker_locality(ws, task, workerid, sched_ctx_id);
 		locality_popped_task(ws, task, victim, sched_ctx_id);
 	}
-	STARPU_PTHREAD_MUTEX_UNLOCK(&ws->per_worker[victim].worker_mutex);
-
-	/* Done with stealing, resynchronize with core */
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock(victim);
 
 #ifndef STARPU_NON_BLOCKING_DRIVERS
         /* While stealing, perhaps somebody actually give us a task, don't miss
          * the opportunity to take it before going to sleep. */
-	if (!task)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(&ws->per_worker[workerid].worker_mutex);
-		task = ws_pick_task(ws, workerid, workerid);
-		if (task)
-			locality_popped_task(ws, task, workerid, sched_ctx_id);
-		STARPU_PTHREAD_MUTEX_UNLOCK(&ws->per_worker[workerid].worker_mutex);
+		struct _starpu_worker *worker = _starpu_get_worker_struct(starpu_worker_get_id());
+		if (!task && worker->state_keep_awake)
+		{
+			task = ws_pick_task(ws, workerid, workerid);
+			if (task)
+			{
+				/* keep_awake notice taken into account here, clear flag */
+				worker->state_keep_awake = 0;
+				locality_popped_task(ws, task, workerid, sched_ctx_id);
+			}
+		}
 	}
 #endif
 
 	if (task)
 	{
+		_starpu_worker_relax_on();
+		_starpu_sched_ctx_lock_write(sched_ctx_id);
+		_starpu_worker_relax_off();
 		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_move_task_to_ctx(task, child_sched_ctx, 1, 1);
-			starpu_sched_ctx_revert_task_counters(sched_ctx_id, task->flops);
+			starpu_sched_ctx_move_task_to_ctx_locked(task, child_sched_ctx, 1);
+			starpu_sched_ctx_revert_task_counters_ctx_locked(sched_ctx_id, task->flops);
+			_starpu_sched_ctx_unlock_write(sched_ctx_id);
 			return NULL;
 		}
+		_starpu_sched_ctx_unlock_write(sched_ctx_id);
 	}
 	ws->per_worker[workerid].busy = !!task;
 	return task;
@@ -639,21 +640,16 @@ int ws_push_task(struct starpu_task *task)
 	if (workerid == -1 || !starpu_sched_ctx_contains_worker(workerid, sched_ctx_id) ||
 			!starpu_worker_can_execute_task_first_impl(workerid, task, NULL))
 		workerid = select_worker(ws, task, sched_ctx_id);
-
-	starpu_pthread_mutex_t *sched_mutex;
-	starpu_pthread_cond_t *sched_cond;
-	starpu_worker_get_sched_condition(workerid, &sched_mutex, &sched_cond);
-	STARPU_PTHREAD_MUTEX_LOCK_SCHED(sched_mutex);
+	_starpu_worker_lock(workerid);
 	STARPU_AYU_ADDTOTASKQUEUE(starpu_task_get_job_id(task), workerid);
-	STARPU_PTHREAD_MUTEX_LOCK(&ws->per_worker[workerid].worker_mutex);
 	_STARPU_TASK_BREAK_ON(task, sched);
 	record_data_locality(task, workerid);
+	STARPU_ASSERT_MSG(ws->per_worker[workerid].queue_array, "workerid=%d, ws=%p\n", workerid, ws);
 	_starpu_fifo_push_task(ws->per_worker[workerid].queue_array, task);
 	locality_pushed_task(ws, task, workerid, sched_ctx_id);
-	STARPU_PTHREAD_MUTEX_UNLOCK(&ws->per_worker[workerid].worker_mutex);
 
 	starpu_push_task_end(task);
-	STARPU_PTHREAD_MUTEX_UNLOCK_SCHED(sched_mutex);
+	_starpu_worker_unlock(workerid);
 	starpu_sched_ctx_list_task_counters_increment(sched_ctx_id, workerid);
 
 #if !defined(STARPU_NON_BLOCKING_DRIVERS) || defined(STARPU_SIMGRID)
@@ -663,7 +659,7 @@ int ws_push_task(struct starpu_task *task)
 
 	workers->init_iterator(workers, &it);
 	while(workers->has_next(workers, &it))
-		starpu_wake_worker(workers->get_next(workers, &it));
+		_starpu_wake_worker_relax(workers->get_next(workers, &it));
 #endif
 	return 0;
 }
@@ -682,7 +678,6 @@ static void ws_add_workers(unsigned sched_ctx_id, int *workerids,unsigned nworke
 		/* Tell helgrind that we are fine with getting outdated values,
 		 * this is just an estimation */
 		STARPU_HG_DISABLE_CHECKING(ws->per_worker[workerid].queue_array->ntasks);
-		STARPU_PTHREAD_MUTEX_INIT(&ws->per_worker[workerid].worker_mutex, NULL);
 		ws->per_worker[workerid].busy = 0;
 		STARPU_HG_DISABLE_CHECKING(ws->per_worker[workerid].busy);
 	}
@@ -704,7 +699,6 @@ static void ws_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nw
 		}
 		free(ws->per_worker[workerid].proxlist);
 		ws->per_worker[workerid].proxlist = NULL;
-		STARPU_PTHREAD_MUTEX_DESTROY(&ws->per_worker[workerid].worker_mutex);
 	}
 }
 
@@ -762,7 +756,7 @@ static int lws_select_victim(struct _starpu_work_stealing_data *ws, unsigned sch
 		int neighbor = ws->per_worker[workerid].proxlist[i];
 		int ntasks = ws->per_worker[neighbor].queue_array->ntasks;
 		if (ntasks && (ws->per_worker[neighbor].busy
-					   || starpu_worker_is_blocked(neighbor)))
+					   || starpu_worker_is_blocked_in_parallel(neighbor)))
 			return neighbor;
 	}
 	return -1;
@@ -783,10 +777,14 @@ static void lws_add_workers(unsigned sched_ctx_id, int *workerids,
 	struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx_id);
 	struct starpu_tree *tree = (struct starpu_tree*)workers->collection_private;
 	unsigned i;
+
+	/* get the complete list of workers (not just the added one) and rebuild the proxlists */
+	nworkers = starpu_sched_ctx_get_workers_list_raw(sched_ctx_id, &workerids);
 	for (i = 0; i < nworkers; i++)
 	{
 		int workerid = workerids[i];
-		_STARPU_MALLOC(ws->per_worker[workerid].proxlist, STARPU_NMAXWORKERS*sizeof(int));
+		if (ws->per_worker[workerid].proxlist == NULL)
+			_STARPU_MALLOC(ws->per_worker[workerid].proxlist, STARPU_NMAXWORKERS*sizeof(int));
 		int bindid;
 
 		struct starpu_sched_ctx_iterator it;

+ 1 - 1
src/worker_collection/worker_list.c

@@ -284,7 +284,7 @@ static void list_init_iterator_for_parallel_tasks(struct starpu_worker_collectio
 	int nm = 0, nub = 0;
 	for(i = 0;  i < nworkers; i++)
 	{
-		if(!starpu_worker_is_blocked(workerids[i]))
+		if(!starpu_worker_is_blocked_in_parallel(workerids[i]))
 		{
 			((int*)workers->unblocked_workers)[nub++] = workerids[i];
 			if(!it->possibly_parallel) /* don't bother filling the table with masters we won't use it anyway */

+ 2 - 2
src/worker_collection/worker_tree.c

@@ -333,10 +333,10 @@ static void tree_init_iterator_for_parallel_tasks(struct starpu_worker_collectio
 	int nworkers = starpu_worker_get_count();
 	for(i = 0; i < nworkers; i++)
 	{
-		workers->is_unblocked[i] = (workers->present[i] && !starpu_worker_is_blocked(i));
+		workers->is_unblocked[i] = (workers->present[i] && !starpu_worker_is_blocked_in_parallel(i));
 		if(!it->possibly_parallel) /* don't bother filling the table with masters we won't use it anyway */
 			continue;
-		workers->is_master[i] = (workers->present[i] && !starpu_worker_is_blocked(i) && !starpu_worker_is_slave_somewhere(i));
+		workers->is_master[i] = (workers->present[i] && !starpu_worker_is_blocked_in_parallel(i) && !starpu_worker_is_slave_somewhere(i));
 	}
 }
 

+ 16 - 9
tests/sched_ctx/sched_ctx_hierarchy.c

@@ -18,7 +18,11 @@
 #include <starpu.h>
 #include "../helper.h"
 
-struct starpu_codelet mycodelet_bis;
+void free_codelet(void *arg)
+{
+	free(arg);
+}
+
 void func_cpu_bis(void *descr[], void *_args)
 {
 	char msg;
@@ -27,6 +31,10 @@ void func_cpu_bis(void *descr[], void *_args)
 	int worker_id_expected;
 	int ntasks;
 
+	struct starpu_codelet *codelet = calloc(1,sizeof(*codelet));
+	codelet->cpu_funcs[0] = func_cpu_bis;
+	codelet->cpu_funcs_name[0] = "func_cpu_bis";
+
 	starpu_worker_get_name(worker_id, worker_name, 256);
 	starpu_codelet_unpack_args(_args, &msg, &ntasks, &worker_id_expected);
 
@@ -36,20 +44,15 @@ void func_cpu_bis(void *descr[], void *_args)
 	if (ntasks > 0)
 	{
 		int nntasks = ntasks - 1;
-		starpu_task_insert(&mycodelet_bis,
+		starpu_task_insert(codelet,
 				   STARPU_VALUE, &msg, sizeof(msg),
 				   STARPU_VALUE, &nntasks, sizeof(ntasks),
 				   STARPU_VALUE, &worker_id, sizeof(worker_id),
+				   STARPU_CALLBACK_WITH_ARG, free_codelet, codelet,
 				   0);
 	}
 }
 
-struct starpu_codelet mycodelet_bis =
-{
-	.cpu_funcs = {func_cpu_bis},
-	.cpu_funcs_name = {"func_cpu_bis"},
-};
-
 void func_cpu(void *descr[], void *_args)
 {
 	char msg;
@@ -59,6 +62,9 @@ void func_cpu(void *descr[], void *_args)
 	int ntasks;
 	unsigned sched_ctx_id;
 	unsigned *sched_ctx_id_p;
+	struct starpu_codelet *codelet = calloc(1,sizeof(*codelet));
+	codelet->cpu_funcs[0] = func_cpu_bis;
+	codelet->cpu_funcs_name[0] = "func_cpu_bis";
 
 	starpu_worker_get_name(worker_id, worker_name, 256);
 	starpu_codelet_unpack_args(_args, &msg, &ntasks, &sched_ctx_id, &worker_id_expected, &sched_ctx_id_p);
@@ -72,10 +78,11 @@ void func_cpu(void *descr[], void *_args)
 	if (ntasks > 0)
 	{
 		int nntasks = ntasks - 1;
-		starpu_task_insert(&mycodelet_bis,
+		starpu_task_insert(codelet,
 				   STARPU_VALUE, &msg, sizeof(msg),
 				   STARPU_VALUE, &nntasks, sizeof(nntasks),
 				   STARPU_VALUE, &worker_id, sizeof(worker_id),
+				   STARPU_CALLBACK_WITH_ARG, free_codelet, codelet,
 				   0);
 	}
 }

+ 2 - 2
tests/sched_policies/simple_cpu_gpu_sched.c

@@ -57,7 +57,7 @@ cpu_task_gpu(struct starpu_task *task,
 	(void) arch;
 	(void) nimpl;
 
-	return 1000.0;
+	return 10000000.0;
 }
 
 static double
@@ -69,7 +69,7 @@ gpu_task_cpu(struct starpu_task *task,
 	(void) arch;
 	(void) nimpl;
 
-	return 1000.0;
+	return 10000000.0;
 }
 
 static double

+ 0 - 37
tools/valgrind/starpu.suppr

@@ -175,40 +175,3 @@
    fun:_starpu_memchunk_recently_used
    ...
 }
-
-{
-   TODO1: This is temporary. It perhaps does not pose problem because only the worker takes this mutex. Fixing this will require changing the scheduler interface, so that the schedulers themselves take the scheduling lock, not the caller. Filter it out for now, so we can see other races more easily.
-   Helgrind:LockOrder
-   fun:mutex_lock_WRK
-   fun:simple_worker_pull_task
-   ...
-}
-
-{
-   TODO1: This is temporary. It perhaps does not pose problem because only the worker takes this mutex. Fixing this will require changing the scheduler interface, so that the schedulers themselves take the scheduling lock, not the caller. Filter it out for now, so we can see other races more easily.
-   Helgrind:LockOrder
-   fun:mutex_lock_WRK
-   fun:starpu_pthread_mutex_lock_sched
-   fun:_starpu_sched_component_worker_lock_scheduling
-   fun:simple_worker_pull_task
-   ...
-}
-
-{
-   TODO2: This is temporary. It perhaps does not pose problem because only the worker takes this mutex. Fixing this will require changing the scheduler interface, so that the schedulers themselves take the scheduling lock, not the caller. Filter it out for now, so we can see other races more easily.
-   Helgrind:LockOrder
-   fun:mutex_lock_WRK
-   fun:_starpu_sched_component_lock_worker
-   fun:simple_worker_pull_task
-   ...
-}
-
-{
-   TODO2: This is temporary. It perhaps does not pose problem because only the worker takes this mutex. Fixing this will require changing the scheduler interface, so that the schedulers themselves take the scheduling lock, not the caller. Filter it out for now, so we can see other races more easily.
-   Helgrind:LockOrder
-   fun:mutex_lock_WRK
-   fun:_starpu_sched_component_lock_worker
-   fun:_starpu_sched_component_worker_lock_scheduling
-   fun:simple_worker_pull_task
-   ...
-}