Mercurial > hg > truffle
annotate src/os/linux/vm/perfMemory_linux.cpp @ 12986:1b422ef5288a
8025728: Missing volatile specifier for field G1AllocRegion::_alloc_region
Summary: The field G1AllocRegion::_alloc_region needs to be declared volatile as it is used with that intention. Otherwise the compiler may generate the code that reloads the value which might have changed in the meantime, leading to spurious crashes.
Reviewed-by: iveresov, simonis, tschatzl
Contributed-by: Axel Siebenborn <axel.siebenborn@sap.com>
author | tschatzl |
---|---|
date | Wed, 23 Oct 2013 10:23:06 +0200 |
parents | 1f4355cee9a2 |
children | 2c2a99f6cf83 |
rev | line source |
---|---|
0 | 1 /* |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
9064
diff
changeset
|
2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/vmSymbols.hpp" | |
27 #include "memory/allocation.inline.hpp" | |
28 #include "memory/resourceArea.hpp" | |
29 #include "oops/oop.inline.hpp" | |
30 #include "os_linux.inline.hpp" | |
31 #include "runtime/handles.inline.hpp" | |
32 #include "runtime/perfMemory.hpp" | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
33 #include "services/memTracker.hpp" |
1972 | 34 #include "utilities/exceptions.hpp" |
0 | 35 |
36 // put OS-includes here | |
37 # include <sys/types.h> | |
38 # include <sys/mman.h> | |
39 # include <errno.h> | |
40 # include <stdio.h> | |
41 # include <unistd.h> | |
42 # include <sys/stat.h> | |
43 # include <signal.h> | |
44 # include <pwd.h> | |
45 | |
46 static char* backing_store_file_name = NULL; // name of the backing store | |
47 // file, if successfully created. | |
48 | |
49 // Standard Memory Implementation Details | |
50 | |
51 // create the PerfData memory region in standard memory. | |
52 // | |
53 static char* create_standard_memory(size_t size) { | |
54 | |
55 // allocate an aligned chuck of memory | |
56 char* mapAddress = os::reserve_memory(size); | |
57 | |
58 if (mapAddress == NULL) { | |
59 return NULL; | |
60 } | |
61 | |
62 // commit memory | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
9064
diff
changeset
|
63 if (!os::commit_memory(mapAddress, size, !ExecMem)) { |
0 | 64 if (PrintMiscellaneous && Verbose) { |
65 warning("Could not commit PerfData memory\n"); | |
66 } | |
67 os::release_memory(mapAddress, size); | |
68 return NULL; | |
69 } | |
70 | |
71 return mapAddress; | |
72 } | |
73 | |
74 // delete the PerfData memory region | |
75 // | |
76 static void delete_standard_memory(char* addr, size_t size) { | |
77 | |
78 // there are no persistent external resources to cleanup for standard | |
79 // memory. since DestroyJavaVM does not support unloading of the JVM, | |
80 // cleanup of the memory resource is not performed. The memory will be | |
81 // reclaimed by the OS upon termination of the process. | |
82 // | |
83 return; | |
84 } | |
85 | |
86 // save the specified memory region to the given file | |
87 // | |
88 // Note: this function might be called from signal handler (by os::abort()), | |
89 // don't allocate heap memory. | |
90 // | |
91 static void save_memory_to_file(char* addr, size_t size) { | |
92 | |
93 const char* destfile = PerfMemory::get_perfdata_file_path(); | |
94 assert(destfile[0] != '\0', "invalid PerfData file path"); | |
95 | |
96 int result; | |
97 | |
98 RESTARTABLE(::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE), | |
99 result);; | |
100 if (result == OS_ERR) { | |
101 if (PrintMiscellaneous && Verbose) { | |
102 warning("Could not create Perfdata save file: %s: %s\n", | |
103 destfile, strerror(errno)); | |
104 } | |
105 } else { | |
106 int fd = result; | |
107 | |
108 for (size_t remaining = size; remaining > 0;) { | |
109 | |
110 RESTARTABLE(::write(fd, addr, remaining), result); | |
111 if (result == OS_ERR) { | |
112 if (PrintMiscellaneous && Verbose) { | |
113 warning("Could not write Perfdata save file: %s: %s\n", | |
114 destfile, strerror(errno)); | |
115 } | |
116 break; | |
117 } | |
118 | |
119 remaining -= (size_t)result; | |
120 addr += result; | |
121 } | |
122 | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
10969
diff
changeset
|
123 result = ::close(fd); |
0 | 124 if (PrintMiscellaneous && Verbose) { |
125 if (result == OS_ERR) { | |
126 warning("Could not close %s: %s\n", destfile, strerror(errno)); | |
127 } | |
128 } | |
129 } | |
6197 | 130 FREE_C_HEAP_ARRAY(char, destfile, mtInternal); |
0 | 131 } |
132 | |
133 | |
134 // Shared Memory Implementation Details | |
135 | |
136 // Note: the solaris and linux shared memory implementation uses the mmap | |
137 // interface with a backing store file to implement named shared memory. | |
138 // Using the file system as the name space for shared memory allows a | |
139 // common name space to be supported across a variety of platforms. It | |
140 // also provides a name space that Java applications can deal with through | |
141 // simple file apis. | |
142 // | |
143 // The solaris and linux implementations store the backing store file in | |
144 // a user specific temporary directory located in the /tmp file system, | |
145 // which is always a local file system and is sometimes a RAM based file | |
146 // system. | |
147 | |
148 // return the user specific temporary directory name. | |
149 // | |
150 // the caller is expected to free the allocated memory. | |
151 // | |
152 static char* get_user_tmp_dir(const char* user) { | |
153 | |
154 const char* tmpdir = os::get_temp_directory(); | |
155 const char* perfdir = PERFDATA_NAME; | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
605
diff
changeset
|
156 size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3; |
6197 | 157 char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 158 |
159 // construct the path name to user specific tmp directory | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
605
diff
changeset
|
160 snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user); |
0 | 161 |
162 return dirname; | |
163 } | |
164 | |
165 // convert the given file name into a process id. if the file | |
166 // does not meet the file naming constraints, return 0. | |
167 // | |
168 static pid_t filename_to_pid(const char* filename) { | |
169 | |
170 // a filename that doesn't begin with a digit is not a | |
171 // candidate for conversion. | |
172 // | |
173 if (!isdigit(*filename)) { | |
174 return 0; | |
175 } | |
176 | |
177 // check if file name can be converted to an integer without | |
178 // any leftover characters. | |
179 // | |
180 char* remainder = NULL; | |
181 errno = 0; | |
182 pid_t pid = (pid_t)strtol(filename, &remainder, 10); | |
183 | |
184 if (errno != 0) { | |
185 return 0; | |
186 } | |
187 | |
188 // check for left over characters. If any, then the filename is | |
189 // not a candidate for conversion. | |
190 // | |
191 if (remainder != NULL && *remainder != '\0') { | |
192 return 0; | |
193 } | |
194 | |
195 // successful conversion, return the pid | |
196 return pid; | |
197 } | |
198 | |
199 | |
200 // check if the given path is considered a secure directory for | |
201 // the backing store files. Returns true if the directory exists | |
202 // and is considered a secure location. Returns false if the path | |
605 | 203 // is a symbolic link or if an error occurred. |
0 | 204 // |
205 static bool is_directory_secure(const char* path) { | |
206 struct stat statbuf; | |
207 int result = 0; | |
208 | |
209 RESTARTABLE(::lstat(path, &statbuf), result); | |
210 if (result == OS_ERR) { | |
211 return false; | |
212 } | |
213 | |
214 // the path exists, now check it's mode | |
215 if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { | |
216 // the path represents a link or some non-directory file type, | |
217 // which is not what we expected. declare it insecure. | |
218 // | |
219 return false; | |
220 } | |
221 else { | |
222 // we have an existing directory, check if the permissions are safe. | |
223 // | |
224 if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { | |
225 // the directory is open for writing and could be subjected | |
226 // to a symlnk attack. declare it insecure. | |
227 // | |
228 return false; | |
229 } | |
230 } | |
231 return true; | |
232 } | |
233 | |
234 | |
235 // return the user name for the given user id | |
236 // | |
237 // the caller is expected to free the allocated memory. | |
238 // | |
239 static char* get_user_name(uid_t uid) { | |
240 | |
241 struct passwd pwent; | |
242 | |
243 // determine the max pwbuf size from sysconf, and hardcode | |
244 // a default if this not available through sysconf. | |
245 // | |
246 long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); | |
247 if (bufsize == -1) | |
248 bufsize = 1024; | |
249 | |
6197 | 250 char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal); |
0 | 251 |
252 // POSIX interface to getpwuid_r is used on LINUX | |
253 struct passwd* p; | |
254 int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p); | |
255 | |
256 if (result != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { | |
257 if (PrintMiscellaneous && Verbose) { | |
258 if (result != 0) { | |
259 warning("Could not retrieve passwd entry: %s\n", | |
260 strerror(result)); | |
261 } | |
262 else if (p == NULL) { | |
263 // this check is added to protect against an observed problem | |
264 // with getpwuid_r() on RedHat 9 where getpwuid_r returns 0, | |
265 // indicating success, but has p == NULL. This was observed when | |
266 // inserting a file descriptor exhaustion fault prior to the call | |
267 // getpwuid_r() call. In this case, error is set to the appropriate | |
268 // error condition, but this is undocumented behavior. This check | |
269 // is safe under any condition, but the use of errno in the output | |
270 // message may result in an erroneous message. | |
271 // Bug Id 89052 was opened with RedHat. | |
272 // | |
273 warning("Could not retrieve passwd entry: %s\n", | |
274 strerror(errno)); | |
275 } | |
276 else { | |
277 warning("Could not determine user name: %s\n", | |
278 p->pw_name == NULL ? "pw_name = NULL" : | |
279 "pw_name zero length"); | |
280 } | |
281 } | |
6197 | 282 FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal); |
0 | 283 return NULL; |
284 } | |
285 | |
6197 | 286 char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal); |
0 | 287 strcpy(user_name, p->pw_name); |
288 | |
6197 | 289 FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal); |
0 | 290 return user_name; |
291 } | |
292 | |
293 // return the name of the user that owns the process identified by vmid. | |
294 // | |
295 // This method uses a slow directory search algorithm to find the backing | |
296 // store file for the specified vmid and returns the user name, as determined | |
297 // by the user name suffix of the hsperfdata_<username> directory name. | |
298 // | |
299 // the caller is expected to free the allocated memory. | |
300 // | |
301 static char* get_user_name_slow(int vmid, TRAPS) { | |
302 | |
303 // short circuit the directory search if the process doesn't even exist. | |
304 if (kill(vmid, 0) == OS_ERR) { | |
305 if (errno == ESRCH) { | |
306 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), | |
307 "Process not found"); | |
308 } | |
309 else /* EPERM */ { | |
310 THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); | |
311 } | |
312 } | |
313 | |
314 // directory search | |
315 char* oldest_user = NULL; | |
316 time_t oldest_ctime = 0; | |
317 | |
318 const char* tmpdirname = os::get_temp_directory(); | |
319 | |
320 DIR* tmpdirp = os::opendir(tmpdirname); | |
321 | |
322 if (tmpdirp == NULL) { | |
323 return NULL; | |
324 } | |
325 | |
326 // for each entry in the directory that matches the pattern hsperfdata_*, | |
327 // open the directory and check if the file for the given vmid exists. | |
328 // The file with the expected name and the latest creation date is used | |
329 // to determine the user name for the process id. | |
330 // | |
331 struct dirent* dentry; | |
6197 | 332 char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal); |
0 | 333 errno = 0; |
334 while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) { | |
335 | |
336 // check if the directory entry is a hsperfdata file | |
337 if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) { | |
338 continue; | |
339 } | |
340 | |
341 char* usrdir_name = NEW_C_HEAP_ARRAY(char, | |
6197 | 342 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); |
0 | 343 strcpy(usrdir_name, tmpdirname); |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
605
diff
changeset
|
344 strcat(usrdir_name, "/"); |
0 | 345 strcat(usrdir_name, dentry->d_name); |
346 | |
347 DIR* subdirp = os::opendir(usrdir_name); | |
348 | |
349 if (subdirp == NULL) { | |
6197 | 350 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
0 | 351 continue; |
352 } | |
353 | |
354 // Since we don't create the backing store files in directories | |
355 // pointed to by symbolic links, we also don't follow them when | |
356 // looking for the files. We check for a symbolic link after the | |
357 // call to opendir in order to eliminate a small window where the | |
358 // symlink can be exploited. | |
359 // | |
360 if (!is_directory_secure(usrdir_name)) { | |
6197 | 361 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
0 | 362 os::closedir(subdirp); |
363 continue; | |
364 } | |
365 | |
366 struct dirent* udentry; | |
6197 | 367 char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); |
0 | 368 errno = 0; |
369 while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) { | |
370 | |
371 if (filename_to_pid(udentry->d_name) == vmid) { | |
372 struct stat statbuf; | |
373 int result; | |
374 | |
375 char* filename = NEW_C_HEAP_ARRAY(char, | |
6197 | 376 strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal); |
0 | 377 |
378 strcpy(filename, usrdir_name); | |
379 strcat(filename, "/"); | |
380 strcat(filename, udentry->d_name); | |
381 | |
382 // don't follow symbolic links for the file | |
383 RESTARTABLE(::lstat(filename, &statbuf), result); | |
384 if (result == OS_ERR) { | |
6197 | 385 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 386 continue; |
387 } | |
388 | |
389 // skip over files that are not regular files. | |
390 if (!S_ISREG(statbuf.st_mode)) { | |
6197 | 391 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 392 continue; |
393 } | |
394 | |
395 // compare and save filename with latest creation time | |
396 if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) { | |
397 | |
398 if (statbuf.st_ctime > oldest_ctime) { | |
399 char* user = strchr(dentry->d_name, '_') + 1; | |
400 | |
6197 | 401 if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal); |
402 oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal); | |
0 | 403 |
404 strcpy(oldest_user, user); | |
405 oldest_ctime = statbuf.st_ctime; | |
406 } | |
407 } | |
408 | |
6197 | 409 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 410 } |
411 } | |
412 os::closedir(subdirp); | |
6197 | 413 FREE_C_HEAP_ARRAY(char, udbuf, mtInternal); |
414 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); | |
0 | 415 } |
416 os::closedir(tmpdirp); | |
6197 | 417 FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal); |
0 | 418 |
419 return(oldest_user); | |
420 } | |
421 | |
422 // return the name of the user that owns the JVM indicated by the given vmid. | |
423 // | |
424 static char* get_user_name(int vmid, TRAPS) { | |
425 return get_user_name_slow(vmid, CHECK_NULL); | |
426 } | |
427 | |
428 // return the file name of the backing store file for the named | |
429 // shared memory region for the given user name and vmid. | |
430 // | |
431 // the caller is expected to free the allocated memory. | |
432 // | |
433 static char* get_sharedmem_filename(const char* dirname, int vmid) { | |
434 | |
435 // add 2 for the file separator and a null terminator. | |
436 size_t nbytes = strlen(dirname) + UINT_CHARS + 2; | |
437 | |
6197 | 438 char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 439 snprintf(name, nbytes, "%s/%d", dirname, vmid); |
440 | |
441 return name; | |
442 } | |
443 | |
444 | |
445 // remove file | |
446 // | |
447 // this method removes the file specified by the given path | |
448 // | |
449 static void remove_file(const char* path) { | |
450 | |
451 int result; | |
452 | |
453 // if the file is a directory, the following unlink will fail. since | |
454 // we don't expect to find directories in the user temp directory, we | |
455 // won't try to handle this situation. even if accidentially or | |
456 // maliciously planted, the directory's presence won't hurt anything. | |
457 // | |
458 RESTARTABLE(::unlink(path), result); | |
459 if (PrintMiscellaneous && Verbose && result == OS_ERR) { | |
460 if (errno != ENOENT) { | |
461 warning("Could not unlink shared memory backing" | |
462 " store file %s : %s\n", path, strerror(errno)); | |
463 } | |
464 } | |
465 } | |
466 | |
467 | |
468 // remove file | |
469 // | |
470 // this method removes the file with the given file name in the | |
471 // named directory. | |
472 // | |
473 static void remove_file(const char* dirname, const char* filename) { | |
474 | |
475 size_t nbytes = strlen(dirname) + strlen(filename) + 2; | |
6197 | 476 char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 477 |
478 strcpy(path, dirname); | |
479 strcat(path, "/"); | |
480 strcat(path, filename); | |
481 | |
482 remove_file(path); | |
483 | |
6197 | 484 FREE_C_HEAP_ARRAY(char, path, mtInternal); |
0 | 485 } |
486 | |
487 | |
488 // cleanup stale shared memory resources | |
489 // | |
490 // This method attempts to remove all stale shared memory files in | |
491 // the named user temporary directory. It scans the named directory | |
492 // for files matching the pattern ^$[0-9]*$. For each file found, the | |
493 // process id is extracted from the file name and a test is run to | |
494 // determine if the process is alive. If the process is not alive, | |
495 // any stale file resources are removed. | |
496 // | |
497 static void cleanup_sharedmem_resources(const char* dirname) { | |
498 | |
499 // open the user temp directory | |
500 DIR* dirp = os::opendir(dirname); | |
501 | |
502 if (dirp == NULL) { | |
503 // directory doesn't exist, so there is nothing to cleanup | |
504 return; | |
505 } | |
506 | |
507 if (!is_directory_secure(dirname)) { | |
508 // the directory is not a secure directory | |
509 return; | |
510 } | |
511 | |
512 // for each entry in the directory that matches the expected file | |
513 // name pattern, determine if the file resources are stale and if | |
514 // so, remove the file resources. Note, instrumented HotSpot processes | |
515 // for this user may start and/or terminate during this search and | |
516 // remove or create new files in this directory. The behavior of this | |
517 // loop under these conditions is dependent upon the implementation of | |
518 // opendir/readdir. | |
519 // | |
520 struct dirent* entry; | |
6197 | 521 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); |
0 | 522 errno = 0; |
523 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { | |
524 | |
525 pid_t pid = filename_to_pid(entry->d_name); | |
526 | |
527 if (pid == 0) { | |
528 | |
529 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { | |
530 | |
531 // attempt to remove all unexpected files, except "." and ".." | |
532 remove_file(dirname, entry->d_name); | |
533 } | |
534 | |
535 errno = 0; | |
536 continue; | |
537 } | |
538 | |
539 // we now have a file name that converts to a valid integer | |
540 // that could represent a process id . if this process id | |
541 // matches the current process id or the process is not running, | |
542 // then remove the stale file resources. | |
543 // | |
544 // process liveness is detected by sending signal number 0 to | |
545 // the process id (see kill(2)). if kill determines that the | |
546 // process does not exist, then the file resources are removed. | |
547 // if kill determines that that we don't have permission to | |
548 // signal the process, then the file resources are assumed to | |
549 // be stale and are removed because the resources for such a | |
550 // process should be in a different user specific directory. | |
551 // | |
552 if ((pid == os::current_process_id()) || | |
553 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { | |
554 | |
555 remove_file(dirname, entry->d_name); | |
556 } | |
557 errno = 0; | |
558 } | |
559 os::closedir(dirp); | |
6197 | 560 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); |
0 | 561 } |
562 | |
563 // make the user specific temporary directory. Returns true if | |
564 // the directory exists and is secure upon return. Returns false | |
565 // if the directory exists but is either a symlink, is otherwise | |
566 // insecure, or if an error occurred. | |
567 // | |
568 static bool make_user_tmp_dir(const char* dirname) { | |
569 | |
570 // create the directory with 0755 permissions. note that the directory | |
571 // will be owned by euid::egid, which may not be the same as uid::gid. | |
572 // | |
573 if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) { | |
574 if (errno == EEXIST) { | |
575 // The directory already exists and was probably created by another | |
576 // JVM instance. However, this could also be the result of a | |
577 // deliberate symlink. Verify that the existing directory is safe. | |
578 // | |
579 if (!is_directory_secure(dirname)) { | |
580 // directory is not secure | |
581 if (PrintMiscellaneous && Verbose) { | |
582 warning("%s directory is insecure\n", dirname); | |
583 } | |
584 return false; | |
585 } | |
586 } | |
587 else { | |
588 // we encountered some other failure while attempting | |
589 // to create the directory | |
590 // | |
591 if (PrintMiscellaneous && Verbose) { | |
592 warning("could not create directory %s: %s\n", | |
593 dirname, strerror(errno)); | |
594 } | |
595 return false; | |
596 } | |
597 } | |
598 return true; | |
599 } | |
600 | |
601 // create the shared memory file resources | |
602 // | |
603 // This method creates the shared memory file with the given size | |
604 // This method also creates the user specific temporary directory, if | |
605 // it does not yet exist. | |
606 // | |
607 static int create_sharedmem_resources(const char* dirname, const char* filename, size_t size) { | |
608 | |
609 // make the user temporary directory | |
610 if (!make_user_tmp_dir(dirname)) { | |
611 // could not make/find the directory or the found directory | |
612 // was not secure | |
613 return -1; | |
614 } | |
615 | |
616 int result; | |
617 | |
618 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); | |
619 if (result == OS_ERR) { | |
620 if (PrintMiscellaneous && Verbose) { | |
621 warning("could not create file %s: %s\n", filename, strerror(errno)); | |
622 } | |
623 return -1; | |
624 } | |
625 | |
626 // save the file descriptor | |
627 int fd = result; | |
628 | |
629 // set the file size | |
630 RESTARTABLE(::ftruncate(fd, (off_t)size), result); | |
631 if (result == OS_ERR) { | |
632 if (PrintMiscellaneous && Verbose) { | |
633 warning("could not set shared memory file size: %s\n", strerror(errno)); | |
634 } | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
10969
diff
changeset
|
635 ::close(fd); |
0 | 636 return -1; |
637 } | |
638 | |
2066
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
639 // Verify that we have enough disk space for this file. |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
640 // We'll get random SIGBUS crashes on memory accesses if |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
641 // we don't. |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
642 |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
643 for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) { |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
644 int zero_int = 0; |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
645 result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos)); |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
646 if (result == -1 ) break; |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
647 RESTARTABLE(::write(fd, &zero_int, 1), result); |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
648 if (result != 1) { |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
649 if (errno == ENOSPC) { |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
650 warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename); |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
651 } |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
652 break; |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
653 } |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
654 } |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
655 |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
656 if (result != -1) { |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
657 return fd; |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
658 } else { |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
10969
diff
changeset
|
659 ::close(fd); |
2066
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
660 return -1; |
02895c6a2f82
7007769: VM crashes with SIGBUS writing PerfData if tmp space is full
bobv
parents:
1972
diff
changeset
|
661 } |
0 | 662 } |
663 | |
664 // open the shared memory file for the given user and vmid. returns | |
665 // the file descriptor for the open file or -1 if the file could not | |
666 // be opened. | |
667 // | |
668 static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { | |
669 | |
670 // open the file | |
671 int result; | |
672 RESTARTABLE(::open(filename, oflags), result); | |
673 if (result == OS_ERR) { | |
674 if (errno == ENOENT) { | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
675 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), |
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
676 "Process not found", OS_ERR); |
0 | 677 } |
678 else if (errno == EACCES) { | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
679 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), |
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
680 "Permission denied", OS_ERR); |
0 | 681 } |
682 else { | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
683 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); |
0 | 684 } |
685 } | |
686 | |
687 return result; | |
688 } | |
689 | |
690 // create a named shared memory region. returns the address of the | |
691 // memory region on success or NULL on failure. A return value of | |
692 // NULL will ultimately disable the shared memory feature. | |
693 // | |
694 // On Solaris and Linux, the name space for shared memory objects | |
695 // is the file system name space. | |
696 // | |
697 // A monitoring application attaching to a JVM does not need to know | |
698 // the file system name of the shared memory object. However, it may | |
699 // be convenient for applications to discover the existence of newly | |
700 // created and terminating JVMs by watching the file system name space | |
701 // for files being created or removed. | |
702 // | |
703 static char* mmap_create_shared(size_t size) { | |
704 | |
705 int result; | |
706 int fd; | |
707 char* mapAddress; | |
708 | |
709 int vmid = os::current_process_id(); | |
710 | |
711 char* user_name = get_user_name(geteuid()); | |
712 | |
713 if (user_name == NULL) | |
714 return NULL; | |
715 | |
716 char* dirname = get_user_tmp_dir(user_name); | |
717 char* filename = get_sharedmem_filename(dirname, vmid); | |
718 | |
719 // cleanup any stale shared memory files | |
720 cleanup_sharedmem_resources(dirname); | |
721 | |
722 assert(((size > 0) && (size % os::vm_page_size() == 0)), | |
723 "unexpected PerfMemory region size"); | |
724 | |
725 fd = create_sharedmem_resources(dirname, filename, size); | |
726 | |
6197 | 727 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); |
728 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | |
0 | 729 |
730 if (fd == -1) { | |
6197 | 731 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 732 return NULL; |
733 } | |
734 | |
735 mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | |
736 | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
10969
diff
changeset
|
737 result = ::close(fd); |
0 | 738 assert(result != OS_ERR, "could not close file"); |
739 | |
740 if (mapAddress == MAP_FAILED) { | |
741 if (PrintMiscellaneous && Verbose) { | |
742 warning("mmap failed - %s\n", strerror(errno)); | |
743 } | |
744 remove_file(filename); | |
6197 | 745 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 746 return NULL; |
747 } | |
748 | |
749 // save the file name for use in delete_shared_memory() | |
750 backing_store_file_name = filename; | |
751 | |
752 // clear the shared memory region | |
753 (void)::memset((void*) mapAddress, 0, size); | |
754 | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
755 // it does not go through os api, the operation has to record from here |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10978
diff
changeset
|
756 MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
757 |
0 | 758 return mapAddress; |
759 } | |
760 | |
761 // release a named shared memory region | |
762 // | |
763 static void unmap_shared(char* addr, size_t bytes) { | |
764 os::release_memory(addr, bytes); | |
765 } | |
766 | |
767 // create the PerfData memory region in shared memory. | |
768 // | |
769 static char* create_shared_memory(size_t size) { | |
770 | |
771 // create the shared memory region. | |
772 return mmap_create_shared(size); | |
773 } | |
774 | |
775 // delete the shared PerfData memory region | |
776 // | |
777 static void delete_shared_memory(char* addr, size_t size) { | |
778 | |
779 // cleanup the persistent shared memory resources. since DestroyJavaVM does | |
780 // not support unloading of the JVM, unmapping of the memory resource is | |
781 // not performed. The memory will be reclaimed by the OS upon termination of | |
782 // the process. The backing store file is deleted from the file system. | |
783 | |
784 assert(!PerfDisableSharedMem, "shouldn't be here"); | |
785 | |
786 if (backing_store_file_name != NULL) { | |
787 remove_file(backing_store_file_name); | |
788 // Don't.. Free heap memory could deadlock os::abort() if it is called | |
789 // from signal handler. OS will reclaim the heap memory. | |
790 // FREE_C_HEAP_ARRAY(char, backing_store_file_name); | |
791 backing_store_file_name = NULL; | |
792 } | |
793 } | |
794 | |
795 // return the size of the file for the given file descriptor | |
796 // or 0 if it is not a valid size for a shared memory file | |
797 // | |
798 static size_t sharedmem_filesize(int fd, TRAPS) { | |
799 | |
800 struct stat statbuf; | |
801 int result; | |
802 | |
803 RESTARTABLE(::fstat(fd, &statbuf), result); | |
804 if (result == OS_ERR) { | |
805 if (PrintMiscellaneous && Verbose) { | |
806 warning("fstat failed: %s\n", strerror(errno)); | |
807 } | |
808 THROW_MSG_0(vmSymbols::java_io_IOException(), | |
809 "Could not determine PerfMemory size"); | |
810 } | |
811 | |
812 if ((statbuf.st_size == 0) || | |
813 ((size_t)statbuf.st_size % os::vm_page_size() != 0)) { | |
814 THROW_MSG_0(vmSymbols::java_lang_Exception(), | |
815 "Invalid PerfMemory size"); | |
816 } | |
817 | |
818 return (size_t)statbuf.st_size; | |
819 } | |
820 | |
821 // attach to a named shared memory region. | |
822 // | |
823 static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) { | |
824 | |
825 char* mapAddress; | |
826 int result; | |
827 int fd; | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
828 size_t size = 0; |
0 | 829 const char* luser = NULL; |
830 | |
831 int mmap_prot; | |
832 int file_flags; | |
833 | |
834 ResourceMark rm; | |
835 | |
836 // map the high level access mode to the appropriate permission | |
837 // constructs for the file and the shared memory mapping. | |
838 if (mode == PerfMemory::PERF_MODE_RO) { | |
839 mmap_prot = PROT_READ; | |
840 file_flags = O_RDONLY; | |
841 } | |
842 else if (mode == PerfMemory::PERF_MODE_RW) { | |
843 #ifdef LATER | |
844 mmap_prot = PROT_READ | PROT_WRITE; | |
845 file_flags = O_RDWR; | |
846 #else | |
847 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
848 "Unsupported access mode"); | |
849 #endif | |
850 } | |
851 else { | |
852 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
853 "Illegal access mode"); | |
854 } | |
855 | |
856 if (user == NULL || strlen(user) == 0) { | |
857 luser = get_user_name(vmid, CHECK); | |
858 } | |
859 else { | |
860 luser = user; | |
861 } | |
862 | |
863 if (luser == NULL) { | |
864 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
865 "Could not map vmid to user Name"); | |
866 } | |
867 | |
868 char* dirname = get_user_tmp_dir(luser); | |
869 | |
870 // since we don't follow symbolic links when creating the backing | |
871 // store file, we don't follow them when attaching either. | |
872 // | |
873 if (!is_directory_secure(dirname)) { | |
6197 | 874 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
0 | 875 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
876 "Process not found"); | |
877 } | |
878 | |
879 char* filename = get_sharedmem_filename(dirname, vmid); | |
880 | |
881 // copy heap memory to resource memory. the open_sharedmem_file | |
882 // method below need to use the filename, but could throw an | |
883 // exception. using a resource array prevents the leak that | |
884 // would otherwise occur. | |
885 char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1); | |
886 strcpy(rfilename, filename); | |
887 | |
888 // free the c heap resources that are no longer needed | |
6197 | 889 if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal); |
890 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | |
891 FREE_C_HEAP_ARRAY(char, filename, mtInternal); | |
0 | 892 |
893 // open the shared memory file for the give vmid | |
894 fd = open_sharedmem_file(rfilename, file_flags, CHECK); | |
895 assert(fd != OS_ERR, "unexpected value"); | |
896 | |
897 if (*sizep == 0) { | |
898 size = sharedmem_filesize(fd, CHECK); | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
899 } else { |
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
900 size = *sizep; |
0 | 901 } |
902 | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
903 assert(size > 0, "unexpected size <= 0"); |
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
904 |
0 | 905 mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); |
906 | |
10978
e95fc50106cf
7178026: os::close can restart ::close but that is not a restartable syscall
rdurbin
parents:
10969
diff
changeset
|
907 result = ::close(fd); |
0 | 908 assert(result != OS_ERR, "could not close file"); |
909 | |
910 if (mapAddress == MAP_FAILED) { | |
911 if (PrintMiscellaneous && Verbose) { | |
912 warning("mmap failed: %s\n", strerror(errno)); | |
913 } | |
914 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), | |
915 "Could not map PerfMemory"); | |
916 } | |
917 | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
918 // it does not go through os api, the operation has to record from here |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10978
diff
changeset
|
919 MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
920 |
0 | 921 *addr = mapAddress; |
922 *sizep = size; | |
923 | |
924 if (PerfTraceMemOps) { | |
925 tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at " | |
926 INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress); | |
927 } | |
928 } | |
929 | |
930 | |
931 | |
932 | |
933 // create the PerfData memory region | |
934 // | |
935 // This method creates the memory region used to store performance | |
936 // data for the JVM. The memory may be created in standard or | |
937 // shared memory. | |
938 // | |
939 void PerfMemory::create_memory_region(size_t size) { | |
940 | |
941 if (PerfDisableSharedMem) { | |
942 // do not share the memory for the performance data. | |
943 _start = create_standard_memory(size); | |
944 } | |
945 else { | |
946 _start = create_shared_memory(size); | |
947 if (_start == NULL) { | |
948 | |
949 // creation of the shared memory region failed, attempt | |
950 // to create a contiguous, non-shared memory region instead. | |
951 // | |
952 if (PrintMiscellaneous && Verbose) { | |
953 warning("Reverting to non-shared PerfMemory region.\n"); | |
954 } | |
955 PerfDisableSharedMem = true; | |
956 _start = create_standard_memory(size); | |
957 } | |
958 } | |
959 | |
960 if (_start != NULL) _capacity = size; | |
961 | |
962 } | |
963 | |
964 // delete the PerfData memory region | |
965 // | |
966 // This method deletes the memory region used to store performance | |
967 // data for the JVM. The memory region indicated by the <address, size> | |
968 // tuple will be inaccessible after a call to this method. | |
969 // | |
970 void PerfMemory::delete_memory_region() { | |
971 | |
972 assert((start() != NULL && capacity() > 0), "verify proper state"); | |
973 | |
974 // If user specifies PerfDataSaveFile, it will save the performance data | |
975 // to the specified file name no matter whether PerfDataSaveToFile is specified | |
976 // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag | |
977 // -XX:+PerfDataSaveToFile. | |
978 if (PerfDataSaveToFile || PerfDataSaveFile != NULL) { | |
979 save_memory_to_file(start(), capacity()); | |
980 } | |
981 | |
982 if (PerfDisableSharedMem) { | |
983 delete_standard_memory(start(), capacity()); | |
984 } | |
985 else { | |
986 delete_shared_memory(start(), capacity()); | |
987 } | |
988 } | |
989 | |
990 // attach to the PerfData memory region for another JVM | |
991 // | |
992 // This method returns an <address, size> tuple that points to | |
993 // a memory buffer that is kept reasonably synchronized with | |
994 // the PerfData memory region for the indicated JVM. This | |
995 // buffer may be kept in synchronization via shared memory | |
996 // or some other mechanism that keeps the buffer updated. | |
997 // | |
998 // If the JVM chooses not to support the attachability feature, | |
999 // this method should throw an UnsupportedOperation exception. | |
1000 // | |
1001 // This implementation utilizes named shared memory to map | |
1002 // the indicated process's PerfData memory region into this JVMs | |
1003 // address space. | |
1004 // | |
1005 void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, char** addrp, size_t* sizep, TRAPS) { | |
1006 | |
1007 if (vmid == 0 || vmid == os::current_process_id()) { | |
1008 *addrp = start(); | |
1009 *sizep = capacity(); | |
1010 return; | |
1011 } | |
1012 | |
1013 mmap_attach_shared(user, vmid, mode, addrp, sizep, CHECK); | |
1014 } | |
1015 | |
1016 // detach from the PerfData memory region of another JVM | |
1017 // | |
1018 // This method detaches the PerfData memory region of another | |
1019 // JVM, specified as an <address, size> tuple of a buffer | |
1020 // in this process's address space. This method may perform | |
1021 // arbitrary actions to accomplish the detachment. The memory | |
1022 // region specified by <address, size> will be inaccessible after | |
1023 // a call to this method. | |
1024 // | |
1025 // If the JVM chooses not to support the attachability feature, | |
1026 // this method should throw an UnsupportedOperation exception. | |
1027 // | |
1028 // This implementation utilizes named shared memory to detach | |
1029 // the indicated process's PerfData memory region from this | |
1030 // process's address space. | |
1031 // | |
1032 void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { | |
1033 | |
1034 assert(addr != 0, "address sanity check"); | |
1035 assert(bytes > 0, "capacity sanity check"); | |
1036 | |
1037 if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) { | |
1038 // prevent accidental detachment of this process's PerfMemory region | |
1039 return; | |
1040 } | |
1041 | |
1042 unmap_shared(addr, bytes); | |
1043 } | |
1044 | |
1045 char* PerfMemory::backing_store_filename() { | |
1046 return backing_store_file_name; | |
1047 } |