Added a new Host class: ReadWriteLock
This abstracts read/write locks on the current host system. It is currently backed by pthread_rwlock_t objects so it should work on all unix systems.
We also need a way to control multi-threaded access to the process through the public API when it is running. For example it isn't a good idea to try and get stack frames while the process is running. To implement this, the lldb_private::Process class now contains a ReadWriteLock member variable named m_run_lock which is used to control the public process state. The public process state represents the state of the process as the client knows it. The private is used to control the actual current process state. So the public state of the process can be stopped, yet the private state can be running when evaluating an expression for example.
Adding the read/write lock where readers are clients that want the process to stay stopped, and writers are clients that run the process, allows us to accurately control multi-threaded access to the process.
Switched the SBThread and SBFrame over to us shared pointers to the ExecutionContextRef class instead of making their own class to track this. This fixed an issue with assigning on SBFrame to another and will also centralize the code that tracks weak references to execution context objects into one location.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@154099 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index ae7f4de..ee87924 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -134,28 +134,37 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- if (process_sp->GetState() == eStateConnected)
+ Process::StopLocker stop_locker;
+
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
{
- if (stop_at_entry)
- launch_flags |= eLaunchFlagStopAtEntry;
- ProcessLaunchInfo launch_info (stdin_path,
- stdout_path,
- stderr_path,
- working_directory,
- launch_flags);
- Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
- if (exe_module)
- launch_info.SetExecutableFile(exe_module->GetFileSpec(), true);
- if (argv)
- launch_info.GetArguments().AppendArguments (argv);
- if (envp)
- launch_info.GetEnvironmentEntries ().SetArguments (envp);
- error.SetError (process_sp->Launch (launch_info));
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ if (process_sp->GetState() == eStateConnected)
+ {
+ if (stop_at_entry)
+ launch_flags |= eLaunchFlagStopAtEntry;
+ ProcessLaunchInfo launch_info (stdin_path,
+ stdout_path,
+ stderr_path,
+ working_directory,
+ launch_flags);
+ Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
+ if (exe_module)
+ launch_info.SetExecutableFile(exe_module->GetFileSpec(), true);
+ if (argv)
+ launch_info.GetArguments().AppendArguments (argv);
+ if (envp)
+ launch_info.GetEnvironmentEntries ().SetArguments (envp);
+ error.SetError (process_sp->Launch (launch_info));
+ }
+ else
+ {
+ error.SetErrorString ("must be in eStateConnected to call RemoteLaunch");
+ }
}
else
{
- error.SetErrorString ("must be in eStateConnected to call RemoteLaunch");
+ error.SetErrorString ("process is running");
}
}
else
@@ -178,16 +187,25 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- if (process_sp->GetState() == eStateConnected)
+ Process::StopLocker stop_locker;
+
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
{
- ProcessAttachInfo attach_info;
- attach_info.SetProcessID (pid);
- error.SetError (process_sp->Attach (attach_info));
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ if (process_sp->GetState() == eStateConnected)
+ {
+ ProcessAttachInfo attach_info;
+ attach_info.SetProcessID (pid);
+ error.SetError (process_sp->Attach (attach_info));
+ }
+ else
+ {
+ error.SetErrorString ("must be in eStateConnected to call RemoteAttachToProcessWithID");
+ }
}
else
{
- error.SetErrorString ("must be in eStateConnected to call RemoteAttachToProcessWithID");
+ error.SetErrorString ("process is running");
}
}
else
@@ -215,8 +233,10 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
+ Process::StopLocker stop_locker;
+
+ const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- const bool can_update = true;
num_threads = process_sp->GetThreadList().GetSize(can_update);
}
@@ -413,8 +433,10 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
+ Process::StopLocker stop_locker;
+ const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index);
+ thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, can_update);
sb_thread.SetThread (thread_sp);
}
@@ -703,7 +725,9 @@
if (process_sp)
{
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- thread_sp = process_sp->GetThreadList().FindThreadByID (tid);
+ Process::StopLocker stop_locker;
+ const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
+ thread_sp = process_sp->GetThreadList().FindThreadByID (tid, can_update);
sb_thread.SetThread (thread_sp);
}
@@ -795,10 +819,16 @@
if (process_sp)
{
- Error error;
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- bytes_read = process_sp->ReadMemory (addr, dst, dst_len, error);
- sb_error.SetError (error);
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ bytes_read = process_sp->ReadMemory (addr, dst, dst_len, sb_error.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
else
{
@@ -829,10 +859,16 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Error error;
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- bytes_read = process_sp->ReadCStringFromMemory (addr, (char *)buf, size, error);
- sb_error.SetError (error);
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ bytes_read = process_sp->ReadCStringFromMemory (addr, (char *)buf, size, sb_error.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
else
{
@@ -844,20 +880,26 @@
uint64_t
SBProcess::ReadUnsignedFromMemory (addr_t addr, uint32_t byte_size, lldb::SBError &sb_error)
{
+ uint64_t value = 0;
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Error error;
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- uint64_t value = process_sp->ReadUnsignedIntegerFromMemory (addr, byte_size, 0, error);
- sb_error.SetError (error);
- return value;
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ value = process_sp->ReadUnsignedIntegerFromMemory (addr, byte_size, 0, sb_error.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
else
{
sb_error.SetErrorString ("SBProcess is invalid");
}
- return 0;
+ return value;
}
lldb::addr_t
@@ -867,10 +909,16 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Error error;
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- ptr = process_sp->ReadPointerFromMemory (addr, error);
- sb_error.SetError (error);
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ ptr = process_sp->ReadPointerFromMemory (addr, sb_error.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
else
{
@@ -900,10 +948,16 @@
if (process_sp)
{
- Error error;
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- bytes_written = process_sp->WriteMemory (addr, src, src_len, error);
- sb_error.SetError (error);
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ bytes_written = process_sp->WriteMemory (addr, src, src_len, sb_error.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
if (log)
@@ -957,8 +1011,16 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- return process_sp->LoadImage (*sb_image_spec, sb_error.ref());
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ return process_sp->LoadImage (*sb_image_spec, sb_error.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
return LLDB_INVALID_IMAGE_TOKEN;
}
@@ -970,8 +1032,16 @@
ProcessSP process_sp(GetSP());
if (process_sp)
{
- Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- sb_error.SetError (process_sp->UnloadImage (image_token));
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
+ sb_error.SetError (process_sp->UnloadImage (image_token));
+ }
+ else
+ {
+ sb_error.SetErrorString("process is running");
+ }
}
else
sb_error.SetErrorString("invalid process");