/****** uti/tq/sge_tq_store_notify() ******************************************* * NAME * sge_tq_store_notify() -- Appends a new task at the end of queue * * SYNOPSIS * bool * sge_tq_store_notify(sge_tq_queue_t *queue, * sge_tq_type_t type, void *data) * * FUNCTION * This function creates a new task using 'type' and 'data'. The new * task will then be appended to 'queue'. If there are threads waiting * in sge_tq_wait_for_task() then one of those waiting threads will be * triggered so that it will wake up. * * If there are multiple threads waiting then it might happen that * always the same thread wakes up to catch the task (starvation). * * INPUTS * sge_tq_queue_t *queue - task queue * sge_tq_type_t type - task type * void *data - task data * * RESULT * bool - error state * true - success * false - error * * NOTES * MT-NOTE: sge_tq_store_notify() is MT safe * * SEE ALSO * uti/tq/sge_tq_wait_for_task() *******************************************************************************/ bool sge_tq_store_notify(sge_tq_queue_t *queue, sge_tq_type_t type, void *data) { bool ret = true; DENTER(TQ_LAYER, "sge_tq_store_notify"); if (queue != NULL && type != SGE_TQ_UNKNOWN && data != NULL) { sge_tq_task_t *new_task = NULL; /* create a new task */ ret &= sge_tq_task_create(&new_task, type, data); /* insert the task in the list and notify one waiting thread if there is one */ sge_mutex_lock(TQ_MUTEX_NAME, SGE_FUNC, __LINE__, sge_sl_get_mutex(queue->list)); if (ret) { ret = sge_sl_insert(queue->list, new_task, SGE_SL_BACKWARD); } if (ret && queue->waiting > 0) { sge_tq_wakeup_waiting(queue); } sge_mutex_unlock(TQ_MUTEX_NAME, SGE_FUNC, __LINE__, sge_sl_get_mutex(queue->list)); } DRETURN(ret); }
void sge_worker_terminate(sge_gdi_ctx_class_t *ctx) { bool do_final_spooling; DENTER(TOP_LAYER, "sge_worker_terminate"); sge_tq_wakeup_waiting(Master_Task_Queue); /* * trigger pthread_cancel for each thread so that further * shutdown process will be faster */ { cl_thread_list_elem_t *thr = NULL; cl_thread_list_elem_t *thr_nxt = NULL; thr_nxt = cl_thread_list_get_first_elem(Main_Control.worker_thread_pool); while ((thr = thr_nxt) != NULL) { thr_nxt = cl_thread_list_get_next_elem(thr); cl_thread_shutdown(thr->thread_config); } } /* * Shutdown/delete the threads and wait for termination */ { cl_thread_settings_t *thread = NULL; thread = cl_thread_list_get_first_thread(Main_Control.worker_thread_pool); while (thread != NULL) { DPRINTF(("gets canceled\n")); cl_thread_list_delete_thread(Main_Control.worker_thread_pool, thread); thread = cl_thread_list_get_first_thread(Main_Control.worker_thread_pool); } DPRINTF(("all "SFN" threads terminated\n", threadnames[WORKER_THREAD])); } do_final_spooling = sge_qmaster_do_final_spooling(); /* shutdown and remove JSV instances */ jsv_list_remove_all(); reporting_shutdown(ctx, NULL, do_final_spooling); DPRINTF(("accounting and reporting module has been shutdown\n")); /* * final spooling is only done if the shutdown of the current instance * of this master process is not triggered due to the fact that * shadowed started another instance which is currently running ... * * ... in that case we would overwrite data which might have already * changed in the second instance of the master */ if (do_final_spooling == true) { sge_store_job_number(ctx, NULL, NULL); sge_store_ar_id(ctx, NULL, NULL); DPRINTF(("job/ar counter made persistent\n")); sge_job_spool(ctx); /* store qmaster jobs to database */ sge_userprj_spool(ctx); /* spool the latest usage */ DPRINTF(("final job and user/project spooling has been triggered\n")); } sge_shutdown_persistence(NULL); DPRINTF(("persistence module has been shutdown\n")); DRETURN_VOID; }