1/*******************************************************************************
2* Copyright 2019-2021 Intel Corporation
3* Copyright 2021 FUJITSU LIMITED
4*
5* Licensed under the Apache License, Version 2.0 (the "License");
6* you may not use this file except in compliance with the License.
7* You may obtain a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS,
13* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14* See the License for the specific language governing permissions and
15* limitations under the License.
16*******************************************************************************/
17
18#include <mutex>
19
20#include "common/utils.hpp"
21
22#include "cpu/platform.hpp"
23
24#ifndef DNNL_ENABLE_JIT_PROFILING
25#define DNNL_ENABLE_JIT_PROFILING 1
26#endif
27
28#ifndef DNNL_ENABLE_JIT_DUMP
29#define DNNL_ENABLE_JIT_DUMP 1
30#endif
31
32#if DNNL_ENABLE_JIT_PROFILING
33#include "common/ittnotify/jitprofiling.h"
34#ifdef __linux__
35#include "cpu/jit_utils/linux_perf/linux_perf.hpp"
36#endif
37#endif
38
39namespace dnnl {
40namespace impl {
41namespace cpu {
42namespace jit_utils {
43
44// WARNING: These functions are not thread safe and must be protected by a
45// mutex
46
47// TODO (rsdubtso): support prefix for code dumps
48
49void dump_jit_code(const void *code, size_t code_size, const char *code_name) {
50#if DNNL_ENABLE_JIT_DUMP
51 if (code && get_jit_dump()) {
52 static int counter = 0;
53#define MAX_FNAME_LEN 256
54 char fname[MAX_FNAME_LEN + 1];
55 // TODO (Roma): support prefix for code / linux perf dumps
56 snprintf(fname, MAX_FNAME_LEN, "dnnl_dump_cpu_%s.%d.bin", code_name,
57 counter);
58 counter++;
59
60 FILE *fp = fopen(fname, "wb+");
61 // Failure to dump code is not fatal
62 if (fp) {
63 size_t unused = fwrite(code, code_size, 1, fp);
64 UNUSED(unused);
65 fclose(fp);
66 }
67 }
68#undef MAX_FNAME_LEN
69#else
70 UNUSED(code);
71 UNUSED(code_size);
72 UNUSED(code_name);
73#endif
74}
75
76void register_jit_code_vtune(const void *code, size_t code_size,
77 const char *code_name, const char *source_file_name) {
78#if DNNL_ENABLE_JIT_PROFILING
79 unsigned flags = get_jit_profiling_flags();
80#if DNNL_X64
81 if ((flags & DNNL_JIT_PROFILE_VTUNE)
82 && iJIT_IsProfilingActive() == iJIT_SAMPLING_ON) {
83 auto jmethod = iJIT_Method_Load();
84 jmethod.method_id = iJIT_GetNewMethodID(); // XXX: not thread-safe
85 jmethod.method_name = (char *)code_name; // XXX: dropping const
86 jmethod.class_file_name = nullptr;
87 jmethod.source_file_name
88 = (char *)source_file_name; // XXX: dropping const
89 jmethod.method_load_address = (void *)code;
90 jmethod.method_size = (unsigned int)code_size;
91
92 iJIT_NotifyEvent(
93 iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void *)&jmethod);
94 }
95#else
96 if (flags & DNNL_JIT_PROFILE_VTUNE)
97 fprintf(stderr, "VTune Amplifier integration is not supported.\n");
98#endif
99#else
100 UNUSED(code);
101 UNUSED(code_size);
102 UNUSED(code_name);
103 UNUSED(source_file_name);
104#endif
105}
106
107void register_jit_code_linux_perf(const void *code, size_t code_size,
108 const char *code_name, const char *source_file_name) {
109#if DNNL_ENABLE_JIT_PROFILING && defined(__linux__)
110 unsigned flags = get_jit_profiling_flags();
111 if (flags & DNNL_JIT_PROFILE_LINUX_JITDUMP)
112 linux_perf_jitdump_record_code_load(code, code_size, code_name);
113 if (flags & DNNL_JIT_PROFILE_LINUX_PERFMAP)
114 linux_perf_perfmap_record_code_load(code, code_size, code_name);
115#else
116 UNUSED(code);
117 UNUSED(code_size);
118 UNUSED(code_name);
119#endif
120 UNUSED(source_file_name);
121}
122
123void register_jit_code(const void *code, size_t code_size,
124 const char *code_name, const char *source_file_name) {
125 // The #ifdef guards are required to avoid generating a function that only
126 // consists of lock and unlock code
127#if DNNL_ENABLE_JIT_PROFILING || DNNL_ENABLE_JIT_DUMP
128 static std::mutex m;
129 std::lock_guard<std::mutex> guard(m);
130
131 dump_jit_code(code, code_size, code_name);
132 register_jit_code_vtune(code, code_size, code_name, source_file_name);
133 register_jit_code_linux_perf(code, code_size, code_name, source_file_name);
134#else
135 UNUSED(code);
136 UNUSED(code_size);
137 UNUSED(code_name);
138 UNUSED(source_file_name);
139#endif
140}
141
142} // namespace jit_utils
143} // namespace cpu
144} // namespace impl
145} // namespace dnnl
146