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