int p_share_work(void) { int worker_q = LOCAL_share_request; int son; if (! BITMAP_member(OrFr_members(REMOTE_top_or_fr(worker_q)), worker_id) || B == REMOTE_top_cp(worker_q) || (LOCAL_load <= DELAYED_RELEASE_LOAD && OrFr_nearest_livenode(LOCAL_top_or_fr) == NULL)) { /* refuse sharing request */ REMOTE_reply_signal(LOCAL_share_request) = no_sharing; LOCAL_share_request = MAX_WORKERS; PUT_OUT_REQUESTABLE(worker_id); return TRUE; } /* sharing request accepted */ REMOTE_reply_signal(worker_q) = sharing; share_private_nodes(worker_q); if ((son = fork()) == 0) { worker_id = worker_q; /* child becomes requesting worker */ LOCAL = REMOTE + worker_id; LOCAL_reply_signal = ready; PUT_IN_REQUESTABLE(worker_id); PUT_BUSY(worker_id); return FALSE; } else { worker_pid(worker_q) = son; LOCAL_share_request = MAX_WORKERS; PUT_IN_REQUESTABLE(worker_id); return TRUE; } }
static inline void worker_write_input_cb(EV_P_ ev_io *w, int revents, struct worker *worker, struct writeq *writeq, enum msg_type type) { int rc; if (worker->session == NULL) { printf("ERROR: worker without session!\n"); worker_stop(EV_A_ worker); return; } if ((revents & EV_ERROR)) { goto err; } rc = writeq_write(writeq, w->fd); if (rc < 0) { goto err; } else if (rc > 0) { /* disarm writes. */ ev_io_stop(EV_A_ w); return; } return; err: DEBUGF(0, "WARNING: worker pid %d input pipe fd=%d error\n", worker_pid(worker), w->fd); ev_io_stop(EV_A_ w); session_on_worker_pipe_err_cb(EV_A_ worker->session, type); }
/* スレッドの起動 (MT-unsafe) */ void launch_lmn_workers(LmnWorkerGroup *wp) { unsigned long i, core_num; core_num = workers_entried_num(wp); for (i = 0; i < core_num; i++) { /** start */ if (i == LMN_PRIMARY_ID) continue; lmn_thread_create(&worker_pid(workers_get_worker(wp, i)), lmn_worker_start, workers_get_worker(wp, i)); } if (lmn_env.profile_level >= 1) profile_start_exec(); lmn_worker_start((void *)workers_get_worker(wp, LMN_PRIMARY_ID)); if (lmn_env.profile_level >= 1) profile_finish_exec(); for (i = 0; i < core_num; i++) { if (i == LMN_PRIMARY_ID) continue; lmn_thread_join(worker_pid(workers_get_worker(wp, i))); } }
void init_workers(void) { int proc; #ifdef THREADS return; #endif NOfThreads = number_workers; #ifdef ACOW if (number_workers > 1) { int son; son = fork(); if (son == -1) Yap_Error(FATAL_ERROR, TermNil, "fork error (init_workers)"); if (son > 0) { /* I am the father, I must stay here and wait for my children to all die */ struct sigaction sigact; GLOBAL_master_worker = getpid(); sigact.sa_handler = SIG_DFL; sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_RESTART; sigaction(SIGINT, &sigact, NULL); pause(); exit(0); } else worker_pid(0) = getpid(); } #endif /* ACOW */ for (proc = 1; proc < number_workers; proc++) { int son; son = fork(); if (son == -1) Yap_Error(FATAL_ERROR, TermNil, "fork error (init_workers)"); if (son == 0) { /* new worker */ worker_id = proc; remap_memory(); break; } else worker_pid(proc) = son; } }
void worker_stop(EV_P_ struct worker *worker) { LOGF(3, "=== %d: worker stopped\n", worker_pid(worker)); if (worker->f_alive) { LOGF(1, "=== %d: worker still alive - sending SIGKILL\n", worker_pid(worker)); kill(worker_pid(worker), SIGKILL); } writeq_uninit(&worker->stdin_writeq); writeq_uninit(&worker->msgin_writeq); if (ev_is_active(&worker->child_watcher)) { ev_child_stop(EV_A_ &worker->child_watcher); } if (ev_is_active(&worker->stdin_w)) { ev_io_stop(EV_A_ &worker->stdin_w); } if (ev_is_active(&worker->stdout_w)) { ev_io_stop(EV_A_ &worker->stdout_w); } if (ev_is_active(&worker->stderr_w)) { ev_io_stop(EV_A_ &worker->stderr_w); } if (ev_is_active(&worker->msgin_w)) { ev_io_stop(EV_A_ &worker->msgin_w); } if (ev_is_active(&worker->msgout_w)) { ev_io_stop(EV_A_ &worker->msgout_w); } close(worker->stdin_w.fd); close(worker->stdout_w.fd); close(worker->stderr_w.fd); close(worker->msgin_w.fd); close(worker->msgout_w.fd); free(worker); }
static void worker_exited_cb(EV_P_ ev_child *w, int revents) { struct worker *worker = CONTAINER_OF(w, struct worker, child_watcher); LOGF(3, "=== %d: worker ended, status=%d\n", worker_pid(worker), w->rstatus); ev_child_stop(EV_A_ w); worker->f_alive = false; if (worker->session == NULL) { printf("WARNING: worker without session!\n"); return; } session_on_worker_exited_cb(EV_A_ worker->session, w->rstatus); }
static inline void worker_read_output_cb(EV_P_ ev_io *w, int revents, struct worker *worker, enum msg_type type) { struct worker_read_ctx ctx = { .session = worker->session, .type = type, }; int rc; if (worker->session == NULL) { printf("ERROR: worker without session!\n"); worker_stop(EV_A_ worker); return; } if ((revents & EV_ERROR)) { goto err; } rc = rbuf_read_chunks(EV_A_ w->fd, worker_rbuf_read_cb, &ctx); if (rc < 0) { goto err; } else if (rc > 0) { /* EOF - disarm reads. */ ev_io_stop(EV_A_ w); // session_on_worker_output_cb(EV_A_ worker->session, NULL, 0, 0, type); } return; err: DEBUGF(0, "WARNING: worker pid %d output pipe fd=%d error\n", worker_pid(worker), w->fd); ev_io_stop(EV_A_ w); session_on_worker_pipe_err_cb(EV_A_ worker->session, type); }
struct worker * worker_start(EV_P_ struct session *session) { struct worker *w; pid_t pid; int stdin_fds [2] = {-1, -1}; int stdout_fds[2] = {-1, -1}; int stderr_fds[2] = {-1, -1}; int msgin_fds [2] = {-1, -1}; int msgout_fds[2] = {-1, -1}; #if WORKER_TIMINGS uint64_t _start = now_us(); #endif if ((w = calloc(1, sizeof(*w))) == NULL) { goto fail; } w->session = session; writeq_init(&w->stdin_writeq); writeq_init(&w->msgin_writeq); if (pipe(stdin_fds ) < 0 || pipe(stdout_fds) < 0 || pipe(stderr_fds) < 0 || pipe(msgin_fds ) < 0 || pipe(msgout_fds) < 0) { LOG_ERRNO("pipe()"); goto fail; } maxfd_update(stdin_fds [0]); maxfd_update(stdin_fds [1]); maxfd_update(stdout_fds[0]); maxfd_update(stdout_fds[1]); maxfd_update(stderr_fds[0]); maxfd_update(stderr_fds[1]); maxfd_update(msgin_fds [0]); maxfd_update(msgin_fds [1]); maxfd_update(msgout_fds[0]); maxfd_update(msgout_fds[1]); pid = fork(); if (pid < 0) { LOG_ERRNO("fork()"); goto fail; } if (pid == 0) { /* child. */ if (dup2(stdin_fds [0], 0) < 0 || dup2(stdout_fds[1], 1) < 0 || dup2(stderr_fds[1], 2) < 0 || dup2(msgin_fds [0], 3) < 0 || dup2(msgout_fds[1], 4) < 0) { exit(EXIT_FAILURE); } maxfd_closeall(5); pyenv_child_after_fork(); exit(EXIT_SUCCESS); } else { /* parent. */ close(stdin_fds [0]); close(stdout_fds[1]); close(stderr_fds[1]); close(msgin_fds [0]); close(msgout_fds[1]); set_fd_nonblocking(stdin_fds [1]); set_fd_nonblocking(stdout_fds[0]); set_fd_nonblocking(stderr_fds[0]); set_fd_nonblocking(msgin_fds [1]); set_fd_nonblocking(msgout_fds[0]); ev_child_init(&w->child_watcher, worker_exited_cb, pid, 0); ev_child_start(EV_A_ &w->child_watcher); ev_io_init(&w->stdin_w , worker_write_stdin_cb, stdin_fds [1], EV_WRITE); ev_io_init(&w->stdout_w, worker_read_stdout_cb, stdout_fds[0], EV_READ); ev_io_init(&w->stderr_w, worker_read_stderr_cb, stderr_fds[0], EV_READ); ev_io_init(&w->msgin_w , worker_write_msgin_cb, msgin_fds [1], EV_WRITE); ev_io_init(&w->msgout_w, worker_read_msgout_cb, msgout_fds[0], EV_READ); ev_io_start(EV_A_ &w->stdout_w); ev_io_start(EV_A_ &w->stderr_w); ev_io_start(EV_A_ &w->msgout_w); LOGF(3, "=== %d: worker started, fds=[%d, %d, %d, %d, %d]\n", worker_pid(w), stdin_fds[1], stdout_fds[0], stderr_fds[0], msgin_fds[1], msgout_fds[0]); w->f_alive = true; } #if WORKER_TIMINGS worker_start_time += now_us() - _start; worker_start_calls++; #endif return w; fail: close(stdin_fds [0]); close(stdin_fds [1]); close(stdout_fds[0]); close(stdout_fds[1]); close(stderr_fds[0]); close(stderr_fds[1]); close(msgin_fds [0]); close(msgin_fds [1]); close(msgout_fds[0]); close(msgout_fds[1]); free(w); return NULL; }
void Yap_init_global(int max_table_size, int n_workers, int sch_loop, int delay_load) { int i; /* global data related to memory management */ #ifdef LIMIT_TABLING if (max_table_size) GLOBAL_MAX_PAGES = ((max_table_size - 1) * 1024 * 1024 / SHMMAX + 1) * SHMMAX / Yap_page_size; else GLOBAL_MAX_PAGES = -1; #endif /* LIMIT_TABLING */ INIT_PAGES(GLOBAL_PAGES_void, void *); #ifdef YAPOR INIT_PAGES(GLOBAL_PAGES_or_fr, struct or_frame); INIT_PAGES(GLOBAL_PAGES_qg_sol_fr, struct query_goal_solution_frame); INIT_PAGES(GLOBAL_PAGES_qg_ans_fr, struct query_goal_answer_frame); #endif /* YAPOR */ #ifdef TABLING_INNER_CUTS INIT_PAGES(GLOBAL_PAGES_tg_sol_fr, struct table_subgoal_solution_frame); INIT_PAGES(GLOBAL_PAGES_tg_ans_fr, struct table_subgoal_answer_frame); #endif /* TABLING_INNER_CUTS */ #ifdef TABLING #ifdef GLOBAL_TRIE INIT_PAGES(GLOBAL_PAGES_gt_node, struct global_trie_node); INIT_PAGES(GLOBAL_PAGES_gt_hash, struct global_trie_hash); #endif /* GLOBAL_TRIE */ INIT_PAGES(GLOBAL_PAGES_tab_ent, struct table_entry); INIT_PAGES(GLOBAL_PAGES_sg_fr, struct subgoal_frame); INIT_PAGES(GLOBAL_PAGES_sg_node, struct subgoal_trie_node); INIT_PAGES(GLOBAL_PAGES_ans_node, struct answer_trie_node); INIT_PAGES(GLOBAL_PAGES_sg_hash, struct subgoal_trie_hash); INIT_PAGES(GLOBAL_PAGES_ans_hash, struct answer_trie_hash); INIT_PAGES(GLOBAL_PAGES_dep_fr, struct dependency_frame); #endif /* TABLING */ #if defined(YAPOR) && defined(TABLING) INIT_PAGES(GLOBAL_PAGES_susp_fr, struct suspension_frame); #endif /* YAPOR && TABLING */ #ifdef YAPOR /* global static data */ number_workers = n_workers; worker_pid(0) = getpid(); for (i = 1; i < number_workers; i++) worker_pid(i) = 0; SCHEDULER_LOOP = sch_loop; DELAYED_RELEASE_LOAD = delay_load; /* global data related to or-performance */ GLOBAL_number_goals = 0; GLOBAL_best_times(0) = 0; GLOBAL_performance_mode = PERFORMANCE_OFF; /* global data related to or-parallelism */ BITMAP_clear(GLOBAL_bm_present_workers); for (i = 0; i < number_workers; i++) BITMAP_insert(GLOBAL_bm_present_workers, i); BITMAP_copy(GLOBAL_bm_idle_workers, GLOBAL_bm_present_workers); BITMAP_clear(GLOBAL_bm_root_cp_workers); BITMAP_clear(GLOBAL_bm_invisible_workers); BITMAP_clear(GLOBAL_bm_requestable_workers); BITMAP_clear(GLOBAL_bm_executing_workers); BITMAP_copy(GLOBAL_bm_finished_workers, GLOBAL_bm_present_workers); INIT_LOCK(GLOBAL_LOCKS_bm_idle_workers); INIT_LOCK(GLOBAL_LOCKS_bm_root_cp_workers); INIT_LOCK(GLOBAL_LOCKS_bm_invisible_workers); INIT_LOCK(GLOBAL_LOCKS_bm_requestable_workers); INIT_LOCK(GLOBAL_LOCKS_bm_executing_workers); INIT_LOCK(GLOBAL_LOCKS_bm_finished_workers); #ifdef TABLING_INNER_CUTS INIT_LOCK(GLOBAL_LOCKS_bm_pruning_workers); #endif /* TABLING_INNER_CUTS */ GLOBAL_LOCKS_who_locked_heap = MAX_WORKERS; INIT_LOCK(GLOBAL_LOCKS_heap_access); INIT_LOCK(GLOBAL_LOCKS_alloc_block); #if defined(YAPOR_ERRORS) || defined(TABLING_ERRORS) INIT_LOCK(GLOBAL_LOCKS_stderr_messages); #endif /* YAPOR_ERRORS || TABLING_ERRORS */ if (number_workers == 1) PARALLEL_EXECUTION_MODE = FALSE; else PARALLEL_EXECUTION_MODE = TRUE; #endif /* YAPOR */ #ifdef TABLING /* global data related to tabling */ GLOBAL_root_tab_ent = NULL; #ifdef GLOBAL_TRIE new_global_trie_node(GLOBAL_root_gt, 0, NULL, NULL, NULL); #endif /* GLOBAL_TRIE */ #ifdef LIMIT_TABLING GLOBAL_first_sg_fr = NULL; GLOBAL_last_sg_fr = NULL; GLOBAL_check_sg_fr = NULL; #endif /* LIMIT_TABLING */ GLOBAL_root_dep_fr = NULL; for (i = 0; i < MAX_TABLE_VARS; i++) { CELL *pt = GLOBAL_table_var_enumerator_addr(i); RESET_VARIABLE(pt); } #ifdef TABLE_LOCK_AT_WRITE_LEVEL for (i = 0; i < TABLE_LOCK_BUCKETS; i++) INIT_LOCK(GLOBAL_table_lock(i)); #endif /* TABLE_LOCK_AT_WRITE_LEVEL */ #endif /* TABLING */ return; }