/** * Clean up engine. * */ void engine_cleanup(engine_type* engine) { size_t i = 0; if (!engine) { return; } if (engine->workers && engine->config) { for (i=0; i < (size_t) engine->config->num_worker_threads; i++) { worker_cleanup(engine->workers[i]); } free(engine->workers); } if (engine->drudgers && engine->config) { for (i=0; i < (size_t) engine->config->num_signer_threads; i++) { worker_cleanup(engine->drudgers[i]); } free(engine->drudgers); } zonelist_cleanup(engine->zonelist); schedule_cleanup(engine->taskq); fifoq_cleanup(engine->signq); cmdhandler_cleanup(engine->cmdhandler); dnshandler_cleanup(engine->dnshandler); xfrhandler_cleanup(engine->xfrhandler); engine_config_cleanup(engine->config); lock_basic_destroy(&engine->signal_lock); lock_basic_off(&engine->signal_cond); free(engine); }
void *worker_run(void* userdata) { int num_events, flush_outbox; worker_t* self = userdata; ev_event_t *event; conn_t *conn; ev_init(&self->loop); ev_watch(&self->loop, self->conn_queue[0], EV_READABLE, self); ev_watch(&self->loop, self->msg_queue[0], EV_READABLE, NULL); while(self->running) { num_events = ev_poll(&self->loop); flush_outbox = 0; if (num_events == -1) continue; while (--num_events >= 0) { event = self->loop.fired[num_events]; if (!event->fired) continue; if (!event->userdata) { if (event->fired & EV_READABLE) worker_flush_inbox(self); else flush_outbox = 1; continue; } else if (event->userdata == self) { worker_accept(self); continue; } conn = event->userdata; if (event->fired & EV_READABLE) if (conn_read(conn) == -1) continue; if (event->fired & EV_WRITEABLE) if (conn_write(conn) == -1) continue; } if (flush_outbox) worker_flush_outbox(self); } worker_cleanup(self); return NULL; }
/** * Clean up engine. * */ void engine_cleanup(engine_type* engine) { size_t i = 0; allocator_type* allocator; cond_basic_type signal_cond; lock_basic_type signal_lock; if (!engine) { return; } allocator = engine->allocator; signal_cond = engine->signal_cond; signal_lock = engine->signal_lock; if (engine->workers && engine->config) { for (i=0; i < (size_t) engine->config->num_worker_threads; i++) { worker_cleanup(engine->workers[i]); } allocator_deallocate(allocator, (void*) engine->workers); } #if HAVE_DRUDGERS if (engine->drudgers && engine->config) { for (i=0; i < (size_t) engine->config->num_signer_threads; i++) { worker_cleanup(engine->drudgers[i]); } allocator_deallocate(allocator, (void*) engine->drudgers); } #endif schedule_cleanup(engine->taskq); fifoq_cleanup(engine->signq); cmdhandler_cleanup(engine->cmdhandler); engine_config_cleanup(engine->config); allocator_deallocate(allocator, (void*) engine); lock_basic_destroy(&signal_lock); lock_basic_off(&signal_cond); allocator_cleanup(allocator); return; }
/*===========================================================================* * sef_cb_lu_prepare * *===========================================================================*/ static int sef_cb_lu_prepare(int state) { /* This function is called to decide whether we can enter the given live * update state, and to prepare for such an update. If we are requested to * update to a request-free or protocol-free state, make sure there is no work * pending or being processed, and shut down all worker threads. */ switch (state) { case SEF_LU_STATE_REQUEST_FREE: case SEF_LU_STATE_PROTOCOL_FREE: if (!worker_idle()) { printf("VFS: worker threads not idle, blocking update\n"); break; } worker_cleanup(); return OK; } return ENOTREADY; }
static void *worker_loop(Worker *t) { int i; enum worker_transaction_states state; lock(); if (!heap_isempty(worker_ready_to_run)) { /* wait for older threads that are ready to run */ worker_wake_up_next(); heap_add(worker_ready_to_run, t); cond_wait(t->sleep); } /* let threads expire after a while so the thread pool can grow and shrink * as needed without hard limits on the number of threads */ for (i = 0; i < THREAD_LIFETIME; i++) { if (i > 0) { /* wait in the pool for a request */ worker_thread_pool = append_elt(worker_thread_pool, t); cond_wait(t->sleep); } worker_active++; /* initialize the exception handler and catch exceptions */ do { state = setjmp(t->jmp); if (state == WORKER_BLOCKED) { /* wait for the blocking transaction to finish, * then start over */ worker_cleanup(t); worker_wake_up_next(); cond_wait(t->sleep); } else if (state == WORKER_MULTISTEP) { /* wait for the next step in this grant/revoke op to wake us up * with more work to do */ if (DEBUG_VERBOSE) printf("WORKER_MULTISTEP sleeping\n"); worker_cleanup(t); t->func = NULL; t->arg = NULL; worker_wake_up_next(); while (t->func == NULL) cond_wait(t->sleep); if (DEBUG_VERBOSE) printf("WORKER_MULTISTEP waking up\n"); } else if (state == WORKER_RETRY) { worker_cleanup(t); } } while (state != WORKER_ZERO); /* process the request */ if (t->func != NULL) t->func(t, t->arg); worker_cleanup(t); t->func = NULL; /* make anyone waiting on this transaction ready to run, then run one */ if (!null(t->blocking)) { for ( ; !null(t->blocking); t->blocking = cdr(t->blocking)) heap_add(worker_ready_to_run, car(t->blocking)); } worker_active--; worker_wake_up_next(); } unlock(); return NULL; }