This way if you have a long stack, you can issue "thread backtrace --count 10" and then subsequent <Return>-s will page you through the stack. This took a little more effort than just adding the repeat command, since the GetRepeatCommand API was returning a "const char *". That meant the command had to keep the repeat string alive, which is inconvenient. The original API returned either a nullptr, or a const char *, so I changed the private API to return an llvm::Optional<std::string>. Most of the patch is propagating that change. Also, there was a little thinko in fetching the repeat command. We don't fetch repeat commands for commands that aren't being added to history, which is in general reasonable. And we don't add repeat commands to the history - also reasonable. But we do want the repeat command to be able to generate the NEXT repeat command. So I adjusted the logic in HandleCommand to work that way. Differential Revision: https://reviews.llvm.org/D119046
65 lines
1.2 KiB
C++
65 lines
1.2 KiB
C++
// This test is intended to create a situation in which two threads are stopped
|
|
// at a breakpoint and the debugger issues a step-out command.
|
|
|
|
#include "pseudo_barrier.h"
|
|
#include <thread>
|
|
|
|
pseudo_barrier_t g_barrier;
|
|
|
|
volatile int g_test = 0;
|
|
|
|
void stop_here() {
|
|
g_test += 5; // Set breakpoint here
|
|
}
|
|
|
|
void recurse_a_bit_1(int count) {
|
|
if (count == 50)
|
|
stop_here();
|
|
else
|
|
recurse_a_bit_1(++count);
|
|
}
|
|
|
|
void recurse_a_bit_2(int count) {
|
|
if (count == 50)
|
|
stop_here();
|
|
else
|
|
recurse_a_bit_2(++count);
|
|
}
|
|
|
|
void *thread_func_1() {
|
|
// Wait until both threads are running
|
|
pseudo_barrier_wait(g_barrier);
|
|
|
|
// Start the recursion:
|
|
recurse_a_bit_1(0);
|
|
|
|
// Return
|
|
return NULL;
|
|
}
|
|
|
|
void *thread_func_2() {
|
|
// Wait until both threads are running
|
|
pseudo_barrier_wait(g_barrier);
|
|
|
|
// Start the recursion:
|
|
recurse_a_bit_2(0);
|
|
|
|
// Return
|
|
return NULL;
|
|
}
|
|
|
|
int main() {
|
|
// Don't let either thread do anything until they're both ready.
|
|
pseudo_barrier_init(g_barrier, 2);
|
|
|
|
// Create two threads
|
|
std::thread thread_1(thread_func_1);
|
|
std::thread thread_2(thread_func_2);
|
|
|
|
// Wait for the threads to finish
|
|
thread_1.join();
|
|
thread_2.join();
|
|
|
|
return 0;
|
|
}
|