[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mono-devel-list
Subject:    [Mono-dev]  [PATCH] Mono DTrace provider v2
From:       Andreas_Färber <andreas.faerber () web ! de>
Date:       2008-05-30 22:09:03
Message-ID: 0610BF94-DE71-4CB9-80A0-EB5372694781 () web ! de
[Download RAW message or body]

Hello,

Here's an updated version of my patch, adding initial DTrace support  
to the Mono runtime.

A new hand-crafted header file has been added, which is to be included  
in place of the generated header file. It defines MONO_PROBE_* macros  
as requested by Zoltan. The generated header file is then only needed  
iff DTrace is enabled.

Ugly build steps for Solaris were moved to a shell script. It extracts  
object files from their library to a temporary directory, patches them  
and puts them back in. This helps keep Makefiles clean and provides a  
one-stop resource to fix things, should they break. Tested on  
OpenSolaris 2008.05 i86. (Warning: I am not experienced in writing  
shell scripts.)

It appears the problem with the gc-end probe on Solaris was due to  
some kind of compiler optimization or the like. Adding a trailing  
sleep(0) call made it work; I have limited this workaround to when the  
gc-end probe is enabled on Solaris, to minimize the impact. Better  
ideas welcome. If we do stick with it and it turns out this is needed  
in more void functions, we could consider turning this into a  
MONO_PROBE_* macro to keep source files clean.

Signed-off-by: Andreas Faerber <andreas.faerber@web.de>

Change Log v2:

* dtrace-prelink.sh.in: New
   Script to prevent ugly Solaris hacks in Makefiles.

* configure.in:
   Prepare support for OSX/x86_64 (untested)
   Output dtrace-prelink.sh script.

* data/mono.d: Renamed (from mono-trace.d)
   Added standard Mono header.
   Added generation argument to gc-{begin,end} probes.
   Added explicit stability attributes.

* mono/utils/dtrace.h: New
   Wrapper around generated mono/utils/mono-dtrace.h.
   Define MONO_PROBE_* macros.

* mono/utils/Makefile.am:
   We no longer need to postprocess the generated header file.

* mono/metadata/Makefile.am,
   mono/mini/Makefile.am:
   Use new dtrace-prelink.sh script.

* mono/mini/mini.c,
   mono/metadata/boehm-gc.c:
   Use new macros

* mono/metadata/boehm-gc.c:
   Add workaround to make gc-end probe work on Solaris.

Andreas

["DTrace-USDT-2.diff" (DTrace-USDT-2.diff)]

diff --git a/configure.in b/configure.in
index afe472e..4a2f249 100644
--- a/configure.in
+++ b/configure.in
@@ -2065,6 +2065,53 @@ AM_CONDITIONAL(HAVE_OPROFILE, test x$OPROFILE = xyes)
 AC_SUBST(OPROFILE_CFLAGS)
 AC_SUBST(OPROFILE_LIBS)
 
+AC_MSG_CHECKING([if DTrace support is requested])
+AC_ARG_ENABLE(dtrace,[ --enable-dtrace	Enable DTrace probes], \
enable_dtrace=$enableval, enable_dtrace=no) +AC_MSG_RESULT($enable_dtrace)
+dtrace_g=no
+if test x$enable_dtrace = xyes; then
+	AC_DEFINE(ENABLE_DTRACE, 1, [Enable DTrace probes])
+	AC_PATH_PROG(DTRACE, [dtrace], [no], [$PATH:/usr/sbin])
+	if test x$DTRACE = xno; then
+		AC_MSG_FAILURE([DTrace requested but not found])
+	fi
+	DTRACEFLAGS=
+	if test "x$ac_cv_sizeof_void_p" = "x8"; then
+		case "$host" in
+			powerpc-*-darwin*)
+			DTRACEFLAGS="-arch ppc64"
+			;;
+			i*86-*-darwin*)
+			DTRACEFLAGS="-arch x86_64"
+			;;
+			*)
+			DTRACEFLAGS=-64
+			;;
+		esac
+	else
+		case "$host" in
+			powerpc-*-darwin*)
+			DTRACEFLAGS="-arch ppc"
+			;;
+			i*86-*-darwin*)
+			DTRACEFLAGS="-arch i386"
+			;;
+			*)
+			DTRACEFLAGS=-32
+			;;
+		esac
+	fi
+	AC_SUBST(DTRACEFLAGS)
+	case "$host" in
+		*-*-solaris*)
+		dtrace_g=yes
+		;;
+	esac
+	AC_CHECK_HEADERS([sys/sdt.h])
+fi
+AM_CONDITIONAL(ENABLE_DTRACE, [test x$enable_dtrace = xyes])
+AM_CONDITIONAL(DTRACE_G_REQUIRED, [test x$dtrace_g = xyes])
+
 libmono_ldflags="$libmono_ldflags $LIBS"
 
 AM_CONDITIONAL(INSTALL_2_0, test x$PREVIEW = xyes)
@@ -2195,6 +2242,7 @@ \
AC_CONFIG_COMMANDS([runtime/etc/mono/2.0/Browsers/Compat.browser],  
 AC_OUTPUT([
 Makefile
+dtrace-prelink.sh
 mono-uninstalled.pc
 scripts/mono-nunit.pc
 scripts/mono-find-provides
diff --git a/data/mono.d b/data/mono.d
new file mode 100644
index 0000000..f5e6b5d
--- /dev/null
+++ b/data/mono.d
@@ -0,0 +1,24 @@
+/* 
+ * mono.d: DTrace provider for Mono
+ * 
+ * Authors:
+ *   Andreas Faerber <andreas.faerber@web.de>
+ * 
+ */
+
+provider mono {
+	/* Virtual Execution System (VES) */
+	probe ves__init__begin ();
+	probe ves__init__end ();
+
+	/* Garbage Collector (GC) */	
+	probe gc__begin (int generation);
+	probe gc__end (int generation);
+};
+
+#pragma D attributes Evolving/Evolving/Common provider mono provider
+#pragma D attributes Private/Private/Unknown provider mono module
+#pragma D attributes Private/Private/Unknown provider mono function
+#pragma D attributes Evolving/Evolving/Common provider mono name
+#pragma D attributes Evolving/Evolving/Common provider mono args
+
diff --git a/dtrace-prelink.sh.in b/dtrace-prelink.sh.in
new file mode 100755
index 0000000..87a0ec4
--- /dev/null
+++ b/dtrace-prelink.sh.in
@@ -0,0 +1,87 @@
+#!/bin/sh
+# 
+# dtrace-prelink.sh: DTrace helper script for Mono
+# 
+# Authors:
+#   Andreas Faerber <andreas.faerber@web.de>
+# 
+
+AR="@AR@"
+DTRACE="@DTRACE@"
+DTRACEFLAGS="@DTRACEFLAGS@"
+
+# Assume that PIC object files live in .libs/, non-PIC code in ./
+PIC=no
+if test "$1" = "--pic"; then
+	PIC=yes
+	shift
+fi
+
+OBJ="$1"
+PROV="$2"
+
+shift
+shift
+
+FILES="$*"
+
+#echo PIC: ${PIC}
+#echo Output: ${OBJ}
+#echo Script: ${PROV}
+#echo Input: ${FILES}
+
+OBJS=
+TMPDIR=.dtrace
+mkdir -p "${TMPDIR}"
+
+# Extract relevant object files to temporary directories
+for FILE in ${FILES}; do
+	if echo "${FILE}" | grep .la > /dev/null; then
+		LIBDIR=`dirname ${FILE}`
+		LIB=".libs/`basename ${FILE} .la`.a"
+		DIR="${TMPDIR}/`basename ${FILE}`"
+		echo Extracting "${LIB}"...
+		mkdir -p ${DIR}
+		(cd "${DIR}" && ${AR} x "../../${LIBDIR}/${LIB}")
+		TMPOBJS=`ls -1 "${DIR}"`
+		for TMPOBJ in ${TMPOBJS}; do
+			#echo "Retrieving object file ${TMPOBJ}..."
+			LO=`basename "${TMPOBJ}" .o`.lo
+			SRCOBJ="${TMPOBJ}"
+			if test x${PIC} = xyes; then
+				SRCOBJ=".libs/${SRCOBJ}"
+			fi
+			# Overwrite with original version
+			#echo cp "${LIBDIR}/${SRCOBJ}" "${DIR}/${TMPOBJ}"
+			cp "${LIBDIR}/${SRCOBJ}" "${DIR}/${TMPOBJ}" || cp "${LIBDIR}/${TMPOBJ}" \
"${DIR}/${TMPOBJ}" || exit +			# Add to list
+			OBJS="${OBJS} ${DIR}/${TMPOBJ}"
+		done
+	fi
+	if echo "${FILE}" | grep .lo > /dev/null; then
+		DIR=`dirname ${FILE}`
+		SRCOBJ=`basename ${FILE} .lo`.o
+		if test x${PIC} = xyes; then
+			SRCOBJ=".libs/${SRCOBJ}"
+		fi
+		OBJS="${OBJS} ${DIR}/${SRCOBJ}"
+	fi
+done
+
+# Run dtrace -G over the temporary objects
+${DTRACE} -G ${DTRACEFLAGS} -s "${PROV}" -o "${OBJ}" ${OBJS} || exit
+
+# Update the archives with the temporary, modified object files so that they are \
linked in +for FILE in ${FILES}; do
+	if echo "${FILE}" | grep .la > /dev/null; then
+		LIBDIR=`dirname ${FILE}`
+		LIB=".libs/`basename ${FILE} .la`.a"
+		DIR="${TMPDIR}/`basename ${FILE}`"
+		echo Updating "${LIB}"...
+		(cd "${DIR}" && ${AR} r "../../${LIBDIR}/${LIB}" *.o)
+	fi
+	# .lo files were modified in-place
+done
+
+rm -rf "${TMPDIR}"
+
diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
index ec075aa..36c3771 100644
--- a/mono/metadata/Makefile.am
+++ b/mono/metadata/Makefile.am
@@ -169,11 +169,22 @@ libmonoruntimeinclude_HEADERS = \
 	debug-helpers.h	\
 	mempool.h
 
+if DTRACE_G_REQUIRED
+
+PEDUMP_DTRACE_OBJECT = pedump-dtrace.$(OBJEXT)
+
+pedump-dtrace.$(OBJEXT): $(top_srcdir)/data/mono.d libmonoruntime.la \
../io-layer/libwapi.la ../utils/libmonoutils.la +	$(SHELL) \
$(top_builddir)/dtrace-prelink.sh --pic pedump-dtrace.$(OBJEXT) \
$(top_srcdir)/data/mono.d libmonoruntime.la ../io-layer/libwapi.la \
../utils/libmonoutils.la +
+else
+PEDUMP_DTRACE_OBJECT = 
+endif
+
 pedump_SOURCES =		\
 	pedump.c
 
 pedump_LDADD = libmonoruntime.la ../io-layer/libwapi.la ../utils/libmonoutils.la \
-	$(LIBGC_LIBS) $(GLIB_LIBS) -lm
+	$(LIBGC_LIBS) $(GLIB_LIBS) -lm $(PEDUMP_DTRACE_OBJECT)
 
 EXTRA_DIST = make-bundle.pl sample-bundle
 
diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c
index 409bf2d..db29f93 100644
--- a/mono/metadata/boehm-gc.c
+++ b/mono/metadata/boehm-gc.c
@@ -13,6 +13,7 @@
 #include <mono/metadata/method-builder.h>
 #include <mono/metadata/opcodes.h>
 #include <mono/utils/mono-logger.h>
+#include <mono/utils/dtrace.h>
 
 #if HAVE_BOEHM_GC
 
@@ -106,7 +107,17 @@ mono_gc_base_init (void)
 void
 mono_gc_collect (int generation)
 {
+	MONO_PROBE_GC_BEGIN (generation);
+	
 	GC_gcollect ();
+	
+	MONO_PROBE_GC_END (generation);
+#if defined(ENABLE_DTRACE) && defined(__sun__)
+	/* This works around a dtrace -G problem on Solaris.
+	   Limit its actual use to when the probe is enabled. */
+	if (MONO_PROBE_GC_END_ENABLED ())
+		sleep(0);
+#endif
 }
 
 int
diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am
index a560ec0..745df38 100644
--- a/mono/mini/Makefile.am
+++ b/mono/mini/Makefile.am
@@ -80,6 +80,18 @@ endif
 mono_SOURCES = \
 	main.c
 
+if DTRACE_G_REQUIRED
+LIBMONO_DTRACE_OBJECT = .libs/mono-dtrace.$(OBJEXT)
+if STATIC_MONO
+MONO_DTRACE_OBJECT = mono-dtrace.$(OBJEXT)
+else
+MONO_DTRACE_OBJECT = 
+endif
+else
+MONO_DTRACE_OBJECT = 
+LIBMONO_DTRACE_OBJECT = 
+endif
+
 if STATIC_MONO
 # Link libmono into mono statically
 # This leads to higher performance, especially with TLS
@@ -91,11 +103,22 @@ endif
 mono_LDADD = \
 	$(MONO_LIB)			\
 	$(GLIB_LIBS)		\
-	-lm
+	-lm	\
+	$(MONO_DTRACE_OBJECT)
 
 mono_LDFLAGS = \
 	$(static_flags) -export-dynamic $(monobinldflags)
 
+if DTRACE_G_REQUIRED
+
+mono-dtrace.$(OBJEXT): $(top_srcdir)/data/mono.d mini.lo \
$(monodir)/mono/metadata/libmonoruntime-static.la +	$(SHELL) \
$(top_builddir)/dtrace-prelink.sh $@ $(top_srcdir)/data/mono.d \
$(monodir)/mono/metadata/libmonoruntime-static.la mini.lo +
+.libs/mono-dtrace.$(OBJEXT): $(top_srcdir)/data/mono.d mini.lo \
$(monodir)/mono/metadata/libmonoruntime.la +	$(SHELL) \
$(top_builddir)/dtrace-prelink.sh --pic $@ $(top_srcdir)/data/mono.d \
$(monodir)/mono/metadata/libmonoruntime.la mini.lo +
+endif
+
 # Create monow.exe, linked for the 'windows' subsystem
 if PLATFORM_WIN32
 monow_LDADD = $(mono_LDADD)
@@ -350,7 +373,7 @@ nodist_libmono_la_SOURCES = inssel.c inssel.h
 libmono_static_la_SOURCES = $(libmono_la_SOURCES)
 nodist_libmono_static_la_SOURCES = $(nodist_libmono_la_SOURCES)
 libmono_static_la_LDFLAGS = -static
-libmono_static_la_LIBADD = $(static_libs)
+libmono_static_la_LIBADD = $(static_libs) $(MONO_DTRACE_OBJECT)
 
 BURGSRC= $(common_BURGSRC) $(arch_BURGSRC)
 
@@ -359,7 +382,7 @@ libmonoincludedir = $(includedir)/mono-$(API_VER)/mono/jit
 libmonoinclude_HEADERS = jit.h
 
 libmono_la_LIBADD = \
-	$(libs)
+	$(libs) $(LIBMONO_DTRACE_OBJECT)
 
 generics.exe: generics.cs TestDriver.dll generics-variant-types.dll
 	$(MCS) -out:$@ $< -r:TestDriver.dll -r:generics-variant-types.dll
diff --git a/mono/mini/mini.c b/mono/mini/mini.c
index 70fcdfc..1b62296 100644
--- a/mono/mini/mini.c
+++ b/mono/mini/mini.c
@@ -64,6 +64,7 @@
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-logger.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/dtrace.h>
 
 #include "mini.h"
 #include <string.h>
@@ -13524,6 +13525,8 @@ mini_init (const char *filename, const char *runtime_version)
 {
 	MonoDomain *domain;
 
+	MONO_PROBE_VES_INIT_BEGIN ();
+
 #ifdef __linux__
 	if (access ("/proc/self/maps", F_OK) != 0) {
 		g_print ("Mono requires /proc to be mounted.\n");
@@ -13798,6 +13801,9 @@ mini_init (const char *filename, const char *runtime_version)
 	mono_generic_sharing_init ();
 
 	mono_thread_attach (domain);
+	
+	MONO_PROBE_VES_INIT_END ();
+	
 	return domain;
 }
 
diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am
index 2ecd435..5ebf845 100644
--- a/mono/utils/Makefile.am
+++ b/mono/utils/Makefile.am
@@ -2,6 +2,15 @@ noinst_LTLIBRARIES = libmonoutils.la
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/mono $(LIBGC_CFLAGS) $(GLIB_CFLAGS)
 
+if ENABLE_DTRACE
+
+BUILT_SOURCES = mono-dtrace.h
+
+mono-dtrace.h: $(top_srcdir)/data/mono.d
+	$(DTRACE) $(DTRACEFLAGS) -h -s $(top_srcdir)/data/mono.d -o $@
+
+endif
+
 if EGLIB_BUILD 
 hash_sources = mono-ehash.c
 else
diff --git a/mono/utils/dtrace.h b/mono/utils/dtrace.h
new file mode 100644
index 0000000..e69aadb
--- /dev/null
+++ b/mono/utils/dtrace.h
@@ -0,0 +1,51 @@
+/*
+ * dtrace.h: DTrace probes
+ * 
+ * Authors:
+ *   Andreas Faerber <andreas.faerber@web.de>
+ * 
+ */
+
+#ifndef __UTILS_DTRACE_H__
+#define __UTILS_DTRACE_H__
+
+#ifdef ENABLE_DTRACE
+
+
+#include <mono/utils/mono-dtrace.h>
+
+#define MONO_PROBE_VES_INIT_BEGIN()		MONO_VES_INIT_BEGIN ()
+#define MONO_PROBE_VES_INIT_BEGIN_ENABLED()	MONO_VES_INIT_BEGIN_ENABLED ()
+
+#define MONO_PROBE_VES_INIT_END()		MONO_VES_INIT_END ()
+#define MONO_PROBE_VES_INIT_END_ENABLED()	MONO_VES_INIT_END_ENABLED ()
+
+
+#define MONO_PROBE_GC_BEGIN(generation)	MONO_GC_BEGIN (generation)
+#define MONO_PROBE_GC_BEGIN_ENABLED()	MONO_GC_BEGIN_ENABLED ()
+
+#define MONO_PROBE_GC_END(generation)	MONO_GC_END (generation)
+#define MONO_PROBE_GC_END_ENABLED()	MONO_GC_END_ENABLED ()
+
+
+#else
+
+
+#define MONO_PROBE_VES_INIT_BEGIN()
+#define MONO_PROBE_VES_INIT_BEGIN_ENABLED() (0)
+
+#define MONO_PROBE_VES_INIT_END()
+#define MONO_PROBE_VES_INIT_END_ENABLED() (0)
+
+
+#define MONO_PROBE_GC_BEGIN(generation)
+#define MONO_PROBE_GC_BEGIN_ENABLED() (0)
+
+#define MONO_PROBE_GC_END(generation)
+#define MONO_PROBE_GC_END_ENABLED() (0)
+
+
+#endif
+
+#endif
+





_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic