source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/util/cpuinfo.h @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 5.9 KB
Line 
1// -*- C++ -*-
2
3/*
4
5  Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7  Copyright (C) 2000-2003 by Emery Berger
8  http://www.cs.umass.edu/~emery
9  emery@cs.umass.edu
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27
28
29#ifndef _CPUINFO_H_
30#define _CPUINFO_H_
31
32#if defined(_WIN32)
33#include <windows.h>
34#include <process.h>
35#else
36#include <unistd.h>
37#endif
38
39
40#if !defined(_WIN32)
41#include <pthread.h>
42#endif
43
44#if defined(__SVR4) // Solaris
45#include <sys/lwp.h>
46extern "C" unsigned int lwp_self(void);
47#include <thread.h>
48extern "C" int _thr_self(void);
49#endif
50
51#if defined(__linux)
52#include <sys/types.h>
53#include <sys/stat.h>
54#include <fcntl.h>
55#include <string.h>
56#include <unistd.h>
57#endif
58
59#if defined(__APPLE__)
60#include <sys/types.h>
61#include <sys/sysctl.h>
62#endif
63
64#if defined(__sgi)
65#include <sys/types.h>
66#include <sys/sysmp.h>
67#include <sys/sysinfo.h>
68#endif
69
70#if defined(hpux)
71#include <sys/mpctl.h>
72#endif
73
74#if defined(_WIN32)
75extern __declspec(thread) int localThreadId;
76#endif
77
78#if defined(__SVR4) && defined(MAP_ALIGN)
79extern volatile int anyThreadStackCreated;
80#endif
81
82namespace HL {
83
84/**
85 * @class CPUInfo
86 * @author Emery Berger <http://www.cs.umass.edu/~emery>
87 *
88 * @brief Architecture-independent wrapper to get number of CPUs.
89 */
90
91class CPUInfo {
92public:
93  CPUInfo (void)
94  {}
95
96  inline static int getNumProcessors (void) {
97    static int _numProcessors = computeNumProcessors();
98    return _numProcessors;
99  }
100
101  static inline int getThreadId (void);
102  inline static int computeNumProcessors (void);
103
104};
105
106
107int CPUInfo::computeNumProcessors (void)
108{
109  static int np = 0;
110  if (!np) {
111#if defined(__linux)
112  // Ugly workaround.  Linux's sysconf indirectly calls malloc() (at
113  // least on multiprocessors).  So we just read the info from the
114  // proc file ourselves and count the occurrences of the word
115  // "processor".
116 
117  // We only parse the first 32K of the CPU file.  By my estimates,
118  // that should be more than enough for at least 64 processors.
119  enum { MAX_PROCFILE_SIZE = 32768 };
120  char line[MAX_PROCFILE_SIZE];
121  int fd = open ("/proc/cpuinfo", O_RDONLY);
122  if (!fd) {
123    return 1;
124  } else {
125    read (fd, line, MAX_PROCFILE_SIZE);
126    char * str = line;
127    np = 0;
128    while (str) {
129      str = strstr(str, "processor");
130      if (str) {
131        np++;
132        str++;
133      }
134    }
135    close (fd);
136    return np;
137  }
138#elif defined(_WIN32)
139  SYSTEM_INFO infoReturn[1];
140  GetSystemInfo (infoReturn);
141  np = (int) (infoReturn->dwNumberOfProcessors);
142  return np;
143#elif defined(__sgi)
144  np = (int) sysmp(MP_NAPROCS);
145  return np;
146#elif defined(hpux)
147  np = mpctl(MPC_GETNUMSPUS, NULL, NULL); // or pthread_num_processors_np()?
148  return np;
149#elif defined(_SC_NPROCESSORS_ONLN)
150  np = (int) (sysconf(_SC_NPROCESSORS_ONLN));
151  return np;
152#elif defined(__APPLE__)
153  size_t size = sizeof( np ); 
154  int name[] = { CTL_HW, HW_NCPU };
155  if ( ::sysctl( name, 2, & np, & size, 0, 0 ) ||
156       ( size != sizeof( np ) ) ) {
157     np = 2;
158  }
159  return np;
160#else
161  np = 2;
162  // Unsupported platform.
163  // Pretend we have at least two processors. This approach avoids the risk of assuming
164  // we're on a uniprocessor, which might lead clever allocators to avoid using atomic
165  // operations for all locks.
166  return np;
167#endif
168  } else {
169    return np;
170  }
171}
172
173  // Note: when stacksize arg is NULL for pthread_attr_setstacksize [Solaris],
174// stack size is 1 MB for 32-bit arch, 2 MB for 64-bit arch.
175// pthread_attr_getstacksize
176// pthread_attr_setstackaddr
177// pthread_attr_getstackaddr
178// PTHREAD_STACK_SIZE is minimum.
179// or should we just assume we have __declspec(thread) or __thread?
180
181#if defined(USE_THREAD_KEYWORD)
182  extern __thread int localThreadId;
183#endif
184
185
186int CPUInfo::getThreadId (void) {
187#if defined(__SVR4)
188  size_t THREAD_STACK_SIZE;
189  if (sizeof(size_t) <= 4) {
190    THREAD_STACK_SIZE = 1048576;
191  } else {
192    // 64-bits.
193    THREAD_STACK_SIZE = 1048576 * 2;
194  }
195  if (0) { // !anyThreadStackCreated) {
196    // We know a priori that all stack variables
197    // are on different stacks. Since no one has created
198    // a special one, we are in control, and thus all stacks
199    // are 1 MB in size and on 1 MB boundaries.
200    // (Actually: 1 MB for 32-bits, 2 MB for 64-bits.)
201    char buf;
202    return (((size_t) &buf) & ~(THREAD_STACK_SIZE-1)) >> 20;
203  } else {
204    return (int) pthread_self();
205  }
206#elif defined(_WIN32)
207  // It looks like thread id's are always multiples of 4, so...
208  return GetCurrentThreadId() >> 2;
209#elif defined(__BEOS__)
210  return find_thread(0);
211#elif defined(USE_THREAD_KEYWORD)
212  return localThreadId;
213#elif defined(__linux) || defined(PTHREAD_KEYS_MAX)
214  // Consecutive thread id's in Linux are 1024 apart;
215  // dividing off the 1024 gives us an appropriate thread id.
216  return (int) pthread_self() >> 10; // >> 20; // FIX ME 10 // (>> 10 = / 1024)
217#elif defined(POSIX) // FIX ME??
218  return (int) pthread_self();
219#elif USE_SPROC
220  // This hairiness has the same effect as calling getpid(),
221  // but it's MUCH faster since it avoids making a system call
222  // and just accesses the sproc-local data directly.
223  int pid = (int) PRDA->sys_prda.prda_sys.t_pid;
224  return pid;
225#else
226  return 0;
227#endif
228}
229
230}
231
232#endif
Note: See TracBrowser for help on using the repository browser.