task_bundle.c 6.1 KB

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