/*
* $Revision: 2523 $
*
* last checkin:
* $Author: gutwenger $
* $Date: 2012-07-02 20:59:27 +0200 (Mon, 02 Jul 2012) $
***************************************************************/
/** \file
* \brief Decalration of System class which provides unified
* access to system information.
*
* \author Carsten Gutwenger
*
* \par License:
* This file is part of the Open Graph Drawing Framework (OGDF).
*
* \par
* Copyright (C)
* See README.txt in the root directory of the OGDF installation for details.
*
* \par
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Version 2 or 3 as published by the Free Software Foundation;
* see the file LICENSE.txt included in the packaging of this file
* for details.
*
* \par
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* \par
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* \see http://www.gnu.org/copyleft/gpl.html
***************************************************************/
#ifdef _MSC_VER
#pragma once
#endif
#ifndef OGDF_SYSTEM_H
#define OGDF_SYSTEM_H
#include "basic.h"
#if defined(OGDF_SYSTEM_OSX)
#include
#elif defined(OGDF_SYSTEM_UNIX) || defined(__MINGW32__)
#include
#endif
// detect processor architecture we're compiling for
//
// OGDF_ARCH_X86 Intel / AMD x86 32-bit processors
// OGDF_ARCH_X64 Intel / AMD x86 64-bit processors
// OGDF_ARCH_IA64 Intel Itanium
// OGDF_ARCH_PPC PowerPC
// OGDF_ARCH_SPARC SUN SPARC
// OGDF_ARCH_SPARC_V9 SUN SPARC V9
#if defined(_M_X64) || defined(__x86_64__)
#define OGDF_ARCH_X64
#elif defined(_M_IX86) || defined(__i386__)
#define OGDF_ARCH_X86
#elif defined(_M_IA64) || defined(__ia64__)
#define OGDF_ARCH_IA64
#elif defined(_M_MPPC) || defined(_M_PPC) || defined(__powerpc__)
#define OGDF_ARCH_PPC
#elif defined(__sparc__)
#define OGDF_ARCH_SPARC
#elif defined(__sparc_v9__)
#define OGDF_ARCH_SPARC_V9
#endif
// use SSE2 always if x64-platform or compiler option is set
#ifndef OGDF_USE_SSE2
#if defined(OGDF_ARCH_X64)
#define OGDF_USE_SSE2
#elif defined(_MSC_VER)
#if _M_IX86_FP >= 2
#define OGDF_USE_SSE2
#endif
#endif
#endif
// macros to check for using special cpu features
//
// OGDF_CHECK_SSE2 returns true if SSE2 can be used
#ifdef OGDF_USE_SSE2
#define OGDF_CHECK_SSE2 true
#elif defined(OGDF_ARCH_X86)
#define OGDF_CHECK_SSE2 ogdf::System::cpuSupports(ogdf::cpufSSE2)
#else
#define OGDF_USE_SSE2 false
#endif
// work-around for MinGW-w64
#ifdef __MINGW64__
#ifndef _aligned_free
#define _aligned_free(a) __mingw_aligned_free(a)
#endif
#ifndef _aligned_malloc
#define _aligned_malloc(a,b) __mingw_aligned_malloc(a,b)
#endif
#endif
namespace ogdf {
//! Special features supported by a x86/x64 CPU.
/**
* This enumeration is used to specify spcial additional features that
* are supported by the CPU, in particular extended instruction sets
* such as SSE.
*/
enum CPUFeature {
cpufMMX, //!< Intel MMX Technology
cpufSSE, //!< Streaming SIMD Extensions (SSE)
cpufSSE2, //!< Streaming SIMD Extensions 2 (SSE2)
cpufSSE3, //!< Streaming SIMD Extensions 3 (SSE3)
cpufSSSE3, //!< Supplemental Streaming SIMD Extensions 3 (SSSE3)
cpufSSE4_1, //!< Streaming SIMD Extensions 4.1 (SSE4.1)
cpufSSE4_2, //!< Streaming SIMD Extensions 4.2 (SSE4.2)
cpufVMX, //!< Virtual Machine Extensions
cpufSMX, //!< Safer Mode Extensions
cpufEST, //!< Enhanced Intel SpeedStep Technology
cpufMONITOR //!< Processor supports MONITOR/MWAIT instructions
};
//! Bit mask for CPU features.
enum CPUFeatureMask {
cpufmMMX = 1 << cpufMMX, //!< Intel MMX Technology
cpufmSSE = 1 << cpufSSE, //!< Streaming SIMD Extensions (SSE)
cpufmSSE2 = 1 << cpufSSE2, //!< Streaming SIMD Extensions 2 (SSE2)
cpufmSSE3 = 1 << cpufSSE3, //!< Streaming SIMD Extensions 3 (SSE3)
cpufmSSSE3 = 1 << cpufSSSE3, //!< Supplemental Streaming SIMD Extensions 3 (SSSE3)
cpufmSSE4_1 = 1 << cpufSSE4_1, //!< Streaming SIMD Extensions 4.1 (SSE4.1)
cpufmSSE4_2 = 1 << cpufSSE4_2, //!< Streaming SIMD Extensions 4.2 (SSE4.2)
cpufmVMX = 1 << cpufVMX, //!< Virtual Machine Extensions
cpufmSMX = 1 << cpufSMX, //!< Safer Mode Extensions
cpufmEST = 1 << cpufEST, //!< Enhanced Intel SpeedStep Technology
cpufmMONITOR = 1 << cpufMONITOR //!< Processor supports MONITOR/MWAIT instructions
};
//! %System specific functionality.
/**
* The class System encapsulates system specific functions
* providing unified access across different operating systems.
* The provided functionality includes:
* - Access to file system functionality (listing directories etc.).
* - Query memory usage.
* - Access to high-perfomance counter under Windows and Cygwin.
* - Query CPU specific information.
*/
class OGDF_EXPORT System {
//friend class ::OgdfInitialization;
public:
/**
* @name Memory usage
* These methods allow to query the amount of physical memory, as well as the
* current memory usage by both the process and OGDF's internal memory manager.
*/
//@{
static void *alignedMemoryAlloc16(size_t size) {
#ifdef OGDF_SYSTEM_WINDOWS
size_t alignment = 16;
return _aligned_malloc(size,alignment);
#elif defined(OGDF_SYSTEM_OSX)
// malloc returns 16 byte aligned memory on OS X.
return malloc(size);
#else
size_t alignment = 16;
return memalign(alignment,size);
#endif
}
static void alignedMemoryFree(void *p) {
#ifdef OGDF_SYSTEM_WINDOWS
_aligned_free(p);
#else
free(p);
#endif
}
//! Returns the page size of virtual memory (in bytes).
static int pageSize() { return s_pageSize; }
//! Returns the total size of physical memory (in bytes).
static long long physicalMemory();
//! Returns the size of available (free) physical memory (in bytes).
static long long availablePhysicalMemory();
//! Returns the amount of memory (in bytes) allocated by the process.
static size_t memoryUsedByProcess();
#if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__)
//! Returns the maximal amount of memory (in bytes) used by the process (Windows/Cygwin only).
static size_t peakMemoryUsedByProcess();
#endif
//! Returns the amount of memory (in bytes) allocated by OGDF's memory manager.
/**
* The memory manager allocates blocks of a fixed size from the system (via malloc())
* and makes it available in its free lists (for allocating small pieces of memory.
* The returned value is the total amount of memory allocated from the system;
* the amount of memory currently allocated from the user is
* memoryAllocatedByMemoryManager() - memoryInFreelistOfMemoryManager().
*
* Keep in mind that the memory manager never releases memory to the system before
* its destruction.
*/
static size_t memoryAllocatedByMemoryManager();
//! Returns the amount of memory (in bytes) contained in the global free list of OGDF's memory manager.
static size_t memoryInGlobalFreeListOfMemoryManager();
//! Returns the amount of memory (in bytes) contained in the thread's free list of OGDF's memory manager.
static size_t memoryInThreadFreeListOfMemoryManager();
//! Returns the amount of memory (in bytes) allocated on the heap (e.g., with malloc).
/**
* This refers to dynamically allocated memory, e.g., memory allocated with malloc()
* or new.
*/
static size_t memoryAllocatedByMalloc();
//! Returns the amount of memory (in bytes) contained in free chunks on the heap.
/**
* This refers to memory that has been deallocated with free() or delete, but has not
* yet been returned to the operating system.
*/
static size_t memoryInFreelistOfMalloc();
#if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__)
//@}
/**
* @name Measuring time
* These methods provide various ways to measure time. The high-performance
* counter (Windows and Cygwin only) can be used to measure real time
* periods with a better resolution than the standard system time function.
*/
//@{
//! Returns the current value of the high-performance counter in \a counter.
static void getHPCounter(LARGE_INTEGER &counter);
//! Returns the elapsed time (in seconds) between \a startCounter and \a endCounter.
static double elapsedSeconds(
const LARGE_INTEGER &startCounter,
const LARGE_INTEGER &endCounter);
#endif
//! Returns the elapsed time (in milliseconds) between \a t and now.
/**
* The functions sets \a t to to the current time. Usually, you first call
* usedRealTime(t) to query the start time \a t, and determine the elapsed time
* after performing some computation by calling usedRealTime(t) again; this time
* the return value gives you the elapsed time in milliseconds.
*/
static __int64 usedRealTime(__int64 &t);
//@}
/**
* @name Processor information
* These methods allow to query information about the current processor such as
* supported instruction sets (e.g., SSE extensions), cache size, and number of
* installed processors.
*/
//@{
//! Returns the bit vector describing the CPU features supported on current system.
static int cpuFeatures() { return s_cpuFeatures; }
//! Returns true if the CPU supports \a feature.
static bool cpuSupports(CPUFeature feature) {
return (s_cpuFeatures & (1 << feature)) != 0;
}
//! Returns the L2-cache size (in KBytes).
static int cacheSizeKBytes() { return s_cacheSize; }
//! Returns the number of bytes in a cache line.
static int cacheLineBytes() { return s_cacheLine; }
//! Returns the number of processors (cores) available on the current system.
static int numberOfProcessors() { return s_numberOfProcessors; }
//@}
private:
static unsigned int s_cpuFeatures; //!< Supported CPU features.
static int s_cacheSize; //!< Cache size in KBytes.
static int s_cacheLine; //!< Bytes in a cache line.
static int s_numberOfProcessors; //!< Number of processors (cores) available.
static int s_pageSize; //!< The page size of virtual memory.
#if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__)
static LARGE_INTEGER s_HPCounterFrequency; //!< Frequency of high-performance counter.
#endif
public:
//! Static initilization routine (automatically called).
static void init();
};
} // end namespace ogdf
#endif