Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use function pointers instead of marshalled delegates in EventSource #79970

Merged
merged 5 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ private static unsafe partial ulong Enable(
// These PInvokes are used by EventSource to interact with the EventPipe.
//
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_CreateProvider", StringMarshalling = StringMarshalling.Utf16)]
internal static partial IntPtr CreateProvider(string providerName, Interop.Advapi32.EtwEnableCallback callbackFunc);
internal static unsafe partial IntPtr CreateProvider(string providerName,
delegate* unmanaged<byte*, int, byte, long, long, Interop.Advapi32.EVENT_FILTER_DESCRIPTOR*, void*, void> callbackFunc,
void* callbackContext);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_DefineEvent")]
internal static unsafe partial IntPtr DefineEvent(IntPtr provHandle, uint eventID, long keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/scripts/genEventPipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ def getMonoEventPipeImplFilePrefix():

ep_return_null_if_nok (provider_name_utf8 != NULL);

EventPipeProvider *provider = ep_create_provider (provider_name_utf8, callback_func, NULL, NULL);
EventPipeProvider *provider = ep_create_provider (provider_name_utf8, callback_func, NULL);

g_free (provider_name_utf8);
return provider;
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/eventpipeadapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ class EventPipeAdapter final
ep_add_provider_to_session (provider, session);
}

static inline EventPipeProvider * CreateProvider(const SString &providerName, EventPipeCallback callback)
static inline EventPipeProvider * CreateProvider(const SString &providerName, EventPipeCallback callback, void* callbackContext = nullptr)
{
CONTRACTL
{
Expand All @@ -329,7 +329,7 @@ class EventPipeAdapter final
CONTRACTL_END;

ep_char8_t *providerNameUTF8 = ep_rt_utf16_to_utf8_string(reinterpret_cast<const ep_char16_t *>(providerName.GetUnicode ()), -1);
EventPipeProvider * provider = ep_create_provider (providerNameUTF8, callback, NULL, NULL);
EventPipeProvider * provider = ep_create_provider (providerNameUTF8, callback, callbackContext);
ep_rt_utf8_string_free (providerNameUTF8);
return provider;
}
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/vm/eventpipeinternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,16 @@ extern "C" BOOL QCALLTYPE EventPipeInternal_GetSessionInfo(UINT64 sessionID, Eve

extern "C" INT_PTR QCALLTYPE EventPipeInternal_CreateProvider(
_In_z_ LPCWSTR providerName,
EventPipeCallback pCallbackFunc)
EventPipeCallback pCallbackFunc,
void* pCallbackContext)
{
QCALL_CONTRACT;

EventPipeProvider *pProvider = NULL;

BEGIN_QCALL;

pProvider = EventPipeAdapter::CreateProvider(providerName, pCallbackFunc);
pProvider = EventPipeAdapter::CreateProvider(providerName, pCallbackFunc, pCallbackContext);

END_QCALL;

Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/eventpipeinternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ extern "C" BOOL QCALLTYPE EventPipeInternal_GetSessionInfo(UINT64 sessionID, Eve

extern "C" INT_PTR QCALLTYPE EventPipeInternal_CreateProvider(
_In_z_ LPCWSTR providerName,
EventPipeCallback pCallbackFunc);
EventPipeCallback pCallbackFunc,
void* pCallbackContext);

extern "C" INT_PTR QCALLTYPE EventPipeInternal_DefineEvent(
INT_PTR provHandle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,5 @@ internal struct EVENT_FILTER_DESCRIPTOR
public int Size;
public int Type;
}

internal unsafe delegate void EtwEnableCallback(
Guid* sourceId,
int isEnabled,
byte level,
long matchAnyKeywords,
long matchAllKeywords,
EVENT_FILTER_DESCRIPTOR* filterData,
void* callbackContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ internal static partial class Advapi32
{
[LibraryImport(Libraries.Advapi32)]
internal static unsafe partial uint EventRegister(
in Guid providerId,
EtwEnableCallback enableCallback,
Guid* providerId,
delegate* unmanaged<Guid*, int, byte, long, long, EVENT_FILTER_DESCRIPTOR*, void*, void> enableCallback,
void* callbackContext,
ref long registrationHandle);
long* registrationHandle);
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,59 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

namespace System.Diagnostics.Tracing
{
internal sealed class EventPipeEventProvider : IEventProvider
{
// The EventPipeProvider handle.
private IntPtr m_provHandle = IntPtr.Zero;
private EventEnableCallback? _enableCallback;
private IntPtr _provHandle;
private GCHandle _gcHandle;

[UnmanagedCallersOnly]
private static unsafe void Callback(byte* sourceId, int isEnabled, byte level,
long matchAnyKeywords, long matchAllKeywords, Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, void* callbackContext)
{
((EventPipeEventProvider)GCHandle.FromIntPtr((IntPtr)callbackContext).Target!)._enableCallback!(
isEnabled, level, matchAnyKeywords, matchAllKeywords, filterData);
}

// Register an event provider.
unsafe uint IEventProvider.EventRegister(
unsafe void IEventProvider.EventRegister(
EventSource eventSource,
Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
EventEnableCallback enableCallback)
{
uint returnStatus = 0;
m_provHandle = EventPipeInternal.CreateProvider(eventSource.Name, enableCallback);
if (m_provHandle != IntPtr.Zero)
{
// Fixed registration handle because a new EventPipeEventProvider
// will be created for each new EventSource.
registrationHandle = 1;
}
else
_enableCallback = enableCallback;

Debug.Assert(!_gcHandle.IsAllocated);
_gcHandle = GCHandle.Alloc(this);

_provHandle = EventPipeInternal.CreateProvider(eventSource.Name, &Callback, (void*)GCHandle.ToIntPtr(_gcHandle));
if (_provHandle == 0)
{
// Unable to create the provider.
returnStatus = 1;
_gcHandle.Free();
throw new OutOfMemoryException();
jkotas marked this conversation as resolved.
Show resolved Hide resolved
jkotas marked this conversation as resolved.
Show resolved Hide resolved
}

return returnStatus;
}

// Unregister an event provider.
uint IEventProvider.EventUnregister(long registrationHandle)
void IEventProvider.EventUnregister()
{
EventPipeInternal.DeleteProvider(m_provHandle);
return 0;
if (_provHandle != 0)
{
EventPipeInternal.DeleteProvider(_provHandle);
_provHandle = 0;
}
if (_gcHandle.IsAllocated)
{
_gcHandle.Free();
}
}

// Write an event.
unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer(
long registrationHandle,
in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Expand Down Expand Up @@ -82,8 +94,7 @@ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl contr
unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level,
byte *pMetadata, uint metadataLength)
{
IntPtr eventHandlePtr = EventPipeInternal.DefineEvent(m_provHandle, eventID, keywords, eventVersion, level, pMetadata, metadataLength);
return eventHandlePtr;
return EventPipeInternal.DefineEvent(_provHandle, eventID, keywords, eventVersion, level, pMetadata, metadataLength);
}

// Get or set the per-thread activity ID.
Expand Down
Loading