예제 #1
0
void __ompc_task_create(omp_task_func taskfunc, void* frame_pointer,
                       void *firstprivates, int may_delay, int is_tied,
                       int blocks_parent)
{
  omp_team_t *team;
  omp_task_t *newtask;
  __omp_tasks_created++;

  team = __ompc_get_current_team();
  newtask = __ompc_task_get(taskfunc, frame_pointer, firstprivates,
                            __omp_task_stack_size);

#if defined(TASK_DEBUG)
  fprintf(stdout,"%d: __ompc_task_create: %lX created %lX\n", __omp_myid, __omp_current_task->coro,
            newtask->coro);
#endif

  if(newtask == NULL || newtask->coro == NULL || newtask->desc == NULL ) {
    fprintf(stderr, "%d: not able to create new tasks\n", __omp_myid);
    exit(1);
  }
  newtask->desc->num_children = 0;
  newtask->desc->is_parallel_task = 0;
  newtask->desc->is_tied = is_tied;
  newtask->desc->may_delay = may_delay;
  newtask->desc->started = 0;
  newtask->desc->safe_to_enqueue = 0;
  newtask->desc->depth = __omp_current_task->desc->depth + 1;
  newtask->desc->pdepth = newtask->desc->depth;
  newtask->desc->blocks_parent = blocks_parent;
  newtask->creator = __omp_current_task;
  pthread_mutex_init(&newtask->lock, NULL);

  /* update number of children - use atomic operation if possible */
  int x;
  x = __ompc_atomic_inc(&__omp_current_task->desc->num_children);
  __ompc_atomic_inc(&(team->num_tasks));

  if (blocks_parent)
    __ompc_atomic_inc(&__omp_current_task->desc->num_blocking_children);


  if (may_delay & ! (__omp_exe_mode & OMP_EXE_MODE_SEQUENTIAL)) {
     /* only switch here if newtask will switch back upon initializing its
      * firstprivates. in that case, when current task resumes it will enqueue
      * the new task into public queue.
      */
    // __ompc_task_switch(__omp_current_task, newtask);
#ifdef SCHED1
    newtask->desc->threadid = friend;
    __sync_bool_compare_and_swap(&__omp_empty_flags[friend], 1, 0);
    __ompc_task_q_put_tail(&(team->public_task_q[friend]), newtask);
#else
    __ompc_task_q_put_tail(&(team->public_task_q[__omp_myid]), newtask);
#endif
  } else if (__omp_exe_mode & OMP_EXE_MODE_SEQUENTIAL) {
예제 #2
0
/* __ompc_add_task_to_pool_default:
 * Adds a task to the task pool. The task will be added to the current
 * thread's queue.
 */
int __ompc_add_task_to_pool_default(omp_task_pool_t *pool, omp_task_t *task)
{
  int success;
  int myid = __omp_myid;
  omp_task_queue_level_t *per_thread;

  Is_True(pool != NULL, ("__ompc_add_task_to_pool: task pool is uninitialized"));
  Is_True(task != NULL,
      ("__ompc_add_task_to_pool: tried to add NULL task to pool"));

  /* num_pending_tasks track not just tasks entered into the task pool, but
   * also tasks marked as deferred that could not fit into the task pool
   */
  if (__ompc_atomic_inc(&pool->num_pending_tasks) == 1) {
    pthread_mutex_lock(&pool->pool_lock);
    pthread_cond_broadcast(&pool->pool_cond);
    pthread_mutex_unlock(&pool->pool_lock);
  }

  per_thread = &pool->level[PER_THREAD];

  if (__ompc_task_is_tied(task))
    /* For tied tasks, we don't use the task_queue API. We explicitly put to
     * the tail */
    success = __ompc_queue_put_tail(
                        &per_thread->task_queue[TIED_IDX(myid)],
                        task);
  else
    success = __ompc_task_queue_put(
                        &per_thread->task_queue[UNTIED_IDX(myid)],
                        task);

  return success;
}
/* __ompc_add_task_to_pool_simple_2level:
 * Adds a task to the task pool. The task will be added to the current
 * thread's queue.
 */
int __ompc_add_task_to_pool_simple_2level(omp_task_pool_t *pool, omp_task_t *task)
{
  int success;
  int myid = __omp_myid;
  omp_task_queue_level_t *per_thread;
  omp_task_queue_level_t *community;

  Is_True(pool != NULL, ("__ompc_add_task_to_pool: task pool is uninitialized"));
  Is_True(task != NULL,
      ("__ompc_add_task_to_pool: tried to add NULL task to pool"));

  success = 0;
  per_thread = &pool->level[PER_THREAD];
  community = &pool->level[COMMUNITY];

  /* num_pending_tasks track not just tasks entered into the task pool, but
   * also tasks marked as deferred that could not fit into the task pool
   */
  if (__ompc_atomic_inc(&pool->num_pending_tasks) == 1) {
    pthread_mutex_lock(&pool->pool_lock);
    pthread_cond_broadcast(&pool->pool_cond);
    pthread_mutex_unlock(&pool->pool_lock);
  }

  /* don't try to place it in per-thread queue if it looks to be full, because
   * we have the community queue to use instead   */
  if (!__ompc_task_queue_is_full(&per_thread->task_queue[myid]))
    success = __ompc_task_queue_put(&pool->level[PER_THREAD].task_queue[myid],
                                    task);

  if (!success)
    success = __ompc_task_queue_donate(pool->level[COMMUNITY].task_queue, task);

  return success;
}
/* __ompc_add_task_to_pool_simple:
 * Adds a task to the task pool. The task will be added to the current
 * thread's queue.
 */
int __ompc_add_task_to_pool_simple(omp_task_pool_t *pool, omp_task_t *task)
{
  int success;
  int myid = __omp_myid;

  Is_True(pool != NULL, ("__ompc_add_task_to_pool: task pool is uninitialized"));
  Is_True(task != NULL,
      ("__ompc_add_task_to_pool: tried to add NULL task to pool"));

  /* num_pending_tasks track not just tasks entered into the task pool, but
   * also tasks marked as deferred that could not fit into the task pool
   */
  if (__ompc_atomic_inc(&pool->num_pending_tasks) == 1) {
    pthread_mutex_lock(&pool->pool_lock);
    pthread_cond_broadcast(&pool->pool_cond);
    pthread_mutex_unlock(&pool->pool_lock);
  }

  success = __ompc_task_queue_put(&pool->level[PER_THREAD].task_queue[myid],
                                  task);

  return success;
}
예제 #5
0
void __ompc_task_create(omp_task_func taskfunc, void *frame_pointer,
        void *firstprivates, int may_delay, int is_tied, int blocks_parent)
{
  int myid;
  omp_team_t *team;
  omp_task_t *current_task, *new_task, *orig_task;
  omp_v_thread_t *current_thread;

  current_task = __omp_current_task;

  if (__ompc_task_cutoff()) {
    //__omp_task_cutoffs++;
    orig_task = current_task;
    __omp_current_task = NULL;
    taskfunc(firstprivates, frame_pointer);
    __omp_current_task = orig_task;
    return;
    /* not reached */
  }


  myid = __omp_myid;
  current_thread = __omp_current_v_thread;
  team = current_thread->team;

#ifdef USE_COLLECTOR_TASK
  OMP_COLLECTOR_API_THR_STATE temp_state =
      (OMP_COLLECTOR_API_THR_STATE)current_thread->state;
  __ompc_set_state(THR_TASK_CREATE_STATE);
  __ompc_event_callback(OMP_EVENT_THR_BEGIN_CREATE_TASK);

#ifndef OMPT
  int new_id = __ompc_atomic_inc(&team->collector_task_id);
#endif
#endif

  if (may_delay) {
    new_task = __ompc_task_new();
    __ompc_task_set_function(new_task, taskfunc);
    __ompc_task_set_frame_pointer(new_task, frame_pointer);
    __ompc_task_set_firstprivates(new_task, firstprivates);
    new_task->creating_thread_id = myid;
    new_task->parent = current_task;
    new_task->depth = current_task->depth + 1;

#ifdef USE_COLLECTOR_TASK
#ifndef OMPT
    new_task->task_id = new_id;
#endif
    __omp_collector_task = new_task;
    __ompc_event_callback(OMP_EVENT_THR_END_CREATE_TASK_DEL);
    __ompc_set_state(temp_state);
#endif

    __ompc_task_set_flags(new_task, OMP_TASK_IS_DEFERRED);

    if (is_tied)
      __ompc_task_set_flags(new_task, OMP_TASK_IS_TIED);

    __ompc_atomic_inc(&current_task->num_children);

    if (blocks_parent) {
      __ompc_task_set_flags(new_task, OMP_TASK_BLOCKS_PARENT);
      __ompc_atomic_inc(&current_task->num_blocking_children);
    }

#ifdef OMPT
    __ompt_event_callback(ompt_event_task_begin);
#endif

    if (__ompc_add_task_to_pool(team->task_pool, new_task) == 0) {
      /* couldn't add to task pool, so execute it immediately */
      __ompc_task_set_state(current_task, OMP_TASK_READY);
      __ompc_task_switch(new_task);
      __ompc_task_set_state(current_task, OMP_TASK_RUNNING);
    }

  } else {
    omp_task_t new_immediate_task;
    new_task = &new_immediate_task;
    memset(new_task, 0, sizeof(omp_task_t));
    __ompc_task_set_function(new_task, taskfunc);
    __ompc_task_set_frame_pointer(new_task, frame_pointer);

    /* firstprivates will be NULL, so don't need to set it */
    Is_True(firstprivates == NULL, ("firstprivates should always be NULL"));

    new_task->creating_thread_id = myid;
    new_task->parent = current_task;
    new_task->depth = current_task->depth + 1;

#ifdef USE_COLLECTOR_TASK
#ifndef OMPT
    new_task->task_id = new_id;
#endif
    __omp_collector_task = new_task;
    __ompc_event_callback(OMP_EVENT_THR_END_CREATE_TASK_IMM);
#endif

    if (is_tied)
      __ompc_task_set_flags(new_task, OMP_TASK_IS_TIED);


#ifdef OMPT
    __ompt_event_callback(ompt_event_task_begin);
#endif

    __ompc_task_set_state(current_task, OMP_TASK_READY);
    if (__ompc_task_is_tied(current_task)) {
      /* if current task is tied, it should not go back into task pool */
      orig_task = current_task;
      ++(current_thread->num_suspended_tied_tasks);
      __omp_current_task = new_task;
      taskfunc(NULL, frame_pointer);
      __omp_current_task = orig_task;
      --(current_thread->num_suspended_tied_tasks);
    } else {
      /* if current task is untied, it can go back into task pool, but this
       * isn't currently supported. */
      orig_task = current_task;
      __omp_current_task = new_task;
      taskfunc(NULL, frame_pointer);
      __omp_current_task = orig_task;
    }
    __ompc_task_set_state(current_task, OMP_TASK_RUNNING);
  }

}