summaryrefslogtreecommitdiffstats
path: root/tools/profiler/public/MicroGeckoProfiler.h
diff options
context:
space:
mode:
Diffstat (limited to 'tools/profiler/public/MicroGeckoProfiler.h')
-rw-r--r--tools/profiler/public/MicroGeckoProfiler.h130
1 files changed, 130 insertions, 0 deletions
diff --git a/tools/profiler/public/MicroGeckoProfiler.h b/tools/profiler/public/MicroGeckoProfiler.h
new file mode 100644
index 0000000000..7b735e1eec
--- /dev/null
+++ b/tools/profiler/public/MicroGeckoProfiler.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This contains things related to the Gecko profiler, for use in third_party
+// code. It is very minimal and is designed to be used by patching over
+// upstream code.
+// Only use the C ABI and guard C++ code with #ifdefs, don't pull anything from
+// Gecko, it must be possible to include the header file into any C++ codebase.
+
+#ifndef MICRO_GECKO_PROFILER
+#define MICRO_GECKO_PROFILER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mozilla/Types.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+# include <libloaderapi.h>
+#else
+# include <dlfcn.h>
+#endif
+
+extern MOZ_EXPORT void uprofiler_register_thread(const char* aName,
+ void* aGuessStackTop);
+
+extern MOZ_EXPORT void uprofiler_unregister_thread();
+
+extern MOZ_EXPORT void uprofiler_simple_event_marker(
+ const char* name, char phase, int num_args, const char** arg_names,
+ const unsigned char* arg_types, const unsigned long long* arg_values);
+#ifdef __cplusplus
+}
+
+struct AutoRegisterProfiler {
+ AutoRegisterProfiler(const char* name, char* stacktop) {
+ if (getenv("MOZ_UPROFILER_LOG_THREAD_CREATION")) {
+ printf("### UProfiler: new thread: '%s'\n", name);
+ }
+ uprofiler_register_thread(name, stacktop);
+ }
+ ~AutoRegisterProfiler() { uprofiler_unregister_thread(); }
+};
+#endif // __cplusplus
+
+void uprofiler_simple_event_marker(const char* name, char phase, int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values);
+
+struct UprofilerFuncPtrs {
+ void (*register_thread)(const char* aName, void* aGuessStackTop);
+ void (*unregister_thread)();
+ void (*simple_event_marker)(const char* name, char phase, int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values);
+};
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+static void register_thread_noop(const char* aName, void* aGuessStackTop) {
+ /* no-op */
+}
+static void unregister_thread_noop() { /* no-op */
+}
+static void simple_event_marker_noop(const char* name, char phase, int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values) {
+ /* no-op */
+}
+
+#pragma GCC diagnostic pop
+
+#if defined(_WIN32)
+# define UPROFILER_OPENLIB() GetModuleHandle(NULL)
+#else
+# define UPROFILER_OPENLIB() dlopen(NULL, RTLD_NOW)
+#endif
+
+#if defined(_WIN32)
+# define UPROFILER_GET_SYM(handle, sym) GetProcAddress(handle, sym)
+#else
+# define UPROFILER_GET_SYM(handle, sym) dlsym(handle, sym)
+#endif
+
+#if defined(_WIN32)
+# define UPROFILER_PRINT_ERROR(func) fprintf(stderr, "%s error\n", #func);
+#else
+# define UPROFILER_PRINT_ERROR(func) \
+ fprintf(stderr, "%s error: %s\n", #func, dlerror());
+#endif
+
+// Assumes that a variable of type UprofilerFuncPtrs, named uprofiler
+// is accessible in the scope
+#define UPROFILER_GET_FUNCTIONS() \
+ void* handle = UPROFILER_OPENLIB(); \
+ if (!handle) { \
+ UPROFILER_PRINT_ERROR(UPROFILER_OPENLIB); \
+ uprofiler.register_thread = register_thread_noop; \
+ uprofiler.unregister_thread = unregister_thread_noop; \
+ uprofiler.simple_event_marker = simple_event_marker_noop; \
+ } \
+ uprofiler.register_thread = \
+ UPROFILER_GET_SYM(handle, "uprofiler_register_thread"); \
+ if (!uprofiler.register_thread) { \
+ UPROFILER_PRINT_ERROR(uprofiler_unregister_thread); \
+ uprofiler.register_thread = register_thread_noop; \
+ } \
+ uprofiler.unregister_thread = \
+ UPROFILER_GET_SYM(handle, "uprofiler_unregister_thread"); \
+ if (!uprofiler.unregister_thread) { \
+ UPROFILER_PRINT_ERROR(uprofiler_unregister_thread); \
+ uprofiler.unregister_thread = unregister_thread_noop; \
+ } \
+ uprofiler.simple_event_marker = \
+ UPROFILER_GET_SYM(handle, "uprofiler_simple_event_marker"); \
+ if (!uprofiler.simple_event_marker) { \
+ UPROFILER_PRINT_ERROR(uprofiler_simple_event_marker); \
+ uprofiler.simple_event_marker = simple_event_marker_noop; \
+ }
+
+#endif // MICRO_GECKO_PROFILER