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) {