summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHafiz Abid Qadeer <hafiz_abid@mentor.com>2015-02-20 10:20:05 +0000
committerHafiz Abid Qadeer <hafiz_abid@mentor.com>2015-02-20 10:20:05 +0000
commit6d87a9c09e3b44a8bba2742869f5200f796c39f0 (patch)
tree58dcd9c496ae9bc98f50f448a02994647a9a2a94
parent846de99fbd2024dd8c0626408c8f3e3211b4cf0d (diff)
downloadbcm5719-llvm-6d87a9c09e3b44a8bba2742869f5200f796c39f0.tar.gz
bcm5719-llvm-6d87a9c09e3b44a8bba2742869f5200f796c39f0.zip
Reduce number of threads in lldb-mi.
LLDB-mi have 3 threads. 1. Wait for input. 2. Process commands. 3. Process events. This revision merges 1 & 2. Same thread waits on input and then process the command. This way, no synchronization is needed between first and 2nd. Also it is easy to check when to exit. A lot of code will redundant and will be cleaned up gradually. All lldb-mi tests pass with gcc and clang as test compiler. Also did minimal testing on command line and works ok. The "quit" and "-gdb-exit" command close the application without needing any further return. Reviewed in http://reviews.llvm.org/D7746. llvm-svn: 230003
-rw-r--r--lldb/tools/lldb-mi/Driver.h1
-rw-r--r--lldb/tools/lldb-mi/MICmnStreamStdin.cpp34
-rw-r--r--lldb/tools/lldb-mi/MICmnStreamStdin.h4
-rw-r--r--lldb/tools/lldb-mi/MIDriver.cpp199
-rw-r--r--lldb/tools/lldb-mi/MIDriver.h8
-rw-r--r--lldb/tools/lldb-mi/MIDriverMain.cpp13
-rw-r--r--lldb/tools/lldb-mi/MIDriverMgr.cpp16
-rw-r--r--lldb/tools/lldb-mi/MIDriverMgr.h2
8 files changed, 105 insertions, 172 deletions
diff --git a/lldb/tools/lldb-mi/Driver.h b/lldb/tools/lldb-mi/Driver.h
index 5bc97383a0c..cd9fc043ea4 100644
--- a/lldb/tools/lldb-mi/Driver.h
+++ b/lldb/tools/lldb-mi/Driver.h
@@ -64,6 +64,7 @@ class Driver : public lldb::SBBroadcaster, public CMIDriverBase, public CMIDrive
virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver);
virtual const CMIUtilString &GetDriverName(void) const;
virtual const CMIUtilString &GetDriverId(void) const;
+ virtual void DeliverSignal(int signal) {}
// Original code:
public:
diff --git a/lldb/tools/lldb-mi/MICmnStreamStdin.cpp b/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
index c57ca4408ab..76f3593732b 100644
--- a/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
+++ b/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
@@ -33,6 +33,7 @@
#else
#include "MICmnStreamStdinLinux.h"
#endif // defined( _MSC_VER )
+#include <string.h> // For std::strerror()
//++ ------------------------------------------------------------------------------------
// Details: CMICmnStreamStdin constructor.
@@ -49,6 +50,7 @@ CMICmnStreamStdin::CMICmnStreamStdin(void)
, m_bShowPrompt(true)
, m_bRedrawPrompt(true)
, m_pStdinReadHandler(nullptr)
+ , m_pCmdBuffer(nullptr)
{
}
@@ -103,6 +105,9 @@ CMICmnStreamStdin::Initialize(void)
return MIstatus::failure;
}
+ if (bOk)
+ m_pCmdBuffer = new MIchar[m_constBufferSize];
+
// Other resources required
if (bOk)
{
@@ -142,6 +147,12 @@ CMICmnStreamStdin::Shutdown(void)
ClrErrorDescription();
+ if (m_pCmdBuffer != nullptr)
+ {
+ delete[] m_pCmdBuffer;
+ m_pCmdBuffer = nullptr;
+ }
+
bool bOk = MIstatus::success;
CMIUtilString errMsg;
@@ -355,7 +366,28 @@ CMICmnStreamStdin::MonitorStdin(bool &vrwbYesAlive)
const MIchar *
CMICmnStreamStdin::ReadLine(CMIUtilString &vwErrMsg)
{
- return m_pStdinReadHandler->ReadLine(vwErrMsg);
+ vwErrMsg.clear();
+
+ // Read user input
+ const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin);
+ if (pText == nullptr)
+ {
+ if (::ferror(stdin) != 0)
+ vwErrMsg = ::strerror(errno);
+ return nullptr;
+ }
+
+ // Strip off new line characters
+ for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++)
+ {
+ if ((*pI == '\n') || (*pI == '\r'))
+ {
+ *pI = '\0';
+ break;
+ }
+ }
+
+ return pText;
}
//++ ------------------------------------------------------------------------------------
diff --git a/lldb/tools/lldb-mi/MICmnStreamStdin.h b/lldb/tools/lldb-mi/MICmnStreamStdin.h
index a6779d53166..ce81ddfb748 100644
--- a/lldb/tools/lldb-mi/MICmnStreamStdin.h
+++ b/lldb/tools/lldb-mi/MICmnStreamStdin.h
@@ -84,6 +84,7 @@ class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase,
bool SetVisitor(IStreamStdin &vrVisitor);
bool SetOSStdinHandler(IOSStdinHandler &vrHandler);
void OnExitHandler(void);
+ const MIchar *ReadLine(CMIUtilString &vwErrMsg);
// Overridden:
public:
@@ -104,7 +105,6 @@ class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase,
void operator=(const CMICmnStreamStdin &);
bool MonitorStdin(bool &vrwbYesExit);
- const MIchar *ReadLine(CMIUtilString &vwErrMsg);
bool
InputAvailable(bool &vbAvail); // Bytes are available on stdin
@@ -122,4 +122,6 @@ class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase,
bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt
bool m_bRedrawPrompt; // True = Prompt needs to be redrawn
IOSStdinHandler *m_pStdinReadHandler;
+ static const int m_constBufferSize = 2048;
+ MIchar *m_pCmdBuffer;
};
diff --git a/lldb/tools/lldb-mi/MIDriver.cpp b/lldb/tools/lldb-mi/MIDriver.cpp
index 8cd115301ad..954815817c2 100644
--- a/lldb/tools/lldb-mi/MIDriver.cpp
+++ b/lldb/tools/lldb-mi/MIDriver.cpp
@@ -500,42 +500,6 @@ CMIDriver::GetDriverIsGDBMICompatibleDriver(void) const
}
//++ ------------------------------------------------------------------------------------
-// Details: Callback function for monitoring stream stdin object. Part of the visitor
-// pattern.
-// This function is called by the CMICmnStreamStdin::CThreadStdin
-// "stdin monitor" thread (ID).
-// Type: Overridden.
-// Args: vStdInBuffer - (R) Copy of the current stdin line data.
-// vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIDriver::ReadLine(const CMIUtilString &vStdInBuffer, bool &vrwbYesExit)
-{
- // For debugging. Update prompt show stdin is working
- // printf( "%s\n", vStdInBuffer.c_str() );
- // fflush( stdout );
-
- // Special case look for the quit command here so stop monitoring stdin stream
- // So we do not go back to fgetc() and wait and hang thread on exit
- if (vStdInBuffer == "quit")
- vrwbYesExit = true;
-
- // 1. Put new line in the queue container by stdin monitor thread
- // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its
- // own thread
- const bool bOk = QueueMICommand(vStdInBuffer);
-
- // Check to see if the *this driver is shutting down (exit application)
- if (!vrwbYesExit)
- vrwbYesExit = m_bDriverIsExiting;
-
- return bOk;
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Start worker threads for the driver.
// Type: Method.
// Args: None.
@@ -551,16 +515,6 @@ CMIDriver::StartWorkerThreads(void)
// Grab the thread manager
CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance();
- // Start the stdin thread
- bOk &= m_rStdin.SetVisitor(*this);
- if (bOk && !rThreadMgr.ThreadStart<CMICmnStreamStdin>(m_rStdin))
- {
- const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE),
- CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str());
- SetErrorDescriptionn(errMsg);
- return MIstatus::failure;
- }
-
// Start the event polling thread
if (bOk && !rThreadMgr.ThreadStart<CMICmnLLDBDebugger>(m_rLldbDebugger))
{
@@ -627,11 +581,31 @@ CMIDriver::DoMainLoop(void)
// While the app is active
while (!m_bExitApp)
{
- // Poll stdin queue and dispatch
- if (!ReadStdinLineQueue())
+ CMIUtilString errorText;
+ const MIchar *pCmd = m_rStdin.ReadLine (errorText);
+ if (pCmd != nullptr)
{
- // Something went wrong
- break;
+ CMIUtilString lineText(pCmd);
+ if (!lineText.empty ())
+ {
+ if (lineText == "quit")
+ {
+ // We want to be exiting when receiving a quit command
+ m_bExitApp = true;
+ break;
+ }
+
+ bool bOk = false;
+ {
+ // Lock Mutex before processing commands so that we don't disturb an event
+ // being processed
+ CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
+ bOk = InterpretCommand(lineText);
+ }
+ // Draw prompt if desired
+ if (bOk && m_rStdin.GetEnablePrompt())
+ m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt());
+ }
}
}
@@ -648,72 +622,6 @@ CMIDriver::DoMainLoop(void)
}
//++ ------------------------------------------------------------------------------------
-// Details: *this driver sits and waits for input to the stdin line queue shared by *this
-// driver and the stdin monitor thread, it queues, *this reads, interprets and
-// reacts.
-// This function is used by the application's main thread.
-// Type: Method.
-// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIDriver::ReadStdinLineQueue(void)
-{
- // True when queue contains input
- bool bHaveInput = false;
-
- // Stores the current input line
- CMIUtilString lineText;
- {
- // Lock while we access the queue
- CMIUtilThreadLock lock(m_threadMutex);
- if (!m_queueStdinLine.empty())
- {
- lineText = m_queueStdinLine.front();
- m_queueStdinLine.pop();
- bHaveInput = !lineText.empty();
- }
- }
-
- // Process while we have input
- if (bHaveInput)
- {
- if (lineText == "quit")
- {
- // We want to be exiting when receiving a quit command
- m_bExitApp = true;
- return MIstatus::success;
- }
-
- // Process the command
- bool bOk = false;
- {
- // Lock Mutex before processing commands so that we don't disturb an event
- // that is being processed.
- CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
- bOk = InterpretCommand(lineText);
- }
-
- // Draw prompt if desired
- if (bOk && m_rStdin.GetEnablePrompt())
- m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt());
-
- // Input has been processed
- bHaveInput = false;
- }
- else
- {
- // Give resources back to the OS
- const std::chrono::milliseconds time(1);
- std::this_thread::sleep_for(time);
- }
-
- return MIstatus::success;
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Set things in motion, set state etc that brings *this driver (and the
// application) to a tidy shutdown.
// This function is used by the application's main thread.
@@ -926,42 +834,6 @@ CMIDriver::GetId(void) const
}
//++ ------------------------------------------------------------------------------------
-// Details: Inject a command into the command processing system to be interpreted as a
-// command read from stdin. The text representing the command is also written
-// out to stdout as the command did not come from via stdin.
-// Type: Method.
-// Args: vMICmd - (R) Text data representing a possible command.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIDriver::InjectMICommand(const CMIUtilString &vMICmd)
-{
- const bool bOk = m_rStdOut.WriteMIResponse(vMICmd);
-
- return bOk && QueueMICommand(vMICmd);
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Add a new command candidate to the command queue to be processed by the
-// command system.
-// Type: Method.
-// Args: vMICmd - (R) Text data representing a possible command.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIDriver::QueueMICommand(const CMIUtilString &vMICmd)
-{
- CMIUtilThreadLock lock(m_threadMutex);
- m_queueStdinLine.push(vMICmd);
-
- return MIstatus::success;
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Interpret the text data and match against current commands to see if there
// is a match. If a match then the command is issued and actioned on. The
// text data if not understood by *this driver is past on to the Fall Thru
@@ -1093,7 +965,7 @@ CMIDriver::SetExitApplicationFlag(const bool vbForceExit)
// but halt the inferior program being debugged instead
if (m_eCurrentDriverState == eDriverState_RunningDebugging)
{
- InjectMICommand("-exec-interrupt");
+ InterpretCommand("-exec-interrupt");
return;
}
@@ -1302,9 +1174,9 @@ CMIDriver::GetExecutableFileNamePathOnCmdLine(void) const
bool
CMIDriver::LocalDebugSessionStartupInjectCommands(void)
{
- const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str()));
-
- return InjectMICommand(strCmd);
+ const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols \"%s\"", m_strCmdLineArgExecuteableFileNamePath.c_str()));
+ const bool bOk = CMICmnStreamStdout::TextToStdout(strCmd);
+ return (bOk && InterpretCommand(strCmd));
}
//++ ------------------------------------------------------------------------------------
@@ -1335,3 +1207,18 @@ CMIDriver::IsDriverDebuggingArgExecutable(void) const
{
return m_bDriverDebuggingArgExecutable;
}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Gets called when lldb-mi gets a signal. Stops the process if it was SIGINT.
+//
+// Type: Method.
+// Args: signal that was delivered
+// Return: None.
+// Throws: None.
+//--
+void
+CMIDriver::DeliverSignal(int signal)
+{
+ if (signal == SIGINT && (m_eCurrentDriverState == eDriverState_RunningDebugging))
+ InterpretCommand("-exec-interrupt");
+}
diff --git a/lldb/tools/lldb-mi/MIDriver.h b/lldb/tools/lldb-mi/MIDriver.h
index dafe1bedcf0..d6ccddf8b72 100644
--- a/lldb/tools/lldb-mi/MIDriver.h
+++ b/lldb/tools/lldb-mi/MIDriver.h
@@ -51,7 +51,6 @@ class CMICmnStreamStdout;
class CMIDriver : public CMICmnBase,
public CMIDriverMgr::IDriver,
public CMIDriverBase,
- public CMICmnStreamStdin::IStreamStdin,
public MI::ISingleton<CMIDriver>
{
friend class MI::ISingleton<CMIDriver>;
@@ -101,7 +100,6 @@ class CMIDriver : public CMICmnBase,
bool WriteMessageToLog(const CMIUtilString &vMessage);
bool SetEnableFallThru(const bool vbYes);
bool GetEnableFallThru(void) const;
- bool InjectMICommand(const CMIUtilString &vMICmd);
bool HaveExecutableFileNamePathOnCmdLine(void) const;
const CMIUtilString &GetExecutableFileNamePathOnCmdLine(void) const;
@@ -128,8 +126,7 @@ class CMIDriver : public CMICmnBase,
virtual FILE *GetStderr(void) const;
virtual const CMIUtilString &GetDriverName(void) const;
virtual const CMIUtilString &GetDriverId(void) const;
- // From CMICmnStreamStdin
- virtual bool ReadLine(const CMIUtilString &vStdInBuffer, bool &vrbYesExit);
+ virtual void DeliverSignal(int signal);
// Typedefs:
private:
@@ -142,7 +139,6 @@ class CMIDriver : public CMICmnBase,
void operator=(const CMIDriver &);
lldb::SBError ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting);
- bool ReadStdinLineQueue(void);
bool DoAppQuit(void);
bool InterpretCommand(const CMIUtilString &vTextLine);
bool InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid);
@@ -152,7 +148,6 @@ class CMIDriver : public CMICmnBase,
bool StopWorkerThreads(void);
bool InitClientIDEToMIDriver(void) const;
bool InitClientIDEEclipse(void) const;
- bool QueueMICommand(const CMIUtilString &vMICmd);
bool LocalDebugSessionStartupInjectCommands(void);
// Overridden:
@@ -168,7 +163,6 @@ class CMIDriver : public CMICmnBase,
//
bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do not pass on command
CMIUtilThreadMutex m_threadMutex;
- QueueStdinLine_t m_queueStdinLine; // Producer = stdin monitor, consumer = *this driver
bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue working
void *m_handleMainThread; // *this driver is run by the main thread
CMICmnStreamStdin &m_rStdin;
diff --git a/lldb/tools/lldb-mi/MIDriverMain.cpp b/lldb/tools/lldb-mi/MIDriverMain.cpp
index 5557799d368..dd1e1d18646 100644
--- a/lldb/tools/lldb-mi/MIDriverMain.cpp
+++ b/lldb/tools/lldb-mi/MIDriverMain.cpp
@@ -132,9 +132,8 @@ sigint_handler(int vSigno)
CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGINT", vSigno));
- // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
- // Signal MI to shutdown or halt a running debug session
- CMICmnStreamStdin::Instance().SetCtrlCHit();
+ // Send signal to driver so that it can take suitable action
+ rDriverMgr.DeliverSignal (vSigno);
}
// ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
@@ -165,8 +164,8 @@ sigtstp_handler(int vSigno)
CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGTSTP", vSigno));
- // Signal MI to shutdown
- CMICmnStreamStdin::Instance().SetCtrlCHit();
+ // Send signal to driver so that it can take suitable action
+ rDriverMgr.DeliverSignal (vSigno);
}
// ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
@@ -196,8 +195,8 @@ sigcont_handler(int vSigno)
CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGCONT", vSigno));
- // Signal MI to shutdown
- CMICmnStreamStdin::Instance().SetCtrlCHit();
+ // Send signal to driver so that it can take suitable action
+ rDriverMgr.DeliverSignal (vSigno);
}
//++ ------------------------------------------------------------------------------------
diff --git a/lldb/tools/lldb-mi/MIDriverMgr.cpp b/lldb/tools/lldb-mi/MIDriverMgr.cpp
index ca900ca6e88..9ef7a4dec27 100644
--- a/lldb/tools/lldb-mi/MIDriverMgr.cpp
+++ b/lldb/tools/lldb-mi/MIDriverMgr.cpp
@@ -778,3 +778,19 @@ CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const
return pDriver;
}
+
+
+//++ ------------------------------------------------------------------------------------
+// Details: Gets called when lldb-mi gets a signal. Passed signal to current driver.
+//
+// Type: Method.
+// Args: signal that was delivered
+// Return: None.
+// Throws: None.
+//--
+void
+CMIDriverMgr::DeliverSignal(int signal)
+{
+ if (m_pDriverCurrent != nullptr)
+ m_pDriverCurrent->DeliverSignal(signal);
+}
diff --git a/lldb/tools/lldb-mi/MIDriverMgr.h b/lldb/tools/lldb-mi/MIDriverMgr.h
index 9e1e121405c..30bc9715581 100644
--- a/lldb/tools/lldb-mi/MIDriverMgr.h
+++ b/lldb/tools/lldb-mi/MIDriverMgr.h
@@ -79,6 +79,7 @@ class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr>
virtual bool GetDriverIsGDBMICompatibleDriver(void) const = 0;
virtual bool SetId(const CMIUtilString &vId) = 0;
virtual const CMIUtilString &GetId(void) const = 0;
+ virtual void DeliverSignal(int signal) = 0;
// Not part of the interface, ignore
/* dtor */ virtual ~IDriver(void) {}
@@ -106,6 +107,7 @@ class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr>
CMIUtilString DriverGetError(void) const;
CMIUtilString DriverGetName(void) const;
lldb::SBDebugger *DriverGetTheDebugger(void);
+ void DeliverSignal(int signal);
// Typedef:
private:
OpenPOWER on IntegriCloud