tbb_misc.h

Go to the documentation of this file.
00001 /*
00002  Copyright 2005-2007 Intel Corporation. All Rights Reserved.
00003 
00004  This file is part of Threading Building Blocks.
00005 
00006  Threading Building Blocks is free software; you can redistribute it
00007  and/or modify it under the terms of the GNU General Public License
00008  version 2 as published by the Free Software Foundation.
00009 
00010  Threading Building Blocks is distributed in the hope that it will be
00011  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00012  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  GNU General Public License for more details.
00014 
00015  You should have received a copy of the GNU General Public License
00016  along with Threading Building Blocks; if not, write to the Free Software
00017  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018 
00019  As a special exception, you may use this file as part of a free software
00020  library without restriction. Specifically, if other files instantiate
00021  templates or use macros or inline functions from this file, or you compile
00022  this file and link it with other files to produce an executable, this
00023  file does not by itself cause the resulting executable to be covered by
00024  the GNU General Public License. This exception does not however
00025  invalidate any other reasons why the executable file might be covered by
00026  the GNU General Public License.
00027 */
00028 
00029 #ifndef _TBB_tbb_misc_H
00030 #define _TBB_tbb_misc_H
00031 
00032 #include "tbb/tbb_stddef.h"
00033 #include "tbb/tbb_machine.h"
00034 
00035 #if __linux__
00036 #include 
00037 #elif __APPLE__
00038 #include 
00039 #include 
00040 #endif
00041 
00042 namespace tbb {
00043 
00044 static volatile int number_of_workers = 0;
00045 
00046 #if defined(__TBB_DetectNumberOfWorkers)
00047 static inline int DetectNumberOfWorkers() {
00048     return __TBB_DetectNumberOfWorkers(); 
00049 }
00050 #else
00051 #if _WIN32||_WIN64
00052 
00053 static inline int DetectNumberOfWorkers() {
00054     if (!number_of_workers) {
00055         SYSTEM_INFO si;
00056         GetSystemInfo(&si);
00057         number_of_workers = static_castint>(si.dwNumberOfProcessors);
00058     }
00059     return number_of_workers; 
00060 }
00061 
00062 #elif __linux__ 
00063 
00064 static inline int DetectNumberOfWorkers( void ) {
00065     if (!number_of_workers) {
00066         number_of_workers = get_nprocs();
00067     }
00068     return number_of_workers; 
00069 }
00070 
00071 #elif __APPLE__
00072 
00073 static inline int DetectNumberOfWorkers( void ) {
00074     if (!number_of_workers) {
00075         int name[2] = {CTL_HW, HW_AVAILCPU};
00076         int ncpu;
00077         size_t size = sizeof(ncpu);
00078         sysctl( name, 2, &ncpu, &size, NULL, 0 );
00079         number_of_workers = ncpu;
00080     }
00081     return number_of_workers; 
00082 }
00083 
00084 #else
00085 
00086 #error Unknown OS
00087 
00088 #endif /* os kind */
00089 
00090 #endif
00091 
00092 namespace internal {
00093 
00094 // assertion_failure is declared in tbb/tbb_stddef.h because it user code
00095 // needs to see its declaration.
00096 
00098 /* The "what" should be fairly short, not more than about 64 characters.
00099  Because we control all the call sites to handle_perror, it is pointless
00100  to bullet-proof it for very long strings.
00101 
00102  Design note: ADR put this routine off to the side in tbb_misc.cpp instead of
00103  Task.cpp because the throw generates a pathetic lot of code, and ADR wanted
00104  this large chunk of code to be placed on a cold page. */
00105 void handle_perror( int error_code, const char* what );
00106 
00108 bool GetBoolEnvironmentVariable( const char * name );
00109 
00111 void PrintVersion();
00112 
00114 void PrintExtraVersionInfo( const char* category, const char* description );
00115 
00116 typedef void (*PointerToHandler)();
00117 
00119 struct DynamicLinkDescriptor {
00121     const char* name;
00123     PointerToHandler* handler;
00124 };
00125 
00127 
00130 bool FillDynamicLinks( const char* libraryname, const DynamicLinkDescriptor list[], size_t n );
00131 
00133 
00137 templatetypename T>
00138 static inline T volatile& volatile_cast(T& location) {
00139     return const_castT volatile&>(location);
00140 }
00141 
00142 templatetypename T>
00143 static inline T const volatile& volatile_cast(T const& location) {
00144     return const_castT const volatile&>(location);
00145 }
00146 
00148 
00149 class ExponentialBackoff {
00151 
00153     static const uintptr LOOPS_BEFORE_YIELD = 0x10;
00154     uintptr count;
00155 public:
00156     ExponentialBackoff() : count(1) {}
00157 
00159     void pause() {
00160         if( count00161             __TBB_Pause(count);
00162             // Pause twice as long the next time.
00163             count*=2;
00164         } else {
00165             // Pause is so long that we might as well yield CPU to scheduler.
00166             __TBB_Yield();
00167         }
00168     }
00169     void reset() {
00170         count = 1;
00171     }
00172 };
00173 
00175 
00176 templatetypename T, typename U>
00177 static inline void SpinwaitWhileEq( const volatile T& location, U value ) {
00178     ExponentialBackoff backoff;
00179     while( location==value ) {
00180         backoff.pause();
00181     }
00182 }
00183 
00185 
00186 templatetypename T, typename U>
00187 static inline void SpinwaitUntilEq( const volatile T& location, const U value ) {
00188     ExponentialBackoff backoff;
00189     while( location!=value ) {
00190         backoff.pause();
00191     }
00192 }
00193 
00194 } // namespace internal
00195 
00196 } // namespace tbb
00197 
00198 #endif /* _TBB_tbb_misc_H */

Generated on Sun Oct 12 01:45:30 2008 for NNTPGrab by  1.5.4