Eneboo - Documentación para desarrolladores
|
00001 // -*- C++ -*- 00002 00003 /* 00004 00005 Heap Layers: An Extensible Memory Allocation Infrastructure 00006 00007 Copyright (C) 2000-2003 by Emery Berger 00008 http://www.cs.umass.edu/~emery 00009 emery@cs.umass.edu 00010 00011 This program is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 This program is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU General Public License for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with this program; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 */ 00026 00027 00028 00029 #ifndef _CPUINFO_H_ 00030 #define _CPUINFO_H_ 00031 00032 #if defined(_WIN32) 00033 #include <windows.h> 00034 #include <process.h> 00035 #else 00036 #include <unistd.h> 00037 #endif 00038 00039 00040 #if !defined(_WIN32) 00041 #include <pthread.h> 00042 #endif 00043 00044 #if defined(__SVR4) // Solaris 00045 #include <sys/lwp.h> 00046 extern "C" unsigned int lwp_self(void); 00047 #include <thread.h> 00048 extern "C" int _thr_self(void); 00049 #endif 00050 00051 #if defined(__linux) 00052 #include <sys/types.h> 00053 #include <sys/stat.h> 00054 #include <fcntl.h> 00055 #include <string.h> 00056 #include <unistd.h> 00057 #endif 00058 00059 #if defined(__APPLE__) 00060 #include <sys/types.h> 00061 #include <sys/sysctl.h> 00062 #endif 00063 00064 #if defined(__sgi) 00065 #include <sys/types.h> 00066 #include <sys/sysmp.h> 00067 #include <sys/sysinfo.h> 00068 #endif 00069 00070 #if defined(hpux) 00071 #include <sys/mpctl.h> 00072 #endif 00073 00074 #if defined(_WIN32) 00075 extern __declspec(thread) int localThreadId; 00076 #endif 00077 00078 #if defined(__SVR4) && defined(MAP_ALIGN) 00079 extern volatile int anyThreadStackCreated; 00080 #endif 00081 00082 namespace HL { 00083 00091 class CPUInfo { 00092 public: 00093 CPUInfo (void) 00094 {} 00095 00096 inline static int getNumProcessors (void) { 00097 static int _numProcessors = computeNumProcessors(); 00098 return _numProcessors; 00099 } 00100 00101 static inline unsigned long getThreadId (void); 00102 inline static int computeNumProcessors (void); 00103 00104 }; 00105 00106 00107 int CPUInfo::computeNumProcessors (void) 00108 { 00109 static int np = 0; 00110 if (!np) { 00111 #if defined(__linux) /*|| defined(__APPLE__)*/ 00112 np = (int) sysconf(_SC_NPROCESSORS_ONLN); 00113 #elif defined(_WIN32) 00114 SYSTEM_INFO infoReturn[1]; 00115 GetSystemInfo (infoReturn); 00116 np = (int) (infoReturn->dwNumberOfProcessors); 00117 #elif defined(__sgi) 00118 np = (int) sysmp(MP_NAPROCS); 00119 #elif defined(hpux) 00120 np = mpctl(MPC_GETNUMSPUS, NULL, NULL); // or pthread_num_processors_np()? 00121 #elif defined(_SC_NPROCESSORS_ONLN) 00122 np = (int) (sysconf(_SC_NPROCESSORS_ONLN)); 00123 #else 00124 np = 2; 00125 // Unsupported platform. 00126 // Pretend we have at least two processors. This approach avoids the risk of assuming 00127 // we're on a uniprocessor, which might lead clever allocators to avoid using atomic 00128 // operations for all locks. 00129 #endif 00130 return np; 00131 } else { 00132 return np; 00133 } 00134 } 00135 00136 // Note: when stacksize arg is NULL for pthread_attr_setstacksize [Solaris], 00137 // stack size is 1 MB for 32-bit arch, 2 MB for 64-bit arch. 00138 // pthread_attr_getstacksize 00139 // pthread_attr_setstackaddr 00140 // pthread_attr_getstackaddr 00141 // PTHREAD_STACK_SIZE is minimum. 00142 // or should we just assume we have __declspec(thread) or __thread? 00143 00144 #if defined(USE_THREAD_KEYWORD) 00145 extern __thread int localThreadId; 00146 #endif 00147 00148 00149 unsigned long CPUInfo::getThreadId (void) { 00150 #if defined(__SVR4) 00151 size_t THREAD_STACK_SIZE; 00152 if (sizeof(size_t) <= 4) { 00153 THREAD_STACK_SIZE = 1048576; 00154 } else { 00155 // 64-bits. 00156 THREAD_STACK_SIZE = 1048576 * 2; 00157 } 00158 if (0) { // !anyThreadStackCreated) { 00159 // We know a priori that all stack variables 00160 // are on different stacks. Since no one has created 00161 // a special one, we are in control, and thus all stacks 00162 // are 1 MB in size and on 1 MB boundaries. 00163 // (Actually: 1 MB for 32-bits, 2 MB for 64-bits.) 00164 char buf; 00165 return (((size_t) &buf) & ~(THREAD_STACK_SIZE-1)) >> 20; 00166 } else { 00167 return (int) pthread_self(); 00168 } 00169 #elif defined(_WIN32) 00170 // It looks like thread id's are always multiples of 4, so... 00171 return GetCurrentThreadId() >> 2; 00172 #elif defined(__APPLE__) 00173 // Consecutive thread id's in Mac OS are 4096 apart; 00174 // dividing off the 4096 gives us an appropriate thread id. 00175 int tid = (int) ((unsigned long) pthread_self()) >> 12; 00176 return tid; 00177 #elif defined(__BEOS__) 00178 return find_thread(0); 00179 #elif defined(USE_THREAD_KEYWORD) 00180 return localThreadId; 00181 #elif defined(__linux) || defined(PTHREAD_KEYS_MAX) 00182 // Consecutive thread id's in Linux are 1024 apart; 00183 // dividing off the 1024 gives us an appropriate thread id. 00184 return (unsigned long) pthread_self() >> 10; 00185 #elif defined(POSIX) 00186 return (unsigned long) pthread_self(); 00187 #elif USE_SPROC 00188 // This hairiness has the same effect as calling getpid(), 00189 // but it's MUCH faster since it avoids making a system call 00190 // and just accesses the sproc-local data directly. 00191 unsigned long pid = (unsigned long) PRDA->sys_prda.prda_sys.t_pid; 00192 return pid; 00193 #else 00194 return 0; 00195 #endif 00196 } 00197 00198 } 00199 00200 #endif