Beispiel #1
0
static void movedTaskWrapper(void* a) {
  movedTaskWrapperDesc_t* pmtwd = (movedTaskWrapperDesc_t*) a;
  if (pmtwd->countRunning)
    chpl_taskRunningCntInc(0, 0);
  (pmtwd->fp)(pmtwd->arg);
  if (pmtwd->countRunning)
    chpl_taskRunningCntDec(0, 0);
  chpl_mem_free(pmtwd, 0, 0);
}
Beispiel #2
0
void chpl_task_stdModulesInitialized(void)
{
    //
    // It's not safe to call the module code to count the main task as
    // running until after the modules have been initialized.  That's
    // when this function is called, so now count the main task.
    //
    canCountRunningTasks = true;
    chpl_taskRunningCntInc(0, NULL);
}
Beispiel #3
0
//
// Pre-user-code hook
//
// This is called on all locales.  The call on locale 0 is made from the
// compiler-emitted code in chpl_gen_main(), right before we enter user
// code.  The call on non-0 locales is made from chpl_main(), above.
//
void chpl_rt_preUserCodeHook(void) {
  chpl_comm_barrier("pre-user-code hook begin");

  chpl_taskRunningCntReset(0, 0);
  if (chpl_nodeID == 0) {
    chpl_taskRunningCntInc(0, 0);
  }

  //
  // Set up any memory tracking requested.
  //
  chpl_setMemFlags();

  chpl_comm_barrier("pre-user-code hook end");
}
Beispiel #4
0
static void
taskCallWrapper(void* a) {
  taskCallWrapperDesc_t* ptcwd = (taskCallWrapperDesc_t*) a;
  if (ptcwd->countRunning)
    chpl_taskRunningCntInc(0, 0);

  if (ptcwd->arg_copy != NULL) {
    (ptcwd->fp)(ptcwd->arg_copy);
    chpl_mem_free(ptcwd->arg_copy, 0, 0);
  } else
    (ptcwd->fp)(ptcwd->arg);

  if (ptcwd->countRunning)
    chpl_taskRunningCntDec(0, 0);
  chpl_mem_free(ptcwd, 0, 0);
}
Beispiel #5
0
static aligned_t chapel_wrapper(void *arg)
{
    chpl_qthread_wrapper_args_t *rarg = arg;
    chpl_qthread_tls_t * data = chpl_qthread_get_tasklocal();

    data->task_filename = rarg->task_filename;
    data->task_lineno = rarg->lineno;
    data->chpl_data = rarg->chpl_data;
    data->lock_filename = NULL;
    data->lock_lineno = 0;

    if (rarg->countRunning) {
        chpl_taskRunningCntInc(0, NULL);
    }

    (*(chpl_fn_p)(rarg->fn))(rarg->args);

    if (rarg->countRunning) {
        chpl_taskRunningCntDec(0, NULL);
    }

    return 0;
}
Beispiel #6
0
void chpl_task_stdModulesInitialized(void) {
  //
  // It's not safe to call the module code to count the main task as
  // running until after the modules have been initialized.
  //
  canCountRunningTasks = true;
  chpl_taskRunningCntInc(0, 0);

  //
  // The task table is implemented in Chapel code in the modules, so
  // we can't use it, and thus can't support task reporting on ^C or
  // deadlock, until the other modules on which it depends have been
  // initialized and the supporting code here is set up.  In this
  // function we're guaranteed that is true, because it is called only
  // after all the standard module initialization is complete.
  //

  //
  // Register this main task in the task table.
  //
  if (taskreport) {
    thread_private_data_t* tp = chpl_thread_getPrivateData();

    chpldev_taskTable_add(tp->ptask->id,
                          tp->ptask->lineno, tp->ptask->filename,
                          (uint64_t) (intptr_t) tp->ptask);
    chpldev_taskTable_set_active(tp->ptask->id);

    chpl_thread_mutexInit(&taskTable_lock);
  }

  //
  // Now we can do task reporting if the user requested it.
  //
  do_taskReport = taskreport;
}
Beispiel #7
0
void chpl_task_executeTasksInList(void** p_task_list_void) {
  task_pool_p* p_task_list_head = (task_pool_p*) p_task_list_void;
  task_pool_p curr_ptask;
  task_pool_p child_ptask;

  //
  // If we're serial, all the tasks have already been executed.
  //
  if (chpl_task_getSerial())
    return;

  curr_ptask = get_current_ptask();

  while (*p_task_list_head != NULL) {
    chpl_fn_p task_to_run_fun = NULL;

    // begin critical section
    chpl_thread_mutexLock(&threading_lock);

    if ((child_ptask = *p_task_list_head) != NULL) {
      task_to_run_fun = child_ptask->bundle.requested_fn;
      dequeue_task(child_ptask);
    }

    // end critical section
    chpl_thread_mutexUnlock(&threading_lock);

    if (task_to_run_fun == NULL)
      continue;

    set_current_ptask(child_ptask);

    // begin critical section
    chpl_thread_mutexLock(&extra_task_lock);

    extra_task_cnt++;

    // end critical section
    chpl_thread_mutexUnlock(&extra_task_lock);

    if (do_taskReport) {
      chpl_thread_mutexLock(&taskTable_lock);
      chpldev_taskTable_set_suspended(curr_ptask->bundle.id);
      chpldev_taskTable_set_active(child_ptask->bundle.id);
      chpl_thread_mutexUnlock(&taskTable_lock);
    }

    if (blockreport)
      initializeLockReportForThread();

    chpl_task_do_callbacks(chpl_task_cb_event_kind_begin,
                           child_ptask->bundle.requested_fid,
                           child_ptask->bundle.filename,
                           child_ptask->bundle.lineno,
                           child_ptask->bundle.id,
                           child_ptask->bundle.is_executeOn);

    if (child_ptask->bundle.countRunning)
        chpl_taskRunningCntInc(0, 0);

    (*task_to_run_fun)(&child_ptask->bundle);

    if (child_ptask->bundle.countRunning)
        chpl_taskRunningCntDec(0, 0);

    chpl_task_do_callbacks(chpl_task_cb_event_kind_end,
                           child_ptask->bundle.requested_fid,
                           child_ptask->bundle.filename,
                           child_ptask->bundle.lineno,
                           child_ptask->bundle.id,
                           child_ptask->bundle.is_executeOn);

    if (do_taskReport) {
      chpl_thread_mutexLock(&taskTable_lock);
      chpldev_taskTable_set_active(curr_ptask->bundle.id);
      chpldev_taskTable_remove(child_ptask->bundle.id);
      chpl_thread_mutexUnlock(&taskTable_lock);
    }

    // begin critical section
    chpl_thread_mutexLock(&extra_task_lock);

    extra_task_cnt--;

    // end critical section
    chpl_thread_mutexUnlock(&extra_task_lock);

    set_current_ptask(curr_ptask);
    chpl_mem_free(child_ptask, 0, 0);

  }
}
Beispiel #8
0
//
// When we create a thread it runs this wrapper function, which just
// executes tasks out of the pool as they become available.
//
static void
thread_begin(void* ptask_void) {
  task_pool_p ptask;
  thread_private_data_t *tp;

  tp = (thread_private_data_t*) chpl_mem_alloc(sizeof(thread_private_data_t),
                                               CHPL_RT_MD_THREAD_PRV_DATA,
                                               0, 0);
  chpl_thread_setPrivateData(tp);

  tp->lockRprt = NULL;
  if (blockreport)
    initializeLockReportForThread();

  while (true) {
    //
    // wait for a task to be present in the task pool
    //

    // In revision 22137, we investigated whether it was beneficial to
    // implement this while loop in a hybrid style, where depending on
    // the number of tasks available, idle threads would either yield or
    // wait on a condition variable to waken them.  Through analysis, we
    // realized this could potential create a case where a thread would
    // become stranded, waiting for a condition signal that would never
    // come.  A potential solution to this was to keep a count of threads
    // that were waiting on the signal, but since there was a performance
    // impact from keeping it as a hybrid as opposed to merely yielding,
    // it was decided that we would return to the simple yield case.
    while (!task_pool_head) {
      if (set_block_loc(0, CHPL_FILE_IDX_IDLE_TASK)) {
        // all other tasks appear to be blocked
        struct timeval deadline, now;
        gettimeofday(&deadline, NULL);
        deadline.tv_sec += 1;
        do {
          chpl_thread_yield();
          if (!task_pool_head)
            gettimeofday(&now, NULL);
        } while (!task_pool_head
                 && (now.tv_sec < deadline.tv_sec
                     || (now.tv_sec == deadline.tv_sec
                         && now.tv_usec < deadline.tv_usec)));
        if (!task_pool_head) {
          check_for_deadlock();
        }
      }
      else {
        do {
          chpl_thread_yield();
        } while (!task_pool_head);
      }

      unset_block_loc();
    }
 
    //
    // Just now the pool had at least one task in it.  Lock and see if
    // there's something still there.
    //
    chpl_thread_mutexLock(&threading_lock);
    if (!task_pool_head) {
      chpl_thread_mutexUnlock(&threading_lock);
      continue;
    }

    //
    // We've found a task to run.
    //

    if (blockreport)
      progress_cnt++;

    //
    // start new task; increment running count and remove task from pool
    // also add to task to task-table (structure in ChapelRuntime that keeps
    // track of currently running tasks for task-reports on deadlock or
    // Ctrl+C).
    //
    ptask = task_pool_head;
    idle_thread_cnt--;
    running_task_cnt++;

    dequeue_task(ptask);

    // end critical section
    chpl_thread_mutexUnlock(&threading_lock);

    tp->ptask = ptask;

    if (do_taskReport) {
      chpl_thread_mutexLock(&taskTable_lock);
      chpldev_taskTable_set_active(ptask->bundle.id);
      chpl_thread_mutexUnlock(&taskTable_lock);
    }

    chpl_task_do_callbacks(chpl_task_cb_event_kind_begin,
                           ptask->bundle.requested_fid,
                           ptask->bundle.filename,
                           ptask->bundle.lineno,
                           ptask->bundle.id,
                           ptask->bundle.is_executeOn);

    if (ptask->bundle.countRunning)
        chpl_taskRunningCntInc(0, 0);

    (ptask->bundle.requested_fn)(&ptask->bundle);

    if (ptask->bundle.countRunning)
        chpl_taskRunningCntDec(0, 0);

    chpl_task_do_callbacks(chpl_task_cb_event_kind_end,
                           ptask->bundle.requested_fid,
                           ptask->bundle.filename,
                           ptask->bundle.lineno,
                           ptask->bundle.id,
                           ptask->bundle.is_executeOn);

    if (do_taskReport) {
      chpl_thread_mutexLock(&taskTable_lock);
      chpldev_taskTable_remove(ptask->bundle.id);
      chpl_thread_mutexUnlock(&taskTable_lock);
    }

    tp->ptask = NULL;
    chpl_mem_free(ptask, 0, 0);

    // begin critical section
    chpl_thread_mutexLock(&threading_lock);

    //
    // finished task; decrement running count and increment idle count
    //
    assert(running_task_cnt > 0);
    running_task_cnt--;
    idle_thread_cnt++;

    // end critical section
    chpl_thread_mutexUnlock(&threading_lock);
  }
}