1 /*
2  * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #include "precompiled.hpp"
26 #include "jvm.h"
27 #include "logging/log.hpp"
28 #include "memory/allocation.inline.hpp"
29 #include "runtime/arguments.hpp"
30 #include "runtime/atomic.hpp"
31 #include "runtime/java.hpp"
32 #include "runtime/mutex.hpp"
33 #include "runtime/mutexLocker.hpp"
34 #include "runtime/os.hpp"
35 #include "runtime/perfData.hpp"
36 #include "runtime/perfMemory.hpp"
37 #include "runtime/safepoint.hpp"
38 #include "runtime/statSampler.hpp"
39 #include "utilities/align.hpp"
40 #include "utilities/globalDefinitions.hpp"
41 
42 // Prefix of performance data file.
43 const char               PERFDATA_NAME[] = "hsperfdata";
44 
45 // Add 1 for the '_' character between PERFDATA_NAME and pid. The '\0' terminating
46 // character will be included in the sizeof(PERFDATA_NAME) operation.
47 static const size_t PERFDATA_FILENAME_LEN = sizeof(PERFDATA_NAME) +
48                                             UINT_CHARS + 1;
49 
50 char*                    PerfMemory::_start = NULL;
51 char*                    PerfMemory::_end = NULL;
52 char*                    PerfMemory::_top = NULL;
53 size_t                   PerfMemory::_capacity = 0;
54 int                      PerfMemory::_initialized = false;
55 PerfDataPrologue*        PerfMemory::_prologue = NULL;
56 bool                     PerfMemory::_destroyed = false;
57 
perfMemory_init()58 void perfMemory_init() {
59 
60   if (!UsePerfData) return;
61 
62   PerfMemory::initialize();
63 }
64 
perfMemory_exit()65 void perfMemory_exit() {
66 
67   if (!UsePerfData) return;
68   if (!PerfMemory::is_usable()) return;
69 
70   // Only destroy PerfData objects if we're at a safepoint and the
71   // StatSampler is not active. Otherwise, we risk removing PerfData
72   // objects that are currently being used by running JavaThreads
73   // or the StatSampler. This method is invoked while we are not at
74   // a safepoint during a VM abort so leaving the PerfData objects
75   // around may also help diagnose the failure. In rare cases,
76   // PerfData objects are used in parallel with a safepoint. See
77   // the work around in PerfDataManager::destroy().
78   //
79   if (SafepointSynchronize::is_at_safepoint() && !StatSampler::is_active()) {
80     PerfDataManager::destroy();
81   }
82 
83   // Remove the persistent external resources, if any. This method
84   // does not unmap or invalidate any virtual memory allocated during
85   // initialization.
86   //
87   PerfMemory::destroy();
88 }
89 
initialize()90 void PerfMemory::initialize() {
91 
92   if (is_initialized())
93     // initialization already performed
94     return;
95 
96   size_t capacity = align_up(PerfDataMemorySize,
97                              os::vm_allocation_granularity());
98 
99   log_debug(perf, memops)("PerfDataMemorySize = " SIZE_FORMAT ","
100                           " os::vm_allocation_granularity = %d,"
101                           " adjusted size = " SIZE_FORMAT,
102                           PerfDataMemorySize,
103                           os::vm_allocation_granularity(),
104                           capacity);
105 
106   // allocate PerfData memory region
107   create_memory_region(capacity);
108 
109   if (_start == NULL) {
110 
111     // the PerfMemory region could not be created as desired. Rather
112     // than terminating the JVM, we revert to creating the instrumentation
113     // on the C heap. When running in this mode, external monitoring
114     // clients cannot attach to and monitor this JVM.
115     //
116     // the warning is issued only in debug mode in order to avoid
117     // additional output to the stdout or stderr output streams.
118     //
119     if (PrintMiscellaneous && Verbose) {
120       warning("Could not create PerfData Memory region, reverting to malloc");
121     }
122 
123     _prologue = NEW_C_HEAP_OBJ(PerfDataPrologue, mtInternal);
124   }
125   else {
126 
127     // the PerfMemory region was created as expected.
128 
129     log_debug(perf, memops)("PerfMemory created: address = " INTPTR_FORMAT ","
130                             " size = " SIZE_FORMAT,
131                             p2i(_start),
132                             _capacity);
133 
134     _prologue = (PerfDataPrologue *)_start;
135     _end = _start + _capacity;
136     _top = _start + sizeof(PerfDataPrologue);
137   }
138 
139   assert(_prologue != NULL, "prologue pointer must be initialized");
140 
141 #ifdef VM_LITTLE_ENDIAN
142   _prologue->magic = (jint)0xc0c0feca;
143   _prologue->byte_order = PERFDATA_LITTLE_ENDIAN;
144 #else
145   _prologue->magic = (jint)0xcafec0c0;
146   _prologue->byte_order = PERFDATA_BIG_ENDIAN;
147 #endif
148 
149   _prologue->major_version = PERFDATA_MAJOR_VERSION;
150   _prologue->minor_version = PERFDATA_MINOR_VERSION;
151   _prologue->accessible = 0;
152 
153   _prologue->entry_offset = sizeof(PerfDataPrologue);
154   _prologue->num_entries = 0;
155   _prologue->used = 0;
156   _prologue->overflow = 0;
157   _prologue->mod_time_stamp = 0;
158 
159   Atomic::release_store(&_initialized, 1);
160 }
161 
destroy()162 void PerfMemory::destroy() {
163 
164   if (!is_usable()) return;
165 
166   if (_start != NULL && _prologue->overflow != 0) {
167 
168     // This state indicates that the contiguous memory region exists and
169     // that it wasn't large enough to hold all the counters. In this case,
170     // we output a warning message to the user on exit if the -XX:+Verbose
171     // flag is set (a debug only flag). External monitoring tools can detect
172     // this condition by monitoring the _prologue->overflow word.
173     //
174     // There are two tunables that can help resolve this issue:
175     //   - increase the size of the PerfMemory with -XX:PerfDataMemorySize=<n>
176     //   - decrease the maximum string constant length with
177     //     -XX:PerfMaxStringConstLength=<n>
178     //
179     if (PrintMiscellaneous && Verbose) {
180       warning("PerfMemory Overflow Occurred.\n"
181               "\tCapacity = " SIZE_FORMAT " bytes"
182               "  Used = " SIZE_FORMAT " bytes"
183               "  Overflow = " INT32_FORMAT " bytes"
184               "\n\tUse -XX:PerfDataMemorySize=<size> to specify larger size.",
185               PerfMemory::capacity(),
186               PerfMemory::used(),
187               _prologue->overflow);
188     }
189   }
190 
191   if (_start != NULL) {
192 
193     // this state indicates that the contiguous memory region was successfully
194     // and that persistent resources may need to be cleaned up. This is
195     // expected to be the typical condition.
196     //
197     delete_memory_region();
198   }
199 
200   _destroyed = true;
201 }
202 
203 // allocate an aligned block of memory from the PerfData memory
204 // region. This method assumes that the PerfData memory region
205 // was aligned on a double word boundary when created.
206 //
alloc(size_t size)207 char* PerfMemory::alloc(size_t size) {
208 
209   if (!UsePerfData) return NULL;
210 
211   MutexLocker ml(PerfDataMemAlloc_lock);
212 
213   assert(is_usable(), "called before init or after destroy");
214 
215   // check that there is enough memory for this request
216   if ((_top + size) >= _end) {
217 
218     _prologue->overflow += (jint)size;
219 
220     return NULL;
221   }
222 
223   char* result = _top;
224 
225   _top += size;
226 
227   assert(contains(result), "PerfData memory pointer out of range");
228 
229   _prologue->used = (jint)used();
230   _prologue->num_entries = _prologue->num_entries + 1;
231 
232   return result;
233 }
234 
mark_updated()235 void PerfMemory::mark_updated() {
236   if (!UsePerfData) return;
237 
238   assert(is_usable(), "called before init or after destroy");
239 
240   _prologue->mod_time_stamp = os::elapsed_counter();
241 }
242 
243 // Returns the complete path including the file name of performance data file.
244 // Caller is expected to release the allocated memory.
get_perfdata_file_path()245 char* PerfMemory::get_perfdata_file_path() {
246   char* dest_file = NULL;
247 
248   if (PerfDataSaveFile != NULL) {
249     // dest_file_name stores the validated file name if file_name
250     // contains %p which will be replaced by pid.
251     dest_file = NEW_C_HEAP_ARRAY(char, JVM_MAXPATHLEN, mtInternal);
252     if(!Arguments::copy_expand_pid(PerfDataSaveFile, strlen(PerfDataSaveFile),
253                                    dest_file, JVM_MAXPATHLEN)) {
254       FREE_C_HEAP_ARRAY(char, dest_file);
255       if (PrintMiscellaneous && Verbose) {
256         warning("Invalid performance data file path name specified, "\
257                 "fall back to a default name");
258       }
259     } else {
260       return dest_file;
261     }
262   }
263   // create the name of the file for retaining the instrumentation memory.
264   dest_file = NEW_C_HEAP_ARRAY(char, PERFDATA_FILENAME_LEN, mtInternal);
265   jio_snprintf(dest_file, PERFDATA_FILENAME_LEN,
266                "%s_%d", PERFDATA_NAME, os::current_process_id());
267 
268   return dest_file;
269 }
270 
is_initialized()271 bool PerfMemory::is_initialized() {
272   return Atomic::load_acquire(&_initialized) != 0;
273 }
274