|
Sierra Toolkit
Version of the Day
|
00001 00010 #include <pwd.h> 00011 #include <unistd.h> 00012 00013 #include <iostream> 00014 #include <ostream> 00015 #include <fstream> 00016 #include <sstream> 00017 #include <cstring> 00018 #include <cstdlib> 00019 #include <stdexcept> 00020 #include <iomanip> 00021 #include <algorithm> 00022 #include <locale> 00023 00024 #include <stk_util/util/FeatureTest.hpp> 00025 #include <stk_util/diag/Env.hpp> 00026 #include <stk_util/diag/Platform.hpp> 00027 #include <stk_util/parallel/Exception.hpp> 00028 #include <stk_util/parallel/ExceptionReport.hpp> 00029 #include <stk_util/parallel/MPI.hpp> 00030 #ifdef STK_BUILT_IN_SIERRA 00031 # include <stk_util/parallel/mpih.hpp> 00032 #endif 00033 #include <stk_util/environment/ProductRegistry.hpp> 00034 00035 #include <stk_util/diag/Writer.hpp> 00036 #include <stk_util/diag/SlibDiagWriter.hpp> 00037 #include <stk_util/diag/Timer.hpp> 00038 #include <stk_util/diag/Trace.hpp> 00039 00040 #include <fcntl.h> 00041 00042 #if defined(__GNUC__) 00043 #include <fstream> 00044 #ifndef __APPLE__ 00045 #include </usr/include/malloc.h> 00046 #else 00047 #include <sys/malloc.h> 00048 #endif 00049 #include <cstdlib> 00050 #include <sys/time.h> 00051 #include <sys/resource.h> 00052 #if __GNUC__ == 3 || __GNUC__ == 4 00053 #include <cxxabi.h> 00054 #endif 00055 00056 #elif defined(__PGI) 00057 #include <fstream> 00058 #include <malloc.h> 00059 #include <cstdlib> 00060 #include <sys/time.h> 00061 #include <sys/resource.h> 00062 00063 #elif defined(__sun) 00064 #include <fstream> 00065 #include <procfs.h> 00066 #include <sys/resource.h> 00067 #include <sys/systeminfo.h> 00068 #include <sys/utsname.h> 00069 #include <sys/time.h> 00070 00071 #elif defined(__SUNPRO_CC) 00072 #include <sys/resource.h> 00073 #include <sys/time.h> 00074 #include <sys/utsname.h> 00075 #include <netdb.h> 00076 #endif 00077 00078 #if defined(__PUMAGON__) 00079 extern "C" { 00080 #include <util.h> 00081 #include <sys/param.h> 00082 } 00083 00084 #elif defined(__sgi) 00085 #include <sys/time.h> 00086 #include <sys/resource.h> 00087 00088 #elif defined(REDS) 00089 #include <sys/param.h> 00090 #include <sys/utsname.h> 00091 #include <sys/time.h> 00092 #include <sys/resource.h> 00093 #include <unistd.h> 00094 #include <catamount/catmalloc.h> 00095 extern void *__heap_start; 00096 extern void *__heap_end; 00097 00098 #elif defined(__JVN) 00099 #include <sys/param.h> 00100 #include <sys/utsname.h> 00101 #include <sys/time.h> 00102 #include <sys/resource.h> 00103 #include <sys/wait.h> 00104 #include <unistd.h> 00105 00106 #elif defined(__IBMC__) || defined(__IBMCPP__) 00107 #include <sys/utsname.h> 00108 #include <sys/time.h> 00109 #include <sys/resource.h> 00110 #include <netdb.h> 00111 00112 #else 00113 #include <sys/utsname.h> 00114 #include <sys/time.h> 00115 #include <netdb.h> 00116 #endif 00117 00118 #include <stk_util/util/MallocUsed.h> 00119 00120 // 00121 // NKC 2/21/08 Some of the calls in this file bomb out purify. Uncomment the line below if trying 00122 // to build a purify executable. 00123 // 00124 //#define PURIFY_BUILD 00125 00126 #if defined(REDS) 00127 namespace { 00128 size_t get_redstorm_base_available_memory(); 00129 } 00130 #endif 00131 00132 namespace sierra { 00133 00134 #ifdef SIERRA_USE_PLATFORM_DEMANGLER 00135 00136 00137 #if defined(__GNUC__) 00138 00139 #if (__GNUC__ == 3) 00140 std::string 00141 demangle( 00142 const char * symbol) 00143 { 00144 #ifdef PURIFY_BUILD 00145 return symbol; 00146 #else 00147 std::string s; 00148 int status; 00149 00150 // GR: PathScale versions 4.x.x attempt to write the length of the demangled 00151 // string to the third argument of __cxa_demangle even if a NULL value is 00152 // provided. This seems to be a compiler bug. The following code change 00153 // provides a work around to prevent a segfault. 00154 //char *demangled_symbol = abi::__cxa_demangle(symbol, 0, 0, &status); 00155 size_t len = 0; 00156 char *demangled_symbol = abi::__cxa_demangle(symbol, 0, &len, &status); 00157 00158 if (demangled_symbol) { 00159 s = std::string(demangled_symbol); 00160 free(demangled_symbol); 00161 } 00162 00163 if (status != 0) 00164 s = std::string(symbol); 00165 00166 return s; 00167 #endif 00168 } 00169 00170 #elif (__GNUC__ == 4) 00171 std::string 00172 demangle( 00173 const char * symbol) 00174 { 00175 #ifdef PURIFY_BUILD 00176 return symbol; 00177 #else 00178 std::string s; 00179 00180 int status; 00181 00182 // GR: PathScale versions 4.x.x attempt to write the length of the demangled 00183 // string to the third argument of __cxa_demangle even if a NULL value is 00184 // provided. This seems to be a compiler bug. The following code change 00185 // provides a work around to prevent a segfault. 00186 //char *demangled_symbol = __cxxabiv1::__cxa_demangle(symbol, 0, 0, &status); 00187 size_t len = 0; 00188 char *demangled_symbol = __cxxabiv1::__cxa_demangle(symbol, 0, &len, &status); 00189 00190 if (demangled_symbol) { 00191 s = std::string(demangled_symbol); 00192 free(demangled_symbol); 00193 } 00194 00195 if (status != 0) 00196 s = std::string(symbol); 00197 00198 return s; 00199 #endif 00200 } 00201 #endif // (__GNUC__ == 3) 00202 00203 #else 00204 std::string demangle(const char *symbol) { 00205 return symbol; 00206 } 00207 #endif // defined(__GNUC__) 00208 00209 #else 00210 const char *demangle(const char *symbol) { 00211 return symbol; 00212 } 00213 #endif // SIERRA_USE_PLATFORM_DEMANGLER 00214 00215 00216 namespace Env { 00217 00218 #if defined(REDS) 00219 // Manipulate standard output buffering 00220 void 00221 startup_preparallel_platform() 00222 { 00223 static char redstorm_cout_buf[32678]; 00224 std::cout.rdbuf()->pubsetbuf(redstorm_cout_buf, sizeof(redstorm_cout_buf)); 00225 00226 static char redstorm_stdout_buf[32678]; 00227 std::setvbuf(stdout, redstorm_stdout_buf, _IOFBF, sizeof(redstorm_stdout_buf)); 00228 00229 static char redstorm_cerr_buf[32678]; 00230 std::cerr.rdbuf()->pubsetbuf(redstorm_cerr_buf, sizeof(redstorm_cerr_buf)); 00231 00232 static char redstorm_stderr_buf[32678]; 00233 std::setvbuf(stderr, redstorm_stderr_buf, _IOFBF, sizeof(redstorm_stderr_buf)); 00234 00235 get_available_memory(); 00236 } 00237 00238 #elif defined(_AIX) 00239 // Cleanup AIX locale initialization problems 00240 void 00241 startup_preparallel_platform() 00242 { 00243 std::locale loc("POSIX"); 00244 00245 std::locale::global(loc); // std::locale::classic()); 00246 std::cout.imbue(loc); // std::locale::classic()); 00247 std::cin.imbue(loc); // std::locale::classic()); 00248 00249 std::ostringstream strout; 00250 strout << "Don't ask why the IBM locale works if I do this " << 10000000 << std::endl; 00251 } 00252 00253 #else 00254 void 00255 startup_preparallel_platform() 00256 {} 00257 #endif 00258 00259 00260 double 00261 wall_now() 00262 { 00263 timeval tp; 00264 struct timezone tz; 00265 gettimeofday(&tp, &tz); 00266 return (tp.tv_sec + (((double)(tp.tv_usec))/1000000.0)); 00267 } 00268 00269 00270 double 00271 cpu_now() 00272 { 00273 #if defined(REDS) 00274 struct rusage my_rusage; 00275 00276 getrusage(RUSAGE_SELF, &my_rusage); 00277 00278 return (double) (my_rusage.ru_utime.tv_sec) 00279 + ((double)(my_rusage.ru_utime.tv_usec))*1.0e-6; 00280 00281 #elif ! defined(__PGI) 00282 struct rusage my_rusage; 00283 00284 getrusage(RUSAGE_SELF, &my_rusage); 00285 00286 return (double) (my_rusage.ru_utime.tv_sec + my_rusage.ru_stime.tv_sec) 00287 + ((double)(my_rusage.ru_utime.tv_usec + my_rusage.ru_stime.tv_usec))*1.0e-6; 00288 #else 00289 return 0; 00290 #endif 00291 } 00292 00293 00294 void 00295 get_heap_info( 00296 size_t & heap_size, 00297 size_t & largest_free) 00298 { 00299 heap_size = 0; 00300 largest_free = 0; 00301 00302 #if defined(SIERRA_HEAP_INFO) 00303 00304 # if defined(SIERRA_PTMALLOC3_ALLOCATOR) || defined(SIERRA_PTMALLOC2_ALLOCATOR) 00305 heap_size = malloc_used(); 00306 00307 # elif 0 // if defined(REDS) // Redstorm now links in gnu's malloc 00308 static size_t reds_fragments; 00309 static unsigned long reds_total_free; 00310 static unsigned long reds_heap_size; 00311 static unsigned long reds_largest_free; 00312 00313 ::heap_info(&reds_fragments, &reds_total_free, &reds_largest_free, &reds_heap_size); 00314 00315 heap_size = reds_heap_size; 00316 largest_free = reds_largest_free; 00317 00318 slibout.m(Slib::LOG_MEMORY) <<"reds_fragments " << reds_fragments 00319 << ", reds_total_free " << reds_total_free 00320 << ", reds_largest_free " << reds_largest_free 00321 << ", reds_heap_size " << reds_heap_size << Diag::dendl; 00322 00323 # elif ( defined(__linux__) || defined(REDS) ) && ! defined(__IBMCPP__) 00324 static struct mallinfo minfo; 00325 minfo = mallinfo(); 00326 heap_size = (unsigned int) minfo.uordblks + (unsigned int) minfo.hblkhd; 00327 largest_free = (unsigned int) minfo.fordblks; 00328 00329 slibout.m(Slib::LOG_MEMORY) << "size_t size " << sizeof(size_t)*8 << " bits" 00330 << ", heap size " << heap_size 00331 << ", arena " << (unsigned int) minfo.arena 00332 << ", ordblks " << minfo.ordblks 00333 << ", smblks " << minfo.smblks 00334 << ", hblks " << minfo.hblks 00335 << ", hblkhd " << (unsigned int) minfo.hblkhd 00336 << ", usmblks " << minfo.usmblks 00337 << ", fsmblks " << minfo.fsmblks 00338 << ", uordblks " << (unsigned int) minfo.uordblks 00339 << ", fordblks " << (unsigned int) minfo.fordblks 00340 << ", keepcost " << minfo.keepcost << Diag::dendl; 00341 00342 00343 # elif defined(__sun) 00344 pstatus_t proc_status; 00345 00346 std::ifstream proc("/proc/self/status", std::ios_base::in|std::ios_base::binary); 00347 if (proc) { 00348 proc.read((char *)&proc_status, sizeof(proc_status)); 00349 heap_size = proc_status.pr_brksize; 00350 slibout.m(Slib::LOG_MEMORY) <<"pr_brksize " << proc_status.pr_brksize 00351 << ", pr_stksize " << proc_status.pr_stksize << Diag::dendl; 00352 } 00353 # endif 00354 #endif // defined(SIERRA_HEAP_INFO) 00355 } 00356 00357 00358 size_t get_available_memory() 00359 { 00360 #if !defined(REDS) 00361 // The value returned for _SC_AVPHYS_PAGES is the amount of memory 00362 // the application can use without hindering any other process 00363 // (given that no other process increases its memory usage). 00364 #if !defined(__APPLE__) && !defined(__FreeBSD__) 00365 static size_t pagesize = getpagesize(); 00366 size_t avail = sysconf(_SC_AVPHYS_PAGES); 00367 return avail * pagesize; 00368 #else 00369 // _SC_AVPHYS_PAGES does not exist on FreeBSD/Apple 00370 return 0; 00371 #endif 00372 #else 00373 // On redstorm, we get an estimate of the available memory at the 00374 // time that the application starts up and then we get the currently 00375 // available memory by subtracting the used memory from that initial 00376 // value. 00377 static size_t initial_memory_size = 0; 00378 if (initial_memory_size == 0) { 00379 initial_memory_size = get_redstorm_base_available_memory(); 00380 } 00381 return initial_memory_size - get_heap_usage(); 00382 #endif 00383 } 00384 00385 void 00386 get_memory_info( 00387 size_t & memory_usage, 00388 size_t & faults) 00389 { 00390 memory_usage = 0; 00391 faults = 0; 00392 00393 #if defined(SIERRA_MEMORY_INFO) 00394 # if defined(REDS) 00395 memory_usage = (size_t) __heap_start + get_heap_usage(); 00396 00397 # elif defined(__linux__) 00398 std::ifstream proc("/proc/self/stat", std::ios_base::in|std::ios_base::binary); 00399 if (proc) { 00400 00401 std::string s; 00402 int i; 00403 for (i = 0; i < 11; ++i) 00404 proc >> s; 00405 00406 proc >> faults; 00407 ++i; 00408 00409 for (; i < 22; ++i) 00410 proc >> s; 00411 00412 proc >> memory_usage; 00413 ++i; 00414 } 00415 # elif defined(__sun) 00416 { 00417 00418 psinfo_t proc_info; 00419 00420 std::ifstream proc("/proc/self/psinfo", std::ios_base::in|std::ios_base::binary); 00421 if (proc) { 00422 proc.read((char *)&proc_info, sizeof(proc_info)); 00423 memory_usage = proc_info.pr_size*1024; 00424 } 00425 } 00426 00427 { 00428 prusage_t proc_usage; 00429 00430 std::ifstream proc("/proc/self/usage", std::ios_base::in|std::ios_base::binary); 00431 if (proc) { 00432 proc.read((char *)&proc_usage, sizeof(proc_usage)); 00433 faults = proc_usage.pr_majf; 00434 } 00435 } 00436 # endif 00437 #endif // defined(SIERRA_MEMORY_INFO) 00438 } 00439 00440 00441 double 00442 vm_now() 00443 { 00444 size_t memory_usage; 00445 size_t faults; 00446 00447 get_memory_info(memory_usage, faults); 00448 00449 return (double) memory_usage; 00450 } 00451 00452 00453 std::string 00454 hostname() 00455 { 00456 char buf[255]; 00457 ::gethostname(buf, sizeof(buf)); 00458 return std::string(buf); 00459 } 00460 00461 00462 std::string 00463 domainname() 00464 { 00465 #if defined(__PUMAGON__) || defined(REDS) 00466 return std::string(".sandia.gov"); 00467 00468 #elif defined(__sun) 00469 std::string domain("."); 00470 char buf[255]; 00471 00472 ::sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf)); 00473 if (std::strlen(buf)) { 00474 domain += buf; 00475 } 00476 return domain; 00477 00478 #else //#elif defined(__linux) || defined(__sgi) || defined(_AIX) 00479 std::string domain("."); 00480 char buf[255]; 00481 00482 ::getdomainname(buf, sizeof(buf)); 00483 if (::strlen(buf)) { 00484 domain += buf; 00485 } 00486 return domain; 00487 00488 #endif 00489 } 00490 00491 00492 std::string 00493 username() 00494 { 00495 #if defined(REDS) || defined(__CRAYXT_COMPUTE_LINUX_TARGET) 00496 if (get_param("username").empty()) 00497 return "unknown"; 00498 else 00499 return get_param("username"); 00500 #else 00501 struct passwd *user_info = ::getpwuid(::geteuid()); 00502 00503 return (user_info ? user_info->pw_name : "unknown"); 00504 #endif 00505 } 00506 00507 00508 std::string 00509 hardware() 00510 { 00511 #ifndef __sgi 00512 struct utsname uts_name; 00513 00514 uname(&uts_name); 00515 00516 return uts_name.machine; 00517 #else 00518 std::string s; 00519 return s; 00520 #endif 00521 } 00522 00523 00524 std::string 00525 osname() 00526 { 00527 #ifndef __sgi 00528 struct utsname uts_name; 00529 00530 uname(&uts_name); 00531 00532 return uts_name.sysname; 00533 #else 00534 std::string s; 00535 return s; 00536 #endif 00537 } 00538 00539 00540 std::string 00541 osversion() 00542 { 00543 #ifndef __sgi 00544 struct utsname uts_name; 00545 00546 uname(&uts_name); 00547 00548 return uts_name.release; 00549 #else 00550 std::string s; 00551 return s; 00552 #endif 00553 } 00554 00555 00556 int 00557 pid() 00558 { 00559 return ::getpid(); 00560 } 00561 00562 00563 int 00564 pgrp() 00565 { 00566 #if defined(__PUMAGON__) || defined(REDS) 00567 return 0; 00568 #else 00569 return ::getpgrp(); 00570 #endif 00571 } 00572 00573 00574 bool 00575 path_access( 00576 const std::string & name, 00577 int mode) 00578 00579 { 00580 return !name.empty() && ::access(name.c_str(), mode) == 0; 00581 } 00582 00583 00584 bool 00585 path_exists( 00586 const std::string & name) 00587 { 00588 return path_access(name, F_OK); 00589 } 00590 00591 00592 bool 00593 path_read_access( 00594 const std::string & name) 00595 { 00596 return path_access(name, R_OK); 00597 } 00598 00599 00600 bool 00601 path_write_access( 00602 const std::string & name) 00603 { 00604 return path_access(name, W_OK); 00605 } 00606 00607 00608 namespace { 00609 00610 struct flock * 00611 file_lock( 00612 short type, 00613 short whence) 00614 { 00615 // /* %TRACE[SPEC]% */ Tracespec trace__("sierra::Fmwk::<unnamed>::file_lock( short type, short whence)"); /* %TRACE% */ 00616 static struct flock ret; 00617 ret.l_type = type; 00618 ret.l_start = 0; 00619 ret.l_whence = whence; 00620 ret.l_len = 0; 00621 ret.l_pid = 0; //getpid(); 00622 return &ret; 00623 } 00624 00625 } // namespace <unnamed> 00626 00627 bool 00628 write_lock( 00629 int fd) 00630 { 00631 int i =::fcntl(fd, F_SETLK, file_lock(F_WRLCK, SEEK_SET)); 00632 // if (i == -1) 00633 // fmwkout << "Write lock failed " << errno << dendl; 00634 00635 return i != -1; 00636 } 00637 00638 00639 bool 00640 release_lock( 00641 int fd) 00642 { 00643 int i =::fcntl(fd, F_SETLK, file_lock(F_UNLCK, SEEK_SET)); 00644 // if (i == -1) 00645 // fmwkout << "Release lock failed " << errno << dendl; 00646 00647 return i != -1; 00648 } 00649 00650 00651 bool 00652 read_lock( 00653 int fd) 00654 { 00655 return ::fcntl(fd, F_SETLK, file_lock(F_RDLCK, SEEK_SET)) != -1; 00656 } 00657 00658 00659 bool 00660 append_lock( 00661 int fd) 00662 { 00663 return ::fcntl(fd, F_SETLK, file_lock(F_WRLCK, SEEK_END)) != -1; 00664 } 00665 00666 } // namespace Env 00667 } // namespace sierra 00668 00669 #if defined(REDS) 00670 00671 #if defined(__GNUC__) 00672 namespace { 00673 size_t get_redstorm_base_available_memory() 00674 { 00675 return 0; 00676 } 00677 } 00678 #else 00679 // Written by Mike Davis 00680 #include <catamount/data.h> 00681 namespace { 00682 00683 void stk_ptr (unsigned long *sp) { 00684 asm ("movq %rsp, (%rdi)"); 00685 } 00686 00687 size_t get_redstorm_base_available_memory() 00688 { 00689 char *p1; 00690 size_t stack_top; 00691 size_t avail_mem; 00692 size_t heap_base; 00693 size_t stack_base; 00694 size_t stack_size; 00695 size_t unmapped_top = 4 * 1048576; 00696 size_t os_foot = 140 * 1048576; 00697 size_t avail_heap; 00698 00703 stk_ptr (&stack_top); 00704 00708 stack_top &= ~0x1fffff; 00709 stack_top += 0x200000; 00710 00716 avail_mem = stack_top + unmapped_top; 00717 00721 avail_mem -= os_foot; 00722 00727 avail_mem /= _my_pcb->upcb_vnm_degree; 00728 00733 p1 = (char *) malloc (1); 00734 heap_base = (size_t) p1; 00735 free (p1); 00736 00742 avail_heap = avail_mem - heap_base; 00743 00748 stack_base = (size_t) _my_pcb; 00749 stack_base &= ~0x1fffff; 00750 stack_base += 0x400000; 00751 00757 stack_size = stack_top - stack_base; 00758 avail_heap -= unmapped_top; 00759 avail_heap -= stack_size; 00760 00761 return avail_heap; 00762 } 00763 } 00764 #endif 00765 #endif