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