Browse Source

Add fields epilogue_callback_func and epilogue_callback_arg in starpu_task, which are executed before task dependencies release

HE Kun 4 years ago
parent
commit
4a7bf96513
3 changed files with 68 additions and 0 deletions
  1. 29 0
      include/starpu_task.h
  2. 35 0
      src/core/jobs.c
  3. 4 0
      src/core/task.c

+ 29 - 0
include/starpu_task.h

@@ -820,6 +820,23 @@ struct starpu_task
 
 	/**
 	   Optional field, the default value is <c>NULL</c>. This is a
+	   function pointer of prototype <c>void (*f)(void *)</c> which specifies
+	   a possible callback just as starpu_task::callback_func. But this function
+	   is executed before task dependencies release. The callback is passed 
+	   the value contained in the starpu_task::epilogue_callback_arg field. 
+	   No callback is executed if the field is set to <c>NULL</c>.
+	*/
+	void (*epilogue_callback_func)(void *);
+	/**
+	   Optional field, the default value is <c>NULL</c>. This is
+	   the pointer passed to the epilogue callback function. This field is
+	   ignored if the field starpu_task::epilogue_callback_func is set to
+	   <c>NULL</c>.
+	*/
+	void *epilogue_callback_arg;
+
+	/**
+	   Optional field, the default value is <c>NULL</c>. This is a
 	   function pointer of prototype <c>void (*f)(void *)</c>
 	   which specifies a possible callback. If this pointer is
 	   non-<c>NULL</c>, the callback function is executed on the
@@ -893,6 +910,16 @@ struct starpu_task
 	*/
 	unsigned callback_arg_free:1;
 
+
+	/**
+	   Optional field. In case starpu_task::epilogue_callback_arg was
+	   allocated by the application through <c>malloc()</c>,
+	   setting starpu_task::epilogue_callback_arg_free to 1 makes StarPU
+	   automatically call <c>free(epilogue_callback_arg)</c> when
+	   destroying the task.
+	*/
+	unsigned epilogue_callback_arg_free:1;
+
 	/**
 	   Optional field. In case starpu_task::prologue_callback_arg
 	   was allocated by the application through <c>malloc()</c>,
@@ -1294,6 +1321,8 @@ struct starpu_task
 	.cl_ret_size = 0,				\
 	.callback_func = NULL,				\
 	.callback_arg = NULL,				\
+	.epilogue_callback_func = NULL,				\
+	.epilogue_callback_arg = NULL,				\
 	.priority = STARPU_DEFAULT_PRIO,		\
 	.use_tag = 0,					\
 	.sequential_consistency = 1,			\

+ 35 - 0
src/core/jobs.c

@@ -296,6 +296,8 @@ void _starpu_handle_job_termination(struct _starpu_job *j)
 	struct starpu_task *end_rdep = NULL;
 	unsigned sched_ctx = task->sched_ctx;
 	double flops = task->flops;
+	void (*epilogue_callback)(void *) = task->epilogue_callback_func;
+	
 	const unsigned continuation =
 #ifdef STARPU_OPENMP
 		j->continuation
@@ -303,6 +305,39 @@ void _starpu_handle_job_termination(struct _starpu_job *j)
 		0
 #endif
 		;
+	if (!continuation)
+	{
+		/* the epilogue callback is executed before the dependencies release*/
+		if (epilogue_callback)
+		{
+			int profiling = starpu_profiling_status_get();
+			if (profiling && task->profiling_info)
+				_starpu_clock_gettime(&task->profiling_info->callback_start_time);
+
+			/* so that we can check whether we are doing blocking calls
+			 * within the callback */
+			_starpu_set_local_worker_status(STATUS_CALLBACK);
+
+			/* Perhaps we have nested callbacks (eg. with chains of empty
+			 * tasks). So we store the current task and we will restore it
+			 * later. */
+			struct starpu_task *current_task = starpu_task_get_current();
+
+			_starpu_set_current_task(task);
+
+			_STARPU_TRACE_START_CALLBACK(j);
+			if (epilogue_callback)
+				epilogue_callback(task->epilogue_callback_arg);
+			_STARPU_TRACE_END_CALLBACK(j);
+
+			_starpu_set_current_task(current_task);
+
+			_starpu_set_local_worker_status(STATUS_UNKNOWN);
+
+			if (profiling && task->profiling_info)
+				_starpu_clock_gettime(&task->profiling_info->callback_end_time);
+		}
+	}
 #ifdef STARPU_DEBUG
 	STARPU_PTHREAD_MUTEX_LOCK(&all_jobs_list_mutex);
 	_starpu_job_multilist_erase_all_submitted(&all_jobs_list, j);

+ 4 - 0
src/core/task.c

@@ -391,6 +391,10 @@ void _starpu_task_destroy(struct starpu_task *task)
 		if (task->callback_arg_free)
 			free(task->callback_arg);
 
+		/* Does user want StarPU release epilogue callback_arg ? */
+		if (task->epilogue_callback_arg_free)
+			free(task->epilogue_callback_arg);
+
 		/* Does user want StarPU release prologue_callback_arg ? */
 		if (task->prologue_callback_arg_free)
 			free(task->prologue_callback_arg);