SystemInformation.cxx 145 KB
Newer Older
1
2
3
/*============================================================================
  KWSys - Kitware System Library
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4

5
6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
7

8
9
10
11
  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
12
13
14

#if defined(_WIN32)
# define NOMINMAX // use our min,max
15
16
17
# if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
#  define _WIN32_WINNT 0x0501
# endif
Sebastien Barre's avatar
Sebastien Barre committed
18
19
20
# include <winsock.h> // WSADATA, include before sys/types.h
#endif

21
22
23
24
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif

25
26
27
28
29
30
31
32
33
34
35
36
// 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

37
#include "kwsysPrivate.h"
38
39
40
#include KWSYS_HEADER(stl/string)
#include KWSYS_HEADER(stl/vector)
#include KWSYS_HEADER(ios/iosfwd)
41
42
43
#include KWSYS_HEADER(SystemInformation.hxx)
#include KWSYS_HEADER(Process.h)
#include KWSYS_HEADER(ios/iostream)
44
#include KWSYS_HEADER(ios/sstream)
45
#include KWSYS_HEADER(ios/fstream)
46

47
48
49
50
51
52
53
54
55
56
57
// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "SystemInformation.hxx.in"
# include "Process.h.in"
# include "Configure.hxx.in"
# include "kwsys_stl.hxx.in"
# include "kwsys_stl_vector.in"
# include "kwsys_stl_iosfwd.in"
# include "kwsys_ios_sstream.h.in"
# include "kwsys_ios_iostream.h.in"
58
# include "kwsys_ios_fstream.h.in"
59
60
#endif

61
#if defined(_WIN32)
62
# include <windows.h>
63
64
65
# if defined(_MSC_VER) && _MSC_VER >= 1800
#  define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# endif
66
# include <errno.h>
67
68
69
# if defined(KWSYS_SYS_HAS_PSAPI)
#  include <psapi.h>
# endif
70
# if !defined(siginfo_t)
71
typedef int siginfo_t;
72
73
74
75
76
# endif
#else
# include <sys/types.h>
# include <sys/time.h>
# include <sys/utsname.h> // int uname(struct utsname *buf);
77
# include <sys/resource.h> // getrlimit
78
79
80
81
# include <unistd.h>
# include <signal.h>
# include <fcntl.h>
# include <errno.h> // extern int errno;
82
83
#endif

84
85
86
87
88
89
90
91
92
93
94
95
#ifdef __FreeBSD__
# include <sys/sysctl.h>
# include <fenv.h>
# include <sys/socket.h>
# include <netdb.h>
# include <netinet/in.h>
# if defined(KWSYS_SYS_HAS_IFADDRS_H)
#  include <ifaddrs.h>
#  define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
#endif

96
97
98
99
100
#if defined(__OpenBSD__) || defined(__NetBSD__)
# include <sys/param.h>
# include <sys/sysctl.h>
#endif

101
102
103
104
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
# include <machine/cpu.h>
#endif

105
106
107
108
#if defined(__DragonFly__)
# include <sys/sysctl.h>
#endif

109
#ifdef __APPLE__
110
111
112
113
114
115
116
117
118
# include <sys/sysctl.h>
# include <mach/vm_statistics.h>
# include <mach/host_info.h>
# include <mach/mach.h>
# include <mach/mach_types.h>
# include <fenv.h>
# include <sys/socket.h>
# include <netdb.h>
# include <netinet/in.h>
119
120
121
122
# if defined(KWSYS_SYS_HAS_IFADDRS_H)
#  include <ifaddrs.h>
#  define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
123
124
# if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050)
#  undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
125
# endif
126
127
#endif

128
#ifdef __linux
129
130
131
132
# include <fenv.h>
# include <sys/socket.h>
# include <netdb.h>
# include <netinet/in.h>
133
134
135
136
137
138
# if defined(KWSYS_SYS_HAS_IFADDRS_H)
#  include <ifaddrs.h>
#  if !defined(__LSB_VERSION__) /* LSB has no getifaddrs */
#   define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#  endif
# endif
139
140
141
142
143
144
145
# if defined(KWSYS_CXX_HAS_RLIMIT64)
typedef struct rlimit64 ResourceLimitType;
#  define GetResourceLimit getrlimit64
# else
typedef struct rlimit ResourceLimitType;
#  define GetResourceLimit getrlimit
# endif
146
#elif defined( __hpux )
147
148
# include <sys/param.h>
# include <sys/pstat.h>
149
150
151
# if defined(KWSYS_SYS_HAS_MPCTL_H)
#  include <sys/mpctl.h>
# endif
152
153
#endif

154
#ifdef __HAIKU__
155
# include <OS.h>
156
157
#endif

158
159
160
161
162
163
164
165
166
167
168
169
170
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
# 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
#else
# undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
# undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
#endif

171
172
173
174
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
175
#include <ctype.h> // int isdigit(int c);
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#if defined(KWSYS_USE_LONG_LONG)
# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
#  define iostreamLongLong(x) (x)
# else
#  define iostreamLongLong(x) ((long)x)
# endif
#elif defined(KWSYS_USE___INT64)
# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
#  define iostreamLongLong(x) (x)
# else
#  define iostreamLongLong(x) ((long)x)
# endif
#else
# error "No Long Long"
#endif

#if defined(KWSYS_CXX_HAS_ATOLL)
# define atoLongLong atoll
#else
# if defined(KWSYS_CXX_HAS__ATOI64)
#  define atoLongLong _atoi64
# elif defined(KWSYS_CXX_HAS_ATOL)
#  define atoLongLong atol
# else
#  define atoLongLong atoi
# endif
#endif

205
206
207
208
209
210
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64)
#define USE_ASM_INSTRUCTIONS 1
#else
#define USE_ASM_INSTRUCTIONS 0
#endif

211
212
213
214
215
216
217
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#include <intrin.h>
#define USE_CPUID_INTRINSICS 1
#else
#define USE_CPUID_INTRINSICS 0
#endif

218
#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
219
220
221
222
223
224
# define USE_CPUID 1
#else
# define USE_CPUID 0
#endif

#if USE_CPUID
225
226
227
228
229
230
231
232
233
234

#define CPUID_AWARE_COMPILER

/**
 * call CPUID instruction
 *
 * Will return false if the instruction failed.
 */
static bool call_cpuid(int select, int result[4])
{
235
236
237
238
#if USE_CPUID_INTRINSICS
  __cpuid(result, select);
  return true;
#else
239
  int tmp[4];
240
#if defined(_MSC_VER)
241
242
243
244
245
  // Use SEH to determine CPUID presence
  __try {
    _asm {
#ifdef CPUID_AWARE_COMPILER
      ; we must push/pop the registers <<CPUID>> writes to, as the
246
      ; optimiser does not know about <<CPUID>>, and so does not expect
247
248
249
250
251
252
253
254
      ; these registers to change.
      push eax
      push ebx
      push ecx
      push edx
#endif
      ; <<CPUID>>
      mov eax, select
255
256
257
258
259
260
#ifdef CPUID_AWARE_COMPILER
      cpuid
#else
      _asm _emit 0x0f
      _asm _emit 0xa2
#endif
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
      mov tmp[0 * TYPE int], eax
      mov tmp[1 * TYPE int], ebx
      mov tmp[2 * TYPE int], ecx
      mov tmp[3 * TYPE int], edx

#ifdef CPUID_AWARE_COMPILER
      pop edx
      pop ecx
      pop ebx
      pop eax
#endif
      }
    }
  __except(1)
    {
    return false;
    }

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    memcpy(result, tmp, sizeof(tmp));
#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
  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;
#endif

297
298
  // The cpuid instruction succeeded.
  return true;
299
#endif
300
301
302
303
}
#endif


304
305
namespace KWSYS_NAMESPACE
{
306
307
template<typename T>
T min(T a, T b){ return a<b ? a : b; }
308

309
310
extern "C" { typedef void (*SigAction)(int,siginfo_t*,void*); }

311
312
313
//  Define SystemInformationImplementation class
typedef  void (*DELAY_FUNC)(unsigned int uiMS);

314
315
class SystemInformationImplementation
{
316
public:
317
  typedef SystemInformation::LongLong LongLong;
318
319
320
321
322
323
324
325
  SystemInformationImplementation ();
  ~SystemInformationImplementation ();

  const char * GetVendorString();
  const char * GetVendorID();
  kwsys_stl::string GetTypeID();
  kwsys_stl::string GetFamilyID();
  kwsys_stl::string GetModelID();
326
  kwsys_stl::string GetModelName();
327
328
329
330
  kwsys_stl::string GetSteppingCode();
  const char * GetExtendedProcessorName();
  const char * GetProcessorSerialNumber();
  int GetProcessorCacheSize();
331
  unsigned int GetLogicalProcessorsPerPhysical();
332
333
334
335
  float GetProcessorClockFrequency();
  int GetProcessorAPICID();
  int GetProcessorCacheXSize(long int);
  bool DoesCPUSupportFeature(long int);
336

337
338
  const char * GetOSName();
  const char * GetHostname();
339
  int GetFullyQualifiedDomainName(kwsys_stl::string &fqdn);
340
341
342
343
344
345
346
347
348
349
350
351
  const char * GetOSRelease();
  const char * GetOSVersion();
  const char * GetOSPlatform();

  bool Is64Bits();

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

  bool DoesCPUSupportCPUID();

  // Retrieve memory information in megabyte.
352
353
354
  size_t GetTotalVirtualMemory();
  size_t GetAvailableVirtualMemory();
  size_t GetTotalPhysicalMemory();
355
356
  size_t GetAvailablePhysicalMemory();

357
  LongLong GetProcessId();
358
359

  // Retrieve memory information in kib
360
361
362
363
364
365
366
367
  LongLong GetHostMemoryTotal();
  LongLong GetHostMemoryAvailable(const char *envVarName);
  LongLong GetHostMemoryUsed();

  LongLong GetProcMemoryAvailable(
        const char *hostLimitEnvVarName,
        const char *procLimitEnvVarName);
  LongLong GetProcMemoryUsed();
368
369
370
371

  // enable/disable stack trace signal handler.
  static
  void SetStackTraceOnError(int enable);
372

373
374
375
376
  // get current stack
  static
  kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);

377
378
379
380
  /** Run the different checks */
  void RunCPUCheck();
  void RunOSCheck();
  void RunMemoryCheck();
381

382
public:
383
  typedef struct tagID
384
385
386
387
388
389
390
    {
    int Type;
    int Family;
    int Model;
    int Revision;
    int ExtendedFamily;
    int ExtendedModel;
391
392
393
    kwsys_stl::string ProcessorName;
    kwsys_stl::string Vendor;
    kwsys_stl::string SerialNumber;
394
    kwsys_stl::string ModelName;
395
396
    } ID;

397
  typedef struct tagCPUPowerManagement
398
399
400
401
402
403
    {
    bool HasVoltageID;
    bool HasFrequencyID;
    bool HasTempSenseDiode;
    } CPUPowerManagement;

404
  typedef struct tagCPUExtendedFeatures
405
406
407
408
409
410
411
    {
    bool Has3DNow;
    bool Has3DNowPlus;
    bool SupportsMP;
    bool HasMMXPlus;
    bool HasSSEMMX;
    bool SupportsHyperthreading;
412
    unsigned int LogicalProcessorsPerPhysical;
413
414
    int APIC_ID;
    CPUPowerManagement PowerManagement;
415
416
417
    } CPUExtendedFeatures;

  typedef struct CPUtagFeatures
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
    {
    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;
    } CPUFeatures;
438
439

  enum Manufacturer
440
    {
441
    AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
442
    Motorola, HP, UnknownManufacturer
443
444
    };

445
protected:
446
  // For windows
447
448
449
450
451
452
453
454
455
456
457
458
  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();
459

460
  // Processor information
461
462
463
464
465
466
467
  Manufacturer  ChipManufacturer;
  CPUFeatures   Features;
  ID            ChipID;
  float         CPUSpeedInMHz;
  unsigned int  NumberOfLogicalCPU;
  unsigned int  NumberOfPhysicalCPU;

468
  int CPUCount(); // For windows
469
  unsigned char LogicalCPUPerPhysicalCPU();
470
  unsigned char GetAPICId(); // For windows
471
  bool IsHyperThreadingSupported();
472
  static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
473

474
  // For Linux and Cygwin, /proc/cpuinfo formats are slightly different
475
  bool RetreiveInformationFromCpuInfoFile();
476
  kwsys_stl::string ExtractValueFromCpuInfoFile(kwsys_stl::string buffer,
Bill Hoffman's avatar
Bill Hoffman committed
477
                                          const char* word, size_t init=0);
478

479
  bool QueryLinuxMemory();
480
  bool QueryCygwinMemory();
481

482
483
484
  static void Delay (unsigned int);
  static void DelayOverhead (unsigned int);

485
  void FindManufacturer(const kwsys_stl::string &family = "");
486
487
488

  // For Mac
  bool ParseSysCtl();
489
  int CallSwVers(const char *arg, kwsys_stl::string &ver);
490
  void TrimNewline(kwsys_stl::string&);
491
492
493
494
  kwsys_stl::string ExtractValueFromSysCtl(const char* word);
  kwsys_stl::string SysCtlBuffer;

  // For Solaris
495
496
  bool QuerySolarisMemory();
  bool QuerySolarisProcessor();
497
498
499
  kwsys_stl::string ParseValueFromKStat(const char* arguments);
  kwsys_stl::string RunProcess(kwsys_stl::vector<const char*> args);

500
501
502
  //For Haiku OS
  bool QueryHaikuInfo();

503
504
505
506
  //For QNX
  bool QueryQNXMemory();
  bool QueryQNXProcessor();

507
508
509
510
  //For OpenBSD, FreeBSD, NetBSD, DragonFly
  bool QueryBSDMemory();
  bool QueryBSDProcessor();

511
  //For HP-UX
512
  bool QueryHPUXMemory();
513
514
  bool QueryHPUXProcessor();

515
516
517
  //For Microsoft Windows
  bool QueryWindowsMemory();

518
519
520
  //For AIX
  bool QueryAIXMemory();

521
  bool QueryProcessorBySysconf();
522
523
  bool QueryProcessor();

524
  // Evaluate the memory information.
525
  bool QueryMemoryBySysconf();
526
  bool QueryMemory();
527
528
529
530
  size_t TotalVirtualMemory;
  size_t AvailableVirtualMemory;
  size_t TotalPhysicalMemory;
  size_t AvailablePhysicalMemory;
531

Bill Hoffman's avatar
Bill Hoffman committed
532
  size_t CurrentPositionInFile;
533
534
535
536
537
538
539

  // Operating System information
  bool QueryOSInformation();
  kwsys_stl::string OSName;
  kwsys_stl::string Hostname;
  kwsys_stl::string OSRelease;
  kwsys_stl::string OSVersion;
540
  kwsys_stl::string OSPlatform;
541
};
542

543

544
SystemInformation::SystemInformation()
545
546
547
548
{
  this->Implementation = new SystemInformationImplementation;
}

549
SystemInformation::~SystemInformation()
550
551
552
553
554
555
556
557
{
  delete this->Implementation;
}

const char * SystemInformation::GetVendorString()
{
  return this->Implementation->GetVendorString();
}
558

559
560
561
562
const char * SystemInformation::GetVendorID()
{
  return this->Implementation->GetVendorID();
}
563

564
565
566
567
kwsys_stl::string SystemInformation::GetTypeID()
{
  return this->Implementation->GetTypeID();
}
568

569
570
571
572
kwsys_stl::string SystemInformation::GetFamilyID()
{
  return this->Implementation->GetFamilyID();
}
573

574
575
576
577
kwsys_stl::string SystemInformation::GetModelID()
{
  return this->Implementation->GetModelID();
}
578

579
580
581
582
583
kwsys_stl::string SystemInformation::GetModelName()
{
  return this->Implementation->GetModelName();
}

584
585
586
587
kwsys_stl::string SystemInformation::GetSteppingCode()
{
  return this->Implementation->GetSteppingCode();
}
588

589
590
591
592
const char * SystemInformation::GetExtendedProcessorName()
{
  return this->Implementation->GetExtendedProcessorName();
}
593

594
595
596
597
const char * SystemInformation::GetProcessorSerialNumber()
{
  return this->Implementation->GetProcessorSerialNumber();
}
598

599
600
601
602
int SystemInformation::GetProcessorCacheSize()
{
  return this->Implementation->GetProcessorCacheSize();
}
603

604
unsigned int SystemInformation::GetLogicalProcessorsPerPhysical()
605
606
607
{
  return this->Implementation->GetLogicalProcessorsPerPhysical();
}
608

609
610
611
612
float SystemInformation::GetProcessorClockFrequency()
{
  return this->Implementation->GetProcessorClockFrequency();
}
613

614
615
616
617
int SystemInformation::GetProcessorAPICID()
{
  return this->Implementation->GetProcessorAPICID();
}
618

619
620
621
622
int SystemInformation::GetProcessorCacheXSize(long int l)
{
  return this->Implementation->GetProcessorCacheXSize(l);
}
623

624
625
626
627
628
bool SystemInformation::DoesCPUSupportFeature(long int i)
{
  return this->Implementation->DoesCPUSupportFeature(i);
}

629
630
kwsys_stl::string SystemInformation::GetCPUDescription()
{
631
  kwsys_ios::ostringstream oss;
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
  oss
    << this->GetNumberOfPhysicalCPU()
    << " core ";
  if (this->GetModelName().empty())
    {
    oss
      << this->GetProcessorClockFrequency()
      << " MHz "
      << this->GetVendorString()
      << " "
      << this->GetExtendedProcessorName();
    }
  else
    {
    oss << this->GetModelName();
    }

  // remove extra spaces
  kwsys_stl::string tmp=oss.str();
  size_t pos;
  while( (pos=tmp.find("  "))!=kwsys_stl::string::npos)
    {
    tmp.replace(pos,2," ");
    }

  return tmp;
}

660
661
662
663
const char * SystemInformation::GetOSName()
{
  return this->Implementation->GetOSName();
}
664

665
666
667
668
const char * SystemInformation::GetHostname()
{
  return this->Implementation->GetHostname();
}
669

670
671
672
kwsys_stl::string SystemInformation::GetFullyQualifiedDomainName()
{
  kwsys_stl::string fqdn;
673
  this->Implementation->GetFullyQualifiedDomainName(fqdn);
674
675
676
  return fqdn;
}

677
678
679
680
const char * SystemInformation::GetOSRelease()
{
  return this->Implementation->GetOSRelease();
}
681

682
683
684
685
const char * SystemInformation::GetOSVersion()
{
  return this->Implementation->GetOSVersion();
}
686

687
688
689
690
691
const char * SystemInformation::GetOSPlatform()
{
  return this->Implementation->GetOSPlatform();
}

692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
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
}

kwsys_stl::string SystemInformation::GetOSDescription()
{
721
  kwsys_ios::ostringstream oss;
722
723
724
725
726
727
728
729
730
731
  oss
    << this->GetOSName()
    << " "
    << this->GetOSRelease()
    << " "
    << this->GetOSVersion();

  return oss.str();
}

732
733
734
735
736
737
738
739
740
bool SystemInformation::Is64Bits()
{
  return this->Implementation->Is64Bits();
}

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

742
743
744
745
746
747
748
749
750
751
752
unsigned int SystemInformation::GetNumberOfPhysicalCPU()
{
  return this->Implementation->GetNumberOfPhysicalCPU();
}

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

// Retrieve memory information in megabyte.
753
size_t SystemInformation::GetTotalVirtualMemory()
754
755
756
{
  return this->Implementation->GetTotalVirtualMemory();
}
757

758
size_t SystemInformation::GetAvailableVirtualMemory()
759
760
761
{
  return this->Implementation->GetAvailableVirtualMemory();
}
762

763
size_t SystemInformation::GetTotalPhysicalMemory()
764
765
766
767
{
  return this->Implementation->GetTotalPhysicalMemory();
}

768
size_t SystemInformation::GetAvailablePhysicalMemory()
769
770
771
772
{
  return this->Implementation->GetAvailablePhysicalMemory();
}

773
774
775
kwsys_stl::string SystemInformation::GetMemoryDescription(
      const char *hostLimitEnvVarName,
      const char *procLimitEnvVarName)
776
{
777
  kwsys_ios::ostringstream oss;
778
  oss
779
780
781
782
783
784
785
786
    << "Host Total: "
    << iostreamLongLong(this->GetHostMemoryTotal())
    << " KiB, Host Available: "
    << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
    << " KiB, Process Available: "
    << iostreamLongLong(
         this->GetProcMemoryAvailable(hostLimitEnvVarName,procLimitEnvVarName))
    << " KiB";
787
788
789
  return oss.str();
}

790
791
// host memory info in units of KiB.
SystemInformation::LongLong SystemInformation::GetHostMemoryTotal()
792
{
793
  return this->Implementation->GetHostMemoryTotal();
794
795
}

796
797
SystemInformation::LongLong
SystemInformation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
798
{
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  return this->Implementation->GetHostMemoryAvailable(hostLimitEnvVarName);
}

SystemInformation::LongLong SystemInformation::GetHostMemoryUsed()
{
  return this->Implementation->GetHostMemoryUsed();
}

// process memory info in units of KiB.
SystemInformation::LongLong
SystemInformation::GetProcMemoryAvailable(
        const char *hostLimitEnvVarName,
        const char *procLimitEnvVarName)
{
  return this->Implementation->GetProcMemoryAvailable(
          hostLimitEnvVarName,
          procLimitEnvVarName);
}

SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
{
  return this->Implementation->GetProcMemoryUsed();
821
822
}

823
SystemInformation::LongLong SystemInformation::GetProcessId()
824
825
826
827
828
829
830
831
832
{
  return this->Implementation->GetProcessId();
}

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

833
834
835
836
837
kwsys_stl::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
{
  return SystemInformationImplementation::GetProgramStack(firstFrame, wholePath);
}

838
839
840
/** Run the different checks */
void SystemInformation::RunCPUCheck()
{
841
  this->Implementation->RunCPUCheck();
842
}
843

844
845
void SystemInformation::RunOSCheck()
{
846
  this->Implementation->RunOSCheck();
847
}
848

849
850
void SystemInformation::RunMemoryCheck()
{
851
  this->Implementation->RunMemoryCheck();
852
853
854
855
856
857
858
859
860
861
862
}


// --------------------------------------------------------------
// SystemInformationImplementation starts here

#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

863
864
865
866
#define MMX_FEATURE            0x00000001
#define MMX_PLUS_FEATURE       0x00000002
#define SSE_FEATURE            0x00000004
#define SSE2_FEATURE           0x00000008
867
#define AMD_3DNOW_FEATURE      0x00000010
868
869
870
871
872
873
874
#define AMD_3DNOW_PLUS_FEATURE 0x00000020
#define IA64_FEATURE           0x00000040
#define MP_CAPABLE             0x00000080
#define HYPERTHREAD_FEATURE    0x00000100
#define SERIALNUMBER_FEATURE   0x00000200
#define APIC_FEATURE           0x00000400
#define SSE_FP_FEATURE         0x00000800
875
#define SSE_MMX_FEATURE        0x00001000
876
877
#define CMOV_FEATURE           0x00002000
#define MTRR_FEATURE           0x00004000
878
879
880
#define L1CACHE_FEATURE        0x00008000
#define L2CACHE_FEATURE        0x00010000
#define L3CACHE_FEATURE        0x00020000
881
882
883
884
885
#define ACPI_FEATURE           0x00040000
#define THERMALMONITOR_FEATURE 0x00080000
#define TEMPSENSEDIODE_FEATURE 0x00100000
#define FREQUENCYID_FEATURE    0x00200000
#define VOLTAGEID_FREQUENCY    0x00400000
886
887
888
889
890
891
892
893
894

// Status Flag
#define HT_NOT_CAPABLE           0
#define HT_ENABLED               1
#define HT_DISABLED              2
#define HT_SUPPORTED_NOT_ENABLED 3
#define HT_CANNOT_DETECT         4

// EDX[28]  Bit 28 is set if HT is supported
895
#define HT_BIT             0x10000000
896
897
898

// EAX[11:8] Bit 8-11 contains family processor ID.
#define FAMILY_ID          0x0F00
899
#define PENTIUM4_ID        0x0F00
900
// EAX[23:20] Bit 20-23 contains extended family processor ID
901
#define EXT_FAMILY_ID      0x0F00000
902
// EBX[23:16] Bit 16-23 in ebx contains the number of logical
903
904
#define NUM_LOGICAL_BITS   0x00FF0000
// processors per physical processor when execute cpuid with
905
// eax set to 1
906
907
// EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
#define INITIAL_APIC_ID_BITS  0xFF000000
908
909
910
// initial APIC ID for the processor this code is running on.
// Default value = 0xff if HT is not supported

911
912
// Hide implementation details in an anonymous namespace.
namespace {
913
// *****************************************************************************
914
#if defined(__linux) || defined(__APPLE__)
915
int LoadLines(
916
      FILE *file,
917
918
919
920
921
922
      kwsys_stl::vector<kwsys_stl::string> &lines)
{
  // Load each line in the given file into a the vector.
  int nRead=0;
  const int bufSize=1024;
  char buf[bufSize]={'\0'};
923
924
925
926
927
928
929
930
931
932
933
  while (!feof(file) && !ferror(file))
    {
    errno=0;
    if (fgets(buf,bufSize,file) == 0)
      {
      if (ferror(file) && (errno==EINTR))
        {
        clearerr(file);
        }
      continue;
      }
934
935
936
937
938
939
    char *pBuf=buf;
    while(*pBuf)
      {
      if (*pBuf=='\n') *pBuf='\0';
      pBuf+=1;
      }
940
941
942
943
    lines.push_back(buf);
    ++nRead;
    }
  if (ferror(file))
944
945
946
    {
    return 0;
    }
947
948
949
  return nRead;
}

950
# if defined(__linux)
951
952
953
954
955
956
957
// *****************************************************************************
int LoadLines(
      const char *fileName,
      kwsys_stl::vector<kwsys_stl::string> &lines)
{
  FILE *file=fopen(fileName,"r");
  if (file==0)
958
    {
959
    return 0;
960
    }
961
962
  int nRead=LoadLines(file,lines);
  fclose(file);
963
964
  return nRead;
}
965
# endif
966
967
968
969
970
971
972
973
974
975

// ****************************************************************************
template<typename T>
int NameValue(
      kwsys_stl::vector<kwsys_stl::string> &lines,
      kwsys_stl::string name, T &value)
{
  size_t nLines=lines.size();
  for (size_t i=0; i<nLines; ++i)
    {
976
977
    size_t at=lines[i].find(name);
    if (at==kwsys_stl::string::npos)
978
      {
979
      continue;
980
      }
981
    kwsys_ios::istringstream is(lines[i].substr(at+name.size()));
982
983
    is >> value;
    return 0;
984
985
986
    }
  return -1;
}
987
#endif
988

989
#if defined(__linux)
990
991
992
993
994
995
// ****************************************************************************
template<typename T>
int GetFieldsFromFile(
      const char *fileName,
      const char **fieldNames,
      T *values)
996
997
998
999
1000
1001
{
  kwsys_stl::vector<kwsys_stl::string> fields;
  if (!LoadLines(fileName,fields))
    {
    return -1;
    }
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  int i=0;
  while (fieldNames[i]!=NULL)
    {
    int ierr=NameValue(fields,fieldNames[i],values[i]);
    if (ierr)
      {
      return -(i+2);
      }
    i+=1;
    }
  return 0;
}

// ****************************************************************************
template<typename T>
1017
1018
int GetFieldFromFile(
      const char *fileName,
1019
1020
1021
      const char *fieldName,
      T &value)
{
1022
  const char *fieldNames[2]={fieldName,NULL};
1023
  T values[1]={T(0)};
1024
  int ierr=GetFieldsFromFile(fileName,fieldNames,values);
1025
1026
  if (ierr)
    {
1027
1028
1029
1030
1031
    return ierr;
    }
  value=values[0];
  return 0;
}
1032
#endif
1033
1034

// ****************************************************************************
1035
#if defined(__APPLE__)
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
template<typename T>
int GetFieldsFromCommand(
      const char *command,
      const char **fieldNames,
      T *values)
{
  FILE *file=popen(command,"r");
  if (file==0)
    {
    return -1;
    }
  kwsys_stl::vector<kwsys_stl::string> fields;
  int nl=LoadLines(file,fields);
  pclose(file);
  if (nl==0)
    {
    return -1;
    }
  int i=0;
  while (fieldNames[i]!=NULL)
    {
    int ierr=NameValue(fields,fieldNames[i],values[i]);
    if (ierr)
      {
      return -(i+2);
      }
    i+=1;
1063
1064
1065
    }
  return 0;
}
1066
#endif
1067

1068
// ****************************************************************************
1069
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
1070
1071
1072
1073
1074
1075
void StacktraceSignalHandler(
      int sigNo,
      siginfo_t *sigInfo,
      void * /*sigContext*/)
{
#if defined(__linux) || defined(__APPLE__)
1076
1077
  kwsys_ios::ostringstream oss;
  oss
1078
     << kwsys_ios::endl
1079
1080
     << "=========================================================" << kwsys_ios::endl
     << "Process id " << getpid() << " ";
1081
1082
  switch (sigNo)
    {
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
    case SIGINT:
      oss << "Caught SIGINT";
      break;

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

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

1095
    case SIGFPE:
1096
1097
1098
1099
1100
      oss
        << "Caught SIGFPE at "
        << (sigInfo->si_addr==0?"0x":"")
        << sigInfo->si_addr
        <<  " ";
1101
1102
      switch (sigInfo->si_code)
        {
1103
# if defined(FPE_INTDIV)
1104
        case FPE_INTDIV:
1105
          oss << "integer division by zero";
1106
          break;
1107
# endif
1108

1109
# if defined(FPE_INTOVF)
1110
        case FPE_INTOVF:
1111
          oss << "integer overflow";
1112
          break;
1113
# endif
1114
1115

        case FPE_FLTDIV:
1116
          oss << "floating point divide by zero";
1117
1118
1119
          break;

        case FPE_FLTOVF:
1120
          oss << "floating point overflow";
1121
1122
1123
          break;

        case FPE_FLTUND:
1124
          oss << "floating point underflow";
1125
1126
1127
          break;

        case FPE_FLTRES:
1128
          oss << "floating point inexact result";
1129
1130
1131
          break;

        case FPE_FLTINV:
1132
          oss << "floating point invalid operation";
1133
1134
          break;

1135
#if defined(FPE_FLTSUB)
1136
        case FPE_FLTSUB:
1137
          oss << "floating point subscript out of range";
1138
          break;
1139
#endif
1140
1141

        default:
1142
          oss << "code " << sigInfo->si_code;
1143
1144
1145
1146
1147
          break;
        }
      break;

    case SIGSEGV:
1148
1149
1150
1151
1152
      oss
        << "Caught SIGSEGV at "
        << (sigInfo->si_addr==0?"0x":"")
        << sigInfo->si_addr
        <<  " ";
1153
1154
1155
      switch (sigInfo->si_code)
        {
        case SEGV_MAPERR:
1156
          oss << "address not mapped to object";
1157
1158
1159
          break;

        case SEGV_ACCERR:
1160
          oss << "invalid permission for mapped object";
1161
1162
1163
          break;

        default:
1164
          oss << "code " << sigInfo->si_code;
1165
1166
1167
1168
1169
          break;
        }
      break;

    case SIGBUS:
1170
1171
1172
1173
1174
      oss
        << "Caught SIGBUS at "
        << (sigInfo->si_addr==0?"0x":"")
        << sigInfo->si_addr
        <<  " ";
1175
1176
1177
      switch (sigInfo->si_code)
        {
        case BUS_ADRALN:
1178
          oss << "invalid address alignment";
1179
1180
          break;

1181
# if defined(BUS_ADRERR)
1182
        case BUS_ADRERR:
1183
          oss << "nonexistent physical address";
1184
          break;
1185
# endif
1186

1187
# if defined(BUS_OBJERR)
1188
        case BUS_OBJERR:
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
          oss << "object-specific hardware error";
          break;
# endif

# if defined(BUS_MCEERR_AR)
        case BUS_MCEERR_AR:
          oss << "Hardware memory error consumed on a machine check; action required.";
          break;
# endif

# if defined(BUS_MCEERR_AO)
        case BUS_MCEERR_AO:
          oss << "Hardware memory error detected in process but not consumed; action optional.";
1202
          break;
1203
# endif
1204
1205

        default:
1206
          oss << "code " << sigInfo->si_code;
1207
1208
1209
1210
1211
          break;
        }
      break;

    case SIGILL:
1212
1213
1214
1215
1216
      oss
        << "Caught SIGILL at "
        << (sigInfo->si_addr==0?"0x":"")
        << sigInfo->si_addr
        <<  " ";
1217
1218
1219
      switch (sigInfo->si_code)
        {
        case ILL_ILLOPC:
1220
          oss << "illegal opcode";
1221
1222
          break;

1223
# if defined(ILL_ILLOPN)
1224
        case ILL_ILLOPN:
1225
          oss << "illegal operand";
1226
          break;
1227
# endif
1228

1229
# if defined(ILL_ILLADR)
1230
        case ILL_ILLADR:
1231
          oss << "illegal addressing mode.";
1232
          break;
1233
# endif