[Lldb-commits] [lldb] r142227 - in /lldb/trunk: include/lldb/API/SBWatchpoint.h include/lldb/Breakpoint/Watchpoint.h scripts/Python/interface/SBWatchpoint.i source/API/SBWatchpoint.cpp source/Breakpoint/Watchpoint.cpp source/Commands/CommandObjectWatchpoint.cpp source/Commands/CommandObjectWatchpoint.h source/Target/StopInfo.cpp test/functionalities/watchpoint/multiple_threads/main.cpp test/functionalities/watchpoint/watchpoint_commands/condition/

Johnny Chen johnny.chen at apple.com
Mon Oct 17 11:58:01 PDT 2011


Author: johnny
Date: Mon Oct 17 13:58:00 2011
New Revision: 142227

URL: http://llvm.org/viewvc/llvm-project?rev=142227&view=rev
Log:
Add a commnad to set a condition for a watchpoint.  Example:

    watchpoint modify -c 'global==5'

modifies the last created watchpoint so that the condition expression
is evaluated at the stop point to decide whether we should proceed with
the stopping.

Also add SBWatchpont::SetCondition(const char *condition) to set condition
programmatically.

Test cases to come later.

Added:
    lldb/trunk/test/functionalities/watchpoint/watchpoint_commands/condition/
Modified:
    lldb/trunk/include/lldb/API/SBWatchpoint.h
    lldb/trunk/include/lldb/Breakpoint/Watchpoint.h
    lldb/trunk/scripts/Python/interface/SBWatchpoint.i
    lldb/trunk/source/API/SBWatchpoint.cpp
    lldb/trunk/source/Breakpoint/Watchpoint.cpp
    lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp
    lldb/trunk/source/Commands/CommandObjectWatchpoint.h
    lldb/trunk/source/Target/StopInfo.cpp
    lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp

Modified: lldb/trunk/include/lldb/API/SBWatchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBWatchpoint.h?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBWatchpoint.h (original)
+++ lldb/trunk/include/lldb/API/SBWatchpoint.h Mon Oct 17 13:58:00 2011
@@ -63,6 +63,12 @@
     void
     SetIgnoreCount (uint32_t n);
 
+    const char *
+    GetCondition ();
+
+    void 
+    SetCondition (const char *condition);
+    
     bool
     GetDescription (lldb::SBStream &description, DescriptionLevel level);
 

Modified: lldb/trunk/include/lldb/Breakpoint/Watchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Watchpoint.h?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Watchpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Watchpoint.h Mon Oct 17 13:58:00 2011
@@ -53,6 +53,7 @@
     void        SetIgnoreCount (uint32_t n);
     void        SetWatchpointType (uint32_t type);
     bool        SetCallback (WatchpointHitCallback callback, void *callback_baton);
+    void        ClearCallback();
     void        SetDeclInfo (std::string &str);
     void        GetDescription (Stream *s, lldb::DescriptionLevel level);
     void        Dump (Stream *s) const;
@@ -60,6 +61,39 @@
     Target      &GetTarget() { return *m_target; }
     const Error &GetError() { return m_error; }
 
+    //------------------------------------------------------------------
+    /// Invoke the callback action when the watchpoint is hit.
+    ///
+    /// @param[in] context
+    ///     Described the watchpoint event.
+    ///
+    /// @return
+    ///     \b true if the target should stop at this watchpoint and \b false not.
+    //------------------------------------------------------------------
+    bool
+    InvokeCallback (StoppointCallbackContext *context);
+
+    //------------------------------------------------------------------
+    // Condition
+    //------------------------------------------------------------------
+    //------------------------------------------------------------------
+    /// Set the breakpoint's condition.
+    ///
+    /// @param[in] condition
+    ///    The condition expression to evaluate when the breakpoint is hit.
+    ///    Pass in NULL to clear the condition.
+    //------------------------------------------------------------------
+    void SetCondition (const char *condition);
+    
+    //------------------------------------------------------------------
+    /// Return a pointer to the text of the condition expression.
+    ///
+    /// @return
+    ///    A pointer to the condition expression text, or NULL if no
+    //     condition has been set.
+    //------------------------------------------------------------------
+    const char *GetConditionText () const;
+
 private:
     friend class Target;
 
@@ -78,6 +112,7 @@
     std::string m_decl_str;            // Declaration information, if any.
     Error       m_error;               // An error object describing errors creating watchpoint.
 
+    std::auto_ptr<ClangUserExpression> m_condition_ap;  // The condition to test.
 
     static lldb::break_id_t
     GetNextID();

Modified: lldb/trunk/scripts/Python/interface/SBWatchpoint.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBWatchpoint.i?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBWatchpoint.i (original)
+++ lldb/trunk/scripts/Python/interface/SBWatchpoint.i Mon Oct 17 13:58:00 2011
@@ -66,6 +66,12 @@
     void
     SetIgnoreCount (uint32_t n);
 
+    const char *
+    GetCondition ();
+
+    void 
+    SetCondition (const char *condition);
+    
     bool
     GetDescription (lldb::SBStream &description, DescriptionLevel level);
 };

Modified: lldb/trunk/source/API/SBWatchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBWatchpoint.cpp?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/source/API/SBWatchpoint.cpp (original)
+++ lldb/trunk/source/API/SBWatchpoint.cpp Mon Oct 17 13:58:00 2011
@@ -205,6 +205,27 @@
     }
 }
 
+const char *
+SBWatchpoint::GetCondition ()
+{
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+        return m_opaque_sp->GetConditionText ();
+    }
+    return NULL;
+}
+
+void
+SBWatchpoint::SetCondition (const char *condition)
+{
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
+        m_opaque_sp->SetCondition (condition);
+    }
+}
+
 bool
 SBWatchpoint::GetDescription (SBStream &description, DescriptionLevel level)
 {

Modified: lldb/trunk/source/Breakpoint/Watchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Watchpoint.cpp?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Watchpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Watchpoint.cpp Mon Oct 17 13:58:00 2011
@@ -13,7 +13,12 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Target/ThreadPlanTestCondition.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -82,16 +87,7 @@
     if (m_hit_count <= GetIgnoreCount())
         return false;
 
-    uint32_t access = 0;
-    if (m_watch_was_read)
-        access |= LLDB_WATCH_TYPE_READ;
-    if (m_watch_was_written)
-        access |= LLDB_WATCH_TYPE_WRITE;
-
-    if (m_callback)
-        return m_callback(m_callback_baton, context, GetID(), access);
-    else
-        return true;
+    return true;
 }
 
 void
@@ -124,8 +120,12 @@
               m_watch_read ? "r" : "",
               m_watch_write ? "w" : "");
 
-    if (description_level >= lldb::eDescriptionLevelFull)
-        s->Printf("\n    declare @ '%s'", m_decl_str.c_str());
+    if (description_level >= lldb::eDescriptionLevelFull) {
+        if (m_decl_str.c_str())
+            s->Printf("\n    declare @ '%s'", m_decl_str.c_str());
+        if (GetConditionText())
+            s->Printf("\n    condition = '%s'", GetConditionText());
+    }
 
     if (description_level >= lldb::eDescriptionLevelVerbose)
         if (m_callback)
@@ -184,3 +184,44 @@
 {
     m_ignore_count = n;
 }
+
+bool
+Watchpoint::InvokeCallback (StoppointCallbackContext *context)
+{
+    if (m_callback && context->is_synchronous)
+    {
+        uint32_t access = 0;
+        if (m_watch_was_read)
+            access |= LLDB_WATCH_TYPE_READ;
+        if (m_watch_was_written)
+            access |= LLDB_WATCH_TYPE_WRITE;
+        return m_callback(m_callback_baton, context, GetID(), access);
+    }
+    else
+        return true;
+}
+
+void 
+Watchpoint::SetCondition (const char *condition)
+{
+    if (condition == NULL || condition[0] == '\0')
+    {
+        if (m_condition_ap.get())
+            m_condition_ap.reset();
+    }
+    else
+    {
+        // Pass NULL for expr_prefix (no translation-unit level definitions).
+        m_condition_ap.reset(new ClangUserExpression (condition, NULL));
+    }
+}
+
+const char *
+Watchpoint::GetConditionText () const
+{
+    if (m_condition_ap.get())
+        return m_condition_ap->GetUserText();
+    else
+        return NULL;
+}
+

Modified: lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectWatchpoint.cpp Mon Oct 17 13:58:00 2011
@@ -156,18 +156,21 @@
     CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
     CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
     CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter));
+    CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter));
 
     list_command_object->SetCommandName ("watchpoint list");
     enable_command_object->SetCommandName("watchpoint enable");
     disable_command_object->SetCommandName("watchpoint disable");
     delete_command_object->SetCommandName("watchpoint delete");
     ignore_command_object->SetCommandName("watchpoint ignore");
+    modify_command_object->SetCommandName("watchpoint modify");
 
     status = LoadSubCommand ("list",       list_command_object);
     status = LoadSubCommand ("enable",     enable_command_object);
     status = LoadSubCommand ("disable",    disable_command_object);
     status = LoadSubCommand ("delete",     delete_command_object);
     status = LoadSubCommand ("ignore",     ignore_command_object);
+    status = LoadSubCommand ("modify",     modify_command_object);
 }
 
 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
@@ -693,3 +696,151 @@
     return result.Succeeded();
 }
 
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointModify::CommandOptions
+//-------------------------------------------------------------------------
+#pragma mark Modify::CommandOptions
+
+CommandObjectWatchpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
+    Options (interpreter),
+    m_condition (),
+    m_condition_passed (false)
+{
+}
+
+CommandObjectWatchpointModify::CommandOptions::~CommandOptions ()
+{
+}
+
+OptionDefinition
+CommandObjectWatchpointModify::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_ALL, false, "condition",    'c', required_argument, NULL, NULL, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
+{ 0,                false, NULL,            0 , 0,                 NULL, 0,    eArgTypeNone, NULL }
+};
+
+const OptionDefinition*
+CommandObjectWatchpointModify::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+Error
+CommandObjectWatchpointModify::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
+{
+    Error error;
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+        case 'c':
+            if (option_arg != NULL)
+                m_condition.assign (option_arg);
+            else
+                m_condition.clear();
+            m_condition_passed = true;
+            break;
+        default:
+            error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+            break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectWatchpointModify::CommandOptions::OptionParsingStarting ()
+{
+    m_condition.clear();
+    m_condition_passed = false;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointModify
+//-------------------------------------------------------------------------
+#pragma mark Modify
+
+CommandObjectWatchpointModify::CommandObjectWatchpointModify (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "watchpoint modify", 
+                   "Modify the options on a watchpoint or set of watchpoints in the executable.  "
+                   "If no watchpoint is specified, act on the last created watchpoint.  "
+                   "Passing an empty argument clears the modification.", 
+                   NULL),
+    m_options (interpreter)
+{
+    CommandArgumentEntry arg;
+    CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
+    // Add the entry for the first argument for this command to the object's arguments vector.
+    m_arguments.push_back (arg);   
+}
+
+CommandObjectWatchpointModify::~CommandObjectWatchpointModify ()
+{
+}
+
+Options *
+CommandObjectWatchpointModify::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectWatchpointModify::Execute
+(
+    Args& args,
+    CommandReturnObject &result
+)
+{
+    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+    if (!CheckTargetForWatchpointOperations(target, result))
+        return false;
+
+    Mutex::Locker locker;
+    target->GetWatchpointList().GetListMutex(locker);
+    
+    const WatchpointList &watchpoints = target->GetWatchpointList();
+
+    size_t num_watchpoints = watchpoints.GetSize();
+
+    if (num_watchpoints == 0)
+    {
+        result.AppendError("No watchpoints exist to be modified.");
+        result.SetStatus(eReturnStatusFailed);
+        return false;
+    }
+
+    if (args.GetArgumentCount() == 0)
+    {
+        WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
+        wp_sp->SetCondition(m_options.m_condition.c_str());
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        // Particular watchpoints selected; set condition on them.
+        std::vector<uint32_t> wp_ids;
+        if (!VerifyWatchpointIDs(args, wp_ids))
+        {
+            result.AppendError("Invalid watchpoints specification.");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        int count = 0;
+        const size_t size = wp_ids.size();
+        for (size_t i = 0; i < size; ++i)
+        {
+            WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
+            if (wp_sp)
+            {
+                wp_sp->SetCondition(m_options.m_condition.c_str());
+                ++count;
+            }
+        }
+        result.AppendMessageWithFormat("%d watchpoints modified.\n",count);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+
+    return result.Succeeded();
+}

Modified: lldb/trunk/source/Commands/CommandObjectWatchpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectWatchpoint.h?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectWatchpoint.h (original)
+++ lldb/trunk/source/Commands/CommandObjectWatchpoint.h Mon Oct 17 13:58:00 2011
@@ -190,6 +190,58 @@
     CommandOptions m_options;
 };
 
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointModify
+//-------------------------------------------------------------------------
+
+class CommandObjectWatchpointModify : public CommandObject
+{
+public:
+
+    CommandObjectWatchpointModify (CommandInterpreter &interpreter);
+
+    virtual
+    ~CommandObjectWatchpointModify ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandReturnObject &result);
+
+    virtual Options *
+    GetOptions ();
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions (CommandInterpreter &interpreter);
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg);
+
+        void
+        OptionParsingStarting ();
+
+        const OptionDefinition*
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        std::string m_condition;
+        bool m_condition_passed;
+    };
+
+private:
+    CommandOptions m_options;
+};
+
 } // namespace lldb_private
 
 #endif  // liblldb_CommandObjectWatchpoint_h_

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Mon Oct 17 13:58:00 2011
@@ -346,6 +346,12 @@
     ShouldStop (Event *event_ptr)
     {
         // ShouldStop() method is idempotent and should not affect hit count.
+        // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
+        // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()->
+        // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()->
+        // StopInfoWatchpoint::ShouldStop() and
+        // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()->
+        // StopInfoWatchpoint::PerformAction().
         if (m_should_stop_is_valid)
             return m_should_stop;
 
@@ -376,6 +382,118 @@
         return m_should_stop;
     }
     
+    // Perform any action that is associated with this stop.  This is done as the
+    // Event is removed from the event queue.
+    virtual void
+    PerformAction (Event *event_ptr)
+    {
+        LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+        // We're going to calculate if we should stop or not in some way during the course of
+        // this code.  Also by default we're going to stop, so set that here.
+        m_should_stop = true;
+        
+        WatchpointSP wp_sp =
+            m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue());
+        if (wp_sp)
+        {
+            StoppointCallbackContext context (event_ptr, 
+                                              &m_thread.GetProcess(), 
+                                              &m_thread, 
+                                              m_thread.GetStackFrameAtIndex(0).get(),
+                                              false);
+            bool stop_requested = wp_sp->InvokeCallback (&context);
+            // Also make sure that the callback hasn't continued the target.  
+            // If it did, when we'll set m_should_start to false and get out of here.
+            if (GetPrivateState() == eStateRunning)
+                m_should_stop = false;
+            
+            if (m_should_stop && !stop_requested)
+            {
+                // We have been vetoed.
+                m_should_stop = false;
+            }
+
+            if (m_should_stop && wp_sp->GetConditionText() != NULL)
+            {
+                // We need to make sure the user sees any parse errors in their condition, so we'll hook the
+                // constructor errors up to the debugger's Async I/O.
+                StoppointCallbackContext context (event_ptr, 
+                                                  &m_thread.GetProcess(), 
+                                                  &m_thread, 
+                                                  m_thread.GetStackFrameAtIndex(0).get(),
+                                                  false);
+                ExecutionResults result_code;
+                ValueObjectSP result_value_sp;
+                const bool discard_on_error = true;
+                Error error;
+                result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
+                                                                      eExecutionPolicyAlways,
+                                                                      discard_on_error,
+                                                                      wp_sp->GetConditionText(),
+                                                                      NULL,
+                                                                      result_value_sp,
+                                                                      error);
+                if (result_code == eExecutionCompleted)
+                {
+                    if (result_value_sp)
+                    {
+                        Scalar scalar_value;
+                        if (result_value_sp->ResolveValue (scalar_value))
+                        {
+                            if (scalar_value.ULongLong(1) == 0)
+                            {
+                                // We have been vetoed.  This takes precedence over querying
+                                // the watchpoint whether it should stop (aka ignore count and
+                                // friends).  See also StopInfoWatchpoint::ShouldStop() as well
+                                // as Process::ProcessEventData::DoOnRemoval().
+                                m_should_stop = false;
+                            }
+                            else
+                                m_should_stop = true;
+                            if (log)
+                                log->Printf("Condition successfully evaluated, result is %s.\n", 
+                                            m_should_stop ? "true" : "false");
+                        }
+                        else
+                        {
+                            m_should_stop = true;
+                            if (log)
+                                log->Printf("Failed to get an integer result from the expression.");
+                        }
+                    }
+                }
+                else
+                {
+                    Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger();
+                    StreamSP error_sp = debugger.GetAsyncErrorStream ();
+                    error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint ");
+                    wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
+                    error_sp->Printf (": \"%s\"", 
+                                      wp_sp->GetConditionText());
+                    error_sp->EOL();
+                    const char *err_str = error.AsCString("<Unknown Error>");
+                    if (log)
+                        log->Printf("Error evaluating condition: \"%s\"\n", err_str);
+
+                    error_sp->PutCString (err_str);
+                    error_sp->EOL();                       
+                    error_sp->Flush();
+                    // If the condition fails to be parsed or run, we should stop.
+                    m_should_stop = true;
+                }
+            }
+        }
+        else
+        {
+            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
+            if (log)
+                log->Printf ("Process::%s could not find watchpoint id: %lld...", __FUNCTION__, m_value);
+        }
+        if (log)
+            log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
+    }
+        
     virtual const char *
     GetDescription ()
     {

Modified: lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp?rev=142227&r1=142226&r2=142227&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp (original)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp Mon Oct 17 13:58:00 2011
@@ -30,8 +30,10 @@
         ::pthread_mutex_lock (&g_access_mutex);
 
     uint32_t old_val = g_val;
-    if (flag != 0)
+    if (flag != 0) {
+        printf("changing g_val to %d...\n", (old_val + 1));
         g_val = old_val + 1;
+    }
 
     if (flag == 0)
         ::pthread_mutex_unlock (&g_access_mutex);





More information about the lldb-commits mailing list