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