1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// File: reimpl.cpp
6//
7
8//
9// Data-access-specific reimplementations of standard code.
10//
11//*****************************************************************************
12
13#include "stdafx.h"
14
15//
16// Get the Thread instance for a specific OS thread ID
17//
18// Arguments:
19// osThread - the OS thread ID of interest.
20//
21// Return value:
22// A Thread object marshalled from the target corresponding to the specified OS thread
23// ID, or NULL if there is no such Thread.
24//
25// Notes:
26// We used to accept a thread ID of '0' to mean "use the current thread", which was based on
27// ICLRDataTarget::GetCurrentThreadID. But this is error-prone and not well-defined (many data targets
28// don't implement that API). It's better to require explicit thread IDs to be passed down when they
29// are needed.
30//
31Thread* __stdcall
32DacGetThread(ULONG32 osThread)
33{
34 _ASSERTE(osThread > 0);
35
36 if (!g_dacImpl)
37 {
38 DacError(E_UNEXPECTED);
39 UNREACHABLE();
40 }
41
42 // Note that if we had access to TLS, we could get this at index gThreadTLSIndex for the specified
43 // thread. However, this is the only place we might want to use TLS, and it's not performance critical,
44 // so we haven't added TLS support to ICorDebugDataTarget (the legacy ICLRDataTarget interface has it though)
45
46 // Scan the whole thread store to see if there's a matching thread.
47
48 if (!ThreadStore::s_pThreadStore)
49 {
50 return NULL;
51 }
52
53 Thread* thread = ThreadStore::s_pThreadStore->m_ThreadList.GetHead();
54 while (thread)
55 {
56 if (thread->GetOSThreadId() == osThread)
57 {
58 return thread;
59 }
60
61 thread = ThreadStore::s_pThreadStore->m_ThreadList.GetNext(thread);
62 }
63
64 return NULL;
65}
66
67EXTERN_C Thread* GetThread()
68{
69 // In dac mode it's unlikely that the thread calling dac
70 // is actually the same "current thread" that the runtime cares
71 // about. Fail all queries of the current thread by
72 // the runtime code to catch any inadvertent usage.
73 // Enumerating the ThreadStore is the proper way to get access
74 // to specific Thread objects.
75 DacError(E_UNEXPECTED);
76 return NULL;
77}
78
79BOOL
80DacGetThreadContext(Thread* thread, T_CONTEXT* context)
81{
82 SUPPORTS_DAC;
83
84 if (!g_dacImpl)
85 {
86 DacError(E_UNEXPECTED);
87 UNREACHABLE();
88 }
89
90 // XXX Microsoft - How do you retrieve the context for
91 // a Thread that's not running?
92 if (!thread->GetOSThreadId() ||
93 thread->GetOSThreadId() == 0xbaadf00d)
94 {
95 DacError(E_UNEXPECTED);
96 UNREACHABLE();
97 }
98
99 ULONG32 contextFlags;
100
101 contextFlags = CONTEXT_ALL;
102
103 HRESULT status =
104 g_dacImpl->m_pTarget->
105 GetThreadContext(thread->GetOSThreadId(), contextFlags,
106 sizeof(*context), (PBYTE)context);
107 if (status != S_OK)
108 {
109 DacError(status);
110 UNREACHABLE();
111 }
112
113 return TRUE;
114}
115
116