Add the ability to set timeout & "run all threads" options both from the "expr" command and from
the SB API's that evaluate expressions.

<rdar://problem/12457211>


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@166062 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBExpressionOptions.cpp b/source/API/SBExpressionOptions.cpp
new file mode 100644
index 0000000..2a4b9f5
--- /dev/null
+++ b/source/API/SBExpressionOptions.cpp
@@ -0,0 +1,142 @@
+//===-- SBExpressionOptions.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBExpressionOptions.h"
+#include "lldb/API/SBStream.h"
+
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBExpressionOptions::SBExpressionOptions ()
+{
+    m_opaque_ap.reset(new EvaluateExpressionOptions());
+}
+
+SBExpressionOptions::SBExpressionOptions (bool coerce_to_id,
+                         bool unwind_on_error,
+                         bool keep_in_memory,
+                         bool run_others,
+                         DynamicValueType use_dynamic,
+                         uint32_t timeout_usec)
+{
+    m_opaque_ap.reset(new EvaluateExpressionOptions());
+    m_opaque_ap->SetCoerceToId(coerce_to_id);
+    m_opaque_ap->SetUnwindOnError(unwind_on_error);
+    m_opaque_ap->SetKeepInMemory(keep_in_memory);
+    m_opaque_ap->SetRunOthers(run_others);
+    m_opaque_ap->SetUseDynamic (use_dynamic);
+    m_opaque_ap->SetTimeoutUsec (timeout_usec);
+}
+
+SBExpressionOptions::SBExpressionOptions (const SBExpressionOptions &rhs)
+{
+    m_opaque_ap.reset(new EvaluateExpressionOptions());
+    *(m_opaque_ap.get()) = rhs.ref();
+}
+
+const SBExpressionOptions &
+SBExpressionOptions::operator = (const SBExpressionOptions &rhs)
+{
+    if (this != &rhs)
+    {
+        this->ref() = rhs.ref();
+    }
+    return *this;
+}
+
+SBExpressionOptions::~SBExpressionOptions()
+{
+}
+
+bool
+SBExpressionOptions::DoesCoerceToId () const
+{
+    return m_opaque_ap->DoesCoerceToId ();
+}
+
+void
+SBExpressionOptions::SetCoerceToId (bool coerce)
+{
+    m_opaque_ap->SetCoerceToId (coerce);
+}
+
+bool
+SBExpressionOptions::DoesUnwindOnError () const
+{
+    return m_opaque_ap->DoesUnwindOnError ();
+}
+
+void
+SBExpressionOptions::SetUnwindOnError (bool unwind)
+{
+    m_opaque_ap->SetUnwindOnError (unwind);
+}
+
+bool
+SBExpressionOptions::DoesKeepInMemory () const
+{
+    return m_opaque_ap->DoesKeepInMemory ();
+}
+
+void
+SBExpressionOptions::SetKeepInMemory (bool keep)
+{
+    m_opaque_ap->SetKeepInMemory (keep);
+}
+
+lldb::DynamicValueType
+SBExpressionOptions::GetUseDynamic () const
+{
+    return m_opaque_ap->GetUseDynamic ();
+}
+
+void
+SBExpressionOptions::SetUseDynamic (lldb::DynamicValueType dynamic)
+{
+    m_opaque_ap->SetUseDynamic (dynamic);
+}
+
+uint32_t
+SBExpressionOptions::GetTimeoutUsec () const
+{
+    return m_opaque_ap->GetTimeoutUsec ();
+}
+
+void
+SBExpressionOptions::SetTimeoutUsec (uint32_t timeout)
+{
+    m_opaque_ap->SetTimeoutUsec (timeout);
+}
+
+bool
+SBExpressionOptions::GetRunOthers () const
+{
+    return m_opaque_ap->GetRunOthers ();
+}
+
+void
+SBExpressionOptions::SetRunOthers (bool run_others)
+{
+    m_opaque_ap->SetRunOthers (run_others);
+}
+
+EvaluateExpressionOptions *
+SBExpressionOptions::get() const
+{
+    return m_opaque_ap.get();
+}
+
+EvaluateExpressionOptions &
+SBExpressionOptions::ref () const
+{
+    return *(m_opaque_ap.get());
+}
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
index b94a0ce..f89c25b 100644
--- a/source/API/SBFrame.cpp
+++ b/source/API/SBFrame.cpp
@@ -40,6 +40,7 @@
 #include "lldb/API/SBDebugger.h"
 #include "lldb/API/SBValue.h"
 #include "lldb/API/SBAddress.h"
+#include "lldb/API/SBExpressionOptions.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/API/SBSymbolContext.h"
 #include "lldb/API/SBThread.h"
@@ -1040,8 +1041,11 @@
     Target *target = exe_ctx.GetTargetPtr();
     if (frame && target)
     {
-        lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue();
-        result = EvaluateExpression (expr, use_dynamic);
+        SBExpressionOptions options;
+        lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue();
+        options.SetUseDynamic (fetch_dynamic_value);
+        options.SetUnwindOnError (true);
+        return EvaluateExpression (expr, options);
     }
     return result;
 }
@@ -1049,12 +1053,24 @@
 SBValue
 SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value)
 {
-    return EvaluateExpression (expr, fetch_dynamic_value, true);
+    SBExpressionOptions options;
+    options.SetUseDynamic (fetch_dynamic_value);
+    options.SetUnwindOnError (true);
+    return EvaluateExpression (expr, options);
 }
 
 SBValue
 SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value, bool unwind_on_error)
 {
+    SBExpressionOptions options;
+    options.SetUseDynamic (fetch_dynamic_value);
+    options.SetUnwindOnError (unwind_on_error);
+    return EvaluateExpression (expr, options);
+}
+
+lldb::SBValue
+SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &options)
+{
     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
     
     LogSP expr_log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1080,16 +1096,12 @@
             StreamString frame_description;
             frame->DumpUsingSettingsFormat (&frame_description);
             Host::SetCrashDescriptionWithFormat ("SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value = %u) %s",
-                                                 expr, fetch_dynamic_value, frame_description.GetString().c_str());
+                                                 expr, options.GetUseDynamic(), frame_description.GetString().c_str());
 #endif
-            Target::EvaluateExpressionOptions options;
-            options.SetUnwindOnError(unwind_on_error)
-            .SetUseDynamic(fetch_dynamic_value);
-            
             exe_results = target->EvaluateExpression (expr, 
                                                       frame,
                                                       expr_value_sp,
-                                                      options);
+                                                      options.ref());
             expr_result.SetSP(expr_value_sp);
 #ifdef LLDB_CONFIGURATION_DEBUG
             Host::SetCrashDescription (NULL);
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index 913a447..0aa01a6 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -40,11 +40,12 @@
 #include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
 
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBExpressionOptions.h"
+#include "lldb/API/SBFrame.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBTarget.h"
 #include "lldb/API/SBThread.h"
-#include "lldb/API/SBFrame.h"
-#include "lldb/API/SBDebugger.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -694,9 +695,12 @@
     if (log)
     {
         if (new_value_sp)
-            log->Printf ("SBValue(%p)::CreateChildAtOffset => \"%s\"", value_sp.get(), new_value_sp->GetName().AsCString());
+            log->Printf ("SBValue(%p)::CreateChildAtOffset => \"%s\"",
+                         value_sp.get(),
+                         new_value_sp->GetName().AsCString());
         else
-            log->Printf ("SBValue(%p)::CreateChildAtOffset => NULL", value_sp.get());
+            log->Printf ("SBValue(%p)::CreateChildAtOffset => NULL",
+                         value_sp.get());
     }
     return sb_value;
 }
@@ -715,6 +719,14 @@
 lldb::SBValue
 SBValue::CreateValueFromExpression (const char *name, const char* expression)
 {
+    SBExpressionOptions options;
+    options.SetKeepInMemory(true);
+    return CreateValueFromExpression (name, expression, options);
+}
+
+lldb::SBValue
+SBValue::CreateValueFromExpression (const char *name, const char *expression, SBExpressionOptions &options)
+{
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
     lldb::SBValue sb_value;
     lldb::ValueObjectSP value_sp(GetSP());
@@ -734,12 +746,11 @@
             Target* target = exe_ctx.GetTargetPtr();
             if (target)
             {
-                Target::EvaluateExpressionOptions options;
                 options.SetKeepInMemory(true);
                 target->EvaluateExpression (expression,
                                             exe_ctx.GetFramePtr(),
                                             new_value_sp,
-                                            options);
+                                            options.ref());
                 if (new_value_sp)
                 {
                     new_value_sp->SetName(ConstString(name));
@@ -1617,7 +1628,9 @@
     }
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
     if (log)
-        log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", value_sp.get(), (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"), addr.GetOffset());
+        log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", value_sp.get(),
+                     (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"),
+                     addr.GetOffset());
     return SBAddress(new Address(addr));
 }
 
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index 23c9dc1..ee05360 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -50,7 +50,9 @@
 OptionDefinition
 CommandObjectExpression::CommandOptions::g_option_table[] =
 {
+    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads",        'a', required_argument, NULL, 0, eArgTypeBoolean,    "Should we run all threads if the execution doesn't complete on one thread."},
     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "dynamic-value",      'd', required_argument, NULL, 0, eArgTypeBoolean,    "Upcast the value resulting from the expression to its dynamic type if available."},
+    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout",            't', required_argument, NULL, 0, eArgTypeUnsignedInteger,  "Timeout value for running the expression."},
     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error",    'u', required_argument, NULL, 0, eArgTypeBoolean,    "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
     { LLDB_OPT_SET_2                 , false, "object-description", 'o', no_argument,       NULL, 0, eArgTypeNone,       "Print the object description of the value resulting from the expression."},
 };
@@ -80,8 +82,16 @@
       //}
       //break;
 
-    case 'o':
-        print_object = true;
+    case 'a':
+        {
+            bool success;
+            bool result;
+            result = Args::StringToBoolean(option_arg, true, &success);
+            if (!success)
+                error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
+            else
+                try_all_threads = result;
+        }
         break;
         
     case 'd':
@@ -101,6 +111,22 @@
         }
         break;
         
+    case 'o':
+        print_object = true;
+        break;
+        
+    case 't':
+        {
+            bool success;
+            uint32_t result;
+            result = Args::StringToUInt32(option_arg, 0, 0, &success);
+            if (success)
+                timeout = result;
+            else
+                error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
+        }
+        break;
+        
     case 'u':
         {
             bool success;
@@ -125,6 +151,8 @@
     unwind_on_error = true;
     show_types = true;
     show_summary = true;
+    try_all_threads = true;
+    timeout = 0;
 }
 
 const OptionDefinition*
@@ -146,7 +174,13 @@
     m_expr_lines ()
 {
   SetHelpLong(
-"Examples: \n\
+"Timeouts:\n\
+    If the expression can be evaluated statically (without runnning code) then it will be.\n\
+    Otherwise, by default the expression will run on the current thread with a short timeout:\n\
+    currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted\n\
+    and resumed with all threads running.  You can use the -a option to disable retrying on all\n\
+    threads.  You can use the -t option to set a shorter timeout.\n\
+Examples: \n\
 \n\
    expr my_struct->a = my_array[3] \n\
    expr -f bin -- (index * 8) + 5 \n\
@@ -298,12 +332,13 @@
             break;
         }
         
-        Target::EvaluateExpressionOptions options;
+        EvaluateExpressionOptions options;
         options.SetCoerceToId(m_command_options.print_object)
         .SetUnwindOnError(m_command_options.unwind_on_error)
         .SetKeepInMemory(keep_in_memory)
         .SetUseDynamic(use_dynamic)
-        .SetSingleThreadTimeoutUsec(0);
+        .SetRunOthers(m_command_options.try_all_threads)
+        .SetTimeoutUsec(m_command_options.timeout);
         
         exe_results = target->EvaluateExpression (expr, 
                                                   m_interpreter.GetExecutionContext().GetFramePtr(),
diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h
index 7c15aa1..4ccadfc 100644
--- a/source/Commands/CommandObjectExpression.h
+++ b/source/Commands/CommandObjectExpression.h
@@ -55,6 +55,8 @@
         bool        unwind_on_error;
         bool        show_types;
         bool        show_summary;
+        uint32_t    timeout;
+        bool        try_all_threads;
     };
 
     CommandObjectExpression (CommandInterpreter &interpreter);
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index 8c2be37..0547d38 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -1314,7 +1314,7 @@
         if (command && command[0] != '\0')
         {
             Target *target = exe_ctx.GetTargetPtr();
-            Target::EvaluateExpressionOptions options;
+            EvaluateExpressionOptions options;
 
             options.SetUnwindOnError(true);
             options.SetUseDynamic(eNoDynamicValues);
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index 8a74471..63275f9 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -1234,11 +1234,12 @@
         }
 
         // Use expression evaluation to arrive at the address to watch.
-        Target::EvaluateExpressionOptions options;
+        EvaluateExpressionOptions options;
         options.SetCoerceToId(false)
         .SetUnwindOnError(true)
         .SetKeepInMemory(false)
-        .SetSingleThreadTimeoutUsec(0);
+        .SetRunOthers(true)
+        .SetTimeoutUsec(0);
         
         ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 
                                                                    frame, 
diff --git a/source/Core/CXXFormatterFunctions.cpp b/source/Core/CXXFormatterFunctions.cpp
index d8b929e..67f7698 100644
--- a/source/Core/CXXFormatterFunctions.cpp
+++ b/source/Core/CXXFormatterFunctions.cpp
@@ -47,7 +47,7 @@
     if (!target || !stack_frame)
         return false;
     
-    Target::EvaluateExpressionOptions options;
+    EvaluateExpressionOptions options;
     options.SetCoerceToId(false)
     .SetUnwindOnError(true)
     .SetKeepInMemory(true)
@@ -85,7 +85,7 @@
     if (!target || !stack_frame)
         return valobj_sp;
     
-    Target::EvaluateExpressionOptions options;
+    EvaluateExpressionOptions options;
     options.SetCoerceToId(false)
     .SetUnwindOnError(true)
     .SetKeepInMemory(true)
@@ -122,7 +122,7 @@
     if (!target || !stack_frame)
         return valobj_sp;
     
-    Target::EvaluateExpressionOptions options;
+    EvaluateExpressionOptions options;
     options.SetCoerceToId(false)
     .SetUnwindOnError(true)
     .SetKeepInMemory(true)
@@ -459,7 +459,7 @@
         if (!target || !stack_frame)
             return false;
         
-        Target::EvaluateExpressionOptions options;
+        EvaluateExpressionOptions options;
         options.SetCoerceToId(false)
         .SetUnwindOnError(true)
         .SetKeepInMemory(true)
@@ -1055,7 +1055,7 @@
     object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
     lldb::ValueObjectSP child_sp;
     m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
-                                                Target::EvaluateExpressionOptions().SetKeepInMemory(true));
+                                                EvaluateExpressionOptions().SetKeepInMemory(true));
     if (child_sp)
         child_sp->SetName(ConstString(idx_name.GetData()));
     return child_sp;
diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp
index 62e4e8a..1909dc2 100644
--- a/source/Expression/ClangFunction.cpp
+++ b/source/Expression/ClangFunction.cpp
@@ -485,13 +485,13 @@
 ClangFunction::ExecuteFunction(
         ExecutionContext &exe_ctx, 
         Stream &errors, 
-        uint32_t single_thread_timeout_usec, 
+        uint32_t timeout_usec, 
         bool try_all_threads, 
         Value &results)
 {
     const bool stop_others = true;
     const bool discard_on_error = true;
-    return ExecuteFunction (exe_ctx, NULL, errors, stop_others, single_thread_timeout_usec, 
+    return ExecuteFunction (exe_ctx, NULL, errors, stop_others, timeout_usec,
                             try_all_threads, discard_on_error, results);
 }
 
@@ -504,7 +504,7 @@
         bool stop_others,
         bool try_all_threads,
         bool discard_on_error,
-        uint32_t single_thread_timeout_usec,
+        uint32_t timeout_usec,
         Stream &errors,
         lldb::addr_t *this_arg)
 {
@@ -529,7 +529,7 @@
                                                                       stop_others, 
                                                                       try_all_threads, 
                                                                       discard_on_error,
-                                                                      single_thread_timeout_usec, 
+                                                                      timeout_usec,
                                                                       errors);
     
     if (exe_ctx.GetProcessPtr())
@@ -544,7 +544,7 @@
         lldb::addr_t *args_addr_ptr, 
         Stream &errors, 
         bool stop_others, 
-        uint32_t single_thread_timeout_usec, 
+        uint32_t timeout_usec, 
         bool try_all_threads,
         bool discard_on_error, 
         Value &results)
@@ -574,7 +574,7 @@
                                                    stop_others, 
                                                    try_all_threads, 
                                                    discard_on_error, 
-                                                   single_thread_timeout_usec, 
+                                                   timeout_usec, 
                                                    errors);
 
     if (args_addr_ptr != NULL)
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index c037d02..4507282 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -544,7 +544,8 @@
                               bool discard_on_error,
                               ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
                               lldb::ClangExpressionVariableSP &result,
-                              uint32_t single_thread_timeout_usec)
+                              bool run_others,
+                              uint32_t timeout_usec)
 {
     // The expression log is quite verbose, and if you're just tracking the execution of the
     // expression, it's quite convenient to have these logs come out with the STEP log as well.
@@ -594,7 +595,7 @@
                                                                                    stop_others, 
                                                                                    try_all_threads, 
                                                                                    discard_on_error,
-                                                                                   single_thread_timeout_usec, 
+                                                                                   timeout_usec, 
                                                                                    error_stream);
         
         if (exe_ctx.GetProcessPtr())
@@ -655,10 +656,21 @@
                                const char *expr_cstr,
                                const char *expr_prefix,
                                lldb::ValueObjectSP &result_valobj_sp,
-                               uint32_t single_thread_timeout_usec)
+                               bool run_others,
+                               uint32_t timeout_usec)
 {
     Error error;
-    return EvaluateWithError (exe_ctx, execution_policy, language, desired_type, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error, single_thread_timeout_usec);
+    return EvaluateWithError (exe_ctx,
+                              execution_policy,
+                              language,
+                              desired_type,
+                              discard_on_error,
+                              expr_cstr,
+                              expr_prefix,
+                              result_valobj_sp,
+                              error,
+                              run_others,
+                              timeout_usec);
 }
 
 ExecutionResults
@@ -671,7 +683,8 @@
                                         const char *expr_prefix,
                                         lldb::ValueObjectSP &result_valobj_sp,
                                         Error &error,
-                                        uint32_t single_thread_timeout_usec)
+                                        bool run_others,
+                                        uint32_t timeout_usec)
 {
     lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
 
@@ -747,7 +760,8 @@
                                                              discard_on_error,
                                                              user_expression_sp, 
                                                              expr_result,
-                                                             single_thread_timeout_usec);
+                                                             run_others,
+                                                             timeout_usec);
             
             if (execution_results != eExecutionCompleted)
             {
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index 453004d..461f821 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -1308,11 +1308,12 @@
                 {
                     ValueObjectSP expr_result_valobj_sp;
                     
-                    Target::EvaluateExpressionOptions options;
+                    EvaluateExpressionOptions options;
                     options.SetCoerceToId(false)
                     .SetUnwindOnError(true)
                     .SetKeepInMemory(false)
-                    .SetSingleThreadTimeoutUsec(0);
+                    .SetRunOthers(true)
+                    .SetTimeoutUsec(0);
                     
                     ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 
                                                                                exe_ctx.GetFramePtr(),
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 4d634f4..040058b 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -50,7 +50,7 @@
             const bool stop_other_threads = true;
             const bool discard_on_error = true;
             const bool try_all_threads = true;
-            const uint32_t single_thread_timeout_usec = 500000;
+            const uint32_t timeout_usec = 500000;
 
             addr_t prot_arg, flags_arg = 0;
             if (prot == eMmapProtNone)
@@ -105,7 +105,7 @@
                                                                           stop_other_threads,
                                                                           try_all_threads,
                                                                           discard_on_error,
-                                                                          single_thread_timeout_usec,
+                                                                          timeout_usec,
                                                                           error_strm);
                         if (result == eExecutionCompleted)
                         {
@@ -154,7 +154,7 @@
            const bool stop_other_threads = true;
            const bool discard_on_error = true;
            const bool try_all_threads = true;
-           const uint32_t single_thread_timeout_usec = 500000;
+           const uint32_t timeout_usec = 500000;
            
            AddressRange munmap_range;
            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
@@ -183,7 +183,7 @@
                                                                          stop_other_threads,
                                                                          try_all_threads,
                                                                          discard_on_error,
-                                                                         single_thread_timeout_usec,
+                                                                         timeout_usec,
                                                                          error_strm);
                        if (result == eExecutionCompleted)
                        {
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 3b37796..e77a898 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -4133,9 +4133,9 @@
 Process::RunThreadPlan (ExecutionContext &exe_ctx,
                         lldb::ThreadPlanSP &thread_plan_sp,
                         bool stop_others,
-                        bool try_all_threads,
+                        bool run_others,
                         bool discard_on_error,
-                        uint32_t single_thread_timeout_usec,
+                        uint32_t timeout_usec,
                         Stream &errors)
 {
     ExecutionResults return_value = eExecutionSetupError;
@@ -4260,6 +4260,8 @@
         
         bool first_timeout = true;
         bool do_resume = true;
+        const uint64_t default_one_thread_timeout_usec = 250000;
+        uint64_t computed_timeout = 0;
         
         while (1)
         {
@@ -4298,9 +4300,12 @@
                 if (stop_state != eStateRunning)
                 {
                     if (log)
-                        log->Printf("Process::RunThreadPlan(): didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
+                        log->Printf("Process::RunThreadPlan(): didn't get running event after "
+                                    "initial resume, got %s instead.",
+                                    StateAsCString(stop_state));
 
-                    errors.Printf("Didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
+                    errors.Printf("Didn't get running event after initial resume, got %s instead.",
+                                  StateAsCString(stop_state));
                     return_value = eExecutionSetupError;
                     break;
                 }
@@ -4313,28 +4318,45 @@
                 // We set the timeout AFTER the resume, since the resume takes some time and we
                 // don't want to charge that to the timeout.
                 
-                if (single_thread_timeout_usec != 0)
+                if (first_timeout)
+                {
+                    if (run_others)
+                    {
+                        // If we are running all threads then we take half the time to run all threads, bounded by
+                        // .25 sec.
+                        if (timeout_usec == 0)
+                            computed_timeout = default_one_thread_timeout_usec;
+                        else
+                        {
+                            computed_timeout = timeout_usec / 2;
+                            if (computed_timeout > default_one_thread_timeout_usec)
+                            {
+                                computed_timeout = default_one_thread_timeout_usec;
+                            }
+                            timeout_usec -= computed_timeout;
+                        }
+                    }
+                    else
+                    {
+                        computed_timeout = timeout_usec;
+                    }
+                }
+                else
+                {
+                    computed_timeout = timeout_usec;
+                }
+                
+                if (computed_timeout != 0)
                 {
                     // we have a > 0 timeout, let us set it so that we stop after the deadline
                     real_timeout = TimeValue::Now();
-                    real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
+                    real_timeout.OffsetWithMicroSeconds(computed_timeout);
                         
                     timeout_ptr = &real_timeout;
                 }
-                else if (first_timeout)
-                {
-                    // if we are willing to wait "forever" we still need to have an initial timeout
-                    // this timeout is going to induce all threads to run when hit. we do this so that
-                    // we can avoid ending locked up because of multithreaded contention issues
-                    real_timeout = TimeValue::Now();
-                    real_timeout.OffsetWithNanoSeconds(500000000UL);
-                    timeout_ptr = &real_timeout;
-                }
                 else
                 {
-                    timeout_ptr = NULL; // if we are in a no-timeout scenario, then we only need a fake timeout the first time through
-                    // at this point in the code, all threads will be running so we are willing to wait forever, and do not
-                    // need a timeout
+                    timeout_ptr = NULL;
                 }
             }
             else
@@ -4471,21 +4493,21 @@
                 // Not really sure what to do if Halt fails here...
                 
                 if (log) {
-                    if (try_all_threads)
+                    if (run_others)
                     {
                         if (first_timeout)
-                            log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
-                                         "trying with all threads enabled.",
-                                         single_thread_timeout_usec);
+                            log->Printf ("Process::RunThreadPlan(): Running function with timeout: %lld timed out, "
+                                         "trying  for %d usec with all threads enabled.",
+                                         computed_timeout, timeout_usec);
                         else
                             log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
-                                         "and timeout: %d timed out.",
-                                         single_thread_timeout_usec);
+                                         "and timeout: %d timed out, abandoning execution.",
+                                         timeout_usec);
                     }
                     else
                         log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
-                                     "halt and abandoning execution.", 
-                                     single_thread_timeout_usec);
+                                     "abandoning execution.", 
+                                     timeout_usec);
                 }
                 
                 Error halt_error = Halt();
@@ -4526,7 +4548,7 @@
                                 break;
                             }
 
-                            if (!try_all_threads)
+                            if (!run_others)
                             {
                                 if (log)
                                     log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 8a89687..0dd3463 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -1747,7 +1747,8 @@
                                                                expr_cstr, 
                                                                prefix, 
                                                                result_valobj_sp,
-                                                               options.GetSingleThreadTimeoutUsec());
+                                                               options.GetRunOthers(),
+                                                               options.GetTimeoutUsec());
         }
     }