123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /* StarPU --- Runtime system for heterogeneous multicore architectures.
- *
- * Copyright (C) 2011, 2013 Université de Bordeaux
- * Copyright (C) 2011 Télécom-SudParis
- * Copyright (C) 2012 INRIA
- *
- * StarPU is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- *
- * StarPU is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * See the GNU Lesser General Public License in COPYING.LGPL for more details.
- */
- #include <starpu.h>
- #include <starpu_task_bundle.h>
- #include <core/task_bundle.h>
- #include <starpu_scheduler.h>
- #include <common/config.h>
- #include <common/utils.h>
- #include <common/list.h>
- #include <common/thread.h>
- /* Initialize a task bundle */
- void starpu_task_bundle_create(starpu_task_bundle_t *bundle)
- {
- _STARPU_MALLOC(*bundle, sizeof(struct _starpu_task_bundle));
- STARPU_PTHREAD_MUTEX_INIT(&(*bundle)->mutex, NULL);
- /* Of course at the beginning a bundle is open,
- * user can insert and remove tasks from it */
- (*bundle)->closed = 0;
- /* Start with an empty list */
- (*bundle)->list = NULL;
- }
- int starpu_task_bundle_insert(starpu_task_bundle_t bundle, struct starpu_task *task)
- {
- STARPU_PTHREAD_MUTEX_LOCK(&bundle->mutex);
- if (bundle->closed)
- {
- /* The bundle is closed, we cannot add task anymore */
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- return -EPERM;
- }
- if (task->status != STARPU_TASK_INVALID)
- {
- /* The task has already been submitted, it's too late to put it
- * into a bundle now. */
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- return -EINVAL;
- }
- /* Insert a task at the end of the bundle */
- struct _starpu_task_bundle_entry *entry;
- _STARPU_MALLOC(entry, sizeof(struct _starpu_task_bundle_entry));
- entry->task = task;
- entry->next = NULL;
- if (!bundle->list)
- {
- bundle->list = entry;
- }
- else
- {
- struct _starpu_task_bundle_entry *item;
- item = bundle->list;
- while (item->next)
- item = item->next;
- item->next = entry;
- }
- /* Mark the task as belonging the bundle */
- task->bundle = bundle;
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- return 0;
- }
- int starpu_task_bundle_remove(starpu_task_bundle_t bundle, struct starpu_task *task)
- {
- struct _starpu_task_bundle_entry *item;
- STARPU_PTHREAD_MUTEX_LOCK(&bundle->mutex);
- item = bundle->list;
- /* List is empty, there is no way the task
- * belong to it */
- if (!item)
- {
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- return -ENOENT;
- }
- STARPU_ASSERT_MSG(task->bundle == bundle, "Task %p was not in bundle %p, but in bundle %p", task, bundle, task->bundle);
- task->bundle = NULL;
- if (item->task == task)
- {
- /* Remove the first element */
- bundle->list = item->next;
- free(item);
- /* If the list is now empty, deinitialize the bundle */
- if (bundle->closed && bundle->list == NULL)
- {
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- _starpu_task_bundle_destroy(bundle);
- return 0;
- }
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- return 0;
- }
- /* Go through the list until we find the right task,
- * then we delete it */
- while (item->next)
- {
- struct _starpu_task_bundle_entry *next;
- next = item->next;
- if (next->task == task)
- {
- /* Remove the next element */
- item->next = next->next;
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- free(next);
- return 0;
- }
- item = next;
- }
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- /* We could not find the task in the bundle */
- return -ENOENT;
- }
- /* Close a bundle. No task can be added to a closed bundle. Tasks can still be
- * removed from a closed bundle. A closed bundle automatically gets
- * deinitialized when it becomes empty. A closed bundle cannot be reopened. */
- void starpu_task_bundle_close(starpu_task_bundle_t bundle)
- {
- STARPU_PTHREAD_MUTEX_LOCK(&bundle->mutex);
- /* If the bundle is already empty, we deinitialize it now as the
- * user closed it and thus don't intend to insert new tasks in it. */
- if (bundle->list == NULL)
- {
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- _starpu_task_bundle_destroy(bundle);
- return;
- }
- /* Mark the bundle as closed */
- bundle->closed = 1;
- STARPU_PTHREAD_MUTEX_UNLOCK(&bundle->mutex);
- }
- void _starpu_task_bundle_destroy(starpu_task_bundle_t bundle)
- {
- /* Remove all entries from the bundle (which is likely to be empty) */
- while (bundle->list)
- {
- struct _starpu_task_bundle_entry *entry = bundle->list;
- bundle->list = bundle->list->next;
- free(entry);
- }
- STARPU_PTHREAD_MUTEX_DESTROY(&bundle->mutex);
- free(bundle);
- }
- void _insertion_handle_sorted(struct _starpu_handle_list **listp, starpu_data_handle_t handle, enum starpu_data_access_mode mode)
- {
- STARPU_ASSERT(listp);
- struct _starpu_handle_list *list = *listp;
- /* If the list is empty or the handle's address the smallest among the
- * list, we insert it as first element */
- if (!list || list->handle > handle)
- {
- struct _starpu_handle_list *link;
- _STARPU_MALLOC(link, sizeof(struct _starpu_handle_list));
- link->handle = handle;
- link->mode = mode;
- link->next = list;
- *listp = link;
- return;
- }
- struct _starpu_handle_list *prev = list;
- /* Look for the same handle if already present in the list.
- * Else place it right before the smallest following handle */
- while (list && (handle >= list->handle))
- {
- prev = list;
- list = list->next;
- }
- if (prev->handle == handle)
- {
- /* The handle is already in the list, the merge both the access modes */
- prev->mode = (enum starpu_data_access_mode) ((int) prev->mode | (int) mode);
- }
- else
- {
- /* The handle was not in the list, we insert it after 'prev', thus right before
- * 'list' which is the smallest following handle */
- struct _starpu_handle_list *link;
- _STARPU_MALLOC(link, sizeof(struct _starpu_handle_list));
- link->handle = handle;
- link->mode = mode;
- link->next = prev->next;
- prev->next = link;
- }
- }
|