SystemInformation.cxx 149 KB
Newer Older
Kitware Robot's avatar
Kitware Robot committed
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
Kitware Robot's avatar
Kitware Robot committed
3
#if defined(_WIN32)
Kitware Robot's avatar
Kitware Robot committed
4 5 6 7 8
#  define NOMINMAX // use our min,max
#  if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
#    define _WIN32_WINNT 0x0501
#  endif
#  include <winsock.h> // WSADATA, include before sys/types.h
Kitware Robot's avatar
Kitware Robot committed
9 10
#endif

Kitware Robot's avatar
Kitware Robot committed
11
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
Kitware Robot's avatar
Kitware Robot committed
12
#  define _GNU_SOURCE
Kitware Robot's avatar
Kitware Robot committed
13 14
#endif

Kitware Robot's avatar
Kitware Robot committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
// TODO:
// We need an alternative implementation for many functions in this file
// when USE_ASM_INSTRUCTIONS gets defined as 0.
//
// Consider using these on Win32/Win64 for some of them:
//
// IsProcessorFeaturePresent
// http://msdn.microsoft.com/en-us/library/ms724482(VS.85).aspx
//
// GetProcessMemoryInfo
// http://msdn.microsoft.com/en-us/library/ms683219(VS.85).aspx

#include "kwsysPrivate.h"
#include KWSYS_HEADER(SystemInformation.hxx)
#include KWSYS_HEADER(Process.h)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
Kitware Robot's avatar
Kitware Robot committed
34 35
#  include "Process.h.in"
#  include "SystemInformation.hxx.in"
Kitware Robot's avatar
Kitware Robot committed
36 37
#endif

Kitware Robot's avatar
Kitware Robot committed
38 39 40
#include <algorithm>
#include <bitset>
#include <cassert>
Kitware Robot's avatar
Kitware Robot committed
41
#include <fstream>
Kitware Robot's avatar
Kitware Robot committed
42
#include <iostream>
Kitware Robot's avatar
Kitware Robot committed
43 44
#include <limits>
#include <set>
Kitware Robot's avatar
Kitware Robot committed
45 46 47 48
#include <sstream>
#include <string>
#include <vector>

Kitware Robot's avatar
Kitware Robot committed
49
#if defined(_WIN32)
Kitware Robot's avatar
Kitware Robot committed
50 51 52 53 54 55 56 57 58
#  include <windows.h>
#  if defined(_MSC_VER) && _MSC_VER >= 1800
#    define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#  endif
#  include <errno.h>
#  if defined(KWSYS_SYS_HAS_PSAPI)
#    include <psapi.h>
#  endif
#  if !defined(siginfo_t)
Kitware Robot's avatar
Kitware Robot committed
59
typedef int siginfo_t;
Kitware Robot's avatar
Kitware Robot committed
60
#  endif
Kitware Robot's avatar
Kitware Robot committed
61
#else
Kitware Robot's avatar
Kitware Robot committed
62 63 64 65 66 67 68 69 70
#  include <sys/types.h>

#  include <errno.h> // extern int errno;
#  include <fcntl.h>
#  include <signal.h>
#  include <sys/resource.h> // getrlimit
#  include <sys/time.h>
#  include <sys/utsname.h> // int uname(struct utsname *buf);
#  include <unistd.h>
Kitware Robot's avatar
Kitware Robot committed
71 72
#endif

Kitware Robot's avatar
Kitware Robot committed
73
#if defined(__CYGWIN__) && !defined(_WIN32)
Kitware Robot's avatar
Kitware Robot committed
74 75
#  include <windows.h>
#  undef _WIN32
Kitware Robot's avatar
Kitware Robot committed
76 77
#endif

Kitware Robot's avatar
Kitware Robot committed
78 79
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) ||    \
  defined(__DragonFly__)
Kitware Robot's avatar
Kitware Robot committed
80 81 82 83 84 85 86 87 88 89
#  include <netdb.h>
#  include <netinet/in.h>
#  include <sys/param.h>
#  include <sys/socket.h>
#  include <sys/sysctl.h>
#  if defined(KWSYS_SYS_HAS_IFADDRS_H)
#    include <ifaddrs.h>
#    include <net/if.h>
#    define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#  endif
Kitware Robot's avatar
Kitware Robot committed
90 91
#endif

Kitware Robot's avatar
Kitware Robot committed
92
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
Kitware Robot's avatar
Kitware Robot committed
93
#  include <machine/cpu.h>
Kitware Robot's avatar
Kitware Robot committed
94 95
#endif

Kitware Robot's avatar
Kitware Robot committed
96
#ifdef __APPLE__
Kitware Robot's avatar
Kitware Robot committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
#  include <mach/host_info.h>
#  include <mach/mach.h>
#  include <mach/mach_types.h>
#  include <mach/vm_statistics.h>
#  include <netdb.h>
#  include <netinet/in.h>
#  include <sys/socket.h>
#  include <sys/sysctl.h>
#  if defined(KWSYS_SYS_HAS_IFADDRS_H)
#    include <ifaddrs.h>
#    include <net/if.h>
#    define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#  endif
#  if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 1050)
#    undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
#  endif
Kitware Robot's avatar
Kitware Robot committed
113 114
#endif

Kitware Robot's avatar
Kitware Robot committed
115 116
#if defined(__linux) || defined(__sun) || defined(_SCO_DS) ||                 \
  defined(__GLIBC__) || defined(__GNU__)
Kitware Robot's avatar
Kitware Robot committed
117 118 119 120 121 122 123
#  include <netdb.h>
#  include <netinet/in.h>
#  include <sys/socket.h>
#  if defined(KWSYS_SYS_HAS_IFADDRS_H)
#    include <ifaddrs.h>
#    include <net/if.h>
#    if defined(__LSB_VERSION__)
Kitware Robot's avatar
Kitware Robot committed
124
/* LSB has no getifaddrs */
Kitware Robot's avatar
Kitware Robot committed
125
#    elif defined(__ANDROID_API__) && __ANDROID_API__ < 24
Kitware Robot's avatar
Kitware Robot committed
126
/* Android has no getifaddrs prior to API 24.  */
Kitware Robot's avatar
Kitware Robot committed
127 128 129 130 131
#    else
#      define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#    endif
#  endif
#  if defined(KWSYS_CXX_HAS_RLIMIT64)
Kitware Robot's avatar
Kitware Robot committed
132
typedef struct rlimit64 ResourceLimitType;
Kitware Robot's avatar
Kitware Robot committed
133 134
#    define GetResourceLimit getrlimit64
#  else
Kitware Robot's avatar
Kitware Robot committed
135
typedef struct rlimit ResourceLimitType;
Kitware Robot's avatar
Kitware Robot committed
136 137
#    define GetResourceLimit getrlimit
#  endif
Kitware Robot's avatar
Kitware Robot committed
138
#elif defined(__hpux)
Kitware Robot's avatar
Kitware Robot committed
139 140 141 142 143
#  include <sys/param.h>
#  include <sys/pstat.h>
#  if defined(KWSYS_SYS_HAS_MPCTL_H)
#    include <sys/mpctl.h>
#  endif
Kitware Robot's avatar
Kitware Robot committed
144 145 146
#endif

#ifdef __HAIKU__
Kitware Robot's avatar
Kitware Robot committed
147
#  include <OS.h>
Kitware Robot's avatar
Kitware Robot committed
148 149
#endif

Kitware Robot's avatar
Kitware Robot committed
150
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
Kitware Robot's avatar
Kitware Robot committed
151 152 153 154 155 156 157
#  include <execinfo.h>
#  if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
#    include <cxxabi.h>
#  endif
#  if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
#    include <dlfcn.h>
#  endif
Kitware Robot's avatar
Kitware Robot committed
158
#else
Kitware Robot's avatar
Kitware Robot committed
159 160
#  undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
#  undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
Kitware Robot's avatar
Kitware Robot committed
161 162
#endif

Kitware Robot's avatar
Kitware Robot committed
163
#include <ctype.h> // int isdigit(int c);
Kitware Robot's avatar
Kitware Robot committed
164 165
#include <memory.h>
#include <stdio.h>
Kitware Robot's avatar
Kitware Robot committed
166
#include <stdlib.h>
Kitware Robot's avatar
Kitware Robot committed
167 168
#include <string.h>

Kitware Robot's avatar
Kitware Robot committed
169
#if defined(KWSYS_USE_LONG_LONG)
Kitware Robot's avatar
Kitware Robot committed
170 171 172 173 174
#  if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
#    define iostreamLongLong(x) (x)
#  else
#    define iostreamLongLong(x) ((long)(x))
#  endif
Kitware Robot's avatar
Kitware Robot committed
175
#elif defined(KWSYS_USE___INT64)
Kitware Robot's avatar
Kitware Robot committed
176 177 178 179 180
#  if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
#    define iostreamLongLong(x) (x)
#  else
#    define iostreamLongLong(x) ((long)(x))
#  endif
Kitware Robot's avatar
Kitware Robot committed
181
#else
Kitware Robot's avatar
Kitware Robot committed
182
#  error "No Long Long"
Kitware Robot's avatar
Kitware Robot committed
183 184 185
#endif

#if defined(KWSYS_CXX_HAS_ATOLL)
Kitware Robot's avatar
Kitware Robot committed
186
#  define atoLongLong atoll
Kitware Robot's avatar
Kitware Robot committed
187
#else
Kitware Robot's avatar
Kitware Robot committed
188 189 190 191 192 193 194
#  if defined(KWSYS_CXX_HAS__ATOI64)
#    define atoLongLong _atoi64
#  elif defined(KWSYS_CXX_HAS_ATOL)
#    define atoLongLong atol
#  else
#    define atoLongLong atoi
#  endif
Kitware Robot's avatar
Kitware Robot committed
195 196
#endif

Kitware Robot's avatar
Kitware Robot committed
197 198
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) &&            \
  !defined(__clang__)
Kitware Robot's avatar
Kitware Robot committed
199
#  define USE_ASM_INSTRUCTIONS 1
Kitware Robot's avatar
Kitware Robot committed
200
#else
Kitware Robot's avatar
Kitware Robot committed
201
#  define USE_ASM_INSTRUCTIONS 0
Kitware Robot's avatar
Kitware Robot committed
202 203
#endif

Kitware Robot's avatar
Kitware Robot committed
204
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__clang__)
Kitware Robot's avatar
Kitware Robot committed
205 206
#  include <intrin.h>
#  define USE_CPUID_INTRINSICS 1
Kitware Robot's avatar
Kitware Robot committed
207
#else
Kitware Robot's avatar
Kitware Robot committed
208
#  define USE_CPUID_INTRINSICS 0
Kitware Robot's avatar
Kitware Robot committed
209 210
#endif

Kitware Robot's avatar
Kitware Robot committed
211 212
#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS ||                           \
  defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
Kitware Robot's avatar
Kitware Robot committed
213
#  define USE_CPUID 1
Kitware Robot's avatar
Kitware Robot committed
214
#else
Kitware Robot's avatar
Kitware Robot committed
215
#  define USE_CPUID 0
Kitware Robot's avatar
Kitware Robot committed
216 217 218 219
#endif

#if USE_CPUID

Kitware Robot's avatar
Kitware Robot committed
220
#  define CPUID_AWARE_COMPILER
Kitware Robot's avatar
Kitware Robot committed
221 222 223 224 225 226 227 228

/**
 * call CPUID instruction
 *
 * Will return false if the instruction failed.
 */
static bool call_cpuid(int select, int result[4])
{
Kitware Robot's avatar
Kitware Robot committed
229
#  if USE_CPUID_INTRINSICS
Kitware Robot's avatar
Kitware Robot committed
230 231
  __cpuid(result, select);
  return true;
Kitware Robot's avatar
Kitware Robot committed
232
#  else
Kitware Robot's avatar
Kitware Robot committed
233
  int tmp[4];
Kitware Robot's avatar
Kitware Robot committed
234
#    if defined(_MSC_VER)
Kitware Robot's avatar
Kitware Robot committed
235 236 237
  // Use SEH to determine CPUID presence
  __try {
    _asm {
Kitware Robot's avatar
Kitware Robot committed
238
#      ifdef CPUID_AWARE_COMPILER
Kitware Robot's avatar
Kitware Robot committed
239
      ; we must push/pop the registers <<CPUID>> writes to, as the
Kitware Robot's avatar
Kitware Robot committed
240
      ; optimiser does not know about <<CPUID>>, and so does not expect
Kitware Robot's avatar
Kitware Robot committed
241 242 243 244 245
      ; these registers to change.
      push eax
      push ebx
      push ecx
      push edx
Kitware Robot's avatar
Kitware Robot committed
246
#      endif
Kitware Robot's avatar
Kitware Robot committed
247 248
      ; <<CPUID>>
      mov eax, select
Kitware Robot's avatar
Kitware Robot committed
249
#      ifdef CPUID_AWARE_COMPILER
Kitware Robot's avatar
Kitware Robot committed
250
      cpuid
Kitware Robot's avatar
Kitware Robot committed
251
#      else
Kitware Robot's avatar
Kitware Robot committed
252 253
      _asm _emit 0x0f
      _asm _emit 0xa2
Kitware Robot's avatar
Kitware Robot committed
254
#      endif
Kitware Robot's avatar
Kitware Robot committed
255 256 257 258 259
      mov tmp[0 * TYPE int], eax
      mov tmp[1 * TYPE int], ebx
      mov tmp[2 * TYPE int], ecx
      mov tmp[3 * TYPE int], edx

Kitware Robot's avatar
Kitware Robot committed
260
#      ifdef CPUID_AWARE_COMPILER
Kitware Robot's avatar
Kitware Robot committed
261 262 263 264
      pop edx
      pop ecx
      pop ebx
      pop eax
Kitware Robot's avatar
Kitware Robot committed
265
#      endif
Kitware Robot's avatar
Kitware Robot committed
266
    }
Kitware Robot's avatar
Kitware Robot committed
267
  } __except (1) {
Kitware Robot's avatar
Kitware Robot committed
268
    return false;
Kitware Robot's avatar
Kitware Robot committed
269
  }
Kitware Robot's avatar
Kitware Robot committed
270

Kitware Robot's avatar
Kitware Robot committed
271
  memcpy(result, tmp, sizeof(tmp));
Kitware Robot's avatar
Kitware Robot committed
272
#    elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
Kitware Robot's avatar
Kitware Robot committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286
  unsigned int a, b, c, d;
  __asm {
    mov EAX, select;
    cpuid
    mov a, EAX;
    mov b, EBX;
    mov c, ECX;
    mov d, EDX;
  }

  result[0] = a;
  result[1] = b;
  result[2] = c;
  result[3] = d;
Kitware Robot's avatar
Kitware Robot committed
287
#    endif
Kitware Robot's avatar
Kitware Robot committed
288

Kitware Robot's avatar
Kitware Robot committed
289 290
  // The cpuid instruction succeeded.
  return true;
Kitware Robot's avatar
Kitware Robot committed
291
#  endif
Kitware Robot's avatar
Kitware Robot committed
292 293 294
}
#endif

Kitware Robot's avatar
Kitware Robot committed
295 296 297
namespace KWSYS_NAMESPACE {
template <typename T>
T min(T a, T b)
Kitware Robot's avatar
Kitware Robot committed
298
{
Kitware Robot's avatar
Kitware Robot committed
299 300
  return a < b ? a : b;
}
Kitware Robot's avatar
Kitware Robot committed
301

Kitware Robot's avatar
Kitware Robot committed
302 303 304
extern "C" {
typedef void (*SigAction)(int, siginfo_t*, void*);
}
Kitware Robot's avatar
Kitware Robot committed
305 306

//  Define SystemInformationImplementation class
Kitware Robot's avatar
Kitware Robot committed
307
typedef void (*DELAY_FUNC)(unsigned int uiMS);
Kitware Robot's avatar
Kitware Robot committed
308 309 310 311

class SystemInformationImplementation
{
public:
Kitware Robot's avatar
Kitware Robot committed
312
  typedef SystemInformation::LongLong LongLong;
Kitware Robot's avatar
Kitware Robot committed
313 314
  SystemInformationImplementation();
  ~SystemInformationImplementation();
Kitware Robot's avatar
Kitware Robot committed
315

Kitware Robot's avatar
Kitware Robot committed
316 317
  const char* GetVendorString();
  const char* GetVendorID();
Kitware Robot's avatar
Kitware Robot committed
318 319 320 321 322
  std::string GetTypeID();
  std::string GetFamilyID();
  std::string GetModelID();
  std::string GetModelName();
  std::string GetSteppingCode();
Kitware Robot's avatar
Kitware Robot committed
323 324
  const char* GetExtendedProcessorName();
  const char* GetProcessorSerialNumber();
Kitware Robot's avatar
Kitware Robot committed
325 326 327 328 329 330
  int GetProcessorCacheSize();
  unsigned int GetLogicalProcessorsPerPhysical();
  float GetProcessorClockFrequency();
  int GetProcessorAPICID();
  int GetProcessorCacheXSize(long int);
  bool DoesCPUSupportFeature(long int);
Kitware Robot's avatar
Kitware Robot committed
331

Kitware Robot's avatar
Kitware Robot committed
332 333 334 335 336 337
  const char* GetOSName();
  const char* GetHostname();
  int GetFullyQualifiedDomainName(std::string& fqdn);
  const char* GetOSRelease();
  const char* GetOSVersion();
  const char* GetOSPlatform();
Kitware Robot's avatar
Kitware Robot committed
338 339 340 341 342 343 344 345

  bool Is64Bits();

  unsigned int GetNumberOfLogicalCPU(); // per physical cpu
  unsigned int GetNumberOfPhysicalCPU();

  bool DoesCPUSupportCPUID();

Kitware Robot's avatar
Kitware Robot committed
346
  // Retrieve memory information in MiB.
Kitware Robot's avatar
Kitware Robot committed
347 348 349
  size_t GetTotalVirtualMemory();
  size_t GetAvailableVirtualMemory();
  size_t GetTotalPhysicalMemory();
Kitware Robot's avatar
Kitware Robot committed
350 351 352 353
  size_t GetAvailablePhysicalMemory();

  LongLong GetProcessId();

Kitware Robot's avatar
Kitware Robot committed
354
  // Retrieve memory information in KiB.
Kitware Robot's avatar
Kitware Robot committed
355
  LongLong GetHostMemoryTotal();
Kitware Robot's avatar
Kitware Robot committed
356
  LongLong GetHostMemoryAvailable(const char* envVarName);
Kitware Robot's avatar
Kitware Robot committed
357 358
  LongLong GetHostMemoryUsed();

Kitware Robot's avatar
Kitware Robot committed
359 360
  LongLong GetProcMemoryAvailable(const char* hostLimitEnvVarName,
                                  const char* procLimitEnvVarName);
Kitware Robot's avatar
Kitware Robot committed
361
  LongLong GetProcMemoryUsed();
Kitware Robot's avatar
Kitware Robot committed
362

Kitware Robot's avatar
Kitware Robot committed
363 364
  double GetLoadAverage();

Kitware Robot's avatar
Kitware Robot committed
365
  // enable/disable stack trace signal handler.
Kitware Robot's avatar
Kitware Robot committed
366
  static void SetStackTraceOnError(int enable);
Kitware Robot's avatar
Kitware Robot committed
367

Kitware Robot's avatar
Kitware Robot committed
368
  // get current stack
Kitware Robot's avatar
Kitware Robot committed
369
  static std::string GetProgramStack(int firstFrame, int wholePath);
Kitware Robot's avatar
Kitware Robot committed
370

Kitware Robot's avatar
Kitware Robot committed
371 372 373 374 375 376 377
  /** Run the different checks */
  void RunCPUCheck();
  void RunOSCheck();
  void RunMemoryCheck();

public:
  typedef struct tagID
Kitware Robot's avatar
Kitware Robot committed
378
  {
Kitware Robot's avatar
Kitware Robot committed
379 380 381 382 383 384
    int Type;
    int Family;
    int Model;
    int Revision;
    int ExtendedFamily;
    int ExtendedModel;
Kitware Robot's avatar
Kitware Robot committed
385 386 387 388
    std::string ProcessorName;
    std::string Vendor;
    std::string SerialNumber;
    std::string ModelName;
Kitware Robot's avatar
Kitware Robot committed
389
  } ID;
Kitware Robot's avatar
Kitware Robot committed
390 391

  typedef struct tagCPUPowerManagement
Kitware Robot's avatar
Kitware Robot committed
392
  {
Kitware Robot's avatar
Kitware Robot committed
393 394 395
    bool HasVoltageID;
    bool HasFrequencyID;
    bool HasTempSenseDiode;
Kitware Robot's avatar
Kitware Robot committed
396
  } CPUPowerManagement;
Kitware Robot's avatar
Kitware Robot committed
397 398

  typedef struct tagCPUExtendedFeatures
Kitware Robot's avatar
Kitware Robot committed
399
  {
Kitware Robot's avatar
Kitware Robot committed
400 401 402 403 404 405 406 407
    bool Has3DNow;
    bool Has3DNowPlus;
    bool SupportsMP;
    bool HasMMXPlus;
    bool HasSSEMMX;
    unsigned int LogicalProcessorsPerPhysical;
    int APIC_ID;
    CPUPowerManagement PowerManagement;
Kitware Robot's avatar
Kitware Robot committed
408
  } CPUExtendedFeatures;
Kitware Robot's avatar
Kitware Robot committed
409 410

  typedef struct CPUtagFeatures
Kitware Robot's avatar
Kitware Robot committed
411
  {
Kitware Robot's avatar
Kitware Robot committed
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
    bool HasFPU;
    bool HasTSC;
    bool HasMMX;
    bool HasSSE;
    bool HasSSEFP;
    bool HasSSE2;
    bool HasIA64;
    bool HasAPIC;
    bool HasCMOV;
    bool HasMTRR;
    bool HasACPI;
    bool HasSerial;
    bool HasThermal;
    int CPUSpeed;
    int L1CacheSize;
    int L2CacheSize;
    int L3CacheSize;
    CPUExtendedFeatures ExtendedFeatures;
Kitware Robot's avatar
Kitware Robot committed
430
  } CPUFeatures;
Kitware Robot's avatar
Kitware Robot committed
431 432

  enum Manufacturer
Kitware Robot's avatar
Kitware Robot committed
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
  {
    AMD,
    Intel,
    NSC,
    UMC,
    Cyrix,
    NexGen,
    IDT,
    Rise,
    Transmeta,
    Sun,
    IBM,
    Motorola,
    HP,
    UnknownManufacturer
  };
Kitware Robot's avatar
Kitware Robot committed
449 450

protected:
Kitware Robot's avatar
Kitware Robot committed
451
  // For windows
Kitware Robot's avatar
Kitware Robot committed
452 453 454 455 456 457 458 459 460 461 462 463 464
  bool RetrieveCPUFeatures();
  bool RetrieveCPUIdentity();
  bool RetrieveCPUCacheDetails();
  bool RetrieveClassicalCPUCacheDetails();
  bool RetrieveCPUClockSpeed();
  bool RetrieveClassicalCPUClockSpeed();
  bool RetrieveCPUExtendedLevelSupport(int);
  bool RetrieveExtendedCPUFeatures();
  bool RetrieveProcessorSerialNumber();
  bool RetrieveCPUPowerManagement();
  bool RetrieveClassicalCPUIdentity();
  bool RetrieveExtendedCPUIdentity();

Kitware Robot's avatar
Kitware Robot committed
465
  // Processor information
Kitware Robot's avatar
Kitware Robot committed
466 467 468 469 470 471
  Manufacturer ChipManufacturer;
  CPUFeatures Features;
  ID ChipID;
  float CPUSpeedInMHz;
  unsigned int NumberOfLogicalCPU;
  unsigned int NumberOfPhysicalCPU;
Kitware Robot's avatar
Kitware Robot committed
472

Kitware Robot's avatar
Kitware Robot committed
473
  void CPUCountWindows();    // For windows
Kitware Robot's avatar
Kitware Robot committed
474
  unsigned char GetAPICId(); // For windows
Kitware Robot's avatar
Kitware Robot committed
475
  bool IsSMTSupported();
Kitware Robot's avatar
Kitware Robot committed
476
  static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
Kitware Robot's avatar
Kitware Robot committed
477 478

  // For Linux and Cygwin, /proc/cpuinfo formats are slightly different
Kitware Robot's avatar
Kitware Robot committed
479
  bool RetreiveInformationFromCpuInfoFile();
Kitware Robot's avatar
Kitware Robot committed
480 481
  std::string ExtractValueFromCpuInfoFile(std::string buffer, const char* word,
                                          size_t init = 0);
Kitware Robot's avatar
Kitware Robot committed
482

Kitware Robot's avatar
Kitware Robot committed
483 484 485
  bool QueryLinuxMemory();
  bool QueryCygwinMemory();

Kitware Robot's avatar
Kitware Robot committed
486 487
  static void Delay(unsigned int);
  static void DelayOverhead(unsigned int);
Kitware Robot's avatar
Kitware Robot committed
488

Kitware Robot's avatar
Kitware Robot committed
489
  void FindManufacturer(const std::string& family = "");
Kitware Robot's avatar
Kitware Robot committed
490 491 492

  // For Mac
  bool ParseSysCtl();
Kitware Robot's avatar
Kitware Robot committed
493
  int CallSwVers(const char* arg, std::string& ver);
Kitware Robot's avatar
Kitware Robot committed
494 495 496
  void TrimNewline(std::string&);
  std::string ExtractValueFromSysCtl(const char* word);
  std::string SysCtlBuffer;
Kitware Robot's avatar
Kitware Robot committed
497 498

  // For Solaris
Kitware Robot's avatar
Kitware Robot committed
499 500
  bool QuerySolarisMemory();
  bool QuerySolarisProcessor();
Kitware Robot's avatar
Kitware Robot committed
501 502
  std::string ParseValueFromKStat(const char* arguments);
  std::string RunProcess(std::vector<const char*> args);
Kitware Robot's avatar
Kitware Robot committed
503

Kitware Robot's avatar
Kitware Robot committed
504
  // For Haiku OS
Kitware Robot's avatar
Kitware Robot committed
505 506
  bool QueryHaikuInfo();

Kitware Robot's avatar
Kitware Robot committed
507
  // For QNX
Kitware Robot's avatar
Kitware Robot committed
508 509 510
  bool QueryQNXMemory();
  bool QueryQNXProcessor();

Kitware Robot's avatar
Kitware Robot committed
511
  // For OpenBSD, FreeBSD, NetBSD, DragonFly
Kitware Robot's avatar
Kitware Robot committed
512 513 514
  bool QueryBSDMemory();
  bool QueryBSDProcessor();

Kitware Robot's avatar
Kitware Robot committed
515
  // For HP-UX
Kitware Robot's avatar
Kitware Robot committed
516 517 518
  bool QueryHPUXMemory();
  bool QueryHPUXProcessor();

Kitware Robot's avatar
Kitware Robot committed
519
  // For Microsoft Windows
Kitware Robot's avatar
Kitware Robot committed
520 521
  bool QueryWindowsMemory();

Kitware Robot's avatar
Kitware Robot committed
522
  // For AIX
Kitware Robot's avatar
Kitware Robot committed
523 524
  bool QueryAIXMemory();

Kitware Robot's avatar
Kitware Robot committed
525
  bool QueryProcessorBySysconf();
Kitware Robot's avatar
Kitware Robot committed
526 527
  bool QueryProcessor();

Kitware Robot's avatar
Kitware Robot committed
528
  // Evaluate the memory information.
Kitware Robot's avatar
Kitware Robot committed
529
  bool QueryMemoryBySysconf();
Kitware Robot's avatar
Kitware Robot committed
530
  bool QueryMemory();
Kitware Robot's avatar
Kitware Robot committed
531 532 533 534 535 536 537 538 539
  size_t TotalVirtualMemory;
  size_t AvailableVirtualMemory;
  size_t TotalPhysicalMemory;
  size_t AvailablePhysicalMemory;

  size_t CurrentPositionInFile;

  // Operating System information
  bool QueryOSInformation();
Kitware Robot's avatar
Kitware Robot committed
540 541 542 543 544
  std::string OSName;
  std::string Hostname;
  std::string OSRelease;
  std::string OSVersion;
  std::string OSPlatform;
Kitware Robot's avatar
Kitware Robot committed
545
  bool OSIs64Bit;
Kitware Robot's avatar
Kitware Robot committed
546 547 548 549 550 551 552 553 554 555 556 557
};

SystemInformation::SystemInformation()
{
  this->Implementation = new SystemInformationImplementation;
}

SystemInformation::~SystemInformation()
{
  delete this->Implementation;
}

Kitware Robot's avatar
Kitware Robot committed
558
const char* SystemInformation::GetVendorString()
Kitware Robot's avatar
Kitware Robot committed
559 560 561 562
{
  return this->Implementation->GetVendorString();
}

Kitware Robot's avatar
Kitware Robot committed
563
const char* SystemInformation::GetVendorID()
Kitware Robot's avatar
Kitware Robot committed
564 565 566 567
{
  return this->Implementation->GetVendorID();
}

Kitware Robot's avatar
Kitware Robot committed
568
std::string SystemInformation::GetTypeID()
Kitware Robot's avatar
Kitware Robot committed
569 570 571 572
{
  return this->Implementation->GetTypeID();
}

Kitware Robot's avatar
Kitware Robot committed
573
std::string SystemInformation::GetFamilyID()
Kitware Robot's avatar
Kitware Robot committed
574 575 576 577
{
  return this->Implementation->GetFamilyID();
}

Kitware Robot's avatar
Kitware Robot committed
578
std::string SystemInformation::GetModelID()
Kitware Robot's avatar
Kitware Robot committed
579 580 581 582
{
  return this->Implementation->GetModelID();
}

Kitware Robot's avatar
Kitware Robot committed
583
std::string SystemInformation::GetModelName()
Kitware Robot's avatar
Kitware Robot committed
584 585 586 587
{
  return this->Implementation->GetModelName();
}

Kitware Robot's avatar
Kitware Robot committed
588
std::string SystemInformation::GetSteppingCode()
Kitware Robot's avatar
Kitware Robot committed
589 590 591 592
{
  return this->Implementation->GetSteppingCode();
}

Kitware Robot's avatar
Kitware Robot committed
593
const char* SystemInformation::GetExtendedProcessorName()
Kitware Robot's avatar
Kitware Robot committed
594 595 596 597
{
  return this->Implementation->GetExtendedProcessorName();
}

Kitware Robot's avatar
Kitware Robot committed
598
const char* SystemInformation::GetProcessorSerialNumber()
Kitware Robot's avatar
Kitware Robot committed
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
{
  return this->Implementation->GetProcessorSerialNumber();
}

int SystemInformation::GetProcessorCacheSize()
{
  return this->Implementation->GetProcessorCacheSize();
}

unsigned int SystemInformation::GetLogicalProcessorsPerPhysical()
{
  return this->Implementation->GetLogicalProcessorsPerPhysical();
}

float SystemInformation::GetProcessorClockFrequency()
{
  return this->Implementation->GetProcessorClockFrequency();
}

int SystemInformation::GetProcessorAPICID()
{
  return this->Implementation->GetProcessorAPICID();
}

int SystemInformation::GetProcessorCacheXSize(long int l)
{
  return this->Implementation->GetProcessorCacheXSize(l);
}

bool SystemInformation::DoesCPUSupportFeature(long int i)
{
  return this->Implementation->DoesCPUSupportFeature(i);
}

Kitware Robot's avatar
Kitware Robot committed
633
std::string SystemInformation::GetCPUDescription()
Kitware Robot's avatar
Kitware Robot committed
634
{
Kitware Robot's avatar
Kitware Robot committed
635
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
636 637 638 639 640
  oss << this->GetNumberOfPhysicalCPU() << " core ";
  if (this->GetModelName().empty()) {
    oss << this->GetProcessorClockFrequency() << " MHz "
        << this->GetVendorString() << " " << this->GetExtendedProcessorName();
  } else {
Kitware Robot's avatar
Kitware Robot committed
641
    oss << this->GetModelName();
Kitware Robot's avatar
Kitware Robot committed
642
  }
Kitware Robot's avatar
Kitware Robot committed
643 644

  // remove extra spaces
Kitware Robot's avatar
Kitware Robot committed
645
  std::string tmp = oss.str();
Kitware Robot's avatar
Kitware Robot committed
646
  size_t pos;
Kitware Robot's avatar
Kitware Robot committed
647 648 649
  while ((pos = tmp.find("  ")) != std::string::npos) {
    tmp.replace(pos, 2, " ");
  }
Kitware Robot's avatar
Kitware Robot committed
650 651 652 653

  return tmp;
}

Kitware Robot's avatar
Kitware Robot committed
654
const char* SystemInformation::GetOSName()
Kitware Robot's avatar
Kitware Robot committed
655 656 657 658
{
  return this->Implementation->GetOSName();
}

Kitware Robot's avatar
Kitware Robot committed
659
const char* SystemInformation::GetHostname()
Kitware Robot's avatar
Kitware Robot committed
660 661 662 663
{
  return this->Implementation->GetHostname();
}

Kitware Robot's avatar
Kitware Robot committed
664
std::string SystemInformation::GetFullyQualifiedDomainName()
Kitware Robot's avatar
Kitware Robot committed
665
{
Kitware Robot's avatar
Kitware Robot committed
666
  std::string fqdn;
Kitware Robot's avatar
Kitware Robot committed
667
  this->Implementation->GetFullyQualifiedDomainName(fqdn);
Kitware Robot's avatar
Kitware Robot committed
668 669 670
  return fqdn;
}

Kitware Robot's avatar
Kitware Robot committed
671
const char* SystemInformation::GetOSRelease()
Kitware Robot's avatar
Kitware Robot committed
672 673 674 675
{
  return this->Implementation->GetOSRelease();
}

Kitware Robot's avatar
Kitware Robot committed
676
const char* SystemInformation::GetOSVersion()
Kitware Robot's avatar
Kitware Robot committed
677 678 679 680
{
  return this->Implementation->GetOSVersion();
}

Kitware Robot's avatar
Kitware Robot committed
681
const char* SystemInformation::GetOSPlatform()
Kitware Robot's avatar
Kitware Robot committed
682 683 684 685
{
  return this->Implementation->GetOSPlatform();
}

Kitware Robot's avatar
Kitware Robot committed
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
int SystemInformation::GetOSIsWindows()
{
#if defined(_WIN32)
  return 1;
#else
  return 0;
#endif
}

int SystemInformation::GetOSIsLinux()
{
#if defined(__linux)
  return 1;
#else
  return 0;
#endif
}

int SystemInformation::GetOSIsApple()
{
#if defined(__APPLE__)
  return 1;
#else
  return 0;
#endif
}

Kitware Robot's avatar
Kitware Robot committed
713
std::string SystemInformation::GetOSDescription()
Kitware Robot's avatar
Kitware Robot committed
714
{
Kitware Robot's avatar
Kitware Robot committed
715
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
716 717
  oss << this->GetOSName() << " " << this->GetOSRelease() << " "
      << this->GetOSVersion();
Kitware Robot's avatar
Kitware Robot committed
718 719 720 721

  return oss.str();
}

Kitware Robot's avatar
Kitware Robot committed
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
bool SystemInformation::Is64Bits()
{
  return this->Implementation->Is64Bits();
}

unsigned int SystemInformation::GetNumberOfLogicalCPU() // per physical cpu
{
  return this->Implementation->GetNumberOfLogicalCPU();
}

unsigned int SystemInformation::GetNumberOfPhysicalCPU()
{
  return this->Implementation->GetNumberOfPhysicalCPU();
}

bool SystemInformation::DoesCPUSupportCPUID()
{
  return this->Implementation->DoesCPUSupportCPUID();
}

Kitware Robot's avatar
Kitware Robot committed
742
// Retrieve memory information in MiB.
Kitware Robot's avatar
Kitware Robot committed
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
size_t SystemInformation::GetTotalVirtualMemory()
{
  return this->Implementation->GetTotalVirtualMemory();
}

size_t SystemInformation::GetAvailableVirtualMemory()
{
  return this->Implementation->GetAvailableVirtualMemory();
}

size_t SystemInformation::GetTotalPhysicalMemory()
{
  return this->Implementation->GetTotalPhysicalMemory();
}

size_t SystemInformation::GetAvailablePhysicalMemory()
{
  return this->Implementation->GetAvailablePhysicalMemory();
}

Kitware Robot's avatar
Kitware Robot committed
763
std::string SystemInformation::GetMemoryDescription(
Kitware Robot's avatar
Kitware Robot committed
764
  const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
Kitware Robot's avatar
Kitware Robot committed
765
{
Kitware Robot's avatar
Kitware Robot committed
766
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
767 768 769 770 771 772 773
  oss << "Host Total: " << iostreamLongLong(this->GetHostMemoryTotal())
      << " KiB, Host Available: "
      << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
      << " KiB, Process Available: "
      << iostreamLongLong(this->GetProcMemoryAvailable(hostLimitEnvVarName,
                                                       procLimitEnvVarName))
      << " KiB";
Kitware Robot's avatar
Kitware Robot committed
774 775 776
  return oss.str();
}

Kitware Robot's avatar
Kitware Robot committed
777 778
// host memory info in units of KiB.
SystemInformation::LongLong SystemInformation::GetHostMemoryTotal()
Kitware Robot's avatar
Kitware Robot committed
779
{
Kitware Robot's avatar
Kitware Robot committed
780
  return this->Implementation->GetHostMemoryTotal();
Kitware Robot's avatar
Kitware Robot committed
781 782
}

Kitware Robot's avatar
Kitware Robot committed
783 784
SystemInformation::LongLong SystemInformation::GetHostMemoryAvailable(
  const char* hostLimitEnvVarName)
Kitware Robot's avatar
Kitware Robot committed
785 786 787 788 789
{
  return this->Implementation->GetHostMemoryAvailable(hostLimitEnvVarName);
}

SystemInformation::LongLong SystemInformation::GetHostMemoryUsed()
Kitware Robot's avatar
Kitware Robot committed
790
{
Kitware Robot's avatar
Kitware Robot committed
791 792 793 794
  return this->Implementation->GetHostMemoryUsed();
}

// process memory info in units of KiB.
Kitware Robot's avatar
Kitware Robot committed
795 796
SystemInformation::LongLong SystemInformation::GetProcMemoryAvailable(
  const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
Kitware Robot's avatar
Kitware Robot committed
797
{
Kitware Robot's avatar
Kitware Robot committed
798 799
  return this->Implementation->GetProcMemoryAvailable(hostLimitEnvVarName,
                                                      procLimitEnvVarName);
Kitware Robot's avatar
Kitware Robot committed
800 801 802 803 804
}

SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
{
  return this->Implementation->GetProcMemoryUsed();
Kitware Robot's avatar
Kitware Robot committed
805 806
}

Kitware Robot's avatar
Kitware Robot committed
807 808 809 810 811
double SystemInformation::GetLoadAverage()
{
  return this->Implementation->GetLoadAverage();
}

Kitware Robot's avatar
Kitware Robot committed
812 813 814 815 816 817 818 819 820 821
SystemInformation::LongLong SystemInformation::GetProcessId()
{
  return this->Implementation->GetProcessId();
}

void SystemInformation::SetStackTraceOnError(int enable)
{
  SystemInformationImplementation::SetStackTraceOnError(enable);
}

Kitware Robot's avatar
Kitware Robot committed
822
std::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
Kitware Robot's avatar
Kitware Robot committed
823
{
Kitware Robot's avatar
Kitware Robot committed
824 825
  return SystemInformationImplementation::GetProgramStack(firstFrame,
                                                          wholePath);
Kitware Robot's avatar
Kitware Robot committed
826 827
}

Kitware Robot's avatar
Kitware Robot committed
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
/** Run the different checks */
void SystemInformation::RunCPUCheck()
{
  this->Implementation->RunCPUCheck();
}

void SystemInformation::RunOSCheck()
{
  this->Implementation->RunOSCheck();
}

void SystemInformation::RunMemoryCheck()
{
  this->Implementation->RunMemoryCheck();
}

// SystemInformationImplementation starts here

Kitware Robot's avatar
Kitware Robot committed
846 847 848 849
#define STORE_TLBCACHE_INFO(x, y) x = (x < (y)) ? (y) : x
#define TLBCACHE_INFO_UNITS (15)
#define CLASSICAL_CPU_FREQ_LOOP 10000000
#define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
Kitware Robot's avatar
Kitware Robot committed
850 851

// Status Flag
Kitware Robot's avatar
Kitware Robot committed
852 853 854
#define HT_NOT_CAPABLE 0
#define HT_ENABLED 1
#define HT_DISABLED 2
Kitware Robot's avatar
Kitware Robot committed
855
#define HT_SUPPORTED_NOT_ENABLED 3
Kitware Robot's avatar
Kitware Robot committed
856
#define HT_CANNOT_DETECT 4
Kitware Robot's avatar
Kitware Robot committed
857 858

// EDX[28]  Bit 28 is set if HT is supported
Kitware Robot's avatar
Kitware Robot committed
859
#define HT_BIT 0x10000000
Kitware Robot's avatar
Kitware Robot committed
860 861

// EAX[11:8] Bit 8-11 contains family processor ID.
Kitware Robot's avatar
Kitware Robot committed
862 863
#define FAMILY_ID 0x0F00
#define PENTIUM4_ID 0x0F00
Kitware Robot's avatar
Kitware Robot committed
864
// EAX[23:20] Bit 20-23 contains extended family processor ID
Kitware Robot's avatar
Kitware Robot committed
865
#define EXT_FAMILY_ID 0x0F00000
Kitware Robot's avatar
Kitware Robot committed
866
// EBX[23:16] Bit 16-23 in ebx contains the number of logical
Kitware Robot's avatar
Kitware Robot committed
867
#define NUM_LOGICAL_BITS 0x00FF0000
Kitware Robot's avatar
Kitware Robot committed
868
// processors per physical processor when execute cpuid with
Kitware Robot's avatar
Kitware Robot committed
869
// eax set to 1
Kitware Robot's avatar
Kitware Robot committed
870
// EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
Kitware Robot's avatar
Kitware Robot committed
871
#define INITIAL_APIC_ID_BITS 0xFF000000
Kitware Robot's avatar
Kitware Robot committed
872 873 874
// initial APIC ID for the processor this code is running on.
// Default value = 0xff if HT is not supported

Kitware Robot's avatar
Kitware Robot committed
875 876 877 878
// Hide implementation details in an anonymous namespace.
namespace {
// *****************************************************************************
#if defined(__linux) || defined(__APPLE__)
Kitware Robot's avatar
Kitware Robot committed
879
int LoadLines(FILE* file, std::vector<std::string>& lines)
Kitware Robot's avatar
Kitware Robot committed
880 881
{
  // Load each line in the given file into a the vector.
Kitware Robot's avatar
Kitware Robot committed
882 883 884 885 886
  int nRead = 0;
  const int bufSize = 1024;
  char buf[bufSize] = { '\0' };
  while (!feof(file) && !ferror(file)) {
    errno = 0;
Kitware Robot's avatar
Kitware Robot committed
887
    if (fgets(buf, bufSize, file) == KWSYS_NULLPTR) {
Kitware Robot's avatar
Kitware Robot committed
888
      if (ferror(file) && (errno == EINTR)) {
Kitware Robot's avatar
Kitware Robot committed
889
        clearerr(file);
Kitware Robot's avatar
Kitware Robot committed
890
      }
Kitware Robot's avatar
Kitware Robot committed
891 892 893 894 895 896 897 898
      continue;
    }
    char* pBuf = buf;
    while (*pBuf) {
      if (*pBuf == '\n')
        *pBuf = '\0';
      pBuf += 1;
    }
Kitware Robot's avatar
Kitware Robot committed
899 900
    lines.push_back(buf);
    ++nRead;
Kitware Robot's avatar
Kitware Robot committed
901 902
  }
  if (ferror(file)) {
Kitware Robot's avatar
Kitware Robot committed
903
    return 0;
Kitware Robot's avatar
Kitware Robot committed
904
  }
Kitware Robot's avatar
Kitware Robot committed
905 906 907
  return nRead;
}

Kitware Robot's avatar
Kitware Robot committed
908
#  if defined(__linux)
Kitware Robot's avatar
Kitware Robot committed
909
// *****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
910
int LoadLines(const char* fileName, std::vector<std::string>& lines)
Kitware Robot's avatar
Kitware Robot committed
911
{
Kitware Robot's avatar
Kitware Robot committed
912 913
  FILE* file = fopen(fileName, "r");
  if (file == 0) {
Kitware Robot's avatar
Kitware Robot committed
914
    return 0;
Kitware Robot's avatar
Kitware Robot committed
915 916
  }
  int nRead = LoadLines(file, lines);
Kitware Robot's avatar
Kitware Robot committed
917
  fclose(file);
Kitware Robot's avatar
Kitware Robot committed
918 919
  return nRead;
}
Kitware Robot's avatar
Kitware Robot committed
920
#  endif
Kitware Robot's avatar
Kitware Robot committed
921 922

// ****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
923
template <typename T>
Kitware Robot's avatar
Kitware Robot committed
924 925
int NameValue(std::vector<std::string> const& lines, std::string const& name,
              T& value)
Kitware Robot's avatar
Kitware Robot committed
926
{
Kitware Robot's avatar
Kitware Robot committed
927 928 929 930
  size_t nLines = lines.size();
  for (size_t i = 0; i < nLines; ++i) {
    size_t at = lines[i].find(name);
    if (at == std::string::npos) {
Kitware Robot's avatar
Kitware Robot committed
931
      continue;
Kitware Robot's avatar
Kitware Robot committed
932 933
    }
    std::istringstream is(lines[i].substr(at + name.size()));
Kitware Robot's avatar
Kitware Robot committed
934 935
    is >> value;
    return 0;
Kitware Robot's avatar
Kitware Robot committed
936
  }
Kitware Robot's avatar
Kitware Robot committed
937 938
  return -1;
}
Kitware Robot's avatar
Kitware Robot committed
939 940 941 942
#endif

#if defined(__linux)
// ****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
943 944
template <typename T>
int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values)
Kitware Robot's avatar
Kitware Robot committed
945
{
Kitware Robot's avatar
Kitware Robot committed
946
  std::vector<std::string> fields;
Kitware Robot's avatar
Kitware Robot committed
947
  if (!LoadLines(fileName, fields)) {
Kitware Robot's avatar
Kitware Robot committed
948
    return -1;
Kitware Robot's avatar
Kitware Robot committed
949 950 951 952 953 954
  }
  int i = 0;
  while (fieldNames[i] != NULL) {
    int ierr = NameValue(fields, fieldNames[i], values[i]);
    if (ierr) {
      return -(i + 2);
Kitware Robot's avatar
Kitware Robot committed
955
    }
Kitware Robot's avatar
Kitware Robot committed
956 957
    i += 1;
  }
Kitware Robot's avatar
Kitware Robot committed
958 959
  return 0;
}
Kitware Robot's avatar
Kitware Robot committed
960 961

// ****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
962 963 964 965 966 967 968
template <typename T>
int GetFieldFromFile(const char* fileName, const char* fieldName, T& value)
{
  const char* fieldNames[2] = { fieldName, NULL };
  T values[1] = { T(0) };
  int ierr = GetFieldsFromFile(fileName, fieldNames, values);
  if (ierr) {
Kitware Robot's avatar
Kitware Robot committed
969
    return ierr;
Kitware Robot's avatar
Kitware Robot committed
970 971
  }
  value = values[0];
Kitware Robot's avatar
Kitware Robot committed
972 973 974 975 976 977
  return 0;
}
#endif

// ****************************************************************************
#if defined(__APPLE__)
Kitware Robot's avatar
Kitware Robot committed
978 979 980 981 982
template <typename T>
int GetFieldsFromCommand(const char* command, const char** fieldNames,
                         T* values)
{
  FILE* file = popen(command, "r");
Kitware Robot's avatar
Kitware Robot committed
983
  if (file == KWSYS_NULLPTR) {
Kitware Robot's avatar
Kitware Robot committed
984
    return -1;
Kitware Robot's avatar
Kitware Robot committed
985
  }
Kitware Robot's avatar
Kitware Robot committed
986
  std::vector<std::string> fields;
Kitware Robot's avatar
Kitware Robot committed
987
  int nl = LoadLines(file, fields);
Kitware Robot's avatar
Kitware Robot committed
988
  pclose(file);
Kitware Robot's avatar
Kitware Robot committed
989
  if (nl == 0) {
Kitware Robot's avatar
Kitware Robot committed
990
    return -1;
Kitware Robot's avatar
Kitware Robot committed
991 992
  }
  int i = 0;
Kitware Robot's avatar
Kitware Robot committed
993
  while (fieldNames[i] != KWSYS_NULLPTR) {
Kitware Robot's avatar
Kitware Robot committed
994 995 996
    int ierr = NameValue(fields, fieldNames[i], values[i]);
    if (ierr) {
      return -(i + 2);
Kitware Robot's avatar
Kitware Robot committed
997
    }
Kitware Robot's avatar
Kitware Robot committed
998 999
    i += 1;
  }
Kitware Robot's avatar
Kitware Robot committed
1000 1001
  return 0;
}
Kitware Robot's avatar
Kitware Robot committed
1002
#endif
Kitware Robot's avatar
Kitware Robot committed
1003

Kitware Robot's avatar
Kitware Robot committed
1004 1005
// ****************************************************************************
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
Kitware Robot's avatar
Kitware Robot committed
1006 1007
void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
                             void* /*sigContext*/)
Kitware Robot's avatar
Kitware Robot committed
1008
{
Kitware Robot's avatar
Kitware Robot committed
1009
#  if defined(__linux) || defined(__APPLE__)
Kitware Robot's avatar
Kitware Robot committed
1010
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
1011 1012 1013 1014 1015
  oss << std::endl
      << "========================================================="
      << std::endl
      << "Process id " << getpid() << " ";
  switch (sigNo) {
Kitware Robot's avatar
Kitware Robot committed
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
    case SIGINT:
      oss << "Caught SIGINT";
      break;

    case SIGTERM:
      oss << "Caught SIGTERM";
      break;

    case SIGABRT:
      oss << "Caught SIGABRT";
      break;

Kitware Robot's avatar
Kitware Robot committed
1028
    case SIGFPE:
Kitware Robot's avatar
Kitware Robot committed
1029 1030
      oss << "Caught SIGFPE at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1031 1032
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1033
#    if defined(FPE_INTDIV)
Kitware Robot's avatar
Kitware Robot committed
1034
        case FPE_INTDIV:
Kitware Robot's avatar
Kitware Robot committed
1035
          oss << "integer division by zero";
Kitware Robot's avatar
Kitware Robot committed
1036
          break;
Kitware Robot's avatar
Kitware Robot committed
1037
#    endif
Kitware Robot's avatar
Kitware Robot committed
1038

Kitware Robot's avatar
Kitware Robot committed
1039
#    if defined(FPE_INTOVF)
Kitware Robot's avatar
Kitware Robot committed
1040
        case FPE_INTOVF:
Kitware Robot's avatar
Kitware Robot committed
1041
          oss << "integer overflow";
Kitware Robot's avatar
Kitware Robot committed
1042
          break;
Kitware Robot's avatar
Kitware Robot committed
1043
#    endif
Kitware Robot's avatar
Kitware Robot committed
1044 1045

        case FPE_FLTDIV:
Kitware Robot's avatar
Kitware Robot committed
1046
          oss << "floating point divide by zero";
Kitware Robot's avatar
Kitware Robot committed
1047 1048 1049
          break;

        case FPE_FLTOVF:
Kitware Robot's avatar
Kitware Robot committed
1050
          oss << "floating point overflow";
Kitware Robot's avatar
Kitware Robot committed
1051 1052 1053
          break;

        case FPE_FLTUND:
Kitware Robot's avatar
Kitware Robot committed
1054
          oss << "floating point underflow";
Kitware Robot's avatar
Kitware Robot committed
1055 1056 1057
          break;

        case FPE_FLTRES:
Kitware Robot's avatar
Kitware Robot committed
1058
          oss << "floating point inexact result";
Kitware Robot's avatar
Kitware Robot committed
1059 1060 1061
          break;

        case FPE_FLTINV:
Kitware Robot's avatar
Kitware Robot committed
1062
          oss << "floating point invalid operation";
Kitware Robot's avatar
Kitware Robot committed
1063 1064
          break;

Kitware Robot's avatar
Kitware Robot committed
1065
#    if defined(FPE_FLTSUB)
Kitware Robot's avatar
Kitware Robot committed
1066
        case FPE_FLTSUB:
Kitware Robot's avatar
Kitware Robot committed
1067
          oss << "floating point subscript out of range";
Kitware Robot's avatar
Kitware Robot committed
1068
          break;
Kitware Robot's avatar
Kitware Robot committed
1069
#    endif
Kitware Robot's avatar
Kitware Robot committed
1070 1071

        default:
Kitware Robot's avatar
Kitware Robot committed
1072
          oss << "code " << sigInfo->si_code;
Kitware Robot's avatar
Kitware Robot committed
1073
          break;
Kitware Robot's avatar
Kitware Robot committed
1074
      }
Kitware Robot's avatar
Kitware Robot committed
1075 1076 1077
      break;

    case SIGSEGV:
Kitware Robot's avatar
Kitware Robot committed
1078 1079
      oss << "Caught SIGSEGV at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1080 1081
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1082
        case SEGV_MAPERR:
Kitware Robot's avatar
Kitware Robot committed
1083
          oss << "address not mapped to object";
Kitware Robot's avatar
Kitware Robot committed
1084 1085 1086
          break;

        case SEGV_ACCERR:
Kitware Robot's avatar
Kitware Robot committed
1087
          oss << "invalid permission for mapped object";
Kitware Robot's avatar
Kitware Robot committed
1088 1089 1090
          break;

        default:
Kitware Robot's avatar
Kitware Robot committed
1091
          oss << "code " << sigInfo->si_code;
Kitware Robot's avatar
Kitware Robot committed
1092
          break;
Kitware Robot's avatar
Kitware Robot committed
1093
      }
Kitware Robot's avatar
Kitware Robot committed
1094 1095 1096
      break;

    case SIGBUS:
Kitware Robot's avatar
Kitware Robot committed
1097 1098
      oss << "Caught SIGBUS at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1099 1100
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1101
        case BUS_ADRALN:
Kitware Robot's avatar
Kitware Robot committed
1102
          oss << "invalid address alignment";
Kitware Robot's avatar
Kitware Robot committed
1103 1104
          break;

Kitware Robot's avatar
Kitware Robot committed
1105
#    if defined(BUS_ADRERR)
Kitware Robot's avatar
Kitware Robot committed
1106
        case BUS_ADRERR:
Kitware Robot's avatar
Kitware Robot committed
1107
          oss << "nonexistent physical address";
Kitware Robot's avatar
Kitware Robot committed
1108
          break;
Kitware Robot's avatar
Kitware Robot committed
1109
#    endif
Kitware Robot's avatar
Kitware Robot committed
1110

Kitware Robot's avatar
Kitware Robot committed
1111
#    if defined(BUS_OBJERR)
Kitware Robot's avatar
Kitware Robot committed
1112
        case BUS_OBJERR:
Kitware Robot's avatar
Kitware Robot committed
1113 1114
          oss << "object-specific hardware error";
          break;
Kitware Robot's avatar
Kitware Robot committed
1115
#    endif
Kitware Robot's avatar
Kitware Robot committed
1116

Kitware Robot's avatar
Kitware Robot committed
1117
#    if defined(BUS_MCEERR_AR)
Kitware Robot's avatar
Kitware Robot committed
1118
        case BUS_MCEERR_AR:
Kitware Robot's avatar
Kitware Robot committed
1119 1120
          oss << "Hardware memory error consumed on a machine check; action "
                 "required.";
Kitware Robot's avatar
Kitware Robot committed
1121
          break;
Kitware Robot's avatar
Kitware Robot committed
1122
#    endif
Kitware Robot's avatar
Kitware Robot committed
1123

Kitware Robot's avatar
Kitware Robot committed
1124
#    if defined(BUS_MCEERR_AO)
Kitware Robot's avatar
Kitware Robot committed
1125
        case BUS_MCEERR_AO:
Kitware Robot's avatar
Kitware Robot committed
1126 1127
          oss << "Hardware memory error detected in process but not consumed; "
                 "action optional.";
Kitware Robot's avatar
Kitware Robot committed
1128
          break;
Kitware Robot's avatar
Kitware Robot committed
1129
#    endif
Kitware Robot's avatar
Kitware Robot committed
1130 1131

        default:
Kitware Robot's avatar
Kitware Robot committed
1132
          oss << "code " << sigInfo->si_code;
Kitware Robot's avatar
Kitware Robot committed
1133
          break;
Kitware Robot's avatar
Kitware Robot committed
1134
      }
Kitware Robot's avatar
Kitware Robot committed
1135 1136 1137
      break;

    case SIGILL:
Kitware Robot's avatar
Kitware Robot committed
1138 1139
      oss << "Caught SIGILL at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1140 1141
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1142
        case ILL_ILLOPC:
Kitware Robot's avatar
Kitware Robot committed
1143
          oss << "illegal opcode";
Kitware Robot's avatar
Kitware Robot committed
1144 1145
          break;

Kitware Robot's avatar
Kitware Robot committed
1146
#    if defined(ILL_ILLOPN)
Kitware Robot's avatar
Kitware Robot committed
1147
        case ILL_ILLOPN:
Kitware Robot's avatar
Kitware Robot committed
1148
          oss << "illegal operand";
Kitware Robot's avatar
Kitware Robot committed
1149
          break;
Kitware Robot's avatar
Kitware Robot committed
1150
#    endif
Kitware Robot's avatar
Kitware Robot committed
1151

Kitware Robot's avatar
Kitware Robot committed
1152
#    if defined(ILL_ILLADR)
Kitware Robot's avatar
Kitware Robot committed
1153
        case ILL_ILLADR:
Kitware Robot's avatar
Kitware Robot committed
1154
          oss << "illegal addressing mode.";
Kitware Robot's avatar
Kitware Robot committed
1155
          break;
Kitware Robot's avatar
Kitware Robot committed
1156
#    endif
Kitware Robot's avatar
Kitware Robot committed
1157 1158

        case ILL_ILLTRP:
Kitware Robot's avatar
Kitware Robot committed
1159
          oss << "illegal trap";
Kitware Robot's avatar
Kitware Robot committed
1160
          break;
Kitware Robot's avatar
Kitware Robot committed
1161 1162

        case ILL_PRVOPC:
Kitware Robot's avatar
Kitware Robot committed
1163
          oss << "privileged opcode";
Kitware Robot's avatar
Kitware Robot committed
1164 1165
          break;

Kitware Robot's avatar
Kitware Robot committed
1166
#    if defined(ILL_PRVREG)
Kitware Robot's avatar
Kitware Robot committed
1167
        case ILL_PRVREG:
Kitware Robot's avatar
Kitware Robot committed
1168
          oss << "privileged register";
Kitware Robot's avatar
Kitware Robot committed
1169
          break;
Kitware Robot's avatar
Kitware Robot committed
1170
#    endif
Kitware Robot's avatar
Kitware Robot committed
1171

Kitware Robot's avatar
Kitware Robot committed
1172
#    if defined(ILL_COPROC)
Kitware Robot's avatar
Kitware Robot committed
1173
        case ILL_COPROC:
Kitware Robot's avatar
Kitware Robot committed
1174
          oss << "co-processor error";
Kitware Robot's avatar
Kitware Robot committed
1175
          break;
Kitware Robot's avatar
Kitware Robot committed
1176
#    endif
Kitware Robot's avatar
Kitware Robot committed
1177