/****** 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); }