/** * Copyright 2017 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include /* not yet used. */ #include #include #include /* Configuration. */ #include "conf.hpp" /* Misc. */ #include "util.hpp" /* Controllers & Sensors. */ #include "interfaces.hpp" #include "pid/zone.hpp" #include "sensors/manager.hpp" /* Threads. */ #include "pid/pidthread.hpp" #include "threads/busthread.hpp" /* The YAML converted sensor list. */ extern std::map SensorConfig; /* The YAML converted PID list. */ extern std::map ZoneConfig; /* The YAML converted Zone configuration. */ extern std::map ZoneDetailsConfig; int main(int argc, char* argv[]) { int rc = 0; int c; std::string configPath = ""; while (1) { static struct option long_options[] = { {"conf", required_argument, 0, 'c'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "c:", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'c': configPath = std::string {optarg}; break; default: /* skip garbage. */ continue; } } auto ModeControlBus = sdbusplus::bus::new_default(); std::shared_ptr mgmr; std::map> zones; // Create a manger for the ModeBus because we own it. static constexpr auto modeRoot = "/xyz/openbmc_project/settings/fanctrl"; sdbusplus::server::manager::manager(ModeControlBus, modeRoot); /* * When building the sensors, if any of the dbus passive ones aren't on the * bus, it'll fail immediately. */ if (configPath.length() > 0) { try { mgmr = BuildSensorsFromConfig(configPath); zones = BuildZonesFromConfig(configPath, mgmr, ModeControlBus); } catch (const std::exception& e) { std::cerr << "Failed during building: " << e.what() << "\n"; exit(EXIT_FAILURE); /* fatal error. */ } } else { mgmr = BuildSensors(SensorConfig); zones = BuildZones(ZoneConfig, ZoneDetailsConfig, mgmr, ModeControlBus); } if (0 == zones.size()) { std::cerr << "No zones defined, exiting.\n"; return rc; } /* * All sensors are managed by one manager, but each zone has a pointer to * it. */ auto& HostSensorBus = mgmr->getHostBus(); auto& PassiveListeningBus = mgmr->getPassiveBus(); std::cerr << "Starting threads\n"; /* TODO(venture): Ask SensorManager if we have any passive sensors. */ struct ThreadParams p = { std::ref(PassiveListeningBus), "" }; std::thread l(BusThread, std::ref(p)); /* TODO(venture): Ask SensorManager if we have any host sensors. */ static constexpr auto hostBus = "xyz.openbmc_project.Hwmon.external"; struct ThreadParams e = { std::ref(HostSensorBus), hostBus }; std::thread te(BusThread, std::ref(e)); static constexpr auto modeBus = "xyz.openbmc_project.State.FanCtrl"; struct ThreadParams m = { std::ref(ModeControlBus), modeBus }; std::thread tm(BusThread, std::ref(m)); std::vector zoneThreads; /* TODO(venture): This was designed to have one thread per zone, but really * it could have one thread for all the zones and iterate through each * sequentially as it goes -- and it'd probably be fast enough to do that, * however, a system isn't likely going to have more than a couple zones. * If it only has a couple zones, then this is fine. */ for (auto& i : zones) { std::cerr << "pushing zone" << std::endl; zoneThreads.push_back(std::thread(PIDControlThread, i.second)); } l.join(); te.join(); tm.join(); for (auto& t : zoneThreads) { t.join(); } return rc; }