1*61c4878aSAndroid Build Coastguard Worker // Copyright 2022 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 #include "pw_thread/thread_iteration.h" 16*61c4878aSAndroid Build Coastguard Worker 17*61c4878aSAndroid Build Coastguard Worker #include <cstddef> 18*61c4878aSAndroid Build Coastguard Worker #include <string_view> 19*61c4878aSAndroid Build Coastguard Worker 20*61c4878aSAndroid Build Coastguard Worker #include "FreeRTOS.h" 21*61c4878aSAndroid Build Coastguard Worker #include "pw_span/span.h" 22*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status.h" 23*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread_info.h" 24*61c4878aSAndroid Build Coastguard Worker #include "pw_thread_freertos/freertos_tsktcb.h" 25*61c4878aSAndroid Build Coastguard Worker #include "pw_thread_freertos/util.h" 26*61c4878aSAndroid Build Coastguard Worker #include "pw_thread_freertos_private/thread_iteration.h" 27*61c4878aSAndroid Build Coastguard Worker 28*61c4878aSAndroid Build Coastguard Worker namespace pw::thread { 29*61c4878aSAndroid Build Coastguard Worker namespace freertos { 30*61c4878aSAndroid Build Coastguard Worker StackInfoCollector(TaskHandle_t current_thread,const pw::thread::ThreadCallback & cb)31*61c4878aSAndroid Build Coastguard Workerbool StackInfoCollector(TaskHandle_t current_thread, 32*61c4878aSAndroid Build Coastguard Worker const pw::thread::ThreadCallback& cb) { 33*61c4878aSAndroid Build Coastguard Worker const tskTCB& tcb = *reinterpret_cast<tskTCB*>(current_thread); 34*61c4878aSAndroid Build Coastguard Worker ThreadInfo thread_info; 35*61c4878aSAndroid Build Coastguard Worker 36*61c4878aSAndroid Build Coastguard Worker span<const std::byte> current_name = 37*61c4878aSAndroid Build Coastguard Worker as_bytes(span(std::string_view(tcb.pcTaskName))); 38*61c4878aSAndroid Build Coastguard Worker thread_info.set_thread_name(current_name); 39*61c4878aSAndroid Build Coastguard Worker 40*61c4878aSAndroid Build Coastguard Worker thread_info.set_stack_pointer(reinterpret_cast<uintptr_t>(tcb.pxTopOfStack)); 41*61c4878aSAndroid Build Coastguard Worker 42*61c4878aSAndroid Build Coastguard Worker // Current thread stack bounds. 43*61c4878aSAndroid Build Coastguard Worker thread_info.set_stack_low_addr(reinterpret_cast<uintptr_t>(tcb.pxStack)); 44*61c4878aSAndroid Build Coastguard Worker #if configRECORD_STACK_HIGH_ADDRESS 45*61c4878aSAndroid Build Coastguard Worker thread_info.set_stack_high_addr( 46*61c4878aSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(tcb.pxEndOfStack)); 47*61c4878aSAndroid Build Coastguard Worker #if INCLUDE_uxTaskGetStackHighWaterMark 48*61c4878aSAndroid Build Coastguard Worker // Walk through the stack from start to end to measure the current peak 49*61c4878aSAndroid Build Coastguard Worker // using high-water marked stack data. 50*61c4878aSAndroid Build Coastguard Worker #if (portSTACK_GROWTH > 0) 51*61c4878aSAndroid Build Coastguard Worker thread_info.set_stack_peak_addr( 52*61c4878aSAndroid Build Coastguard Worker thread_info.stack_high_addr().value() - 53*61c4878aSAndroid Build Coastguard Worker (sizeof(StackType_t) * uxTaskGetStackHighWaterMark(current_thread))); 54*61c4878aSAndroid Build Coastguard Worker #else 55*61c4878aSAndroid Build Coastguard Worker thread_info.set_stack_peak_addr( 56*61c4878aSAndroid Build Coastguard Worker thread_info.stack_low_addr().value() + 57*61c4878aSAndroid Build Coastguard Worker (sizeof(StackType_t) * uxTaskGetStackHighWaterMark(current_thread))); 58*61c4878aSAndroid Build Coastguard Worker #endif // portSTACK_GROWTH > 0 59*61c4878aSAndroid Build Coastguard Worker #endif // INCLUDE_uxTaskGetStackHighWaterMark 60*61c4878aSAndroid Build Coastguard Worker #endif // configRECORD_STACK_HIGH_ADDRESS 61*61c4878aSAndroid Build Coastguard Worker 62*61c4878aSAndroid Build Coastguard Worker return cb(thread_info); 63*61c4878aSAndroid Build Coastguard Worker } 64*61c4878aSAndroid Build Coastguard Worker 65*61c4878aSAndroid Build Coastguard Worker } // namespace freertos 66*61c4878aSAndroid Build Coastguard Worker 67*61c4878aSAndroid Build Coastguard Worker // This will disable the scheduler. ForEachThread(const pw::thread::ThreadCallback & cb)68*61c4878aSAndroid Build Coastguard WorkerStatus ForEachThread(const pw::thread::ThreadCallback& cb) { 69*61c4878aSAndroid Build Coastguard Worker pw::thread::freertos::ThreadCallback adapter_cb = 70*61c4878aSAndroid Build Coastguard Worker [&cb](TaskHandle_t current_thread, eTaskState) -> bool { 71*61c4878aSAndroid Build Coastguard Worker return freertos::StackInfoCollector(current_thread, cb); 72*61c4878aSAndroid Build Coastguard Worker }; 73*61c4878aSAndroid Build Coastguard Worker // Suspend scheduler. 74*61c4878aSAndroid Build Coastguard Worker vTaskSuspendAll(); 75*61c4878aSAndroid Build Coastguard Worker Status status = pw::thread::freertos::ForEachThread(adapter_cb); 76*61c4878aSAndroid Build Coastguard Worker // Resume scheduler. 77*61c4878aSAndroid Build Coastguard Worker xTaskResumeAll(); 78*61c4878aSAndroid Build Coastguard Worker return status; 79*61c4878aSAndroid Build Coastguard Worker } 80*61c4878aSAndroid Build Coastguard Worker 81*61c4878aSAndroid Build Coastguard Worker } // namespace pw::thread 82