diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 8536a161e64..7e9b07cb547 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -68,6 +68,7 @@ #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" +#include "services/stathist.hpp" #include "utilities/align.hpp" #include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" @@ -154,6 +155,126 @@ enum CoredumpFilterBit { DAX_SHARED_BIT = 1 << 8 }; + + +// SAPMACHINE + +class ProcFile { + char* _buf; + + // To keep the code simple, I just use a fixed sized buffer. + enum { bufsize = 4*K }; + +public: + + ProcFile() : _buf(NULL) { + _buf = (char*)os::malloc(bufsize, mtInternal); + } + + ~ProcFile () { + os::free(_buf); + } + + bool read(const char* filename) { + + FILE* f = ::fopen(filename, "r"); + if (f == NULL) { + return false; + } + memset(_buf, 0, bufsize); + size_t bytes_read = ::fread(_buf, 1, bufsize, f); + _buf[bufsize - 1] = '\0'; + + ::fclose(f); + + return bytes_read > 0 && bytes_read < bufsize; + } + + const char* text() const { return _buf; } + + const char* get_prefixed_line(const char* prefix) const { + return ::strstr(_buf, prefix); + } + + uint64_t parsed_prefixed_value(const char* prefix, size_t scale = 1) const { + uint64_t value = 0; + const char* const s = get_prefixed_line(prefix); + if (s != NULL) { + errno = 0; + const char* p = s + ::strlen(prefix); + char* endptr = NULL; + value = (uint64_t)::strtoll(p, &endptr, 10); + if (p == endptr || errno != 0) { + value = 0; + } else { + value *= scale; + } + } + return value; + } + +}; + +// Helper function, returns true if string is a numerical id +static bool is_numerical_id(const char* s) { + const char* p = s; + while(*p >= '0' && *p <= '9') { + p ++; + } + return *p == '\0' ? true : false; +} + +static void print_processes_and_their_threads(outputStream* st) { + ProcFile bf; + char tmp[128]; + int total_processes = 0; + int total_threads = 0; + DIR* d = ::opendir("/proc"); + if (d != NULL) { + struct dirent* en = NULL; + do { + en = ::readdir(d); + if (en != NULL) { + if (is_numerical_id(en->d_name)) { + total_processes ++; + st->print("%s: ", en->d_name); + // num threads + jio_snprintf(tmp, sizeof(tmp), "/proc/%s/stat", en->d_name); + if (bf.read(tmp)) { + const char* text = bf.text(); + // See man proc(5) + // (20) num_threads %ld + long num_threads = 0; + ::sscanf(text, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %*d %*d %ld", &num_threads); + st->print(", %ld threads", num_threads); + total_threads += num_threads; + } + // command line + jio_snprintf(tmp, sizeof(tmp), "/proc/%s/cmdline", en->d_name); + bf.read(tmp); + st->print_cr(", cmdline: %s ", bf.text()); + } + } + } while(en != NULL); + ::closedir(d); + } + st->print_cr("%d processes, %d threads in total ", total_processes, total_threads); + +} + + + + + + + + + + + + + + //////////////////////////////////////////////////////////////////////////////// // global variables julong os::Linux::_physical_memory = 0; @@ -866,12 +987,17 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); // Log some OS information which might explain why creating the thread failed. - log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads()); - LogStream st(Log(os, thread)::info()); + log_warning(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads()); + LogStream st(Log(os, thread)::warning()); os::Posix::print_rlimit_info(&st); - os::print_memory_info(&st); + { + StatisticsHistory::print_info_t pi = *StatisticsHistory::default_settings(); + pi.no_legend = true; + StatisticsHistory::print_report(&st, &pi); + } + print_processes_and_their_threads(&st); os::Linux::print_proc_sys_info(&st); - os::Linux::print_container_info(&st); + //os::Linux::print_container_info(&st); } pthread_attr_destroy(&attr);