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