/*===========================================================================* * get_work * *===========================================================================*/ static void get_work(struct worker_thread *worker) { /* Find new work to do. Work can be 'queued', 'pending', or absent. In the * latter case wait for new work to come in. */ struct job *new_job; struct fproc *rfp; ASSERTW(worker); self = worker; /* Do we have queued work to do? */ if ((new_job = worker->w_job.j_next) != NULL) { worker->w_job = *new_job; free(new_job); return; } else if (worker != &sys_worker && worker != &dl_worker && pending > 0) { /* Find pending work */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { if (rfp->fp_flags & FP_PENDING) { worker->w_job = rfp->fp_job; rfp->fp_job.j_func = NULL; rfp->fp_flags &= ~FP_PENDING; /* No longer pending */ pending--; assert(pending >= 0); return; } } panic("Pending work inconsistency"); } /* Wait for work to come to us */ worker_sleep(worker); }
/** * Work. * */ void worker_start(worker_type* worker) { time_t now, timeout = 1; task_type *task_that_was_worked_on; ods_log_assert(worker); while (worker->need_to_exit == 0) { ods_log_debug("[worker[%i]]: report for duty", worker->thread_num); lock_basic_lock(&worker->engine->taskq->schedule_lock); /* [LOCK] schedule */ worker->task = schedule_pop_task(worker->engine->taskq); if (worker->task) { /* [UNLOCK] schedule */ lock_basic_unlock(&worker->engine->taskq->schedule_lock); ods_log_debug("[worker[%i]] start working", worker->thread_num); worker->clock_in = time(NULL); worker_perform_task(worker); task_that_was_worked_on = worker->task; worker->task = NULL; ods_log_debug("[worker[%i]] finished working", worker->thread_num); if (task_that_was_worked_on) (void) lock_and_schedule_task(worker->engine->taskq, task_that_was_worked_on, 1); timeout = 1; } else { ods_log_debug("[worker[%i]] nothing to do", worker->thread_num); worker->task = schedule_get_first_task(worker->engine->taskq); /* [UNLOCK] schedule */ lock_basic_unlock(&worker->engine->taskq->schedule_lock); now = time_now(); if (worker->task && !worker->engine->taskq->loading) { timeout = (worker->task->when - now); } else { timeout *= 2; if (timeout > ODS_SE_MAX_BACKOFF) { timeout = ODS_SE_MAX_BACKOFF; } } worker->task = NULL; worker_sleep(worker, timeout); } } return; }
/*===========================================================================* * worker_wait * *===========================================================================*/ void worker_wait(void) { self->w_job.j_err_code = err_code; worker_sleep(self); /* We continue here after waking up */ fp = self->w_job.j_fp; /* Restore global data */ err_code = self->w_job.j_err_code; assert(self->w_next == NULL); }
/** * Work. * */ static void worker_work(worker_type* worker) { time_t now = 0; time_t timeout = 1; engine_type* engine = NULL; zone_type* zone = NULL; ods_status status = ODS_STATUS_OK; ods_log_assert(worker); ods_log_assert(worker->type == WORKER_WORKER); engine = (engine_type*) worker->engine; while (worker->need_to_exit == 0) { ods_log_debug("[%s[%i]] report for duty", worker2str(worker->type), worker->thread_num); now = time_now(); lock_basic_lock(&engine->taskq->schedule_lock); worker->task = schedule_pop_task(engine->taskq); if (worker->task) { worker->working_with = worker->task->what; lock_basic_unlock(&engine->taskq->schedule_lock); zone = (zone_type*) worker->task->zone; lock_basic_lock(&zone->zone_lock); ods_log_debug("[%s[%i]] start working on zone %s", worker2str(worker->type), worker->thread_num, zone->name); worker->clock_in = time(NULL); worker_perform_task(worker); zone->task = worker->task; ods_log_debug("[%s[%i]] finished working on zone %s", worker2str(worker->type), worker->thread_num, zone->name); lock_basic_lock(&engine->taskq->schedule_lock); worker->task = NULL; worker->working_with = TASK_NONE; status = schedule_task(engine->taskq, zone->task, 1); if (status != ODS_STATUS_OK) { ods_log_error("[%s[%i]] unable to schedule task for zone %s: " "%s", worker2str(worker->type), worker->thread_num, zone->name, ods_status2str(status)); } lock_basic_unlock(&engine->taskq->schedule_lock); lock_basic_unlock(&zone->zone_lock); timeout = 1; /** Do we need to tell the engine that we require a reload? */ lock_basic_lock(&engine->signal_lock); if (engine->need_to_reload) { lock_basic_alarm(&engine->signal_cond); } lock_basic_unlock(&engine->signal_lock); } else { ods_log_debug("[%s[%i]] nothing to do", worker2str(worker->type), worker->thread_num); worker->task = schedule_get_first_task(engine->taskq); lock_basic_unlock(&engine->taskq->schedule_lock); if (worker->task && !engine->taskq->loading) { timeout = (worker->task->when - now); } else { timeout *= 2; } if (timeout > ODS_SE_MAX_BACKOFF) { timeout = ODS_SE_MAX_BACKOFF; } worker->task = NULL; worker_sleep(worker, timeout); } } return; }