1//===- include/Core/Instrumentation.h - Instrumentation API ---------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8/// 9/// \file 10/// Provide an Instrumentation API that optionally uses VTune interfaces. 11/// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLD_CORE_INSTRUMENTATION_H 15#define LLD_CORE_INSTRUMENTATION_H 16 17#include "llvm/Support/Compiler.h" 18#include <utility> 19 20#ifdef LLD_HAS_VTUNE 21# include <ittnotify.h> 22#endif 23 24namespace lld { 25#ifdef LLD_HAS_VTUNE 26/// A unique global scope for instrumentation data. 27/// 28/// Domains last for the lifetime of the application and cannot be destroyed. 29/// Multiple Domains created with the same name represent the same domain. 30class Domain { 31 __itt_domain *_domain; 32 33public: 34 explicit Domain(const char *name) : _domain(__itt_domain_createA(name)) {} 35 36 operator __itt_domain *() const { return _domain; } 37 __itt_domain *operator->() const { return _domain; } 38}; 39 40/// A global reference to a string constant. 41/// 42/// These are uniqued by the ITT runtime and cannot be deleted. They are not 43/// specific to a domain. 44/// 45/// Prefer reusing a single StringHandle over passing a ntbs when the same 46/// string will be used often. 47class StringHandle { 48 __itt_string_handle *_handle; 49 50public: 51 StringHandle(const char *name) : _handle(__itt_string_handle_createA(name)) {} 52 53 operator __itt_string_handle *() const { return _handle; } 54}; 55 56/// A task on a single thread. Nests within other tasks. 57/// 58/// Each thread has its own task stack and tasks nest recursively on that stack. 59/// A task cannot transfer threads. 60/// 61/// SBRM is used to ensure task starts and ends are balanced. The lifetime of 62/// a task is either the lifetime of this object, or until end is called. 63class ScopedTask { 64 __itt_domain *_domain; 65 66 ScopedTask(const ScopedTask &) = delete; 67 ScopedTask &operator=(const ScopedTask &) = delete; 68 69public: 70 /// Create a task in Domain \p d named \p s. 71 ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) { 72 __itt_task_begin(d, __itt_null, __itt_null, s); 73 } 74 75 ScopedTask(ScopedTask &&other) { 76 *this = std::move(other); 77 } 78 79 ScopedTask &operator=(ScopedTask &&other) { 80 _domain = other._domain; 81 other._domain = nullptr; 82 return *this; 83 } 84 85 /// Prematurely end this task. 86 void end() { 87 if (_domain) 88 __itt_task_end(_domain); 89 _domain = nullptr; 90 } 91 92 ~ScopedTask() { end(); } 93}; 94 95/// A specific point in time. Allows metadata to be associated. 96class Marker { 97public: 98 Marker(const Domain &d, const StringHandle &s) { 99 __itt_marker(d, __itt_null, s, __itt_scope_global); 100 } 101}; 102#else 103class Domain { 104public: 105 Domain(const char *name) {} 106}; 107 108class StringHandle { 109public: 110 StringHandle(const char *name) {} 111}; 112 113class ScopedTask { 114public: 115 ScopedTask(const Domain &d, const StringHandle &s) {} 116 void end() {} 117}; 118 119class Marker { 120public: 121 Marker(const Domain &d, const StringHandle &s) {} 122}; 123#endif 124 125inline const Domain &getDefaultDomain() { 126 static Domain domain("org.llvm.lld"); 127 return domain; 128} 129} // end namespace lld. 130 131#endif 132