#include "Unix.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/TimeValue.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
# include <termios.h>
#endif
+// See if we can use curses to detect information about a terminal when
+// connected to one.
+#ifdef HAVE_CURSES
+# if defined(HAVE_CURSES_H)
+# include <curses.h>
+# elif defined(HAVE_NCURSES_H)
+# include <ncurses.h>
+# elif defined(HAVE_NCURSESW_H)
+# include <ncursesw.h>
+# elif defined(HAVE_NCURSES_CURSES_H)
+# include <ncurses/curses.h>
+# elif defined(HAVE_NCURSESW_CURSES_H)
+# include <ncursesw/curses.h>
+# else
+# error Have a curses library but unable to find a curses header!
+# endif
+# include <term.h>
+#endif
+
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
return getpid();
}
+static std::pair<TimeValue, TimeValue> getRUsageTimes() {
+#if defined(HAVE_GETRUSAGE)
+ struct rusage RU;
+ ::getrusage(RUSAGE_SELF, &RU);
+ return std::make_pair(
+ TimeValue(
+ static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
+ static_cast<TimeValue::NanoSecondsType>(
+ RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
+ TimeValue(
+ static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
+ static_cast<TimeValue::NanoSecondsType>(
+ RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
+#else
+#warning Cannot get usage times on this platform
+ return std::make_pair(TimeValue(), TimeValue());
+#endif
+}
+
+TimeValue self_process::get_user_time() const {
+#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
+ // Try to get a high resolution CPU timer.
+ struct timespec TS;
+ if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
+ return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
+ static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
+#endif
+
+ // Otherwise fall back to rusage based timing.
+ return getRUsageTimes().first;
+}
+
+TimeValue self_process::get_system_time() const {
+ // We can only collect system time by inspecting the results of getrusage.
+ return getRUsageTimes().second;
+}
+
static unsigned getPageSize() {
#if defined(__CYGWIN__)
// On Cygwin, getpagesize() returns 64k but the page size for the purposes of
#endif
}
-void
-Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
- TimeValue& sys_time)
-{
+void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
+ TimeValue &sys_time) {
elapsed = TimeValue::now();
-#if defined(HAVE_GETRUSAGE)
- struct rusage usage;
- ::getrusage(RUSAGE_SELF, &usage);
- user_time = TimeValue(
- static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
- static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
- TimeValue::NANOSECONDS_PER_MICROSECOND ) );
- sys_time = TimeValue(
- static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
- static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
- TimeValue::NANOSECONDS_PER_MICROSECOND ) );
-#else
-#warning Cannot get usage times on this platform
- user_time.seconds(0);
- user_time.microseconds(0);
- sys_time.seconds(0);
- sys_time.microseconds(0);
-#endif
+ llvm::tie(user_time, sys_time) = getRUsageTimes();
}
int Process::GetCurrentUserId() {
return getColumns(2);
}
-static bool terminalHasColors() {
- if (const char *term = std::getenv("TERM")) {
- // Most modern terminals support ANSI escape sequences for colors.
- // We could check terminfo, or have a list of known terms that support
- // colors, but that would be overkill.
- // The user can always ask for no colors by setting TERM to dumb, or
- // using a commandline flag.
- return strcmp(term, "dumb") != 0;
- }
+static bool terminalHasColors(int fd) {
+#ifdef HAVE_CURSES
+ // First, acquire a global lock because the curses C routines are thread
+ // hostile.
+ static sys::Mutex M;
+ MutexGuard G(M);
+
+ int errret = 0;
+ if (setupterm((char *)0, fd, &errret) != OK)
+ // Regardless of why, if we can't get terminfo, we shouldn't try to print
+ // colors.
+ return false;
+
+ // Test whether the terminal as set up supports color output.
+ if (has_colors() == TRUE)
+ return true;
+#endif
+
+ // Otherwise, be conservative.
return false;
}
bool Process::FileDescriptorHasColors(int fd) {
// A file descriptor has colors if it is displayed and the terminal has
// colors.
- return FileDescriptorIsDisplayed(fd) && terminalHasColors();
+ return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
}
bool Process::StandardOutHasColors() {