xref: /aosp_15_r20/external/pigweed/pw_system/system.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #define PW_LOG_MODULE_NAME "pw_system"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_system/system.h"
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker #include <utility>
20*61c4878aSAndroid Build Coastguard Worker 
21*61c4878aSAndroid Build Coastguard Worker #include "pw_allocator/best_fit.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_allocator/synchronized_allocator.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_async2/allocate_task.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_async2/pend_func_task.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h"
27*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/echo_service_pwpb.h"
28*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/interrupt_spin_lock.h"
29*61c4878aSAndroid Build Coastguard Worker #include "pw_system/config.h"
30*61c4878aSAndroid Build Coastguard Worker #include "pw_system/device_service.h"
31*61c4878aSAndroid Build Coastguard Worker #include "pw_system/file_service.h"
32*61c4878aSAndroid Build Coastguard Worker #include "pw_system/internal/async_packet_io.h"
33*61c4878aSAndroid Build Coastguard Worker #include "pw_system/log.h"
34*61c4878aSAndroid Build Coastguard Worker #include "pw_system/thread_snapshot_service.h"
35*61c4878aSAndroid Build Coastguard Worker #include "pw_system/transfer_service.h"
36*61c4878aSAndroid Build Coastguard Worker #include "pw_system/work_queue.h"
37*61c4878aSAndroid Build Coastguard Worker #include "pw_system_private/threads.h"
38*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/detached_thread.h"
39*61c4878aSAndroid Build Coastguard Worker 
40*61c4878aSAndroid Build Coastguard Worker #if PW_SYSTEM_ENABLE_CRASH_HANDLER
41*61c4878aSAndroid Build Coastguard Worker #include "pw_system/crash_handler.h"
42*61c4878aSAndroid Build Coastguard Worker #include "pw_system/crash_snapshot.h"
43*61c4878aSAndroid Build Coastguard Worker #endif  // PW_SYSTEM_ENABLE_CRASH_HANDLER
44*61c4878aSAndroid Build Coastguard Worker 
45*61c4878aSAndroid Build Coastguard Worker namespace pw {
46*61c4878aSAndroid Build Coastguard Worker 
SystemStart(channel::ByteReaderWriter & io_channel)47*61c4878aSAndroid Build Coastguard Worker void SystemStart(channel::ByteReaderWriter& io_channel) {
48*61c4878aSAndroid Build Coastguard Worker   System().Init(io_channel);
49*61c4878aSAndroid Build Coastguard Worker 
50*61c4878aSAndroid Build Coastguard Worker   system::StartScheduler();
51*61c4878aSAndroid Build Coastguard Worker }
52*61c4878aSAndroid Build Coastguard Worker 
53*61c4878aSAndroid Build Coastguard Worker namespace system {
54*61c4878aSAndroid Build Coastguard Worker namespace {
55*61c4878aSAndroid Build Coastguard Worker 
56*61c4878aSAndroid Build Coastguard Worker using pw::allocator::BestFitAllocator;
57*61c4878aSAndroid Build Coastguard Worker using pw::allocator::SynchronizedAllocator;
58*61c4878aSAndroid Build Coastguard Worker 
59*61c4878aSAndroid Build Coastguard Worker // TODO: b/349654108 - Standardize component declaration and initialization.
60*61c4878aSAndroid Build Coastguard Worker alignas(internal::PacketIO) std::byte packet_io_[sizeof(internal::PacketIO)];
61*61c4878aSAndroid Build Coastguard Worker 
InitializePacketIoGlobal(channel::ByteReaderWriter & io_channel)62*61c4878aSAndroid Build Coastguard Worker internal::PacketIO& InitializePacketIoGlobal(
63*61c4878aSAndroid Build Coastguard Worker     channel::ByteReaderWriter& io_channel) {
64*61c4878aSAndroid Build Coastguard Worker   static std::byte buffer[256];
65*61c4878aSAndroid Build Coastguard Worker   internal::PacketIO* packet_io = new (packet_io_) internal::PacketIO(
66*61c4878aSAndroid Build Coastguard Worker       io_channel, buffer, System().allocator(), System().rpc_server());
67*61c4878aSAndroid Build Coastguard Worker   return *packet_io;
68*61c4878aSAndroid Build Coastguard Worker }
69*61c4878aSAndroid Build Coastguard Worker 
70*61c4878aSAndroid Build Coastguard Worker // Functions for quickly creating a task from a function. This functions could
71*61c4878aSAndroid Build Coastguard Worker // be moved to `pw::system::AsyncCore`.
72*61c4878aSAndroid Build Coastguard Worker template <typename Func>
PostTaskFunction(Func && func)73*61c4878aSAndroid Build Coastguard Worker [[nodiscard]] bool PostTaskFunction(Func&& func) {
74*61c4878aSAndroid Build Coastguard Worker   async2::Task* task = async2::AllocateTask<async2::PendFuncTask<Func>>(
75*61c4878aSAndroid Build Coastguard Worker       System().allocator(), std::forward<Func>(func));
76*61c4878aSAndroid Build Coastguard Worker   if (task == nullptr) {
77*61c4878aSAndroid Build Coastguard Worker     return false;
78*61c4878aSAndroid Build Coastguard Worker   }
79*61c4878aSAndroid Build Coastguard Worker   System().dispatcher().Post(*task);
80*61c4878aSAndroid Build Coastguard Worker   return true;
81*61c4878aSAndroid Build Coastguard Worker }
82*61c4878aSAndroid Build Coastguard Worker 
83*61c4878aSAndroid Build Coastguard Worker template <typename Func>
PostTaskFunctionOrCrash(Func && func)84*61c4878aSAndroid Build Coastguard Worker void PostTaskFunctionOrCrash(Func&& func) {
85*61c4878aSAndroid Build Coastguard Worker   PW_CHECK(PostTaskFunction(std::forward<Func>(func)));
86*61c4878aSAndroid Build Coastguard Worker }
87*61c4878aSAndroid Build Coastguard Worker 
88*61c4878aSAndroid Build Coastguard Worker }  // namespace
89*61c4878aSAndroid Build Coastguard Worker 
dispatcher()90*61c4878aSAndroid Build Coastguard Worker async2::Dispatcher& AsyncCore::dispatcher() {
91*61c4878aSAndroid Build Coastguard Worker   static async2::Dispatcher dispatcher;
92*61c4878aSAndroid Build Coastguard Worker   return dispatcher;
93*61c4878aSAndroid Build Coastguard Worker }
94*61c4878aSAndroid Build Coastguard Worker 
allocator()95*61c4878aSAndroid Build Coastguard Worker Allocator& AsyncCore::allocator() {
96*61c4878aSAndroid Build Coastguard Worker   alignas(uintptr_t) static std::byte buffer[8192];
97*61c4878aSAndroid Build Coastguard Worker   static BestFitAllocator<> block_allocator(buffer);
98*61c4878aSAndroid Build Coastguard Worker   static SynchronizedAllocator<::pw::sync::InterruptSpinLock> sync_allocator(
99*61c4878aSAndroid Build Coastguard Worker       block_allocator);
100*61c4878aSAndroid Build Coastguard Worker   return sync_allocator;
101*61c4878aSAndroid Build Coastguard Worker }
102*61c4878aSAndroid Build Coastguard Worker 
RunOnce(Function<void ()> && function)103*61c4878aSAndroid Build Coastguard Worker bool AsyncCore::RunOnce(Function<void()>&& function) {
104*61c4878aSAndroid Build Coastguard Worker   return GetWorkQueue().PushWork(std::move(function)).ok();
105*61c4878aSAndroid Build Coastguard Worker }
106*61c4878aSAndroid Build Coastguard Worker 
Init(channel::ByteReaderWriter & io_channel)107*61c4878aSAndroid Build Coastguard Worker void AsyncCore::Init(channel::ByteReaderWriter& io_channel) {
108*61c4878aSAndroid Build Coastguard Worker #if PW_SYSTEM_ENABLE_CRASH_HANDLER
109*61c4878aSAndroid Build Coastguard Worker   RegisterCrashHandler();
110*61c4878aSAndroid Build Coastguard Worker #endif  // PW_SYSTEM_ENABLE_CRASH_HANDLER
111*61c4878aSAndroid Build Coastguard Worker 
112*61c4878aSAndroid Build Coastguard Worker   PW_LOG_INFO("Initializing pw_system");
113*61c4878aSAndroid Build Coastguard Worker 
114*61c4878aSAndroid Build Coastguard Worker #if PW_SYSTEM_ENABLE_CRASH_HANDLER
115*61c4878aSAndroid Build Coastguard Worker   if (HasCrashSnapshot()) {
116*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR("==========================");
117*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR("======CRASH DETECTED======");
118*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR("==========================");
119*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR("Crash snapshots available.");
120*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR(
121*61c4878aSAndroid Build Coastguard Worker         "Run `device.get_crash_snapshots()` to download and clear the "
122*61c4878aSAndroid Build Coastguard Worker         "snapshots.");
123*61c4878aSAndroid Build Coastguard Worker   } else {
124*61c4878aSAndroid Build Coastguard Worker     PW_LOG_DEBUG("No crash snapshot");
125*61c4878aSAndroid Build Coastguard Worker   }
126*61c4878aSAndroid Build Coastguard Worker #endif  // PW_SYSTEM_ENABLE_CRASH_HANDLER
127*61c4878aSAndroid Build Coastguard Worker 
128*61c4878aSAndroid Build Coastguard Worker   PostTaskFunctionOrCrash(InitTask);
129*61c4878aSAndroid Build Coastguard Worker 
130*61c4878aSAndroid Build Coastguard Worker   // Initialize the packet_io subsystem
131*61c4878aSAndroid Build Coastguard Worker   internal::PacketIO& packet_io = InitializePacketIoGlobal(io_channel);
132*61c4878aSAndroid Build Coastguard Worker   packet_io.Start(System().dispatcher(), RpcThreadOptions());
133*61c4878aSAndroid Build Coastguard Worker 
134*61c4878aSAndroid Build Coastguard Worker   thread::DetachedThread(DispatcherThreadOptions(),
135*61c4878aSAndroid Build Coastguard Worker                          [] { System().dispatcher().RunToCompletion(); });
136*61c4878aSAndroid Build Coastguard Worker 
137*61c4878aSAndroid Build Coastguard Worker   thread::DetachedThread(WorkQueueThreadOptions(), GetWorkQueue());
138*61c4878aSAndroid Build Coastguard Worker }
139*61c4878aSAndroid Build Coastguard Worker 
InitTask(async2::Context &)140*61c4878aSAndroid Build Coastguard Worker async2::Poll<> AsyncCore::InitTask(async2::Context&) {
141*61c4878aSAndroid Build Coastguard Worker   PW_LOG_INFO("Initializing pw_system");
142*61c4878aSAndroid Build Coastguard Worker 
143*61c4878aSAndroid Build Coastguard Worker   const Status status = GetLogThread().OpenUnrequestedLogStream(
144*61c4878aSAndroid Build Coastguard Worker       kLoggingRpcChannelId, System().rpc_server(), GetLogService());
145*61c4878aSAndroid Build Coastguard Worker   if (!status.ok()) {
146*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR("Error opening unrequested log streams %d",
147*61c4878aSAndroid Build Coastguard Worker                  static_cast<int>(status.code()));
148*61c4878aSAndroid Build Coastguard Worker   }
149*61c4878aSAndroid Build Coastguard Worker 
150*61c4878aSAndroid Build Coastguard Worker   System().rpc_server().RegisterService(GetLogService());
151*61c4878aSAndroid Build Coastguard Worker   thread::DetachedThread(system::LogThreadOptions(), GetLogThread());
152*61c4878aSAndroid Build Coastguard Worker 
153*61c4878aSAndroid Build Coastguard Worker   static rpc::EchoService echo_service;
154*61c4878aSAndroid Build Coastguard Worker   System().rpc_server().RegisterService(echo_service);
155*61c4878aSAndroid Build Coastguard Worker 
156*61c4878aSAndroid Build Coastguard Worker   RegisterDeviceService(System().rpc_server());
157*61c4878aSAndroid Build Coastguard Worker 
158*61c4878aSAndroid Build Coastguard Worker   if (PW_SYSTEM_ENABLE_THREAD_SNAPSHOT_SERVICE != 0) {
159*61c4878aSAndroid Build Coastguard Worker     RegisterThreadSnapshotService(System().rpc_server());
160*61c4878aSAndroid Build Coastguard Worker   }
161*61c4878aSAndroid Build Coastguard Worker 
162*61c4878aSAndroid Build Coastguard Worker   if (PW_SYSTEM_ENABLE_TRANSFER_SERVICE != 0) {
163*61c4878aSAndroid Build Coastguard Worker     RegisterTransferService(System().rpc_server());
164*61c4878aSAndroid Build Coastguard Worker     RegisterFileService(System().rpc_server());
165*61c4878aSAndroid Build Coastguard Worker     thread::DetachedThread(system::TransferThreadOptions(),
166*61c4878aSAndroid Build Coastguard Worker                            GetTransferThread());
167*61c4878aSAndroid Build Coastguard Worker     InitTransferService();
168*61c4878aSAndroid Build Coastguard Worker   }
169*61c4878aSAndroid Build Coastguard Worker 
170*61c4878aSAndroid Build Coastguard Worker   PW_LOG_INFO("pw_system initialization complete");
171*61c4878aSAndroid Build Coastguard Worker   return async2::Ready();
172*61c4878aSAndroid Build Coastguard Worker }
173*61c4878aSAndroid Build Coastguard Worker 
174*61c4878aSAndroid Build Coastguard Worker }  // namespace system
175*61c4878aSAndroid Build Coastguard Worker }  // namespace pw
176