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