1 // Copyright 2022 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 #pragma once 15 16 #include "pw_rpc/raw/server_reader_writer.h" 17 #include "pw_span/span.h" 18 #include "pw_status/status.h" 19 #include "pw_thread/config.h" 20 #include "pw_thread/thread_info.h" 21 #include "pw_thread_protos/thread.pwpb.h" 22 #include "pw_thread_protos/thread_snapshot_service.pwpb.h" 23 #include "pw_thread_protos/thread_snapshot_service.raw_rpc.pb.h" 24 25 namespace pw::thread::proto { 26 27 Status ProtoEncodeThreadInfo(pwpb::SnapshotThreadInfo::StreamEncoder& encoder, 28 const ThreadInfo& thread_info); 29 30 // Calculates encoded buffer size based on code gen constants. 31 constexpr size_t RequiredServiceBufferSize( 32 size_t num_threads = PW_THREAD_MAXIMUM_THREADS) { 33 constexpr size_t kSizeOfResponse = 34 pwpb::SnapshotThreadInfo::kMaxEncodedSizeBytes + 35 pwpb::Thread::kMaxEncodedSizeBytes; 36 return kSizeOfResponse * num_threads; 37 } 38 39 // The ThreadSnapshotService will return peak stack usage across running 40 // threads when requested by GetPeak(). 41 // 42 // Parameter encode_buffer: buffer where thread information is encoded. Size 43 // depends on RequiredBufferSize(). 44 // 45 // Parameter thread_proto_indices: array keeping track of thread boundaries in 46 // the encode buffer. The service uses these indices to send response data out 47 // in bundles. 48 // 49 // Parameter num_bundled_threads: constant describing number of threads per 50 // bundle in response. 51 class ThreadSnapshotService 52 : public pw_rpc::raw::ThreadSnapshotService::Service< 53 ThreadSnapshotService> { 54 public: 55 constexpr ThreadSnapshotService( 56 span<std::byte> encode_buffer, 57 Vector<size_t>& thread_proto_indices, 58 size_t num_bundled_threads = PW_THREAD_NUM_BUNDLED_THREADS) encode_buffer_(encode_buffer)59 : encode_buffer_(encode_buffer), 60 thread_proto_indices_(thread_proto_indices), 61 num_bundled_threads_(num_bundled_threads) {} 62 void GetPeakStackUsage(ConstByteSpan request, rpc::RawServerWriter& response); 63 64 private: 65 span<std::byte> encode_buffer_; 66 Vector<size_t>& thread_proto_indices_; 67 size_t num_bundled_threads_; 68 }; 69 70 // A ThreadSnapshotService that allocates required buffers based on the 71 // number of running threads on a device. 72 template <size_t kNumThreads = PW_THREAD_MAXIMUM_THREADS> 73 class ThreadSnapshotServiceBuffer : public ThreadSnapshotService { 74 public: ThreadSnapshotServiceBuffer()75 ThreadSnapshotServiceBuffer() 76 : ThreadSnapshotService(encode_buffer_, thread_proto_indices_) {} 77 78 private: 79 std::array<std::byte, RequiredServiceBufferSize(kNumThreads)> encode_buffer_; 80 // + 1 is needed to account for extra index that comes with the first 81 // submessage start or the last submessage end. 82 Vector<size_t, kNumThreads + 1> thread_proto_indices_; 83 }; 84 85 } // namespace pw::thread::proto 86