Fixed min/max macro problem in MS VC++
[libcds.git] / cds / os / linux / topology.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_OS_LINUX_TOPOLOGY_H
4 #define CDSLIB_OS_LINUX_TOPOLOGY_H
5
6 #ifndef CDSLIB_OS_TOPOLOGY_H
7 #   error "<cds/os/topology.h> must be included instead"
8 #endif
9
10 #include <cds/details/defs.h>
11 #include <cds/threading/model.h>
12
13 #include <sys/syscall.h>
14 #include <sched.h>
15
16 namespace cds { namespace OS {
17     /// Linux-specific wrappers
18     CDS_CXX11_INLINE_NAMESPACE namespace Linux {
19
20         /// System topology
21         /**
22             The implementation assumes that processor IDs are in numerical order
23             from 0 to N - 1, where N - count of processor in the system
24         */
25         struct topology {
26         private:
27             //@cond
28             static unsigned int     s_nProcessorCount;
29             //@endcond
30         public:
31
32             /// Logical processor count for the system
33             static unsigned int processor_count()
34             {
35                 return s_nProcessorCount;
36             }
37
38             /// Get current processor number
39             /**
40                 Caveat: \p current_processor calls system \p sched_getcpu function
41                 that may not be defined for target system (\p sched_getcpu is available since glibc 2.6).
42                 If \p sched_getcpu is not defined the function emulates "current processor number" using
43                 thread-specific data. You may manually disable the \p sched_getcpu usage compiling with
44                 <tt>-DCDS_LINUX_NO_sched_getcpu</tt>.
45             */
46             static unsigned int current_processor()
47             {
48             // Compile libcds with -DCDS_LINUX_NO_sched_getcpu if your linux does not have sched_getcpu (glibc version less than 2.6)
49 #           if !defined(CDS_LINUX_NO_sched_getcpu) && defined(SYS_getcpu)
50                 int nProcessor = ::sched_getcpu();
51                 return nProcessor == -1 ? 0 : (unsigned int) nProcessor;
52 #           else
53                 // Use fake "current processor number" assigned for current thread
54                 return (unsigned int) threading::Manager::fake_current_processor();
55
56                 /*
57                 Another way (for x86/amd64 only)
58
59                 Using cpuid and APIC ID (http://www.scss.tcd.ie/Jeremy.Jones/GetCurrentProcessorNumberXP.htm)
60                 for x86 and amd64
61                 {
62                     _asm {mov eax, 1}
63                     _asm {cpuid}
64                     _asm {shr ebx, 24}
65                     _asm {mov eax, ebx}
66                 }
67                 However:
68                     - cpuid is full sync barrier
69                     - it is only for x86/amd64 architecture
70                 */
71 #           endif
72             }
73
74             /// Synonym for \ref current_processor
75             static unsigned int native_current_processor()
76             {
77                 return current_processor();
78             }
79
80             //@cond
81             static void init();
82             static void fini();
83             //@endcond
84         };
85     }   // namespace Linux
86
87 #ifndef CDS_CXX11_INLINE_NAMESPACE_SUPPORT
88     using Linux::topology;
89 #endif
90 }}  // namespace cds::OS
91
92 #endif  // #ifndef CDSLIB_OS_LINUX_TOPOLOGY_H