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