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
24 namespace 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.
30 class Domain {
31 __itt_domain *_domain;
32
33 public:
Domain(const char * name)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.
47 class StringHandle {
48 __itt_string_handle *_handle;
49
50 public:
StringHandle(const char * name)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.
63 class ScopedTask {
64 __itt_domain *_domain;
65
66 ScopedTask(const ScopedTask &) = delete;
67 ScopedTask &operator=(const ScopedTask &) = delete;
68
69 public:
70 /// Create a task in Domain \p d named \p s.
ScopedTask(const Domain & d,const StringHandle & s)71 ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) {
72 __itt_task_begin(d, __itt_null, __itt_null, s);
73 }
74
ScopedTask(ScopedTask && other)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.
end()86 void end() {
87 if (_domain)
88 __itt_task_end(_domain);
89 _domain = nullptr;
90 }
91
~ScopedTask()92 ~ScopedTask() { end(); }
93 };
94
95 /// A specific point in time. Allows metadata to be associated.
96 class Marker {
97 public:
Marker(const Domain & d,const StringHandle & s)98 Marker(const Domain &d, const StringHandle &s) {
99 __itt_marker(d, __itt_null, s, __itt_scope_global);
100 }
101 };
102 #else
103 class Domain {
104 public:
105 Domain(const char *name) {}
106 };
107
108 class StringHandle {
109 public:
110 StringHandle(const char *name) {}
111 };
112
113 class ScopedTask {
114 public:
115 ScopedTask(const Domain &d, const StringHandle &s) {}
116 void end() {}
117 };
118
119 class Marker {
120 public:
121 Marker(const Domain &d, const StringHandle &s) {}
122 };
123 #endif
124
getDefaultDomain()125 inline const Domain &getDefaultDomain() {
126 static Domain domain("org.llvm.lld");
127 return domain;
128 }
129 } // end namespace lld.
130
131 #endif
132