Sierra Toolkit  Version of the Day
Platform.cpp
1 
10 #include <pwd.h>
11 #include <unistd.h>
12 
13 #include <iostream>
14 #include <ostream>
15 #include <fstream>
16 #include <sstream>
17 #include <cstring>
18 #include <cstdlib>
19 #include <stdexcept>
20 #include <iomanip>
21 #include <algorithm>
22 #include <locale>
23 
24 #include <stk_util/util/FeatureTest.hpp>
25 #include <stk_util/diag/Env.hpp>
26 #include <stk_util/diag/Platform.hpp>
28 #include <stk_util/parallel/ExceptionReport.hpp>
29 #include <stk_util/parallel/MPI.hpp>
30 #ifdef STK_BUILT_IN_SIERRA
32 #endif
33 #include <stk_util/environment/ProductRegistry.hpp>
34 
35 #include <stk_util/diag/Writer.hpp>
36 #include <stk_util/diag/SlibDiagWriter.hpp>
37 #include <stk_util/diag/Timer.hpp>
38 #include <stk_util/diag/Trace.hpp>
39 
40 #include <fcntl.h>
41 
42 #if defined(__GNUC__)
43 #include <fstream>
44 #ifndef __APPLE__
45 #include <malloc.h>
46 #else
47 #include <sys/malloc.h>
48 #endif
49 #include <cstdlib>
50 #include <sys/time.h>
51 #include <sys/resource.h>
52 #if __GNUC__ == 3 || __GNUC__ == 4
53 #include <cxxabi.h>
54 #endif
55 
56 #elif defined(__PGI)
57 #include <fstream>
58 #include <malloc.h>
59 #include <cstdlib>
60 #include <sys/time.h>
61 #include <sys/resource.h>
62 
63 #elif defined(__sun)
64 #include <fstream>
65 #include <procfs.h>
66 #include <sys/resource.h>
67 #include <sys/systeminfo.h>
68 #include <sys/utsname.h>
69 #include <sys/time.h>
70 
71 #elif defined(__SUNPRO_CC)
72 #include <sys/resource.h>
73 #include <sys/time.h>
74 #include <sys/utsname.h>
75 #include <netdb.h>
76 #endif
77 
78 #if defined(__PUMAGON__)
79 extern "C" {
80 #include <util.h>
81 #include <sys/param.h>
82 }
83 
84 #elif defined(__sgi)
85 #include <sys/time.h>
86 #include <sys/resource.h>
87 
88 #elif defined(REDS)
89 #include <sys/param.h>
90 #include <sys/utsname.h>
91 #include <sys/time.h>
92 #include <sys/resource.h>
93 #include <unistd.h>
94 #include <catamount/catmalloc.h>
95 extern void *__heap_start;
96 extern void *__heap_end;
97 
98 #elif defined(__JVN)
99 #include <sys/param.h>
100 #include <sys/utsname.h>
101 #include <sys/time.h>
102 #include <sys/resource.h>
103 #include <sys/wait.h>
104 #include <unistd.h>
105 
106 #elif defined(__IBMC__) || defined(__IBMCPP__)
107 #include <sys/utsname.h>
108 #include <sys/time.h>
109 #include <sys/resource.h>
110 #include <netdb.h>
111 
112 #else
113 #include <sys/utsname.h>
114 #include <sys/time.h>
115 #include <netdb.h>
116 #endif
117 
118 #include <stk_util/util/MallocUsed.h>
119 
120 //
121 // NKC 2/21/08 Some of the calls in this file bomb out purify. Uncomment the line below if trying
122 // to build a purify executable.
123 //
124 //#define PURIFY_BUILD
125 
126 #if defined(REDS)
127 namespace {
128  size_t get_redstorm_base_available_memory();
129 }
130 #endif
131 
132 namespace sierra {
133 
134 #ifdef SIERRA_USE_PLATFORM_DEMANGLER
135 
136 
137 #if defined(__GNUC__)
138 
139 #if (__GNUC__ == 3)
140 std::string
141 demangle(
142  const char * symbol)
143 {
144 #ifdef PURIFY_BUILD
145  return symbol;
146 #else
147  std::string s;
148  int status;
149 
150  // GR: PathScale versions 4.x.x attempt to write the length of the demangled
151  // string to the third argument of __cxa_demangle even if a NULL value is
152  // provided. This seems to be a compiler bug. The following code change
153  // provides a work around to prevent a segfault.
154  //char *demangled_symbol = abi::__cxa_demangle(symbol, 0, 0, &status);
155  size_t len = 0;
156  char *demangled_symbol = abi::__cxa_demangle(symbol, 0, &len, &status);
157 
158  if (demangled_symbol) {
159  s = std::string(demangled_symbol);
160  free(demangled_symbol);
161  }
162 
163  if (status != 0)
164  s = std::string(symbol);
165 
166  return s;
167 #endif
168 }
169 
170 #elif (__GNUC__ == 4)
171 std::string
172 demangle(
173  const char * symbol)
174 {
175 #ifdef PURIFY_BUILD
176  return symbol;
177 #else
178  std::string s;
179 
180  int status;
181 
182  // GR: PathScale versions 4.x.x attempt to write the length of the demangled
183  // string to the third argument of __cxa_demangle even if a NULL value is
184  // provided. This seems to be a compiler bug. The following code change
185  // provides a work around to prevent a segfault.
186  //char *demangled_symbol = __cxxabiv1::__cxa_demangle(symbol, 0, 0, &status);
187  size_t len = 0;
188  char *demangled_symbol = __cxxabiv1::__cxa_demangle(symbol, 0, &len, &status);
189 
190  if (demangled_symbol) {
191  s = std::string(demangled_symbol);
192  free(demangled_symbol);
193  }
194 
195  if (status != 0)
196  s = std::string(symbol);
197 
198  return s;
199 #endif
200 }
201 #endif // (__GNUC__ == 3)
202 
203 #else
204 std::string demangle(const char *symbol) {
205  return symbol;
206 }
207 #endif // defined(__GNUC__)
208 
209 #else
210 const char *demangle(const char *symbol) {
211  return symbol;
212 }
213 #endif // SIERRA_USE_PLATFORM_DEMANGLER
214 
215 
216 namespace Env {
217 
218 #if defined(REDS)
219 // Manipulate standard output buffering
220 void
222 {
223  static char redstorm_cout_buf[32678];
224  std::cout.rdbuf()->pubsetbuf(redstorm_cout_buf, sizeof(redstorm_cout_buf));
225 
226  static char redstorm_stdout_buf[32678];
227  std::setvbuf(stdout, redstorm_stdout_buf, _IOFBF, sizeof(redstorm_stdout_buf));
228 
229  static char redstorm_cerr_buf[32678];
230  std::cerr.rdbuf()->pubsetbuf(redstorm_cerr_buf, sizeof(redstorm_cerr_buf));
231 
232  static char redstorm_stderr_buf[32678];
233  std::setvbuf(stderr, redstorm_stderr_buf, _IOFBF, sizeof(redstorm_stderr_buf));
234 
236 }
237 
238 #elif defined(_AIX)
239 // Cleanup AIX locale initialization problems
240 void
242 {
243  std::locale loc("POSIX");
244 
245  std::locale::global(loc); // std::locale::classic());
246  std::cout.imbue(loc); // std::locale::classic());
247  std::cin.imbue(loc); // std::locale::classic());
248 
249  std::ostringstream strout;
250  strout << "Don't ask why the IBM locale works if I do this " << 10000000 << std::endl;
251 }
252 
253 #else
254 void
256 {}
257 #endif
258 
259 
260 double
262 {
263  timeval tp;
264  struct timezone tz;
265  gettimeofday(&tp, &tz);
266  return (tp.tv_sec + (((double)(tp.tv_usec))/1000000.0));
267 }
268 
269 
270 double
272 {
273 #if defined(REDS)
274  struct rusage my_rusage;
275 
276  getrusage(RUSAGE_SELF, &my_rusage);
277 
278  return (double) (my_rusage.ru_utime.tv_sec)
279  + ((double)(my_rusage.ru_utime.tv_usec))*1.0e-6;
280 
281 #elif ! defined(__PGI)
282  struct rusage my_rusage;
283 
284  getrusage(RUSAGE_SELF, &my_rusage);
285 
286  return (double) (my_rusage.ru_utime.tv_sec + my_rusage.ru_stime.tv_sec)
287  + ((double)(my_rusage.ru_utime.tv_usec + my_rusage.ru_stime.tv_usec))*1.0e-6;
288 #else
289  return 0;
290 #endif
291 }
292 
293 
294 void
296  size_t & heap_size,
297  size_t & largest_free)
298 {
299  heap_size = 0;
300  largest_free = 0;
301 
302 #if defined(SIERRA_HEAP_INFO)
303 
304 # if defined(SIERRA_PTMALLOC3_ALLOCATOR) || defined(SIERRA_PTMALLOC2_ALLOCATOR)
305  heap_size = malloc_used();
306 
307 # elif 0 // if defined(REDS) // Redstorm now links in gnu's malloc
308  static size_t reds_fragments;
309  static unsigned long reds_total_free;
310  static unsigned long reds_heap_size;
311  static unsigned long reds_largest_free;
312 
313  ::heap_info(&reds_fragments, &reds_total_free, &reds_largest_free, &reds_heap_size);
314 
315  heap_size = reds_heap_size;
316  largest_free = reds_largest_free;
317 
318  slibout.m(Slib::LOG_MEMORY) <<"reds_fragments " << reds_fragments
319  << ", reds_total_free " << reds_total_free
320  << ", reds_largest_free " << reds_largest_free
321  << ", reds_heap_size " << reds_heap_size << Diag::dendl;
322 
323 # elif ( defined(__linux__) || defined(REDS) ) && ! defined(__IBMCPP__)
324  static struct mallinfo minfo;
325  minfo = mallinfo();
326  heap_size = (unsigned int) minfo.uordblks + (unsigned int) minfo.hblkhd;
327  largest_free = (unsigned int) minfo.fordblks;
328 
329  slibout.m(Slib::LOG_MEMORY) << "size_t size " << sizeof(size_t)*8 << " bits"
330  << ", heap size " << heap_size
331  << ", arena " << (unsigned int) minfo.arena
332  << ", ordblks " << minfo.ordblks
333  << ", smblks " << minfo.smblks
334  << ", hblks " << minfo.hblks
335  << ", hblkhd " << (unsigned int) minfo.hblkhd
336  << ", usmblks " << minfo.usmblks
337  << ", fsmblks " << minfo.fsmblks
338  << ", uordblks " << (unsigned int) minfo.uordblks
339  << ", fordblks " << (unsigned int) minfo.fordblks
340  << ", keepcost " << minfo.keepcost << Diag::dendl;
341 
342 
343 # elif defined(__sun)
344  pstatus_t proc_status;
345 
346  std::ifstream proc("/proc/self/status", std::ios_base::in|std::ios_base::binary);
347  if (proc) {
348  proc.read((char *)&proc_status, sizeof(proc_status));
349  heap_size = proc_status.pr_brksize;
350  slibout.m(Slib::LOG_MEMORY) <<"pr_brksize " << proc_status.pr_brksize
351  << ", pr_stksize " << proc_status.pr_stksize << Diag::dendl;
352  }
353 # endif
354 #endif // defined(SIERRA_HEAP_INFO)
355 }
356 
357 
359 {
360 #if !defined(REDS)
361  // The value returned for _SC_AVPHYS_PAGES is the amount of memory
362  // the application can use without hindering any other process
363  // (given that no other process increases its memory usage).
364 #if !defined(__APPLE__) && !defined(__FreeBSD__)
365  static size_t pagesize = getpagesize();
366  size_t avail = sysconf(_SC_AVPHYS_PAGES);
367  return avail * pagesize;
368 #else
369  // _SC_AVPHYS_PAGES does not exist on FreeBSD/Apple
370  return 0;
371 #endif
372 #else
373  // On redstorm, we get an estimate of the available memory at the
374  // time that the application starts up and then we get the currently
375  // available memory by subtracting the used memory from that initial
376  // value.
377  static size_t initial_memory_size = 0;
378  if (initial_memory_size == 0) {
379  initial_memory_size = get_redstorm_base_available_memory();
380  }
381  return initial_memory_size - get_heap_usage();
382 #endif
383 }
384 
385 void
387  size_t & memory_usage,
388  size_t & faults)
389 {
390  memory_usage = 0;
391  faults = 0;
392 
393 #if defined(SIERRA_MEMORY_INFO)
394 # if defined(REDS)
395  memory_usage = (size_t) __heap_start + get_heap_usage();
396 
397 # elif defined(__linux__)
398  std::ifstream proc("/proc/self/stat", std::ios_base::in|std::ios_base::binary);
399  if (proc) {
400 
401  std::string s;
402  int i;
403  for (i = 0; i < 11; ++i)
404  proc >> s;
405 
406  proc >> faults;
407  ++i;
408 
409  for (; i < 22; ++i)
410  proc >> s;
411 
412  proc >> memory_usage;
413  ++i;
414  }
415 # elif defined(__sun)
416  {
417 
418  psinfo_t proc_info;
419 
420  std::ifstream proc("/proc/self/psinfo", std::ios_base::in|std::ios_base::binary);
421  if (proc) {
422  proc.read((char *)&proc_info, sizeof(proc_info));
423  memory_usage = proc_info.pr_size*1024;
424  }
425  }
426 
427  {
428  prusage_t proc_usage;
429 
430  std::ifstream proc("/proc/self/usage", std::ios_base::in|std::ios_base::binary);
431  if (proc) {
432  proc.read((char *)&proc_usage, sizeof(proc_usage));
433  faults = proc_usage.pr_majf;
434  }
435  }
436 # endif
437 #endif // defined(SIERRA_MEMORY_INFO)
438 }
439 
440 
441 double
443 {
444  size_t memory_usage;
445  size_t faults;
446 
447  get_memory_info(memory_usage, faults);
448 
449  return (double) memory_usage;
450 }
451 
452 
453 std::string
455 {
456  char buf[255];
457  ::gethostname(buf, sizeof(buf));
458  return std::string(buf);
459 }
460 
461 
462 std::string
464 {
465 #if defined(__PUMAGON__) || defined(REDS)
466  return std::string(".sandia.gov");
467 
468 #elif defined(__sun)
469  std::string domain(".");
470  char buf[255];
471 
472  ::sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf));
473  if (std::strlen(buf)) {
474  domain += buf;
475  }
476  return domain;
477 
478 #else //#elif defined(__linux) || defined(__sgi) || defined(_AIX)
479  std::string domain(".");
480  char buf[255];
481 
482  ::getdomainname(buf, sizeof(buf));
483  if (::strlen(buf)) {
484  domain += buf;
485  }
486  return domain;
487 
488 #endif
489 }
490 
491 
492 std::string
494 {
495 #if defined(REDS) || defined(__CRAYXT_COMPUTE_LINUX_TARGET)
496  if (get_param("username").empty())
497  return "unknown";
498  else
499  return get_param("username");
500 #else
501  struct passwd *user_info = ::getpwuid(::geteuid());
502 
503  return (user_info ? user_info->pw_name : "unknown");
504 #endif
505 }
506 
507 
508 std::string
510 {
511 #ifndef __sgi
512  struct utsname uts_name;
513 
514  uname(&uts_name);
515 
516  return uts_name.machine;
517 #else
518  std::string s;
519  return s;
520 #endif
521 }
522 
523 
524 std::string
526 {
527 #ifndef __sgi
528  struct utsname uts_name;
529 
530  uname(&uts_name);
531 
532  return uts_name.sysname;
533 #else
534  std::string s;
535  return s;
536 #endif
537 }
538 
539 
540 std::string
542 {
543 #ifndef __sgi
544  struct utsname uts_name;
545 
546  uname(&uts_name);
547 
548  return uts_name.release;
549 #else
550  std::string s;
551  return s;
552 #endif
553 }
554 
555 
556 int
558 {
559  return ::getpid();
560 }
561 
562 
563 int
565 {
566 #if defined(__PUMAGON__) || defined(REDS)
567  return 0;
568 #else
569  return ::getpgrp();
570 #endif
571 }
572 
573 
574 bool
576  const std::string & name,
577  int mode)
578 
579 {
580  return !name.empty() && ::access(name.c_str(), mode) == 0;
581 }
582 
583 
584 bool
586  const std::string & name)
587 {
588  return path_access(name, F_OK);
589 }
590 
591 
592 bool
594  const std::string & name)
595 {
596  return path_access(name, R_OK);
597 }
598 
599 
600 bool
602  const std::string & name)
603 {
604  return path_access(name, W_OK);
605 }
606 
607 
608 namespace {
609 
610 struct flock *
611 file_lock(
612  short type,
613  short whence)
614 {
615 // /* %TRACE[SPEC]% */ Tracespec trace__("sierra::Fmwk::<unnamed>::file_lock( short type, short whence)"); /* %TRACE% */
616  static struct flock ret;
617  ret.l_type = type;
618  ret.l_start = 0;
619  ret.l_whence = whence;
620  ret.l_len = 0;
621  ret.l_pid = 0; //getpid();
622  return &ret;
623 }
624 
625 } // namespace <unnamed>
626 
627 bool
629  int fd)
630 {
631  int i =::fcntl(fd, F_SETLK, file_lock(F_WRLCK, SEEK_SET));
632 // if (i == -1)
633 // fmwkout << "Write lock failed " << errno << dendl;
634 
635  return i != -1;
636 }
637 
638 
639 bool
641  int fd)
642 {
643  int i =::fcntl(fd, F_SETLK, file_lock(F_UNLCK, SEEK_SET));
644 // if (i == -1)
645 // fmwkout << "Release lock failed " << errno << dendl;
646 
647  return i != -1;
648 }
649 
650 
651 bool
653  int fd)
654 {
655  return ::fcntl(fd, F_SETLK, file_lock(F_RDLCK, SEEK_SET)) != -1;
656 }
657 
658 
659 bool
661  int fd)
662 {
663  return ::fcntl(fd, F_SETLK, file_lock(F_WRLCK, SEEK_END)) != -1;
664 }
665 
666 } // namespace Env
667 } // namespace sierra
668 
669 #if defined(REDS)
670 
671 #if defined(__GNUC__)
672 namespace {
673  size_t get_redstorm_base_available_memory()
674  {
675  return 0;
676  }
677 }
678 #else
679 // Written by Mike Davis
680 #include <catamount/data.h>
681 namespace {
682 
683  void stk_ptr (unsigned long *sp) {
684  asm ("movq %rsp, (%rdi)");
685  }
686 
687  size_t get_redstorm_base_available_memory()
688  {
689  char *p1;
690  size_t stack_top;
691  size_t avail_mem;
692  size_t heap_base;
693  size_t stack_base;
694  size_t stack_size;
695  size_t unmapped_top = 4 * 1048576;
696  size_t os_foot = 140 * 1048576;
697  size_t avail_heap;
698 
703  stk_ptr (&stack_top);
704 
708  stack_top &= ~0x1fffff;
709  stack_top += 0x200000;
710 
716  avail_mem = stack_top + unmapped_top;
717 
721  avail_mem -= os_foot;
722 
727  avail_mem /= _my_pcb->upcb_vnm_degree;
728 
733  p1 = (char *) malloc (1);
734  heap_base = (size_t) p1;
735  free (p1);
736 
742  avail_heap = avail_mem - heap_base;
743 
748  stack_base = (size_t) _my_pcb;
749  stack_base &= ~0x1fffff;
750  stack_base += 0x400000;
751 
757  stack_size = stack_top - stack_base;
758  avail_heap -= unmapped_top;
759  avail_heap -= stack_size;
760 
761  return avail_heap;
762  }
763 }
764 #endif
765 #endif
size_t get_available_memory()
Function get_available_memory returns an estimation of the amount of memory available to the process...
Definition: Platform.cpp:358
double cpu_now()
Member function cpu_now returns the accumlated cpu time for the process as a double precision value i...
Definition: Platform.cpp:271
std::string osversion()
Function osversion returns the hardware type of the host running the application. ...
Definition: Platform.cpp:541
Definition: Env.cpp:53
double wall_now()
Member function wall_now returns the epoch as a double precision value in seconds to "millisecond" ac...
Definition: Platform.cpp:261
int pid()
Function pid returns the process id of the process running the application.
Definition: Platform.cpp:557
void get_memory_info(size_t &memory_usage, size_t &faults)
Function get_memory_info returns the total memory usage of the process and the number of page faults ...
Definition: Platform.cpp:386
bool path_write_access(const std::string &name)
Function path_write_access returns true if the process has write access to the path.
Definition: Platform.cpp:601
const char * demangle(const char *symbol)
Function demangle returns the demangled C++ symbol from the mangled C++ symbol. The mangled named is ...
Definition: Platform.cpp:210
void startup_preparallel_platform()
Function startup_preparallel_platform ...
Definition: Platform.cpp:255
bool release_lock(int fd)
Function release_lock returns true if the process was able to release a lock previously palced on the...
Definition: Platform.cpp:640
void get_heap_info(size_t &heap_size, size_t &largest_free)
Member function get_heap_info returns the amount of heap memory used in bytes and the largest free bl...
Definition: Platform.cpp:295
bool write_lock(int fd)
Function write_lock returns true if the process was able to place an exclusive lock on the specified ...
Definition: Platform.cpp:628
size_t get_heap_usage()
Function get_heap_usage returns the number of bytes used by the heap.
Definition: Platform.hpp:152
bool append_lock(int fd)
Function append_lock returns true if the process was able to place an exclusive lock on the end of th...
Definition: Platform.cpp:660
double vm_now()
Member function vm_now returns the virtual memory in use for the process as a double precision value ...
Definition: Platform.cpp:442
bool path_access(const std::string &name, int mode)
Function path_access returns true if the process has permission to access path with the specified mod...
Definition: Platform.cpp:575
Writer & dendl(Writer &dout)
Writer function dendl calls the Writer::dendl manipulator.
Definition: Writer.hpp:520
std::string hardware()
Function hardware returns the hardware type of the host running the application.
Definition: Platform.cpp:509
std::string domainname()
Function domainname returns the domainname of the domain running the application. ...
Definition: Platform.cpp:463
bool read_lock(int fd)
Function read_lock returns true if the process was able to place a shared lock on the specified file ...
Definition: Platform.cpp:652
bool path_exists(const std::string &name)
Function path_exists returns true if the path exists.
Definition: Platform.cpp:585
const std::string & get_param(const char *const option)
Function query_env_param searches the command line options for the specified option. If not found, a const reference to an empty string is returned.
Definition: Env.cpp:1164
std::string username()
Function username returns the username of the user running the application.
Definition: Platform.cpp:493
bool path_read_access(const std::string &name)
Function path_read_access returns true if the process has read access to the path.
Definition: Platform.cpp:593
int pgrp()
Function pgrp returns the process group id of the process running the application.
Definition: Platform.cpp:564
std::string osname()
Function osname returns the operating system nameof the host running the application.
Definition: Platform.cpp:525
std::string hostname()
Function hostname returns the hostname of the host running the application.
Definition: Platform.cpp:454