Skip to content

Commit c5b55f0

Browse files
authored
Initial work of porting native diagnostic eventpipe library to C. (#34600)
First bulk of changes related to porting EventPipe C++ library from CoreCLR into a C library that can be shared between Mono as well as CoreCLR runtime. Due to dependencies and current time line it has been decided to initially target Mono runtime (since it doesn't have event pipe functionality at the moment), but library is still designed to integrate into other runtimes, replacing current C++ library implementation, when time permits. Until that happens, we will need to make sure changes done in C++ code base gets ported over to C library. The amount of changes going into the native library should however be small and if major changes needs to be done, we should first make sure to move over to use the shared version of event pipe C-library in CoreCLR and then only do changes into shared version of the library. Port is currently mapping existing C++ code base, no focus on rewrite or change current implementation (unless needed to port code over to C). Library source files are currently placed into mono/eventpipe folder and build as a separate library, linked into runtime, but will be moved when ready to be shared between runtimes. We might also move all code into a loadable library and p/invokes, depending on size, at least for Mono runtime targeting mobile devices. There is also a unit test runner under mono/eventpipe/tests using eglib test runner, running through a set of unit tests covering the eventpipe library implementation. Library is split up over a couple of source files closely mapping corresponding coreclr source files. Most code could be shared between runtimes and artifacts that are runtime specific, like locks/lists/maps/strings/pal layer etc, a shim API is defined in ep-rt.h and ep-rt-types.h that gets implemented by the targeted runtime consuming the event pipe C library, like ep-rt-mono.h and ep-rt-types-mono.h. All function in the shim API is small and should be inlinable. For example, locking the configuration lock is declared like this in ep-rt.h: bool ep_rt_config_aquire (void); and in ep-rt-mono.h it is implemented like this: static inline bool ep_rt_config_aquire (void) { ep_rt_spin_lock_aquire (ep_rt_mono_config_lock_get ()); return true; } and CoreCLR should implement the function using its corresponding locking primitives. NOTE, since we primarily target Mono in initial port there might smaller adjustments needed to the shim API once bringing it over to CoreCLR, but those changes/adjustments can be done when needed. Since library could be shared, it tries to standardize on common C99 data types when available. If there are runtime specific types needed, they are declared in ep-rt-types.h and implemented by each runtime in corresponding file. Most of library is currently following Mono coding guidelines. For shared types naming is done like this, EventPipe[Type], like EventPipeProvider. This naming follow naming of other types in Mono as well as CoreCLR. There is one exception to this rule, types that are runtime specific implementation, naming is following function naming with a _t prefix, like ep_rt_session_provider_list_t, that is a list specific type, implemented by each runtime. This is done to make it easier to see difference of types implemented in the runtime specific shim and types implemented in the shared library API surface. Since library shim implemented by targeted runtime will be called by C code, it can't throw exceptions, the C library should however compile under C++, meaning that CoreCLR's shim should be able to use C++ constructions as long as it don't throw any exceptions. Library function naming follows the following pattern, for "public" functions included in ep-*.h , ep_ + object + action, so for example, ep_config_create_provider, corresponds to EventPipe::Configuration::CreateProvider in C++ library. For "private/internal" functions not, ep_ prefix is dropped, but object + action is still preserved, for example config_create_provider and function is marked as being static when possible. If a function assumes a lock is held when getting called, it is using _lock_held (similar to SAL annotations) postfix to indicate that function doesn't claim lock and if function needs lock to be held by caller, it will assert that condition on enter (similar to PRECONDITION(EventPipe::IsLockOwnedByCurrentThread())). Library uses asserts internally to validate state and conditions. This is a debug/checked build assert that should be excluded in release builds. It is defined in EP_ASSERT and should be redefined by targeted runtime. Private/internal functions asserts incorrect input parameters and state, while "public" functions return back error to caller when detecting incorrect input parameters. Incorrect state can still be assert in all kinds of functions. Getters/Setters are setup for accessing type members. All functions except a type's own alloc/init/fini/free implemented in ep-*.c are not allowed to use direct type member access and should go through available inlinable getter/setter functions. There is also a way to build the library that catches incorrect use of members at compile time (not in ep-*-internals.c since it include alloc/init/fini/free implementations, but in other source files). Types that can be stack allocated offers a init/fini function pairs. Types that should only be heap allocated, alloc/free, and types supporting both stack/heap, implements alloc/init/fini/free. Since C can't prevent incorrect usage patterns, the implementation needs to follow correct life time management patterns. Types allocated using alloc should be freed with corresponding free function. For example, ep_event_alloc should be freed by ep_event_free, the init/fini methods are then called by the alloc/free implementations. For types supporting stack allocation and allocated on stack or aggregated within other types, init must be called before first use and fini before going out of scope. Ownership of allocated objects is only considered complete on successful function calls. If a function fails, caller still owns resource and need to take actions. Library uses UTF8 strings internally, mainly since Mono runtime already uses that and it is more portable. Number of strings in the library is limited, and in cases where stream protocol uses UTF16 strings, a prealloc string is stored on the type, reducing need to do multiple UTF8 -> UTF16 conversions over the lifetime of the type. NOTE, this is first commit setting up most of the direction of the library and (as part of doing that) ported a great deal of eventpipe code and added ~40 native unittests. It is however not complete, or fully working, so there will be several follow up commit building on top of this work in order to get complete library.
1 parent 2d88a3d commit c5b55f0

File tree

93 files changed

+13904
-121
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+13904
-121
lines changed

src/mono/cmake/config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,9 @@
16471647
/* Enable private types checked build */
16481648
#cmakedefine ENABLE_CHECKED_BUILD_CRASH_REPORTING 1
16491649

1650+
/* Enable EventPipe library support */
1651+
#cmakedefine ENABLE_PERFTRACING 1
1652+
16501653
/* Define to 1 if you have /usr/include/malloc.h. */
16511654
#cmakedefine HAVE_USR_INCLUDE_MALLOC_H 1
16521655

src/mono/configure.ac

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,16 @@ if test x$with_core = xonly; then
943943
fi
944944
AM_CONDITIONAL(ENABLE_NETCORE, test x$with_core = xonly)
945945

946+
if test x$with_core = xonly; then
947+
if test -f $srcdir/mono/eventpipe/ep.h; then
948+
enable_perftracing=yes
949+
fi
950+
if test x$enable_perftracing = xyes; then
951+
AC_DEFINE(ENABLE_PERFTRACING,1,[Enables support for eventpipe library])
952+
fi
953+
fi
954+
AM_CONDITIONAL(ENABLE_PERFTRACING, test x$enable_perftracing = xyes)
955+
946956
#
947957
# A sanity check to catch cases where the package was unpacked
948958
# with an ancient tar program (Solaris)

src/mono/m4/mono-output.m4

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ AC_DEFUN([AC_MONO_OUTPUT], [
1212
mono/utils/Makefile
1313
mono/metadata/Makefile
1414
mono/zlib/Makefile
15+
mono/eventpipe/Makefile
16+
mono/eventpipe/test/Makefile
1517
mono/arch/Makefile
1618
mono/arch/x86/Makefile
1719
mono/arch/amd64/Makefile

src/mono/mono.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@
728728
<ItemGroup>
729729
<_MonoBuildParams Include="/p:MONO_BUILD_DIR_PREFIX=&quot;&quot;$(MonoObjDir)&quot;&quot;" />
730730
<_MonoBuildParams Include="/p:MONO_ENABLE_NETCORE=true" />
731+
<_MonoBuildParams Include="/p:MONO_ENABLE_PERFTRACING=true" />
731732
<_MonoBuildParams Include="/p:MONO_USE_STATIC_C_RUNTIME=true" />
732733
<_MonoBuildParams Include="/p:CL_MPCount=$([System.Environment]::ProcessorCount)" />
733734
<_MonoBuildParams Include="/v:minimal" />

src/mono/mono/Makefile.am

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,20 @@ native_dirs = native
1313
endif
1414

1515
if ENABLE_NETCORE
16-
btls_dirs =
16+
btls_dirs =
17+
managed_unit_test_dirs =
18+
native_unit_test_dirs =
19+
else
20+
managed_unit_test_dirs = tests
21+
native_unit_test_dirs = unit-tests
22+
endif
23+
24+
if ENABLE_PERFTRACING
25+
eventpipe_dirs = eventpipe
1726
endif
1827

1928
if ENABLE_NETCORE
20-
SUBDIRS = eglib arch utils sgen zlib metadata mini profiler
29+
SUBDIRS = eglib arch utils sgen zlib $(eventpipe_dirs) metadata mini profiler $(native_unit_test_dirs)
2130
else
2231

2332
if CROSS_COMPILING
@@ -26,9 +35,9 @@ else
2635
if INSTALL_MONOTOUCH
2736
SUBDIRS = $(btls_dirs) eglib arch utils zlib $(sgen_dirs) metadata mini profiler $(native_dirs)
2837
else
29-
SUBDIRS = $(btls_dirs) eglib arch utils cil zlib $(sgen_dirs) metadata mini dis tests unit-tests benchmark profiler $(native_dirs)
38+
SUBDIRS = $(btls_dirs) eglib arch utils cil zlib $(sgen_dirs) metadata mini dis $(managed_unit_test_dirs) $(native_unit_test_dirs) benchmark profiler $(native_dirs)
3039
endif
3140
endif
3241
endif
3342

34-
DIST_SUBDIRS = btls native eglib arch utils cil zlib $(sgen_dirs) metadata mini dis tests unit-tests benchmark profiler
43+
DIST_SUBDIRS = btls native eglib arch utils cil zlib $(sgen_dirs) metadata mini dis $(managed_unit_test_dirs) $(native_unit_test_dirs) benchmark profiler
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
MAKEFLAGS := $(MAKEFLAGS) --no-builtin-rules
2+
3+
if !ENABLE_MSVC_ONLY
4+
if ENABLE_PERFTRACING
5+
6+
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(GLIB_CFLAGS) $(SHARED_CFLAGS)
7+
8+
noinst_LTLIBRARIES = libeventpipe.la
9+
10+
eventpipe_sources = \
11+
ep.c\
12+
ep.h\
13+
ep-block.c\
14+
ep-block.h\
15+
ep-block-internals.c\
16+
ep-buffer.h\
17+
ep-buffer-manager.c\
18+
ep-buffer-manager.h\
19+
ep-buffer-manager-internals.c\
20+
ep-config.c\
21+
ep-config.h\
22+
ep-config-internals.c\
23+
ep-event.h\
24+
ep-event-instance.h\
25+
ep-event-instance.c\
26+
ep-event-instance-internals.c\
27+
ep-event-internals.c\
28+
ep-event-payload-internals.c\
29+
ep-event-payload.h\
30+
ep-event-source.c\
31+
ep-event-source.h\
32+
ep-event-source-internals.c\
33+
ep-file.c\
34+
ep-file.h\
35+
ep-file-internals.c\
36+
ep-internals.c\
37+
ep-metadata-generator.c\
38+
ep-metadata-generator.h\
39+
ep-metadata-generator-internals.c\
40+
ep-provider.c\
41+
ep-provider.h\
42+
ep-provider-internals.c\
43+
ep-rt.h\
44+
ep-rt-config.h\
45+
ep-rt-config-mono.h\
46+
ep-rt-mono.c\
47+
ep-rt-mono.h\
48+
ep-rt-types.h\
49+
ep-rt-types-mono.h\
50+
ep-thread.c\
51+
ep-thread.h\
52+
ep-thread-internals.c\
53+
ep-types.h\
54+
ep-session.c\
55+
ep-session.h\
56+
ep-session-internals.c\
57+
ep-session-provider.c\
58+
ep-session-provider-internals.h\
59+
ep-session-provider-internals.c\
60+
ep-stream.c\
61+
ep-stream.h\
62+
ep-stream-internals.c\
63+
ep-stack-contents.h
64+
65+
66+
libeventpipe_la_SOURCES = $(eventpipe_sources)
67+
68+
endif # ENABLE_PERFTRACING
69+
endif # !ENABLE_MSVC_ONLY
70+
71+
CFLAGS := $(filter-out @CXX_REMOVE_CFLAGS@, @CFLAGS@) @CXX_ADD_CFLAGS@

0 commit comments

Comments
 (0)