task_bundle.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. * Copyright (C) 2011 Télécom-SudParis
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. #include <starpu.h>
  18. #include <starpu_task_bundle.h>
  19. #include <core/task_bundle.h>
  20. #include <starpu_scheduler.h>
  21. #include <common/config.h>
  22. #include <common/utils.h>
  23. #include <common/list.h>
  24. #include <common/thread.h>
  25. /* Initialize a task bundle */
  26. void starpu_task_bundle_create(starpu_task_bundle_t *bundle)
  27. {
  28. _STARPU_CALLOC(*bundle, 1, sizeof(struct _starpu_task_bundle));
  29. STARPU_PTHREAD_MUTEX_INIT0(&(*bundle)->mutex, NULL);
  30. /* Of course at the beginning a bundle is open,
  31. * user can insert and remove tasks from it */
  32. //(*bundle)->closed = 0;
  33. /* Start with an empty list */
  34. //(*bundle)->list = NULL;
  35. }
  36. int starpu_task_bundle_insert(starpu_task_bundle_t bundle, struct starpu_task *task)
  37. {
  38. STARPU_PTHREAD_MUTEX_LOCK(&bundle->mutex);
  39. if (bundle->closed)
  40. {
  41. /* The bundle is closed, we cannot add task anymore */
  42. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  43. return -EPERM;
  44. }
  45. if (task->status != STARPU_TASK_INIT)
  46. {
  47. /* The task has already been submitted, it's too late to put it
  48. * into a bundle now. */
  49. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  50. return -EINVAL;
  51. }
  52. /* Insert a task at the end of the bundle */
  53. struct _starpu_task_bundle_entry *entry;
  54. _STARPU_MALLOC(entry, sizeof(struct _starpu_task_bundle_entry));
  55. entry->task = task;
  56. entry->next = NULL;
  57. if (!bundle->list)
  58. {
  59. bundle->list = entry;
  60. }
  61. else
  62. {
  63. struct _starpu_task_bundle_entry *item;
  64. item = bundle->list;
  65. while (item->next)
  66. item = item->next;
  67. item->next = entry;
  68. }
  69. /* Mark the task as belonging the bundle */
  70. task->bundle = bundle;
  71. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  72. return 0;
  73. }
  74. int starpu_task_bundle_remove(starpu_task_bundle_t bundle, struct starpu_task *task)
  75. {
  76. struct _starpu_task_bundle_entry *item;
  77. STARPU_PTHREAD_MUTEX_LOCK(&bundle->mutex);
  78. item = bundle->list;
  79. /* List is empty, there is no way the task
  80. * belong to it */
  81. if (!item)
  82. {
  83. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  84. return -ENOENT;
  85. }
  86. STARPU_ASSERT_MSG(task->bundle == bundle, "Task %p was not in bundle %p, but in bundle %p", task, bundle, task->bundle);
  87. task->bundle = NULL;
  88. if (item->task == task)
  89. {
  90. /* Remove the first element */
  91. bundle->list = item->next;
  92. free(item);
  93. /* If the list is now empty, deinitialize the bundle */
  94. if (bundle->closed && bundle->list == NULL)
  95. {
  96. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  97. _starpu_task_bundle_destroy(bundle);
  98. return 0;
  99. }
  100. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  101. return 0;
  102. }
  103. /* Go through the list until we find the right task,
  104. * then we delete it */
  105. while (item->next)
  106. {
  107. struct _starpu_task_bundle_entry *next;
  108. next = item->next;
  109. if (next->task == task)
  110. {
  111. /* Remove the next element */
  112. item->next = next->next;
  113. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  114. free(next);
  115. return 0;
  116. }
  117. item = next;
  118. }
  119. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  120. /* We could not find the task in the bundle */
  121. return -ENOENT;
  122. }
  123. /* Close a bundle. No task can be added to a closed bundle. Tasks can still be
  124. * removed from a closed bundle. A closed bundle automatically gets
  125. * deinitialized when it becomes empty. A closed bundle cannot be reopened. */
  126. void starpu_task_bundle_close(starpu_task_bundle_t bundle)
  127. {
  128. STARPU_PTHREAD_MUTEX_LOCK(&bundle->mutex);
  129. /* If the bundle is already empty, we deinitialize it now as the
  130. * user closed it and thus don't intend to insert new tasks in it. */
  131. if (bundle->list == NULL)
  132. {
  133. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  134. _starpu_task_bundle_destroy(bundle);
  135. return;
  136. }
  137. /* Mark the bundle as closed */
  138. bundle->closed = 1;
  139. STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
  140. }
  141. void _starpu_task_bundle_destroy(starpu_task_bundle_t bundle)
  142. {
  143. /* Remove all entries from the bundle (which is likely to be empty) */
  144. while (bundle->list)
  145. {
  146. struct _starpu_task_bundle_entry *entry = bundle->list;
  147. bundle->list = bundle->list->next;
  148. free(entry);
  149. }
  150. STARPU_PTHREAD_MUTEX_DESTROY(&bundle->mutex);
  151. free(bundle);
  152. }
  153. void _insertion_handle_sorted(struct _starpu_handle_list **listp, starpu_data_handle_t handle, enum starpu_data_access_mode mode)
  154. {
  155. STARPU_ASSERT(listp);
  156. struct _starpu_handle_list *list = *listp;
  157. /* If the list is empty or the handle's address the smallest among the
  158. * list, we insert it as first element */
  159. if (!list || list->handle > handle)
  160. {
  161. struct _starpu_handle_list *link;
  162. _STARPU_MALLOC(link, sizeof(struct _starpu_handle_list));
  163. link->handle = handle;
  164. link->mode = mode;
  165. link->next = list;
  166. *listp = link;
  167. return;
  168. }
  169. struct _starpu_handle_list *prev = list;
  170. /* Look for the same handle if already present in the list.
  171. * Else place it right before the smallest following handle */
  172. while (list && (handle >= list->handle))
  173. {
  174. prev = list;
  175. list = list->next;
  176. }
  177. if (prev->handle == handle)
  178. {
  179. /* The handle is already in the list, the merge both the access modes */
  180. prev->mode = (enum starpu_data_access_mode) ((int) prev->mode | (int) mode);
  181. }
  182. else
  183. {
  184. /* The handle was not in the list, we insert it after 'prev', thus right before
  185. * 'list' which is the smallest following handle */
  186. struct _starpu_handle_list *link;
  187. _STARPU_MALLOC(link, sizeof(struct _starpu_handle_list));
  188. link->handle = handle;
  189. link->mode = mode;
  190. link->next = prev->next;
  191. prev->next = link;
  192. }
  193. }