starpu_insert_task_utils.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011 Centre National de la Recherche Scientifique
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include <util/starpu_insert_task_utils.h>
  17. #include <common/config.h>
  18. #include <common/utils.h>
  19. /* Deal with callbacks. The unpack function may be called multiple times when
  20. * we have a parallel task, and we should not free the cl_arg parameter from
  21. * the callback function. */
  22. struct insert_task_cb_wrapper {
  23. void (*callback_func)(void *);
  24. void *callback_arg;
  25. void *arg_stack;
  26. };
  27. void starpu_task_insert_callback_wrapper(void *_cl_arg_wrapper)
  28. {
  29. struct insert_task_cb_wrapper *cl_arg_wrapper = _cl_arg_wrapper;
  30. /* Execute the callback specified by the application */
  31. if (cl_arg_wrapper->callback_func)
  32. cl_arg_wrapper->callback_func(cl_arg_wrapper->callback_arg);
  33. /* Free the stack of arguments */
  34. free(cl_arg_wrapper->arg_stack);
  35. }
  36. size_t _starpu_insert_task_get_arg_size(va_list varg_list)
  37. {
  38. int arg_type;
  39. size_t arg_buffer_size;
  40. arg_buffer_size = 0;
  41. arg_buffer_size += sizeof(char);
  42. while ((arg_type = va_arg(varg_list, int)) != 0) {
  43. if (arg_type==STARPU_R || arg_type==STARPU_W || arg_type==STARPU_RW || arg_type == STARPU_SCRATCH || arg_type == STARPU_REDUX) {
  44. va_arg(varg_list, starpu_data_handle);
  45. }
  46. else if (arg_type==STARPU_VALUE) {
  47. va_arg(varg_list, void *);
  48. size_t cst_size = va_arg(varg_list, size_t);
  49. arg_buffer_size += sizeof(size_t);
  50. arg_buffer_size += cst_size;
  51. }
  52. else if (arg_type==STARPU_CALLBACK) {
  53. va_arg(varg_list, void (*)(void *));
  54. }
  55. else if (arg_type==STARPU_CALLBACK_ARG) {
  56. va_arg(varg_list, void *);
  57. }
  58. else if (arg_type==STARPU_PRIORITY) {
  59. va_arg(varg_list, int);
  60. }
  61. else if (arg_type==STARPU_EXECUTE) {
  62. va_arg(varg_list, int);
  63. }
  64. }
  65. va_end(varg_list);
  66. return arg_buffer_size;
  67. }
  68. int _starpu_pack_cl_args(size_t arg_buffer_size, char **arg_buffer, va_list varg_list)
  69. {
  70. int arg_type;
  71. unsigned current_arg_offset = 0;
  72. unsigned char nargs = 0;
  73. /* The buffer will contain : nargs, {size, content} (x nargs)*/
  74. *arg_buffer = malloc(arg_buffer_size);
  75. /* We will begin the buffer with the number of args (which is stored as a char) */
  76. current_arg_offset += sizeof(char);
  77. while((arg_type = va_arg(varg_list, int)) != 0)
  78. {
  79. if (arg_type==STARPU_R || arg_type==STARPU_W || arg_type==STARPU_RW || arg_type == STARPU_SCRATCH || arg_type == STARPU_REDUX)
  80. {
  81. va_arg(varg_list, starpu_data_handle);
  82. }
  83. else if (arg_type==STARPU_VALUE)
  84. {
  85. /* We have a constant value: this should be followed by a pointer to the cst value and the size of the constant */
  86. void *ptr = va_arg(varg_list, void *);
  87. size_t cst_size = va_arg(varg_list, size_t);
  88. *(size_t *)(&(*arg_buffer)[current_arg_offset]) = cst_size;
  89. current_arg_offset += sizeof(size_t);
  90. memcpy(&(*arg_buffer)[current_arg_offset], ptr, cst_size);
  91. current_arg_offset += cst_size;
  92. nargs++;
  93. STARPU_ASSERT(current_arg_offset <= arg_buffer_size);
  94. }
  95. else if (arg_type==STARPU_CALLBACK)
  96. {
  97. va_arg(varg_list, void (*)(void *));
  98. }
  99. else if (arg_type==STARPU_CALLBACK_ARG) {
  100. va_arg(varg_list, void *);
  101. }
  102. else if (arg_type==STARPU_PRIORITY)
  103. {
  104. va_arg(varg_list, int);
  105. }
  106. else if (arg_type==STARPU_EXECUTE) {
  107. va_arg(varg_list, int);
  108. }
  109. }
  110. (*arg_buffer)[0] = nargs;
  111. va_end(varg_list);
  112. return 0;
  113. }
  114. static void _starpu_prepare_task(char *arg_buffer, starpu_codelet *cl, struct starpu_task **task, va_list varg_list) {
  115. int arg_type;
  116. unsigned current_buffer = 0;
  117. struct insert_task_cb_wrapper *cl_arg_wrapper = malloc(sizeof(struct insert_task_cb_wrapper));
  118. STARPU_ASSERT(cl_arg_wrapper);
  119. cl_arg_wrapper->callback_func = NULL;
  120. cl_arg_wrapper->arg_stack = arg_buffer;
  121. while((arg_type = va_arg(varg_list, int)) != 0)
  122. {
  123. if (arg_type==STARPU_R || arg_type==STARPU_W || arg_type==STARPU_RW || arg_type == STARPU_SCRATCH || arg_type == STARPU_REDUX)
  124. {
  125. /* We have an access mode : we expect to find a handle */
  126. starpu_data_handle handle = va_arg(varg_list, starpu_data_handle);
  127. starpu_access_mode mode = arg_type;
  128. (*task)->buffers[current_buffer].handle = handle;
  129. (*task)->buffers[current_buffer].mode = mode;
  130. current_buffer++;
  131. }
  132. else if (arg_type==STARPU_VALUE)
  133. {
  134. va_arg(varg_list, void *);
  135. va_arg(varg_list, size_t);
  136. }
  137. else if (arg_type==STARPU_CALLBACK)
  138. {
  139. void (*callback_func)(void *);
  140. callback_func = va_arg(varg_list, void (*)(void *));
  141. cl_arg_wrapper->callback_func = callback_func;
  142. }
  143. else if (arg_type==STARPU_CALLBACK_ARG) {
  144. void *callback_arg = va_arg(varg_list, void *);
  145. cl_arg_wrapper->callback_arg = callback_arg;
  146. }
  147. else if (arg_type==STARPU_PRIORITY)
  148. {
  149. /* Followed by a priority level */
  150. int prio = va_arg(varg_list, int);
  151. (*task)->priority = prio;
  152. }
  153. else if (arg_type==STARPU_EXECUTE) {
  154. va_arg(varg_list, int);
  155. }
  156. }
  157. va_end(varg_list);
  158. STARPU_ASSERT(current_buffer == cl->nbuffers);
  159. (*task)->cl = cl;
  160. (*task)->cl_arg = arg_buffer;
  161. /* The callback will free the argument stack and execute the
  162. * application's callback, if any. */
  163. (*task)->callback_func = starpu_task_insert_callback_wrapper;
  164. (*task)->callback_arg = cl_arg_wrapper;
  165. }
  166. int _starpu_insert_task_create_and_submit(char *arg_buffer, starpu_codelet *cl, struct starpu_task **task, va_list varg_list) {
  167. _starpu_prepare_task(arg_buffer, cl, task, varg_list);
  168. int ret = starpu_task_submit(*task);
  169. if (STARPU_UNLIKELY(ret == -ENODEV))
  170. fprintf(stderr, "No one can execute task %p wih cl %p (symbol %s)\n", *task, (*task)->cl, ((*task)->cl->model && (*task)->cl->model->symbol)?(*task)->cl->model->symbol:"none");
  171. STARPU_ASSERT(!ret);
  172. return ret;
  173. }
  174. int _starpu_insert_task_create_and_submit_to_ctx(char *arg_buffer, starpu_codelet *cl, struct starpu_task **task, va_list varg_list, struct starpu_sched_ctx *sched_ctx) {
  175. _starpu_prepare_task(arg_buffer, cl, task, varg_list);
  176. int ret = starpu_task_submit_to_ctx(*task, sched_ctx);
  177. if (STARPU_UNLIKELY(ret == -ENODEV))
  178. fprintf(stderr, "No one can execute task %p wih cl %p (symbol %s)\n", *task, (*task)->cl, ((*task)->cl->model && (*task)->cl->model->symbol)?(*task)->cl->model->symbol:"none");
  179. STARPU_ASSERT(!ret);
  180. return ret;
  181. }