1 //===-- HostThreadWindows.cpp -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/Error.h"
11 
12 #include "lldb/Host/windows/windows.h"
13 #include "lldb/Host/windows/HostThreadWindows.h"
14 
15 #include "llvm/ADT/STLExtras.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 namespace
21 {
22 void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode)
23 {
24     ::ExitThread(dwExitCode);
25 }
26 }
27 
28 HostThreadWindows::HostThreadWindows()
29     : HostNativeThreadBase()
30     , m_owns_handle(true)
31 {
32 }
33 
34 HostThreadWindows::HostThreadWindows(lldb::thread_t thread)
35     : HostNativeThreadBase(thread)
36     , m_owns_handle(true)
37 {
38 }
39 
40 HostThreadWindows::~HostThreadWindows()
41 {
42     Reset();
43 }
44 
45 void
46 HostThreadWindows::SetOwnsHandle(bool owns)
47 {
48     m_owns_handle = owns;
49 }
50 
51 Error
52 HostThreadWindows::Join(lldb::thread_result_t *result)
53 {
54     Error error;
55     if (IsJoinable())
56     {
57         DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE);
58         if (WAIT_OBJECT_0 == wait_result && result)
59         {
60             DWORD exit_code = 0;
61             if (!::GetExitCodeThread(m_thread, &exit_code))
62                 *result = 0;
63             *result = exit_code;
64         }
65         else if (WAIT_OBJECT_0 != wait_result)
66             error.SetError(::GetLastError(), eErrorTypeWin32);
67     }
68     else
69         error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32);
70 
71     Reset ();
72     return error;
73 }
74 
75 Error
76 HostThreadWindows::Cancel()
77 {
78     Error error;
79 
80     DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0);
81     error.SetError(result, eErrorTypeWin32);
82     return error;
83 }
84 
85 lldb::tid_t
86 HostThreadWindows::GetThreadId() const
87 {
88     return ::GetThreadId(m_thread);
89 }
90 
91 void
92 HostThreadWindows::Reset()
93 {
94     if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD)
95         ::CloseHandle(m_thread);
96 
97     HostNativeThreadBase::Reset();
98 }
99