ErrorStack EnginePimpl::uninitialize_once() { LOG(INFO) << "================================================================================"; LOG(INFO) << "=================== FOEDUS ENGINE (" << describe_short() << ") EXITTING...... ================"; LOG(INFO) << "================================================================================"; if (is_master() && soc_manager_.is_initialized()) { soc_manager_.get_shared_memory_repo()->change_master_status( soc::MasterEngineStatus::kWaitingForChildTerminate); } ErrorStackBatch batch; // uninit in reverse order of initialization auto modules = get_modules(); std::reverse(modules.begin(), modules.end()); for (ModulePtr& module : modules) { if (!module.ptr_->is_initialized()) { continue; } // During uninitialization, master waits for SOCs' uninitialization before its uninit. if (is_master()) { batch.emprace_back(soc_manager_.wait_for_children_module(false, module.type_)); } batch.emprace_back(module.ptr_->uninitialize()); on_module_uninitialized(module.type_); // Then SOCs wait for master before moving on to next module. if (!is_master()) { batch.emprace_back(soc_manager_.wait_for_master_module(false, module.type_)); } } // SOC manager is special. We must uninitialize it at last. batch.emprace_back(soc_manager_.uninitialize()); // after that, we can't even set status. shared memory has been detached. return SUMMARIZE_ERROR_BATCH(batch); }
ErrorStack EnginePimpl::initialize_once() { if (is_master()) { CHECK_ERROR(check_valid_options()); } // SOC manager is special. We must initialize it first. CHECK_ERROR(soc_manager_.initialize()); on_module_initialized(kSoc); ErrorStack module_initialize_error = initialize_modules(); if (module_initialize_error.is_error()) { LOG(ERROR) << "*******************************************************************************"; LOG(ERROR) << "*** ERROR while module initailization in " << describe_short() << ". " << module_initialize_error << ""; LOG(ERROR) << "*******************************************************************************"; soc_manager_.report_engine_fatal_error(); CHECK_ERROR(module_initialize_error); } // The following can assume SOC manager is already initialized if (is_master()) { soc::SharedMemoryRepo* repo = soc_manager_.get_shared_memory_repo(); repo->change_master_status(soc::MasterEngineStatus::kRunning); // wait for children's kRunning status // TASK(Hideaki) should be a function in soc manager uint16_t soc_count = engine_->get_options().thread_.group_count_; while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); assorted::memory_fence_acq_rel(); bool error_happened = false; bool remaining = false; for (uint16_t node = 0; node < soc_count; ++node) { soc::ChildEngineStatus* status = repo->get_node_memory_anchors(node)->child_status_memory_; if (status->status_code_ == soc::ChildEngineStatus::kFatalError) { error_happened = true; break; } if (status->status_code_ == soc::ChildEngineStatus::kRunning) { continue; // ok } remaining = true; } if (error_happened) { LOG(ERROR) << "[FOEDUS] ERROR! error while waiting child kRunning"; soc_manager_.report_engine_fatal_error(); return ERROR_STACK(kErrorCodeSocChildInitFailed); } else if (!remaining) { break; } } } LOG(INFO) << "================================================================================"; LOG(INFO) << "================== FOEDUS ENGINE (" << describe_short() << ") INITIALIZATION DONE ==========="; LOG(INFO) << "================================================================================"; // In a few places, we check if we are running under valgrind and, if so, turn off // optimizations valgrind can't handle (eg hugepages). bool running_on_valgrind = RUNNING_ON_VALGRIND; if (running_on_valgrind) { LOG(INFO) << "=============== ATTENTION: VALGRIND MODE! =================="; LOG(INFO) << "This Engine is running under valgrind, which disables several optimizations"; LOG(INFO) << "If you see this message while usual execution, something is wrong."; LOG(INFO) << "=============== ATTENTION: VALGRIND MODE! =================="; } return kRetOk; }
virtual void describe(std::ostream &out) const { describe_short(out); out << std::endl; if (!_description.empty()) out << _description << std::endl; }