//===-- ThreadList.cpp ------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>

#include <algorithm>

#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConvertEnum.h"

using namespace lldb;
using namespace lldb_private;

ThreadList::ThreadList (Process *process) :
    ThreadCollection(),
    m_process (process),
    m_stop_id (0),
    m_selected_tid (LLDB_INVALID_THREAD_ID)
{
}

ThreadList::ThreadList (const ThreadList &rhs) :
    ThreadCollection(),
    m_process (rhs.m_process),
    m_stop_id (rhs.m_stop_id),
    m_selected_tid ()
{
    // Use the assignment operator since it uses the mutex
    *this = rhs;
}

const ThreadList&
ThreadList::operator = (const ThreadList& rhs)
{
    if (this != &rhs)
    {
        // Lock both mutexes to make sure neither side changes anyone on us
        // while the assignement occurs
        Mutex::Locker locker(GetMutex());
        m_process = rhs.m_process;
        m_stop_id = rhs.m_stop_id;
        m_threads = rhs.m_threads;
        m_selected_tid = rhs.m_selected_tid;
    }
    return *this;
}


ThreadList::~ThreadList()
{
    // Clear the thread list. Clear will take the mutex lock
    // which will ensure that if anyone is using the list
    // they won't get it removed while using it.
    Clear();
}


uint32_t
ThreadList::GetStopID () const
{
    return m_stop_id;
}

void
ThreadList::SetStopID (uint32_t stop_id)
{
    m_stop_id = stop_id;
}

uint32_t
ThreadList::GetSize (bool can_update)
{
    Mutex::Locker locker(GetMutex());
    if (can_update)
        m_process->UpdateThreadListIfNeeded();
    return m_threads.size();
}

ThreadSP
ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update)
{
    Mutex::Locker locker(GetMutex());
    if (can_update)
        m_process->UpdateThreadListIfNeeded();

    ThreadSP thread_sp;
    if (idx < m_threads.size())
        thread_sp = m_threads[idx];
    return thread_sp;
}

ThreadSP
ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update)
{
    Mutex::Locker locker(GetMutex());

    if (can_update)
        m_process->UpdateThreadListIfNeeded();

    ThreadSP thread_sp;
    uint32_t idx = 0;
    const uint32_t num_threads = m_threads.size();
    for (idx = 0; idx < num_threads; ++idx)
    {
        if (m_threads[idx]->GetID() == tid)
        {
            thread_sp = m_threads[idx];
            break;
        }
    }
    return thread_sp;
}

ThreadSP
ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update)
{
    Mutex::Locker locker(GetMutex());
    
    if (can_update)
        m_process->UpdateThreadListIfNeeded();
    
    ThreadSP thread_sp;
    uint32_t idx = 0;
    const uint32_t num_threads = m_threads.size();
    for (idx = 0; idx < num_threads; ++idx)
    {
        if (m_threads[idx]->GetProtocolID() == tid)
        {
            thread_sp = m_threads[idx];
            break;
        }
    }
    return thread_sp;
}


ThreadSP
ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update)
{
    Mutex::Locker locker(GetMutex());
    
    if (can_update)
        m_process->UpdateThreadListIfNeeded();
    
    ThreadSP thread_sp;
    uint32_t idx = 0;
    const uint32_t num_threads = m_threads.size();
    for (idx = 0; idx < num_threads; ++idx)
    {
        if (m_threads[idx]->GetID() == tid)
        {
            thread_sp = m_threads[idx];
            m_threads.erase(m_threads.begin()+idx);
            break;
        }
    }
    return thread_sp;
}

ThreadSP
ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update)
{
    Mutex::Locker locker(GetMutex());
    
    if (can_update)
        m_process->UpdateThreadListIfNeeded();
    
    ThreadSP thread_sp;
    uint32_t idx = 0;
    const uint32_t num_threads = m_threads.size();
    for (idx = 0; idx < num_threads; ++idx)
    {
        if (m_threads[idx]->GetProtocolID() == tid)
        {
            thread_sp = m_threads[idx];
            m_threads.erase(m_threads.begin()+idx);
            break;
        }
    }
    return thread_sp;
}

ThreadSP
ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr)
{
    ThreadSP thread_sp;
    if (thread_ptr)
    {
        Mutex::Locker locker(GetMutex());

        uint32_t idx = 0;
        const uint32_t num_threads = m_threads.size();
        for (idx = 0; idx < num_threads; ++idx)
        {
            if (m_threads[idx].get() == thread_ptr)
            {
                thread_sp = m_threads[idx];
                break;
            }
        }
    }
    return thread_sp;
}



ThreadSP
ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update)
{
    Mutex::Locker locker(GetMutex());

    if (can_update)
        m_process->UpdateThreadListIfNeeded();

    ThreadSP thread_sp;
    const uint32_t num_threads = m_threads.size();
    for (uint32_t idx = 0; idx < num_threads; ++idx)
    {
        if (m_threads[idx]->GetIndexID() == index_id)
        {
            thread_sp = m_threads[idx];
            break;
        }
    }
    return thread_sp;
}

bool
ThreadList::ShouldStop (Event *event_ptr)
{
    // Running events should never stop, obviously...

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    // The ShouldStop method of the threads can do a whole lot of work,
    // figuring out whether the thread plan conditions are met.  So we don't want
    // to keep the ThreadList locked the whole time we are doing this.
    // FIXME: It is possible that running code could cause new threads
    // to be created.  If that happens, we will miss asking them whether
    // they should stop.  This is not a big deal since we haven't had
    // a chance to hang any interesting operations on those threads yet.
    
    collection threads_copy;
    {
        // Scope for locker
        Mutex::Locker locker(GetMutex());

        m_process->UpdateThreadListIfNeeded();
        threads_copy = m_threads;
    }

    collection::iterator pos, end = threads_copy.end();

    if (log)
    {
        log->PutCString("");
        log->Printf ("ThreadList::%s: %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size());
    }

    bool did_anybody_stop_for_a_reason = false;
    
    // If the event is an Interrupt event, then we're going to stop no matter what.  Otherwise, presume we won't stop.
    bool should_stop = false;
    if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr))
    {
        if (log)
            log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__);
        
        should_stop = true;
    }
    
    // Now we run through all the threads and get their stop info's.  We want to make sure to do this first before
    // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a
    // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly.
    // We don't need to use it here, we just want to make sure it gets computed.
    
    for (pos = threads_copy.begin(); pos != end; ++pos)
    {
        ThreadSP thread_sp(*pos);
        thread_sp->GetStopInfo();
    }
    
    for (pos = threads_copy.begin(); pos != end; ++pos)
    {
        ThreadSP thread_sp(*pos);
        
        // We should never get a stop for which no thread had a stop reason, but sometimes we do see this -
        // for instance when we first connect to a remote stub.  In that case we should stop, since we can't figure out
        // the right thing to do and stopping gives the user control over what to do in this instance.
        //
        // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint,
        // but not the thread which we are waiting for.  All the threads that are not "supposed" to hit the breakpoint
        // are marked as having no stop reason, which is right, they should not show a stop reason.  But that triggers this
        // code and causes us to stop seemingly for no reason.
        //
        // Since the only way we ever saw this error was on first attach, I'm only going to trigger set did_anybody_stop_for_a_reason
        // to true unless this is the first stop.
        //
        // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid
        // everywhere but at this check.
    
        if (thread_sp->GetProcess()->GetStopID() > 1)
            did_anybody_stop_for_a_reason = true;
        else
            did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
        
        const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
        if (thread_should_stop)
            should_stop |= true;
    }

    if (!should_stop && !did_anybody_stop_for_a_reason)
    {
        should_stop = true;
        if (log)
            log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__);
    }
    
    if (log)
        log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop);

    if (should_stop)
    {
        for (pos = threads_copy.begin(); pos != end; ++pos)
        {
            ThreadSP thread_sp(*pos);
            thread_sp->WillStop ();
        }
    }

    return should_stop;
}

Vote
ThreadList::ShouldReportStop (Event *event_ptr)
{
    Mutex::Locker locker(GetMutex());

    Vote result = eVoteNoOpinion;
    m_process->UpdateThreadListIfNeeded();
    collection::iterator pos, end = m_threads.end();

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    if (log)
        log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size());

    // Run through the threads and ask whether we should report this event.
    // For stopping, a YES vote wins over everything.  A NO vote wins over NO opinion.
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        ThreadSP thread_sp(*pos);
        const Vote vote = thread_sp->ShouldReportStop (event_ptr);
        switch (vote)
        {
        case eVoteNoOpinion:
            continue;

        case eVoteYes:
            result = eVoteYes;
            break;

        case eVoteNo:
            if (result == eVoteNoOpinion)
            {
                result = eVoteNo;
            }
            else
            {
                if (log)
                    log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s",
                                 __FUNCTION__,
                                 thread_sp->GetID (), 
                                 GetVoteAsCString (vote),
                                 GetVoteAsCString (result));
            }
            break;
        }
    }
    if (log)
        log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result));
    return result;
}

void
ThreadList::SetShouldReportStop (Vote vote)
{
    Mutex::Locker locker(GetMutex());
    m_process->UpdateThreadListIfNeeded();
    collection::iterator pos, end = m_threads.end();
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        ThreadSP thread_sp(*pos);
        thread_sp->SetShouldReportStop (vote);
    }
}

Vote
ThreadList::ShouldReportRun (Event *event_ptr)
{

    Mutex::Locker locker(GetMutex());

    Vote result = eVoteNoOpinion;
    m_process->UpdateThreadListIfNeeded();
    collection::iterator pos, end = m_threads.end();

    // Run through the threads and ask whether we should report this event.
    // The rule is NO vote wins over everything, a YES vote wins over no opinion.

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        if ((*pos)->GetResumeState () != eStateSuspended)
        {
            switch ((*pos)->ShouldReportRun (event_ptr))
            {
                case eVoteNoOpinion:
                    continue;
                case eVoteYes:
                    if (result == eVoteNoOpinion)
                        result = eVoteYes;
                    break;
                case eVoteNo:
                    if (log)
                        log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.",
                                     (*pos)->GetIndexID(), 
                                     (*pos)->GetID());
                    result = eVoteNo;
                    break;
            }
        }
    }
    return result;
}

void
ThreadList::Clear()
{
    Mutex::Locker locker(GetMutex());
    m_stop_id = 0;
    m_threads.clear();
    m_selected_tid = LLDB_INVALID_THREAD_ID;
}

void
ThreadList::Destroy()
{
    Mutex::Locker locker(GetMutex());
    const uint32_t num_threads = m_threads.size();
    for (uint32_t idx = 0; idx < num_threads; ++idx)
    {
        m_threads[idx]->DestroyThread();
    }
}

void
ThreadList::RefreshStateAfterStop ()
{
    Mutex::Locker locker(GetMutex());

    m_process->UpdateThreadListIfNeeded();
    
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (log && log->GetVerbose())
        log->Printf ("Turning off notification of new threads while single stepping a thread.");

    collection::iterator pos, end = m_threads.end();
    for (pos = m_threads.begin(); pos != end; ++pos)
        (*pos)->RefreshStateAfterStop ();
}

void
ThreadList::DiscardThreadPlans ()
{
    // You don't need to update the thread list here, because only threads
    // that you currently know about have any thread plans.
    Mutex::Locker locker(GetMutex());

    collection::iterator pos, end = m_threads.end();
    for (pos = m_threads.begin(); pos != end; ++pos)
        (*pos)->DiscardThreadPlans (true);

}

bool
ThreadList::WillResume ()
{
    // Run through the threads and perform their momentary actions.
    // But we only do this for threads that are running, user suspended
    // threads stay where they are.

    Mutex::Locker locker(GetMutex());
    m_process->UpdateThreadListIfNeeded();

    collection::iterator pos, end = m_threads.end();

    // See if any thread wants to run stopping others.  If it does, then we won't
    // setup the other threads for resume, since they aren't going to get a chance
    // to run.  This is necessary because the SetupForResume might add "StopOthers"
    // plans which would then get to be part of the who-gets-to-run negotiation, but
    // they're coming in after the fact, and the threads that are already set up should
    // take priority.
    
    bool wants_solo_run = false;
    
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        if ((*pos)->GetResumeState() != eStateSuspended &&
                 (*pos)->GetCurrentPlan()->StopOthers())
        {
            if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread())
                continue;
            wants_solo_run = true;
            break;
        }
    }   

    if (wants_solo_run)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
        if (log && log->GetVerbose())
            log->Printf ("Turning on notification of new threads while single stepping a thread.");
        m_process->StartNoticingNewThreads();
    }
    else
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
        if (log && log->GetVerbose())
            log->Printf ("Turning off notification of new threads while single stepping a thread.");
        m_process->StopNoticingNewThreads();
    }
    
    // Give all the threads that are likely to run a last chance to set up their state before we
    // negotiate who is actually going to get a chance to run...
    // Don't set to resume suspended threads, and if any thread wanted to stop others, only
    // call setup on the threads that request StopOthers...
    
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        if ((*pos)->GetResumeState() != eStateSuspended
            && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers()))
        {
            if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread())
                continue;
            (*pos)->SetupForResume ();
        }
    }

    // Now go through the threads and see if any thread wants to run just itself.
    // if so then pick one and run it.
    
    ThreadList run_me_only_list (m_process);
    
    run_me_only_list.SetStopID(m_process->GetStopID());

    bool run_only_current_thread = false;

    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        ThreadSP thread_sp(*pos);
        if (thread_sp->GetResumeState() != eStateSuspended &&
                 thread_sp->GetCurrentPlan()->StopOthers())
        {
            if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread())
                continue;

            // You can't say "stop others" and also want yourself to be suspended.
            assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);

            if (thread_sp == GetSelectedThread())
            {
                // If the currently selected thread wants to run on its own, always let it.
                run_only_current_thread = true;
                run_me_only_list.Clear();
                run_me_only_list.AddThread (thread_sp);
                break;
            }

            run_me_only_list.AddThread (thread_sp);
        }

    }

    bool need_to_resume = true;
    
    if (run_me_only_list.GetSize (false) == 0)
    {
        // Everybody runs as they wish:
        for (pos = m_threads.begin(); pos != end; ++pos)
        {
            ThreadSP thread_sp(*pos);
            StateType run_state;
            if (thread_sp->GetResumeState() != eStateSuspended)
                run_state = thread_sp->GetCurrentPlan()->RunState();
            else
                run_state = eStateSuspended;
            if (!thread_sp->ShouldResume(run_state))
                need_to_resume = false;
        }
    }
    else
    {
        ThreadSP thread_to_run;

        if (run_only_current_thread)
        {
            thread_to_run = GetSelectedThread();
        }
        else if (run_me_only_list.GetSize (false) == 1)
        {
            thread_to_run = run_me_only_list.GetThreadAtIndex (0);
        }
        else
        {
            int random_thread = (int)
                    ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0));
            thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread);
        }

        for (pos = m_threads.begin(); pos != end; ++pos)
        {
            ThreadSP thread_sp(*pos);
            if (thread_sp == thread_to_run)
            {
                if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
                    need_to_resume = false;
            }
            else
                thread_sp->ShouldResume (eStateSuspended);
        }
    }

    return need_to_resume;
}

void
ThreadList::DidResume ()
{
    Mutex::Locker locker(GetMutex());
    collection::iterator pos, end = m_threads.end();
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        // Don't clear out threads that aren't going to get a chance to run, rather
        // leave their state for the next time around.
        ThreadSP thread_sp(*pos);
        if (thread_sp->GetResumeState() != eStateSuspended)
            thread_sp->DidResume ();
    }
}

void
ThreadList::DidStop ()
{
    Mutex::Locker locker(GetMutex());
    collection::iterator pos, end = m_threads.end();
    for (pos = m_threads.begin(); pos != end; ++pos)
    {
        // Notify threads that the process just stopped.
        // Note, this currently assumes that all threads in the list
        // stop when the process stops.  In the future we will want to support
        // a debugging model where some threads continue to run while others
        // are stopped.  We either need to handle that somehow here or
        // create a special thread list containing only threads which will
        // stop in the code that calls this method (currently
        // Process::SetPrivateState).
        ThreadSP thread_sp(*pos);
        if (StateIsRunningState(thread_sp->GetState()))
            thread_sp->DidStop ();
    }
}

ThreadSP
ThreadList::GetSelectedThread ()
{
    Mutex::Locker locker(GetMutex());
    ThreadSP thread_sp = FindThreadByID(m_selected_tid);
    if (!thread_sp.get())
    {
        if (m_threads.size() == 0)
            return thread_sp;
        m_selected_tid = m_threads[0]->GetID();
        thread_sp = m_threads[0];
    }
    return thread_sp;
}

bool
ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify)
{
    Mutex::Locker locker(GetMutex());
    ThreadSP selected_thread_sp(FindThreadByID(tid));
    if  (selected_thread_sp)
    {
        m_selected_tid = tid;
        selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
    }
    else
        m_selected_tid = LLDB_INVALID_THREAD_ID;

    if (notify)
        NotifySelectedThreadChanged(m_selected_tid);
    
    return m_selected_tid != LLDB_INVALID_THREAD_ID;
}

bool
ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify)
{
    Mutex::Locker locker(GetMutex());
    ThreadSP selected_thread_sp (FindThreadByIndexID(index_id));
    if  (selected_thread_sp.get())
    {
        m_selected_tid = selected_thread_sp->GetID();
        selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
    }
    else
        m_selected_tid = LLDB_INVALID_THREAD_ID;

    if (notify)
        NotifySelectedThreadChanged(m_selected_tid);
    
    return m_selected_tid != LLDB_INVALID_THREAD_ID;
}

void
ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid)
{
    ThreadSP selected_thread_sp (FindThreadByID(tid));
    if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected))
        selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected,
                                           new Thread::ThreadEventData(selected_thread_sp));
}

void
ThreadList::Update (ThreadList &rhs)
{
    if (this != &rhs)
    {
        // Lock both mutexes to make sure neither side changes anyone on us
        // while the assignement occurs
        Mutex::Locker locker(GetMutex());
        m_process = rhs.m_process;
        m_stop_id = rhs.m_stop_id;
        m_threads.swap(rhs.m_threads);
        m_selected_tid = rhs.m_selected_tid;
        
        
        // Now we look for threads that we are done with and
        // make sure to clear them up as much as possible so 
        // anyone with a shared pointer will still have a reference,
        // but the thread won't be of much use. Using std::weak_ptr
        // for all backward references (such as a thread to a process)
        // will eventually solve this issue for us, but for now, we
        // need to work around the issue
        collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
        for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos)
        {
            const lldb::tid_t tid = (*rhs_pos)->GetID();
            bool thread_is_alive = false;
            const uint32_t num_threads = m_threads.size();
            for (uint32_t idx = 0; idx < num_threads; ++idx)
            {
                if (m_threads[idx]->GetID() == tid)
                {
                    thread_is_alive = true;
                    break;
                }
            }
            if (!thread_is_alive)
                (*rhs_pos)->DestroyThread();
        }        
    }
}

void
ThreadList::Flush ()
{
    Mutex::Locker locker(GetMutex());
    collection::iterator pos, end = m_threads.end();
    for (pos = m_threads.begin(); pos != end; ++pos)
        (*pos)->Flush ();
}

Mutex &
ThreadList::GetMutex ()
{
    return m_process->m_thread_mutex;
}

