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 <bitset> 17 #include <optional> 18 19 #include "pw_span/span.h" 20 21 namespace pw::thread { 22 23 // The class ThreadInfo provides a summary of specific thread information and is 24 // used by thread iteration to dump thread info generically. 25 // 26 // Captures the following fields: 27 // stack_start_pointer 28 // stack_end_pointer 29 // stack_est_peak_pointer 30 // thread_name 31 class ThreadInfo { 32 public: 33 ThreadInfo() = default; 34 stack_low_addr()35 constexpr std::optional<uintptr_t> stack_low_addr() const { 36 return get_stack_info_ptr(kStackLowAddress); 37 } 38 set_stack_low_addr(uintptr_t val)39 void set_stack_low_addr(uintptr_t val) { 40 set_stack_info_ptr(kStackLowAddress, val); 41 } 42 clear_stack_low_addr()43 void clear_stack_low_addr() { clear_stack_info_ptr(kStackLowAddress); } 44 stack_high_addr()45 constexpr std::optional<uintptr_t> stack_high_addr() const { 46 return get_stack_info_ptr(kStackHighAddress); 47 } 48 set_stack_high_addr(uintptr_t val)49 void set_stack_high_addr(uintptr_t val) { 50 set_stack_info_ptr(kStackHighAddress, val); 51 } 52 clear_stack_high_addr()53 void clear_stack_high_addr() { clear_stack_info_ptr(kStackHighAddress); } 54 stack_pointer()55 constexpr std::optional<uintptr_t> stack_pointer() const { 56 return get_stack_info_ptr(kStackPointer); 57 } 58 set_stack_pointer(uintptr_t val)59 void set_stack_pointer(uintptr_t val) { 60 set_stack_info_ptr(kStackPointer, val); 61 } 62 clear_stack_pointer()63 void clear_stack_pointer() { clear_stack_info_ptr(kStackPointer); } 64 stack_peak_addr()65 constexpr std::optional<uintptr_t> stack_peak_addr() const { 66 return get_stack_info_ptr(kStackPeakAddress); 67 } 68 set_stack_peak_addr(uintptr_t val)69 void set_stack_peak_addr(uintptr_t val) { 70 set_stack_info_ptr(kStackPeakAddress, val); 71 } 72 clear_stack_peak_addr()73 void clear_stack_peak_addr() { clear_stack_info_ptr(kStackPeakAddress); } 74 thread_name()75 constexpr std::optional<span<const std::byte>> thread_name() const { 76 return has_value_[kThreadName] ? std::make_optional(thread_name_) 77 : std::nullopt; 78 } 79 set_thread_name(span<const std::byte> val)80 void set_thread_name(span<const std::byte> val) { 81 thread_name_ = val; 82 has_value_.set(kThreadName, true); 83 } 84 clear_thread_name()85 void clear_thread_name() { clear_stack_info_ptr(kThreadName); } 86 87 private: 88 enum ThreadInfoIndex { 89 kStackLowAddress, 90 kStackHighAddress, 91 kStackPointer, 92 kStackPeakAddress, 93 kThreadName, 94 kMaxNumMembersDoNotUse, 95 }; 96 get_stack_info_ptr(ThreadInfoIndex index)97 constexpr std::optional<uintptr_t> get_stack_info_ptr( 98 ThreadInfoIndex index) const { 99 return has_value_[index] ? std::make_optional(stack_info_ptrs_[index]) 100 : std::nullopt; 101 } 102 set_stack_info_ptr(ThreadInfoIndex index,uintptr_t val)103 void set_stack_info_ptr(ThreadInfoIndex index, uintptr_t val) { 104 stack_info_ptrs_[index] = val; 105 has_value_.set(index, true); 106 } 107 clear_stack_info_ptr(ThreadInfoIndex index)108 void clear_stack_info_ptr(ThreadInfoIndex index) { 109 has_value_.set(index, false); 110 } 111 112 std::bitset<ThreadInfoIndex::kMaxNumMembersDoNotUse> has_value_; 113 uintptr_t stack_info_ptrs_[ThreadInfoIndex::kMaxNumMembersDoNotUse]; 114 span<const std::byte> thread_name_; 115 }; 116 117 } // namespace pw::thread 118