13
13
#include < mutex>
14
14
15
15
// Other libraries and framework includes
16
+ #include " llvm/Support/ScopedPrinter.h"
16
17
// Project includes
17
18
#include " Plugins/Process/Utility/InferiorCallPOSIX.h"
18
19
#include " lldb/Breakpoint/BreakpointLocation.h"
@@ -4799,6 +4800,45 @@ class RestorePlanState {
4799
4800
};
4800
4801
} // anonymous namespace
4801
4802
4803
+ static microseconds
4804
+ GetOneThreadExpressionTimeout (const EvaluateExpressionOptions &options) {
4805
+ const milliseconds default_one_thread_timeout (250 );
4806
+
4807
+ // If the overall wait is forever, then we don't need to worry about it.
4808
+ if (options.GetTimeoutUsec () == 0 ) {
4809
+ if (options.GetOneThreadTimeoutUsec () != 0 )
4810
+ return microseconds (options.GetOneThreadTimeoutUsec ());
4811
+ return default_one_thread_timeout;
4812
+ }
4813
+
4814
+ // If the one thread timeout is set, use it.
4815
+ if (options.GetOneThreadTimeoutUsec () != 0 )
4816
+ return microseconds (options.GetOneThreadTimeoutUsec ());
4817
+
4818
+ // Otherwise use half the total timeout, bounded by the
4819
+ // default_one_thread_timeout.
4820
+ return std::min<microseconds>(default_one_thread_timeout,
4821
+ microseconds (options.GetTimeoutUsec ()) / 2 );
4822
+ }
4823
+
4824
+ static Timeout<std::micro>
4825
+ GetExpressionTimeout (const EvaluateExpressionOptions &options,
4826
+ bool before_first_timeout) {
4827
+ // If we are going to run all threads the whole time, or if we are only
4828
+ // going to run one thread, we can just return the overall timeout.
4829
+ if (!options.GetStopOthers () || !options.GetTryAllThreads ())
4830
+ return ConvertTimeout (microseconds (options.GetTimeoutUsec ()));
4831
+
4832
+ if (before_first_timeout)
4833
+ return GetOneThreadExpressionTimeout (options);
4834
+
4835
+ if (options.GetTimeoutUsec () == 0 )
4836
+ return llvm::None;
4837
+ else
4838
+ return microseconds (options.GetTimeoutUsec ()) -
4839
+ GetOneThreadExpressionTimeout (options);
4840
+ }
4841
+
4802
4842
ExpressionResults
4803
4843
Process::RunThreadPlan (ExecutionContext &exe_ctx,
4804
4844
lldb::ThreadPlanSP &thread_plan_sp,
@@ -4879,6 +4919,16 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
4879
4919
}
4880
4920
}
4881
4921
4922
+ // Make sure the timeout values make sense. The one thread timeout needs to be
4923
+ // smaller than the overall timeout.
4924
+ if (options.GetOneThreadTimeoutUsec () != 0 && options.GetTimeoutUsec () != 0 &&
4925
+ options.GetTimeoutUsec () < options.GetOneThreadTimeoutUsec ()) {
4926
+ diagnostic_manager.PutString (eDiagnosticSeverityError,
4927
+ " RunThreadPlan called with one thread "
4928
+ " timeout greater than total timeout" );
4929
+ return eExpressionSetupError;
4930
+ }
4931
+
4882
4932
StackID ctx_frame_id = selected_frame_sp->GetStackID ();
4883
4933
4884
4934
// N.B. Running the target may unset the currently selected thread and frame.
@@ -4985,67 +5035,20 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
4985
5035
// that we have to halt the target.
4986
5036
bool do_resume = true ;
4987
5037
bool handle_running_event = true ;
4988
- const uint64_t default_one_thread_timeout_usec = 250000 ;
4989
5038
4990
5039
// This is just for accounting:
4991
5040
uint32_t num_resumes = 0 ;
4992
5041
4993
- uint32_t timeout_usec = options.GetTimeoutUsec ();
4994
- uint32_t one_thread_timeout_usec;
4995
- uint32_t all_threads_timeout_usec = 0 ;
4996
-
4997
5042
// If we are going to run all threads the whole time, or if we are only
4998
- // going to run one thread,
4999
- // then we don't need the first timeout. So we set the final timeout, and
5000
- // pretend we are after the
5001
- // first timeout already.
5002
-
5003
- if (!options.GetStopOthers () || !options.GetTryAllThreads ()) {
5043
+ // going to run one thread, then we don't need the first timeout. So we
5044
+ // pretend we are after the first timeout already.
5045
+ if (!options.GetStopOthers () || !options.GetTryAllThreads ())
5004
5046
before_first_timeout = false ;
5005
- one_thread_timeout_usec = 0 ;
5006
- all_threads_timeout_usec = timeout_usec;
5007
- } else {
5008
- uint32_t option_one_thread_timeout = options.GetOneThreadTimeoutUsec ();
5009
-
5010
- // If the overall wait is forever, then we only need to set the one thread
5011
- // timeout:
5012
- if (timeout_usec == 0 ) {
5013
- if (option_one_thread_timeout != 0 )
5014
- one_thread_timeout_usec = option_one_thread_timeout;
5015
- else
5016
- one_thread_timeout_usec = default_one_thread_timeout_usec;
5017
- } else {
5018
- // Otherwise, if the one thread timeout is set, make sure it isn't
5019
- // longer than the overall timeout,
5020
- // and use it, otherwise use half the total timeout, bounded by the
5021
- // default_one_thread_timeout_usec.
5022
- uint64_t computed_one_thread_timeout;
5023
- if (option_one_thread_timeout != 0 ) {
5024
- if (timeout_usec < option_one_thread_timeout) {
5025
- diagnostic_manager.PutString (eDiagnosticSeverityError,
5026
- " RunThreadPlan called without one "
5027
- " thread timeout greater than total "
5028
- " timeout" );
5029
- return eExpressionSetupError;
5030
- }
5031
- computed_one_thread_timeout = option_one_thread_timeout;
5032
- } else {
5033
- computed_one_thread_timeout = timeout_usec / 2 ;
5034
- if (computed_one_thread_timeout > default_one_thread_timeout_usec)
5035
- computed_one_thread_timeout = default_one_thread_timeout_usec;
5036
- }
5037
- one_thread_timeout_usec = computed_one_thread_timeout;
5038
- all_threads_timeout_usec = timeout_usec - one_thread_timeout_usec;
5039
- }
5040
- }
5041
5047
5042
5048
if (log )
5043
- log ->Printf (
5044
- " Stop others: %u, try all: %u, before_first: %u, one thread: %" PRIu32
5045
- " - all threads: %" PRIu32 " .\n " ,
5046
- options.GetStopOthers (), options.GetTryAllThreads (),
5047
- before_first_timeout, one_thread_timeout_usec,
5048
- all_threads_timeout_usec);
5049
+ log ->Printf (" Stop others: %u, try all: %u, before_first: %u.\n " ,
5050
+ options.GetStopOthers (), options.GetTryAllThreads (),
5051
+ before_first_timeout);
5049
5052
5050
5053
// This isn't going to work if there are unfetched events on the queue.
5051
5054
// Are there cases where we might want to run the remaining events here, and
@@ -5083,8 +5086,6 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
5083
5086
// The expression evaluation should still succeed.
5084
5087
bool miss_first_event = true ;
5085
5088
#endif
5086
- std::chrono::microseconds timeout = std::chrono::microseconds (0 );
5087
-
5088
5089
while (true ) {
5089
5090
// We usually want to resume the process if we get to the top of the loop.
5090
5091
// The only exception is if we get two running events with no intervening
@@ -5178,36 +5179,21 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
5178
5179
log ->PutCString (" Process::RunThreadPlan(): waiting for next event." );
5179
5180
}
5180
5181
5181
- if (before_first_timeout) {
5182
- if (options.GetTryAllThreads ())
5183
- timeout = std::chrono::microseconds (one_thread_timeout_usec);
5184
- else
5185
- timeout = std::chrono::microseconds (timeout_usec);
5186
- } else {
5187
- if (timeout_usec == 0 )
5188
- timeout = std::chrono::microseconds (0 );
5189
- else
5190
- timeout = std::chrono::microseconds (all_threads_timeout_usec);
5191
- }
5192
-
5193
5182
do_resume = true ;
5194
5183
handle_running_event = true ;
5195
5184
5196
5185
// Now wait for the process to stop again:
5197
5186
event_sp.reset ();
5198
5187
5188
+ Timeout<std::micro> timeout =
5189
+ GetExpressionTimeout (options, before_first_timeout);
5199
5190
if (log ) {
5200
- if (timeout.count ()) {
5201
- log ->Printf (
5202
- " Process::RunThreadPlan(): about to wait - now is %llu - "
5203
- " endpoint is %llu" ,
5204
- static_cast <unsigned long long >(
5205
- std::chrono::system_clock::now ().time_since_epoch ().count ()),
5206
- static_cast <unsigned long long >(
5207
- std::chrono::time_point<std::chrono::system_clock,
5208
- std::chrono::microseconds>(timeout)
5209
- .time_since_epoch ()
5210
- .count ()));
5191
+ if (timeout) {
5192
+ auto now = system_clock::now ();
5193
+ log ->Printf (" Process::RunThreadPlan(): about to wait - now is %s - "
5194
+ " endpoint is %s" ,
5195
+ llvm::to_string (now).c_str (),
5196
+ llvm::to_string (now + *timeout).c_str ());
5211
5197
} else {
5212
5198
log ->Printf (" Process::RunThreadPlan(): about to wait forever." );
5213
5199
}
@@ -5221,7 +5207,7 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
5221
5207
got_event = false ;
5222
5208
} else
5223
5209
#endif
5224
- got_event = listener_sp->GetEvent (event_sp, ConvertTimeout ( timeout) );
5210
+ got_event = listener_sp->GetEvent (event_sp, timeout);
5225
5211
5226
5212
if (got_event) {
5227
5213
if (event_sp) {
@@ -5371,27 +5357,19 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
5371
5357
if (log ) {
5372
5358
if (options.GetTryAllThreads ()) {
5373
5359
if (before_first_timeout) {
5374
- if (timeout_usec != 0 ) {
5375
- log ->Printf (" Process::RunThreadPlan(): Running function with "
5376
- " one thread timeout timed out, "
5377
- " running for %" PRIu32
5378
- " usec with all threads enabled." ,
5379
- all_threads_timeout_usec);
5380
- } else {
5381
- log ->Printf (" Process::RunThreadPlan(): Running function with "
5382
- " one thread timeout timed out, "
5383
- " running forever with all threads enabled." );
5384
- }
5360
+ log ->Printf (" Process::RunThreadPlan(): Running function with "
5361
+ " one thread timeout timed out." );
5385
5362
} else
5386
5363
log ->Printf (" Process::RunThreadPlan(): Restarting function with "
5387
5364
" all threads enabled "
5388
- " and timeout: %u timed out, abandoning execution." ,
5389
- timeout_usec);
5365
+ " and timeout: %" PRIu64
5366
+ " timed out, abandoning execution." ,
5367
+ timeout ? timeout->count () : -1 );
5390
5368
} else
5391
5369
log ->Printf (" Process::RunThreadPlan(): Running function with "
5392
- " timeout: %u timed out, "
5370
+ " timeout: %" PRIu64 " timed out, "
5393
5371
" abandoning execution." ,
5394
- timeout_usec );
5372
+ timeout ? timeout-> count () : - 1 );
5395
5373
}
5396
5374
5397
5375
// It is possible that between the time we issued the Halt, and we get
0 commit comments