Skip to content

Commit ac16e8e

Browse files
committed
Native AOT runtime implementation
1 parent 9cf5f08 commit ac16e8e

File tree

5 files changed

+503
-613
lines changed

5 files changed

+503
-613
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
4+
#ifndef __NativeaotEventPipeSupport_h__
5+
#define __NativeaotEventPipeSupport_h__
6+
7+
// This file is included only when compiling shared EventPipe source files and contains any
8+
// definitions which are needed by these source files but are not available in NativeAOT
9+
// runtime source files.
10+
11+
// As mentioned PalRedhawk*.cpp, in general we don't want to assume that Windows and
12+
// Redhawk global definitions can co-exist, meaning NativeAOT runtime source files
13+
// generally do not have access to windows.h; that said, the HOST_WIN32 parts of the shared
14+
// EventPipe code are designed to rely on windows.h, so windows.h must be included when
15+
// compiling shared EventPipe source files, and a marker is set to indicate that windows.h
16+
// has been added to the compilation in this manner.
17+
18+
#include <windows.h>
19+
20+
#define BUILDING_SHARED_NATIVEAOT_EVENTPIPE_CODE
21+
22+
#endif // __NativeaotEventPipeSupport_h__

src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h

Lines changed: 35 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,7 @@ ds_rt_auto_trace_init (void)
9292
STATIC_CONTRACT_NOTHROW;
9393

9494
#ifdef FEATURE_AUTO_TRACE
95-
EX_TRY
96-
{
97-
auto_trace_init ();
98-
}
99-
EX_CATCH {}
100-
EX_END_CATCH(SwallowAllExceptions);
95+
auto_trace_init ();
10196
#endif
10297
}
10398

@@ -108,12 +103,7 @@ ds_rt_auto_trace_launch (void)
108103
STATIC_CONTRACT_NOTHROW;
109104

110105
#ifdef FEATURE_AUTO_TRACE
111-
EX_TRY
112-
{
113-
auto_trace_launch ();
114-
}
115-
EX_CATCH {}
116-
EX_END_CATCH(SwallowAllExceptions);
106+
auto_trace_launch ();
117107
#endif
118108
}
119109

@@ -124,12 +114,7 @@ ds_rt_auto_trace_signal (void)
124114
STATIC_CONTRACT_NOTHROW;
125115

126116
#ifdef FEATURE_AUTO_TRACE
127-
EX_TRY
128-
{
129-
auto_trace_signal ();
130-
}
131-
EX_CATCH {}
132-
EX_END_CATCH(SwallowAllExceptions);
117+
auto_trace_signal ();
133118
#endif
134119
}
135120

@@ -140,12 +125,7 @@ ds_rt_auto_trace_wait (void)
140125
STATIC_CONTRACT_NOTHROW;
141126

142127
#ifdef FEATURE_AUTO_TRACE
143-
EX_TRY
144-
{
145-
auto_trace_wait ();
146-
}
147-
EX_CATCH {}
148-
EX_END_CATCH(SwallowAllExceptions);
128+
auto_trace_wait ();
149129
#endif
150130
}
151131

@@ -159,18 +139,18 @@ bool
159139
ds_rt_config_value_get_enable (void)
160140
{
161141
STATIC_CONTRACT_NOTHROW;
162-
return CLRConfig::GetConfigValue (CLRConfig::EXTERNAL_EnableDiagnostics) != 0;
142+
143+
// TODO: EventPipe Configuration values - RhConfig?
144+
return true;
163145
}
164146

165147
static
166148
inline
167149
ep_char8_t *
168150
ds_rt_config_value_get_ports (void)
169151
{
170-
STATIC_CONTRACT_NOTHROW;
171-
172-
CLRConfigStringHolder value(CLRConfig::GetConfigValue (CLRConfig::EXTERNAL_DOTNET_DiagnosticPorts));
173-
return ep_rt_utf16_to_utf8_string (reinterpret_cast<ep_char16_t *>(value.GetValue ()), -1);
152+
// TODO: EventPipe Configuration values - RhConfig?
153+
return nullptr;
174154
}
175155

176156
static
@@ -179,7 +159,8 @@ uint32_t
179159
ds_rt_config_value_get_default_port_suspend (void)
180160
{
181161
STATIC_CONTRACT_NOTHROW;
182-
return static_cast<uint32_t>(CLRConfig::GetConfigValue (CLRConfig::EXTERNAL_DOTNET_DefaultDiagnosticPortSuspend));
162+
// TODO: EventPipe Configuration values - RhConfig?
163+
return 0;
183164
}
184165

185166
/*
@@ -197,24 +178,11 @@ ds_rt_generate_core_dump (
197178
STATIC_CONTRACT_NOTHROW;
198179

199180
ds_ipc_result_t result = DS_IPC_E_FAIL;
200-
EX_TRY
201-
{
202-
uint32_t flags = ds_generate_core_dump_command_payload_get_flags(payload);
203-
if (commandId == DS_DUMP_COMMANDID_GENERATE_CORE_DUMP)
204-
{
205-
// For the old commmand, this payload field is a bool of whether to enable logging
206-
flags = flags != 0 ? GenerateDumpFlagsLoggingEnabled : 0;
207-
}
208-
LPCWSTR dumpName = reinterpret_cast<LPCWSTR>(ds_generate_core_dump_command_payload_get_dump_name (payload));
209-
int32_t dumpType = static_cast<int32_t>(ds_generate_core_dump_command_payload_get_dump_type (payload));
210-
if (GenerateDump(dumpName, dumpType, flags, errorMessageBuffer, cbErrorMessageBuffer))
211-
{
212-
result = DS_IPC_S_OK;
213-
}
214-
}
215-
EX_CATCH {}
216-
EX_END_CATCH(SwallowAllExceptions);
217-
return result;
181+
uint32_t flags = ds_generate_core_dump_command_payload_get_flags(payload);
182+
// TODO: Generate an exception dump
183+
__debugbreak();
184+
185+
return 0;
218186
}
219187

220188
/*
@@ -233,10 +201,11 @@ ds_rt_transport_get_default_name (
233201
const ep_char8_t *suffix)
234202
{
235203
STATIC_CONTRACT_NOTHROW;
236-
237-
#ifdef TARGET_UNIX
238-
PAL_GetTransportName (name_len, name, prefix, id, group_id, suffix);
239-
#endif
204+
205+
// TODO: PAL_GetTransportName is defined in coreclr\pal\inc\pal.h
206+
// #ifdef TARGET_UNIX
207+
// PAL_GetTransportName (name_len, name, prefix, id, group_id, suffix);
208+
// #endif
240209
return true;
241210
}
242211

@@ -289,14 +258,11 @@ ds_rt_profiler_attach (DiagnosticsAttachProfilerCommandPayload *payload)
289258
ClrFlsSetThreadType (ThreadType_ProfAPI_Attach);
290259

291260
HRESULT hr = S_OK;
292-
EX_TRY {
293-
hr = ProfilingAPIUtility::LoadProfilerForAttach (reinterpret_cast<const CLSID *>(ds_attach_profiler_command_payload_get_profiler_guid_cref (payload)),
294-
reinterpret_cast<LPCWSTR>(ds_attach_profiler_command_payload_get_profiler_path (payload)),
295-
reinterpret_cast<LPVOID>(ds_attach_profiler_command_payload_get_client_data (payload)),
296-
static_cast<UINT>(ds_attach_profiler_command_payload_get_client_data_len (payload)),
297-
static_cast<DWORD>(ds_attach_profiler_command_payload_get_attach_timeout (payload)));
298-
}
299-
EX_CATCH_HRESULT (hr);
261+
hr = ProfilingAPIUtility::LoadProfilerForAttach (reinterpret_cast<const CLSID *>(ds_attach_profiler_command_payload_get_profiler_guid_cref (payload)),
262+
reinterpret_cast<LPCWSTR>(ds_attach_profiler_command_payload_get_profiler_path (payload)),
263+
reinterpret_cast<LPVOID>(ds_attach_profiler_command_payload_get_client_data (payload)),
264+
static_cast<UINT>(ds_attach_profiler_command_payload_get_client_data_len (payload)),
265+
static_cast<DWORD>(ds_attach_profiler_command_payload_get_attach_timeout (payload)));
300266

301267
// Clear the flag so this thread isn't permanently marked as the attach thread.
302268
ClrFlsClearThreadType (ThreadType_ProfAPI_Attach);
@@ -312,14 +278,11 @@ ds_rt_profiler_startup (DiagnosticsStartupProfilerCommandPayload *payload)
312278
STATIC_CONTRACT_NOTHROW;
313279

314280
HRESULT hr = S_OK;
315-
EX_TRY {
316-
StoredProfilerNode *profilerData = new StoredProfilerNode();
317-
profilerData->guid = *(reinterpret_cast<const CLSID *>(ds_startup_profiler_command_payload_get_profiler_guid_cref (payload)));
318-
profilerData->path.Set(reinterpret_cast<LPCWSTR>(ds_startup_profiler_command_payload_get_profiler_path (payload)));
281+
StoredProfilerNode *profilerData = new StoredProfilerNode();
282+
profilerData->guid = *(reinterpret_cast<const CLSID *>(ds_startup_profiler_command_payload_get_profiler_guid_cref (payload)));
283+
profilerData->path.Set(reinterpret_cast<LPCWSTR>(ds_startup_profiler_command_payload_get_profiler_path (payload)));
319284

320-
g_profControlBlock.storedProfilers.InsertHead(profilerData);
321-
}
322-
EX_CATCH_HRESULT (hr);
285+
g_profControlBlock.storedProfilers.InsertHead(profilerData);
323286

324287
return hr;
325288
}
@@ -329,7 +292,9 @@ static
329292
uint32_t
330293
ds_rt_set_environment_variable (const ep_char16_t *name, const ep_char16_t *value)
331294
{
332-
return SetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(name), reinterpret_cast<LPCWSTR>(value)) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
295+
// return SetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(name), reinterpret_cast<LPCWSTR>(value)) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
296+
__debugbreak();
297+
return 0xffff;
333298
}
334299

335300
/*
@@ -343,19 +308,8 @@ ds_rt_server_log_pause_message (void)
343308
STATIC_CONTRACT_NOTHROW;
344309

345310
const char diagPortsName[] = "DOTNET_DiagnosticPorts";
346-
CLRConfigNoCache diagPorts = CLRConfigNoCache::Get(diagPortsName);
347-
LPCSTR ports = nullptr;
348-
if (diagPorts.IsSet())
349-
{
350-
ports = diagPorts.AsString();
351-
}
352-
353-
uint32_t port_suspended = ds_rt_config_value_get_default_port_suspend();
354-
355-
printf("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n");
356-
printf("%s=\"%s\"\n", diagPortsName, ports == nullptr ? "" : ports);
357-
printf("DOTNET_DefaultDiagnosticPortSuspend=%u\n", port_suspended);
358-
fflush(stdout);
311+
// TODO: Cannot find nocache versions of RhConfig
312+
__debugbreak();
359313
}
360314

361315
#endif /* ENABLE_PERFTRACING */

src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp

Lines changed: 2 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <eventpipe/ep.h>
66
#include <eventpipe/ep-stack-contents.h>
77
#include <eventpipe/ep-rt.h>
8-
#include "threadsuspend.h"
98

109
ep_rt_lock_handle_t _ep_rt_aot_config_lock_handle;
1110
CrstStatic _ep_rt_aot_config_lock;
@@ -22,71 +21,21 @@ uint32_t *_ep_rt_aot_proc_group_offsets;
2221
* Forward declares of all static functions.
2322
*/
2423

25-
static
26-
StackWalkAction
27-
stack_walk_callback (
28-
CrawlFrame *frame,
29-
EventPipeStackContents *stack_contents);
3024

3125
static
3226
void
3327
walk_managed_stack_for_threads (
3428
ep_rt_thread_handle_t sampling_thread,
3529
EventPipeEvent *sampling_event);
3630

37-
static
38-
StackWalkAction
39-
stack_walk_callback (
40-
CrawlFrame *frame,
41-
EventPipeStackContents *stack_contents)
42-
{
43-
STATIC_CONTRACT_NOTHROW;
44-
EP_ASSERT (frame != NULL);
45-
EP_ASSERT (stack_contents != NULL);
46-
47-
// Get the IP.
48-
UINT_PTR control_pc = (UINT_PTR)frame->GetRegisterSet ()->ControlPC;
49-
if (control_pc == NULL) {
50-
if (ep_stack_contents_get_length (stack_contents) == 0) {
51-
// This happens for pinvoke stubs on the top of the stack.
52-
return SWA_CONTINUE;
53-
}
54-
}
55-
56-
EP_ASSERT (control_pc != NULL);
57-
58-
// Add the IP to the captured stack.
59-
ep_stack_contents_append (stack_contents, control_pc, frame->GetFunction ());
60-
61-
// Continue the stack walk.
62-
return SWA_CONTINUE;
63-
}
6431

6532
bool
6633
ep_rt_aot_walk_managed_stack_for_thread (
6734
ep_rt_thread_handle_t thread,
6835
EventPipeStackContents *stack_contents)
6936
{
70-
STATIC_CONTRACT_NOTHROW;
71-
EP_ASSERT (thread != NULL);
72-
EP_ASSERT (stack_contents != NULL);
73-
74-
// Calling into StackWalkFrames in preemptive mode violates the host contract,
75-
// but this contract is not used on Aot.
76-
CONTRACT_VIOLATION (HostViolation);
77-
78-
// Before we call into StackWalkFrames we need to mark GC_ON_TRANSITIONS as FALSE
79-
// because under GCStress runs (GCStress=0x3), a GC will be triggered for every transition,
80-
// which will cause the GC to try to walk the stack while we are in the middle of walking the stack.
81-
bool gc_on_transitions = GC_ON_TRANSITIONS (FALSE);
82-
83-
StackWalkAction result = thread->StackWalkFrames (
84-
(PSTACKWALKFRAMESCALLBACK)stack_walk_callback,
85-
stack_contents,
86-
ALLOW_ASYNC_STACK_WALK | FUNCTIONSONLY | HANDLESKIPPEDFRAMES | ALLOW_INVALID_OBJECTS);
87-
88-
GC_ON_TRANSITIONS (gc_on_transitions);
89-
return ((result == SWA_DONE) || (result == SWA_CONTINUE));
37+
__debugbreak();
38+
return false;
9039
}
9140

9241
// The thread store lock must already be held by the thread before this function
@@ -97,68 +46,13 @@ walk_managed_stack_for_threads (
9746
ep_rt_thread_handle_t sampling_thread,
9847
EventPipeEvent *sampling_event)
9948
{
100-
STATIC_CONTRACT_NOTHROW;
101-
EP_ASSERT (sampling_thread != NULL);
102-
103-
Thread *target_thread = NULL;
104-
105-
EventPipeStackContents stack_contents;
106-
EventPipeStackContents *current_stack_contents;
107-
current_stack_contents = ep_stack_contents_init (&stack_contents);
108-
109-
EP_ASSERT (current_stack_contents != NULL);
110-
111-
// Iterate over all managed threads.
112-
// Assumes that the ThreadStoreLock is held because we've suspended all threads.
113-
while ((target_thread = ThreadStore::GetThreadList (target_thread)) != NULL) {
114-
ep_stack_contents_reset (current_stack_contents);
115-
116-
// Walk the stack and write it out as an event.
117-
if (ep_rt_aot_walk_managed_stack_for_thread (target_thread, current_stack_contents) && !ep_stack_contents_is_empty (current_stack_contents)) {
118-
// Set the payload. If the GC mode on suspension > 0, then the thread was in cooperative mode.
119-
// Even though there are some cases where this is not managed code, we assume it is managed code here.
120-
// If the GC mode on suspension == 0 then the thread was in preemptive mode, which we qualify as external here.
121-
uint32_t payload_data = target_thread->GetGCModeOnSuspension () ? EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED : EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
122-
123-
// Write the sample.
124-
ep_write_sample_profile_event (
125-
sampling_thread,
126-
sampling_event,
127-
target_thread,
128-
current_stack_contents,
129-
(uint8_t *)&payload_data,
130-
sizeof (payload_data));
131-
}
132-
133-
// Reset the GC mode.
134-
target_thread->ClearGCModeOnSuspension ();
135-
}
136-
137-
ep_stack_contents_fini (current_stack_contents);
13849
}
13950

14051
void
14152
ep_rt_aot_sample_profiler_write_sampling_event_for_threads (
14253
ep_rt_thread_handle_t sampling_thread,
14354
EventPipeEvent *sampling_event)
14455
{
145-
STATIC_CONTRACT_NOTHROW;
146-
EP_ASSERT (sampling_thread != NULL);
147-
148-
// Check to see if we can suspend managed execution.
149-
if (ThreadSuspend::SysIsSuspendInProgress () || (ThreadSuspend::GetSuspensionThread () != 0))
150-
return;
151-
152-
// Actually suspend managed execution.
153-
ThreadSuspend::SuspendEE (ThreadSuspend::SUSPEND_REASON::SUSPEND_OTHER);
154-
155-
// Walk all managed threads and capture stacks.
156-
walk_managed_stack_for_threads (sampling_thread, sampling_event);
157-
158-
// Resume managed execution.
159-
ThreadSuspend::RestartEE (FALSE /* bFinishedGC */, TRUE /* SuspendSucceeded */);
160-
161-
return;
16256
}
16357

16458
#endif /* ENABLE_PERFTRACING */

0 commit comments

Comments
 (0)