Beispiel #1
0
/****** uti/tq/sge_tq_wait_for_task() ******************************************
*  NAME
*     sge_tq_wait_for_task() -- Waits for a task 
*
*  SYNOPSIS
*     bool 
*     sge_tq_wait_for_task(sge_tq_queue_t *queue, int seconds, 
*                          sge_tq_type_t type, void **data);
*
*  FUNCTION
*     This function tries to get a task of 'type'. If there is one
*     available then the data pointer will be returned in 'data'.  If there
*     is none available the this function will sleep a number of 'seconds'
*     before it checks again if there is a task available. 
*
*     The sleep time might be interrupted by another thread that adds a
*     task to the queue via sge_tq_store_notify() or by a thread that
*     called sge_tq_wakeup_waiting().
*
*     The function returns either if a task of the correct type is 
*     available of if sge_thread_has_shutdown_started() returns true to
*     indicate that the shutdown of the thread/process has been triggered.
*     In that case the function might return with NULL in *data.
*
*  INPUTS
*     sge_tq_queue_t *queue - task queue 
*     int seconds           - max number of seconds to sleep 
*     sge_tq_type_t type    - type of the task that should be returned 
*     void **data           - NULL in case of thread/process shutdown 
*                             or the data pointer of the task
*
*  RESULT
*     bool - error state
*        true  - success
*        false - error
*
*  NOTES
*     MT-NOTE: sge_tq_wait_for_task() is MT safe 
*
*  SEE ALSO
*     uti/tq/sge_tq_store_notify()
*     uti/tq/sge_tq_wakeup_waiting()
*     uti/thread_ctrl/sge_thread_has_shutdown_started()
*     uti/thread_ctrl/sge_thread_notify_all_waiting()
*******************************************************************************/
bool
sge_tq_wait_for_task(sge_tq_queue_t *queue, int seconds,
                     sge_tq_type_t type, void **data) {
   bool ret = true;
   
   DENTER(TQ_LAYER, "sge_tq_wait_for_task");
   if (queue != NULL && data != NULL) {
      sge_sl_elem_t *elem = NULL;
      sge_tq_task_t key;

      key.type = type;
      *data = NULL;

      sge_mutex_lock(TQ_MUTEX_NAME, SGE_FUNC, __LINE__, sge_sl_get_mutex(queue->list));
     
      /*
       * block until either
       * - number of 'seconds' have elapsed and there is a task in the list
       * - someone notified to wakeup and shutdown of current thread/process has been triggered
       */  
      ret = sge_sl_elem_search(queue->list, &elem, &key, 
                               sge_tq_task_compare_type, SGE_SL_FORWARD);
      if (ret && elem == NULL && sge_thread_has_shutdown_started() == false) {
         queue->waiting++;
         do {
            struct timespec ts;

            sge_relative_timespec(seconds, &ts);
            pthread_cond_timedwait(&(queue->cond), sge_sl_get_mutex(queue->list), &ts);
            ret = sge_sl_elem_search(queue->list, &elem, &key, 
                                     sge_tq_task_compare_type, SGE_SL_FORWARD);
         } while (ret && elem == NULL && sge_thread_has_shutdown_started() == false);
         queue->waiting--;
      }

      /*
       * If we found a element that matches the key then remove and destroy if and return the data
       */ 
      if (ret && elem != NULL) {
         if (ret) {
            ret = sge_sl_dechain(queue->list, elem);
         }
         if (ret) {
            sge_tq_task_t *task = NULL;

            task = sge_sl_elem_data(elem);
            *data = task->data;
            ret = sge_sl_elem_destroy(&elem, (sge_sl_destroy_f)sge_tq_task_destroy);
         }
      }
 
      sge_mutex_unlock(TQ_MUTEX_NAME, SGE_FUNC, __LINE__, sge_sl_get_mutex(queue->list));
   }
   DRETURN(ret);
}
void *
sge_event_master_main(void *arg)
{
   bool do_endlessly = true;
   cl_thread_settings_t *thread_config = (cl_thread_settings_t*)arg;
   sge_gdi_ctx_class_t *ctx = NULL;
   monitoring_t monitor;
   monitoring_t *monitorp = &monitor;

   lListElem *report = NULL;
   lList *report_list = NULL;
   time_t next_prof_output = 0;

   DENTER(TOP_LAYER, "sge_event_master_main");

   DPRINTF(("started"));
   cl_thread_func_startup(thread_config);
   sge_monitor_init(&monitor, thread_config->thread_name, EDT_EXT, EMT_WARNING, EMT_ERROR);
   sge_qmaster_thread_init(&ctx, QMASTER, DELIVERER_THREAD, true);

   /* register at profiling module */
   set_thread_name(pthread_self(), "Deliver Thread");
   conf_update_thread_profiling("Deliver Thread");

   report_list = lCreateListHash("report list", REP_Type, false);
   report = lCreateElem(REP_Type);
   lSetUlong(report, REP_type, NUM_REP_REPORT_EVENTS);
   lSetHost(report, REP_host, ctx->get_qualified_hostname(ctx));
   lAppendElem(report_list, report);
 
   while (do_endlessly) {
      int execute = 0;

      thread_start_stop_profiling();

      /*
       * did a new event arrive which has a flush time of 0 seconds?
       */
      MONITOR_IDLE_TIME(sge_event_master_wait_next(), (&monitor), mconf_get_monitor_time(), 
                        mconf_is_monitor_message());

      MONITOR_MESSAGES((monitorp));
      MONITOR_EDT_COUNT((&monitor));
      MONITOR_CLIENT_COUNT((&monitor), lGetNumberOfElem(Event_Master_Control.clients));

      sge_event_master_process_requests(&monitor);
      sge_event_master_send_events(ctx, report, report_list, &monitor);
      sge_monitor_output(&monitor);

      thread_output_profiling("event master thread profiling summary:\n",
                              &next_prof_output);

      /* pthread cancelation point */
      pthread_cleanup_push((void (*)(void *))sge_event_master_cleanup_monitor,
                           (void *)&monitor);
      pthread_cleanup_push((void (*)(void *))sge_event_master_cleanup_report_list,
                           (void *)&report_list);
      cl_thread_func_testcancel(thread_config);
      pthread_cleanup_pop(execute); 
      pthread_cleanup_pop(execute); 
      if (sge_thread_has_shutdown_started()) {
         DPRINTF(("waiting for termination\n"));
         sleep(1);
      }
   }

   /*
    * Don't add cleanup code here. It will never be executed. Instead register
    * a cleanup function with pthread_cleanup_push()/pthread_cleanup_pop() before 
    * and after the call of cl_thread_func_testcancel()
    */

   DRETURN(NULL);
}